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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 314f4b59 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • 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 <halt.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_list);
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_list.head.next;
122 cur != &CPU->timeout_active_list.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_insert_after(&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_list.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_list.
187 */
188
189 link_t *cur = timeout->link.next;
190 if (cur != &timeout->cpu->timeout_active_list.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.