source: mainline/kernel/generic/src/time/timeout.c@ da1bafb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since da1bafb was da1bafb, checked in by Martin Decky <martin@…>, 15 years ago

major code revision

  • replace spinlocks taken with interrupts disabled with irq_spinlocks
  • change spacing (not indendation) to be tab-size independent
  • use unsigned integer types where appropriate (especially bit flags)
  • visual separation
  • remove argument names in function prototypes
  • string changes
  • correct some formating directives
  • replace various cryptic single-character variables (t, a, m, c, b, etc.) with proper identifiers (thread, task, timeout, as, itm, itc, etc.)
  • unify some assembler constructs
  • unused page table levels are now optimized out in compile time
  • replace several ints (with boolean semantics) with bools
  • use specifically sized types instead of generic types where appropriate (size_t, uint32_t, btree_key_t)
  • improve comments
  • split asserts with conjuction into multiple independent asserts
  • Property mode set to 100644
File size: 5.4 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/** @addtogroup time
30 * @{
31 */
32
33/**
34 * @file
35 * @brief Timeout management functions.
36 */
37
38#include <time/timeout.h>
39#include <typedefs.h>
40#include <config.h>
41#include <panic.h>
42#include <synch/spinlock.h>
43#include <func.h>
44#include <cpu.h>
45#include <arch/asm.h>
46#include <arch.h>
47
48/** Initialize timeouts
49 *
50 * Initialize kernel timeouts.
51 *
52 */
53void timeout_init(void)
54{
55 irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");
56 list_initialize(&CPU->timeout_active_head);
57}
58
59/** Reinitialize timeout
60 *
61 * Initialize all members except the lock.
62 *
63 * @param timeout Timeout to be initialized.
64 *
65 */
66void timeout_reinitialize(timeout_t *timeout)
67{
68 timeout->cpu = NULL;
69 timeout->ticks = 0;
70 timeout->handler = NULL;
71 timeout->arg = NULL;
72 link_initialize(&timeout->link);
73}
74
75/** Initialize timeout
76 *
77 * Initialize all members including the lock.
78 *
79 * @param timeout Timeout to be initialized.
80 *
81 */
82void timeout_initialize(timeout_t *timeout)
83{
84 irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
85 timeout_reinitialize(timeout);
86}
87
88/** Register timeout
89 *
90 * Insert timeout handler f (with argument arg)
91 * to timeout list and make it execute in
92 * time microseconds (or slightly more).
93 *
94 * @param timeout Timeout structure.
95 * @param time Number of usec in the future to execute the handler.
96 * @param handler Timeout handler function.
97 * @param arg Timeout handler argument.
98 *
99 */
100void timeout_register(timeout_t *timeout, uint64_t time,
101 timeout_handler_t handler, void *arg)
102{
103 irq_spinlock_lock(&CPU->timeoutlock, true);
104 irq_spinlock_lock(&timeout->lock, false);
105
106 if (timeout->cpu)
107 panic("Unexpected: timeout->cpu != 0.");
108
109 timeout->cpu = CPU;
110 timeout->ticks = us2ticks(time);
111
112 timeout->handler = handler;
113 timeout->arg = arg;
114
115 /*
116 * Insert timeout into the active timeouts list according to timeout->ticks.
117 */
118 uint64_t sum = 0;
119 timeout_t *target = NULL;
120 link_t *cur;
121 for (cur = CPU->timeout_active_head.next;
122 cur != &CPU->timeout_active_head; cur = cur->next) {
123 target = list_get_instance(cur, timeout_t, link);
124 irq_spinlock_lock(&target->lock, false);
125
126 if (timeout->ticks < sum + target->ticks) {
127 irq_spinlock_unlock(&target->lock, false);
128 break;
129 }
130
131 sum += target->ticks;
132 irq_spinlock_unlock(&target->lock, false);
133 }
134
135 /* Avoid using cur->prev directly */
136 link_t *prev = cur->prev;
137 list_prepend(&timeout->link, prev);
138
139 /*
140 * Adjust timeout->ticks according to ticks
141 * accumulated in target's predecessors.
142 */
143 timeout->ticks -= sum;
144
145 /*
146 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
147 */
148 if (cur != &CPU->timeout_active_head) {
149 irq_spinlock_lock(&target->lock, false);
150 target->ticks -= timeout->ticks;
151 irq_spinlock_unlock(&target->lock, false);
152 }
153
154 irq_spinlock_unlock(&timeout->lock, false);
155 irq_spinlock_unlock(&CPU->timeoutlock, true);
156}
157
158/** Unregister timeout
159 *
160 * Remove timeout from timeout list.
161 *
162 * @param timeout Timeout to unregister.
163 *
164 * @return True on success, false on failure.
165 *
166 */
167bool timeout_unregister(timeout_t *timeout)
168{
169 DEADLOCK_PROBE_INIT(p_tolock);
170
171grab_locks:
172 irq_spinlock_lock(&timeout->lock, true);
173 if (!timeout->cpu) {
174 irq_spinlock_unlock(&timeout->lock, true);
175 return false;
176 }
177
178 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
179 irq_spinlock_unlock(&timeout->lock, true);
180 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
181 goto grab_locks;
182 }
183
184 /*
185 * Now we know for sure that timeout hasn't been activated yet
186 * and is lurking in timeout->cpu->timeout_active_head queue.
187 */
188
189 link_t *cur = timeout->link.next;
190 if (cur != &timeout->cpu->timeout_active_head) {
191 timeout_t *tmp = list_get_instance(cur, timeout_t, link);
192 irq_spinlock_lock(&tmp->lock, false);
193 tmp->ticks += timeout->ticks;
194 irq_spinlock_unlock(&tmp->lock, false);
195 }
196
197 list_remove(&timeout->link);
198 irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
199
200 timeout_reinitialize(timeout);
201 irq_spinlock_unlock(&timeout->lock, true);
202
203 return true;
204}
205
206/** @}
207 */
Note: See TracBrowser for help on using the repository browser.