2
* Copyright (c) 2001-2004 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
* @brief Timeout management functions.
38
#include <time/timeout.h>
39
#include <arch/types.h>
42
#include <synch/spinlock.h>
48
/** Initialize timeouts
50
* Initialize kernel timeouts.
53
void timeout_init(void)
55
spinlock_initialize(&CPU->timeoutlock, "timeout_lock");
56
list_initialize(&CPU->timeout_active_head);
60
/** Reinitialize timeout
62
* Initialize all members except the lock.
64
* @param t Timeout to be initialized.
67
void timeout_reinitialize(timeout_t *t)
73
link_initialize(&t->link);
77
/** Initialize timeout
79
* Initialize all members including the lock.
81
* @param t Timeout to be initialized.
84
void timeout_initialize(timeout_t *t)
86
spinlock_initialize(&t->lock, "timeout_t_lock");
87
timeout_reinitialize(t);
93
* Insert timeout handler f (with argument arg)
94
* to timeout list and make it execute in
95
* time microseconds (or slightly more).
97
* @param t Timeout structure.
98
* @param time Number of usec in the future to execute the handler.
99
* @param f Timeout handler function.
100
* @param arg Timeout handler argument.
104
timeout_register(timeout_t *t, uint64_t time, timeout_handler_t f, void *arg)
106
timeout_t *hlp = NULL;
111
ipl = interrupts_disable();
112
spinlock_lock(&CPU->timeoutlock);
113
spinlock_lock(&t->lock);
116
panic("Unexpected: t->cpu != 0.");
119
t->ticks = us2ticks(time);
125
* Insert t into the active timeouts list according to t->ticks.
128
l = CPU->timeout_active_head.next;
129
while (l != &CPU->timeout_active_head) {
130
hlp = list_get_instance(l, timeout_t, link);
131
spinlock_lock(&hlp->lock);
132
if (t->ticks < sum + hlp->ticks) {
133
spinlock_unlock(&hlp->lock);
137
spinlock_unlock(&hlp->lock);
142
list_prepend(&t->link, m); /* avoid using l->prev */
145
* Adjust t->ticks according to ticks accumulated in h's predecessors.
150
* Decrease ticks of t's immediate succesor by t->ticks.
152
if (l != &CPU->timeout_active_head) {
153
spinlock_lock(&hlp->lock);
154
hlp->ticks -= t->ticks;
155
spinlock_unlock(&hlp->lock);
158
spinlock_unlock(&t->lock);
159
spinlock_unlock(&CPU->timeoutlock);
160
interrupts_restore(ipl);
164
/** Unregister timeout
166
* Remove timeout from timeout list.
168
* @param t Timeout to unregister.
170
* @return True on success, false on failure.
172
bool timeout_unregister(timeout_t *t)
177
DEADLOCK_PROBE_INIT(p_tolock);
180
ipl = interrupts_disable();
181
spinlock_lock(&t->lock);
183
spinlock_unlock(&t->lock);
184
interrupts_restore(ipl);
187
if (!spinlock_trylock(&t->cpu->timeoutlock)) {
188
spinlock_unlock(&t->lock);
189
interrupts_restore(ipl);
190
DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
195
* Now we know for sure that t hasn't been activated yet
196
* and is lurking in t->cpu->timeout_active_head queue.
200
if (l != &t->cpu->timeout_active_head) {
201
hlp = list_get_instance(l, timeout_t, link);
202
spinlock_lock(&hlp->lock);
203
hlp->ticks += t->ticks;
204
spinlock_unlock(&hlp->lock);
207
list_remove(&t->link);
208
spinlock_unlock(&t->cpu->timeoutlock);
210
timeout_reinitialize(t);
211
spinlock_unlock(&t->lock);
213
interrupts_restore(ipl);