source: mainline/generic/src/time/timeout.c@ 953b0f33

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 953b0f33 was cf26ba9, checked in by Jakub Jermar <jakub@…>, 20 years ago

Improve Doxygen-comments.

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*
2 * Copyright (C) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/**
30 * @file timeout.c
31 * @brief Timeout management functions.
32 */
33
34#include <time/timeout.h>
35#include <typedefs.h>
36#include <arch/types.h>
37#include <config.h>
38#include <panic.h>
39#include <synch/spinlock.h>
40#include <func.h>
41#include <cpu.h>
42#include <arch/asm.h>
43#include <arch.h>
44
45
46/** Initialize timeouts
47 *
48 * Initialize kernel timeouts.
49 *
50 */
51void timeout_init(void)
52{
53 spinlock_initialize(&CPU->timeoutlock, "timeout_lock");
54 list_initialize(&CPU->timeout_active_head);
55}
56
57
58/** Reinitialize timeout
59 *
60 * Initialize all members except the lock.
61 *
62 * @param t Timeout to be initialized.
63 *
64 */
65void timeout_reinitialize(timeout_t *t)
66{
67 t->cpu = NULL;
68 t->ticks = 0;
69 t->handler = NULL;
70 t->arg = NULL;
71 link_initialize(&t->link);
72}
73
74
75/** Initialize timeout
76 *
77 * Initialize all members including the lock.
78 *
79 * @param t Timeout to be initialized.
80 *
81 */
82void timeout_initialize(timeout_t *t)
83{
84 spinlock_initialize(&t->lock, "timeout_t_lock");
85 timeout_reinitialize(t);
86}
87
88
89/** Register timeout
90 *
91 * Insert timeout handler f (with argument arg)
92 * to timeout list and make it execute in
93 * time microseconds (or slightly more).
94 *
95 * @param t Timeout structure.
96 * @param time Number of usec in the future to execute
97 * the handler.
98 * @param f Timeout handler function.
99 * @param arg Timeout handler argument.
100 *
101 */
102void timeout_register(timeout_t *t, __u64 time, timeout_handler_t f, void *arg)
103{
104 timeout_t *hlp = NULL;
105 link_t *l, *m;
106 ipl_t ipl;
107 __u64 sum;
108
109 ipl = interrupts_disable();
110 spinlock_lock(&CPU->timeoutlock);
111 spinlock_lock(&t->lock);
112
113 if (t->cpu)
114 panic("t->cpu != 0");
115
116 t->cpu = CPU;
117 t->ticks = us2ticks(time);
118
119 t->handler = f;
120 t->arg = arg;
121
122 /*
123 * Insert t into the active timeouts list according to t->ticks.
124 */
125 sum = 0;
126 l = CPU->timeout_active_head.next;
127 while (l != &CPU->timeout_active_head) {
128 hlp = list_get_instance(l, timeout_t, link);
129 spinlock_lock(&hlp->lock);
130 if (t->ticks < sum + hlp->ticks) {
131 spinlock_unlock(&hlp->lock);
132 break;
133 }
134 sum += hlp->ticks;
135 spinlock_unlock(&hlp->lock);
136 l = l->next;
137 }
138
139 m = l->prev;
140 list_prepend(&t->link, m); /* avoid using l->prev */
141
142 /*
143 * Adjust t->ticks according to ticks accumulated in h's predecessors.
144 */
145 t->ticks -= sum;
146
147 /*
148 * Decrease ticks of t's immediate succesor by t->ticks.
149 */
150 if (l != &CPU->timeout_active_head) {
151 spinlock_lock(&hlp->lock);
152 hlp->ticks -= t->ticks;
153 spinlock_unlock(&hlp->lock);
154 }
155
156 spinlock_unlock(&t->lock);
157 spinlock_unlock(&CPU->timeoutlock);
158 interrupts_restore(ipl);
159}
160
161
162/** Unregister timeout
163 *
164 * Remove timeout from timeout list.
165 *
166 * @param t Timeout to unregister.
167 *
168 * @return true on success, false on failure.
169 */
170bool timeout_unregister(timeout_t *t)
171{
172 timeout_t *hlp;
173 link_t *l;
174 ipl_t ipl;
175
176grab_locks:
177 ipl = interrupts_disable();
178 spinlock_lock(&t->lock);
179 if (!t->cpu) {
180 spinlock_unlock(&t->lock);
181 interrupts_restore(ipl);
182 return false;
183 }
184 if (!spinlock_trylock(&t->cpu->timeoutlock)) {
185 spinlock_unlock(&t->lock);
186 interrupts_restore(ipl);
187 goto grab_locks;
188 }
189
190 /*
191 * Now we know for sure that t hasn't been activated yet
192 * and is lurking in t->cpu->timeout_active_head queue.
193 */
194
195 l = t->link.next;
196 if (l != &t->cpu->timeout_active_head) {
197 hlp = list_get_instance(l, timeout_t, link);
198 spinlock_lock(&hlp->lock);
199 hlp->ticks += t->ticks;
200 spinlock_unlock(&hlp->lock);
201 }
202
203 list_remove(&t->link);
204 spinlock_unlock(&t->cpu->timeoutlock);
205
206 timeout_reinitialize(t);
207 spinlock_unlock(&t->lock);
208
209 interrupts_restore(ipl);
210 return true;
211}
Note: See TracBrowser for help on using the repository browser.