source: mainline/generic/src/time/timeout.c@ 280a27e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 280a27e was 280a27e, checked in by Josef Cejka <malyzelenyhnus@…>, 20 years ago

Printf ported back from uspace to kernel.
Printf calls changed to match new conventions.

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