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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 69114714 was 55b77d9, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Separate list_t typedef from link_t (kernel part).

  • list_t represents lists
  • Use list_first(), list_last(), list_empty() where appropriate
  • Use list_foreach() where possible
  • Replace improper uses of list_prepend() with list_insert_after()
  • Replace improper uses of list_append() with list_insert_before()
  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[f761f1eb]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
[1bb2e7a]29/** @addtogroup time
[b45c443]30 * @{
31 */
32
[cf26ba9]33/**
[b45c443]34 * @file
[da1bafb]35 * @brief Timeout management functions.
[cf26ba9]36 */
37
[f761f1eb]38#include <time/timeout.h>
[d99c1d2]39#include <typedefs.h>
[f761f1eb]40#include <config.h>
[02a99d2]41#include <panic.h>
[f761f1eb]42#include <synch/spinlock.h>
43#include <func.h>
44#include <cpu.h>
45#include <arch/asm.h>
46#include <arch.h>
47
[70527f1]48/** Initialize timeouts
49 *
50 * Initialize kernel timeouts.
51 *
52 */
[f761f1eb]53void timeout_init(void)
54{
[da1bafb]55 irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");
[55b77d9]56 list_initialize(&CPU->timeout_active_list);
[f761f1eb]57}
58
[da1bafb]59/** Reinitialize timeout
[70527f1]60 *
[ba1b2194]61 * Initialize all members except the lock.
[70527f1]62 *
[da1bafb]63 * @param timeout Timeout to be initialized.
[70527f1]64 *
65 */
[da1bafb]66void timeout_reinitialize(timeout_t *timeout)
[f761f1eb]67{
[da1bafb]68 timeout->cpu = NULL;
69 timeout->ticks = 0;
70 timeout->handler = NULL;
71 timeout->arg = NULL;
72 link_initialize(&timeout->link);
[f761f1eb]73}
74
[ba1b2194]75/** Initialize timeout
[70527f1]76 *
[ba1b2194]77 * Initialize all members including the lock.
[70527f1]78 *
[da1bafb]79 * @param timeout Timeout to be initialized.
[70527f1]80 *
81 */
[da1bafb]82void timeout_initialize(timeout_t *timeout)
[f761f1eb]83{
[da1bafb]84 irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");
85 timeout_reinitialize(timeout);
[f761f1eb]86}
87
[ba1b2194]88/** Register timeout
[70527f1]89 *
[ba1b2194]90 * Insert timeout handler f (with argument arg)
91 * to timeout list and make it execute in
[70527f1]92 * time microseconds (or slightly more).
93 *
[da1bafb]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.
[70527f1]98 *
[f761f1eb]99 */
[da1bafb]100void timeout_register(timeout_t *timeout, uint64_t time,
101 timeout_handler_t handler, void *arg)
[f761f1eb]102{
[da1bafb]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;
[f761f1eb]114
115 /*
[da1bafb]116 * Insert timeout into the active timeouts list according to timeout->ticks.
[f761f1eb]117 */
[da1bafb]118 uint64_t sum = 0;
119 timeout_t *target = NULL;
120 link_t *cur;
[55b77d9]121 for (cur = CPU->timeout_active_list.head.next;
122 cur != &CPU->timeout_active_list.head; cur = cur->next) {
[da1bafb]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);
[f761f1eb]128 break;
129 }
[da1bafb]130
131 sum += target->ticks;
132 irq_spinlock_unlock(&target->lock, false);
[f761f1eb]133 }
[da1bafb]134
135 /* Avoid using cur->prev directly */
136 link_t *prev = cur->prev;
[55b77d9]137 list_insert_after(&timeout->link, prev);
[da1bafb]138
[f761f1eb]139 /*
[da1bafb]140 * Adjust timeout->ticks according to ticks
141 * accumulated in target's predecessors.
[f761f1eb]142 */
[da1bafb]143 timeout->ticks -= sum;
144
[f761f1eb]145 /*
[da1bafb]146 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
[f761f1eb]147 */
[55b77d9]148 if (cur != &CPU->timeout_active_list.head) {
[da1bafb]149 irq_spinlock_lock(&target->lock, false);
150 target->ticks -= timeout->ticks;
151 irq_spinlock_unlock(&target->lock, false);
[f761f1eb]152 }
[da1bafb]153
154 irq_spinlock_unlock(&timeout->lock, false);
155 irq_spinlock_unlock(&CPU->timeoutlock, true);
[f761f1eb]156}
157
[ba1b2194]158/** Unregister timeout
[70527f1]159 *
160 * Remove timeout from timeout list.
161 *
[da1bafb]162 * @param timeout Timeout to unregister.
163 *
164 * @return True on success, false on failure.
[70527f1]165 *
166 */
[da1bafb]167bool timeout_unregister(timeout_t *timeout)
[f761f1eb]168{
[31d8e10]169 DEADLOCK_PROBE_INIT(p_tolock);
[da1bafb]170
[f761f1eb]171grab_locks:
[da1bafb]172 irq_spinlock_lock(&timeout->lock, true);
173 if (!timeout->cpu) {
174 irq_spinlock_unlock(&timeout->lock, true);
[ba1b2194]175 return false;
[f761f1eb]176 }
[da1bafb]177
178 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
179 irq_spinlock_unlock(&timeout->lock, true);
[31d8e10]180 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
[f761f1eb]181 goto grab_locks;
182 }
183
184 /*
[da1bafb]185 * Now we know for sure that timeout hasn't been activated yet
[55b77d9]186 * and is lurking in timeout->cpu->timeout_active_list.
[f761f1eb]187 */
[da1bafb]188
189 link_t *cur = timeout->link.next;
[55b77d9]190 if (cur != &timeout->cpu->timeout_active_list.head) {
[da1bafb]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);
[f761f1eb]195 }
196
[da1bafb]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
[ba1b2194]203 return true;
[f761f1eb]204}
[b45c443]205
[1bb2e7a]206/** @}
[b45c443]207 */
Note: See TracBrowser for help on using the repository browser.