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>
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 DEFINE_SPINLOCK(krxtimod_lock
);
29 static int krxtimod(void *arg
);
31 /*****************************************************************************/
33 * start the timeout daemon
35 int rxrpc_krxtimod_start(void)
39 ret
= kernel_thread(krxtimod
, NULL
, 0);
43 wait_for_completion(&krxtimod_alive
);
46 } /* end rxrpc_krxtimod_start() */
48 /*****************************************************************************/
50 * stop the timeout daemon
52 void rxrpc_krxtimod_kill(void)
54 /* get rid of my daemon */
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
);
71 printk("Started krxtimod %d\n", current
->pid
);
73 daemonize("krxtimod");
75 complete(&krxtimod_alive
);
77 /* loop around looking for things to attend to */
79 set_current_state(TASK_INTERRUPTIBLE
);
80 add_wait_queue(&krxtimod_sleepq
, &myself
);
86 /* deal with the server being asked to die */
88 remove_wait_queue(&krxtimod_sleepq
, &myself
);
90 complete_and_exit(&krxtimod_dead
, 0);
95 /* discard pending signals */
96 rxrpc_discard_my_signals();
98 /* work out the time to elapse before the next event */
99 spin_lock(&krxtimod_lock
);
100 if (list_empty(&krxtimod_list
)) {
101 timeout
= MAX_SCHEDULE_TIMEOUT
;
104 timer
= list_entry(krxtimod_list
.next
,
105 rxrpc_timer_t
, link
);
106 timeout
= timer
->timo_jif
;
109 if (time_before_eq((unsigned long) timeout
, jif
))
113 timeout
= (long) timeout
- (long) jiffies
;
116 spin_unlock(&krxtimod_lock
);
118 schedule_timeout(timeout
);
120 set_current_state(TASK_INTERRUPTIBLE
);
123 /* the thing on the front of the queue needs processing
124 * - we come here with the lock held and timer pointing to the expired
128 remove_wait_queue(&krxtimod_sleepq
, &myself
);
129 set_current_state(TASK_RUNNING
);
131 _debug("@@@ Begin Timeout of %p", timer
);
133 /* dequeue the timer */
134 list_del_init(&timer
->link
);
135 spin_unlock(&krxtimod_lock
);
137 /* call the timeout function */
138 timer
->ops
->timed_out(timer
);
140 _debug("@@@ End Timeout");
143 } /* end krxtimod() */
145 /*****************************************************************************/
149 void rxrpc_krxtimod_add_timer(rxrpc_timer_t
*timer
, unsigned long timeout
)
151 struct list_head
*_p
;
152 rxrpc_timer_t
*ptimer
;
154 _enter("%p,%lu", timer
, timeout
);
156 spin_lock(&krxtimod_lock
);
158 list_del(&timer
->link
);
160 /* the timer was deferred or reset - put it back in the queue at the
162 timer
->timo_jif
= jiffies
+ timeout
;
164 list_for_each(_p
, &krxtimod_list
) {
165 ptimer
= list_entry(_p
, rxrpc_timer_t
, link
);
166 if (time_before(timer
->timo_jif
, ptimer
->timo_jif
))
170 list_add_tail(&timer
->link
, _p
); /* insert before stopping point */
172 spin_unlock(&krxtimod_lock
);
174 wake_up(&krxtimod_sleepq
);
177 } /* end rxrpc_krxtimod_add_timer() */
179 /*****************************************************************************/
182 * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
184 int rxrpc_krxtimod_del_timer(rxrpc_timer_t
*timer
)
190 spin_lock(&krxtimod_lock
);
192 if (list_empty(&timer
->link
))
195 list_del_init(&timer
->link
);
197 spin_unlock(&krxtimod_lock
);
199 wake_up(&krxtimod_sleepq
);
201 _leave(" = %d", ret
);
203 } /* end rxrpc_krxtimod_del_timer() */