initial commit with v2.6.9
[linux-2.6.9-moxart.git] / net / rxrpc / krxtimod.c
blob31771577c5bbf80e1532baa80ee296d3f1162402
1 /* krxtimod.c: RXRPC timeout daemon
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/completion.h>
16 #include <rxrpc/rxrpc.h>
17 #include <rxrpc/krxtimod.h>
18 #include <asm/errno.h>
19 #include "internal.h"
21 static DECLARE_COMPLETION(krxtimod_alive);
22 static DECLARE_COMPLETION(krxtimod_dead);
23 static DECLARE_WAIT_QUEUE_HEAD(krxtimod_sleepq);
24 static int krxtimod_die;
26 static LIST_HEAD(krxtimod_list);
27 static spinlock_t krxtimod_lock = SPIN_LOCK_UNLOCKED;
29 static int krxtimod(void *arg);
31 /*****************************************************************************/
33 * start the timeout daemon
35 int rxrpc_krxtimod_start(void)
37 int ret;
39 ret = kernel_thread(krxtimod, NULL, 0);
40 if (ret < 0)
41 return ret;
43 wait_for_completion(&krxtimod_alive);
45 return ret;
46 } /* end rxrpc_krxtimod_start() */
48 /*****************************************************************************/
50 * stop the timeout daemon
52 void rxrpc_krxtimod_kill(void)
54 /* get rid of my daemon */
55 krxtimod_die = 1;
56 wake_up(&krxtimod_sleepq);
57 wait_for_completion(&krxtimod_dead);
59 } /* end rxrpc_krxtimod_kill() */
61 /*****************************************************************************/
63 * timeout processing daemon
65 static int krxtimod(void *arg)
67 DECLARE_WAITQUEUE(myself, current);
69 rxrpc_timer_t *timer;
71 printk("Started krxtimod %d\n", current->pid);
73 daemonize("krxtimod");
75 complete(&krxtimod_alive);
77 /* loop around looking for things to attend to */
78 loop:
79 set_current_state(TASK_INTERRUPTIBLE);
80 add_wait_queue(&krxtimod_sleepq, &myself);
82 for (;;) {
83 unsigned long jif;
84 signed long timeout;
86 /* deal with the server being asked to die */
87 if (krxtimod_die) {
88 remove_wait_queue(&krxtimod_sleepq, &myself);
89 _leave("");
90 complete_and_exit(&krxtimod_dead, 0);
93 /* discard pending signals */
94 rxrpc_discard_my_signals();
96 /* work out the time to elapse before the next event */
97 spin_lock(&krxtimod_lock);
98 if (list_empty(&krxtimod_list)) {
99 timeout = MAX_SCHEDULE_TIMEOUT;
101 else {
102 timer = list_entry(krxtimod_list.next,
103 rxrpc_timer_t, link);
104 timeout = timer->timo_jif;
105 jif = jiffies;
107 if (time_before_eq((unsigned long) timeout, jif))
108 goto immediate;
110 else {
111 timeout = (long) timeout - (long) jiffies;
114 spin_unlock(&krxtimod_lock);
116 schedule_timeout(timeout);
118 set_current_state(TASK_INTERRUPTIBLE);
121 /* the thing on the front of the queue needs processing
122 * - we come here with the lock held and timer pointing to the expired
123 * entry
125 immediate:
126 remove_wait_queue(&krxtimod_sleepq, &myself);
127 set_current_state(TASK_RUNNING);
129 _debug("@@@ Begin Timeout of %p", timer);
131 /* dequeue the timer */
132 list_del_init(&timer->link);
133 spin_unlock(&krxtimod_lock);
135 /* call the timeout function */
136 timer->ops->timed_out(timer);
138 _debug("@@@ End Timeout");
139 goto loop;
141 } /* end krxtimod() */
143 /*****************************************************************************/
145 * (re-)queue a timer
147 void rxrpc_krxtimod_add_timer(rxrpc_timer_t *timer, unsigned long timeout)
149 struct list_head *_p;
150 rxrpc_timer_t *ptimer;
152 _enter("%p,%lu", timer, timeout);
154 spin_lock(&krxtimod_lock);
156 list_del(&timer->link);
158 /* the timer was deferred or reset - put it back in the queue at the
159 * right place */
160 timer->timo_jif = jiffies + timeout;
162 list_for_each(_p, &krxtimod_list) {
163 ptimer = list_entry(_p, rxrpc_timer_t, link);
164 if (time_before(timer->timo_jif, ptimer->timo_jif))
165 break;
168 list_add_tail(&timer->link, _p); /* insert before stopping point */
170 spin_unlock(&krxtimod_lock);
172 wake_up(&krxtimod_sleepq);
174 _leave("");
175 } /* end rxrpc_krxtimod_add_timer() */
177 /*****************************************************************************/
179 * dequeue a timer
180 * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
182 int rxrpc_krxtimod_del_timer(rxrpc_timer_t *timer)
184 int ret = 0;
186 _enter("%p", timer);
188 spin_lock(&krxtimod_lock);
190 if (list_empty(&timer->link))
191 ret = -ENOENT;
192 else
193 list_del_init(&timer->link);
195 spin_unlock(&krxtimod_lock);
197 wake_up(&krxtimod_sleepq);
199 _leave(" = %d", ret);
200 return ret;
201 } /* end rxrpc_krxtimod_del_timer() */