Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16 204 lines 4.7 kB view raw
1/* kafstimod.c: AFS timeout daemon 2 * 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/sched.h> 15#include <linux/completion.h> 16#include "cell.h" 17#include "volume.h" 18#include "kafstimod.h" 19#include <asm/errno.h> 20#include "internal.h" 21 22static DECLARE_COMPLETION(kafstimod_alive); 23static DECLARE_COMPLETION(kafstimod_dead); 24static DECLARE_WAIT_QUEUE_HEAD(kafstimod_sleepq); 25static int kafstimod_die; 26 27static LIST_HEAD(kafstimod_list); 28static DEFINE_SPINLOCK(kafstimod_lock); 29 30static int kafstimod(void *arg); 31 32/*****************************************************************************/ 33/* 34 * start the timeout daemon 35 */ 36int afs_kafstimod_start(void) 37{ 38 int ret; 39 40 ret = kernel_thread(kafstimod, NULL, 0); 41 if (ret < 0) 42 return ret; 43 44 wait_for_completion(&kafstimod_alive); 45 46 return ret; 47} /* end afs_kafstimod_start() */ 48 49/*****************************************************************************/ 50/* 51 * stop the timeout daemon 52 */ 53void afs_kafstimod_stop(void) 54{ 55 /* get rid of my daemon */ 56 kafstimod_die = 1; 57 wake_up(&kafstimod_sleepq); 58 wait_for_completion(&kafstimod_dead); 59 60} /* end afs_kafstimod_stop() */ 61 62/*****************************************************************************/ 63/* 64 * timeout processing daemon 65 */ 66static int kafstimod(void *arg) 67{ 68 struct afs_timer *timer; 69 70 DECLARE_WAITQUEUE(myself, current); 71 72 printk("kAFS: Started kafstimod %d\n", current->pid); 73 74 daemonize("kafstimod"); 75 76 complete(&kafstimod_alive); 77 78 /* loop around looking for things to attend to */ 79 loop: 80 set_current_state(TASK_INTERRUPTIBLE); 81 add_wait_queue(&kafstimod_sleepq, &myself); 82 83 for (;;) { 84 unsigned long jif; 85 signed long timeout; 86 87 /* deal with the server being asked to die */ 88 if (kafstimod_die) { 89 remove_wait_queue(&kafstimod_sleepq, &myself); 90 _leave(""); 91 complete_and_exit(&kafstimod_dead, 0); 92 } 93 94 try_to_freeze(); 95 96 /* discard pending signals */ 97 afs_discard_my_signals(); 98 99 /* work out the time to elapse before the next event */ 100 spin_lock(&kafstimod_lock); 101 if (list_empty(&kafstimod_list)) { 102 timeout = MAX_SCHEDULE_TIMEOUT; 103 } 104 else { 105 timer = list_entry(kafstimod_list.next, 106 struct afs_timer, link); 107 timeout = timer->timo_jif; 108 jif = jiffies; 109 110 if (time_before_eq((unsigned long) timeout, jif)) 111 goto immediate; 112 113 else { 114 timeout = (long) timeout - (long) jiffies; 115 } 116 } 117 spin_unlock(&kafstimod_lock); 118 119 schedule_timeout(timeout); 120 121 set_current_state(TASK_INTERRUPTIBLE); 122 } 123 124 /* the thing on the front of the queue needs processing 125 * - we come here with the lock held and timer pointing to the expired 126 * entry 127 */ 128 immediate: 129 remove_wait_queue(&kafstimod_sleepq, &myself); 130 set_current_state(TASK_RUNNING); 131 132 _debug("@@@ Begin Timeout of %p", timer); 133 134 /* dequeue the timer */ 135 list_del_init(&timer->link); 136 spin_unlock(&kafstimod_lock); 137 138 /* call the timeout function */ 139 timer->ops->timed_out(timer); 140 141 _debug("@@@ End Timeout"); 142 goto loop; 143 144} /* end kafstimod() */ 145 146/*****************************************************************************/ 147/* 148 * (re-)queue a timer 149 */ 150void afs_kafstimod_add_timer(struct afs_timer *timer, unsigned long timeout) 151{ 152 struct afs_timer *ptimer; 153 struct list_head *_p; 154 155 _enter("%p,%lu", timer, timeout); 156 157 spin_lock(&kafstimod_lock); 158 159 list_del(&timer->link); 160 161 /* the timer was deferred or reset - put it back in the queue at the 162 * right place */ 163 timer->timo_jif = jiffies + timeout; 164 165 list_for_each(_p, &kafstimod_list) { 166 ptimer = list_entry(_p, struct afs_timer, link); 167 if (time_before(timer->timo_jif, ptimer->timo_jif)) 168 break; 169 } 170 171 list_add_tail(&timer->link, _p); /* insert before stopping point */ 172 173 spin_unlock(&kafstimod_lock); 174 175 wake_up(&kafstimod_sleepq); 176 177 _leave(""); 178} /* end afs_kafstimod_add_timer() */ 179 180/*****************************************************************************/ 181/* 182 * dequeue a timer 183 * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued 184 */ 185int afs_kafstimod_del_timer(struct afs_timer *timer) 186{ 187 int ret = 0; 188 189 _enter("%p", timer); 190 191 spin_lock(&kafstimod_lock); 192 193 if (list_empty(&timer->link)) 194 ret = -ENOENT; 195 else 196 list_del_init(&timer->link); 197 198 spin_unlock(&kafstimod_lock); 199 200 wake_up(&kafstimod_sleepq); 201 202 _leave(" = %d", ret); 203 return ret; 204} /* end afs_kafstimod_del_timer() */