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

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 901b302 was 583c2a3, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Avoid most cases of direct used of list_t.prev/next in kernel

  • 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
[e88eb48]29/** @addtogroup kernel_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>
[b2e121a]43#include <halt.h>
[f761f1eb]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);
[a35b458]105
[da1bafb]106 if (timeout->cpu)
107 panic("Unexpected: timeout->cpu != 0.");
[a35b458]108
[da1bafb]109 timeout->cpu = CPU;
110 timeout->ticks = us2ticks(time);
[a35b458]111
[da1bafb]112 timeout->handler = handler;
113 timeout->arg = arg;
[a35b458]114
[f761f1eb]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;
[583c2a3]120 link_t *cur, *prev;
121 prev = NULL;
122 for (cur = list_first(&CPU->timeout_active_list);
123 cur != NULL; cur = list_next(cur, &CPU->timeout_active_list)) {
[da1bafb]124 target = list_get_instance(cur, timeout_t, link);
125 irq_spinlock_lock(&target->lock, false);
[a35b458]126
[da1bafb]127 if (timeout->ticks < sum + target->ticks) {
128 irq_spinlock_unlock(&target->lock, false);
[f761f1eb]129 break;
130 }
[a35b458]131
[da1bafb]132 sum += target->ticks;
133 irq_spinlock_unlock(&target->lock, false);
[583c2a3]134 prev = cur;
[f761f1eb]135 }
[a35b458]136
[583c2a3]137 if (prev == NULL)
138 list_prepend(&timeout->link, &CPU->timeout_active_list);
139 else
140 list_insert_after(&timeout->link, prev);
[a35b458]141
[f761f1eb]142 /*
[da1bafb]143 * Adjust timeout->ticks according to ticks
144 * accumulated in target's predecessors.
[f761f1eb]145 */
[da1bafb]146 timeout->ticks -= sum;
[a35b458]147
[f761f1eb]148 /*
[da1bafb]149 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
[f761f1eb]150 */
[583c2a3]151 if (cur != NULL) {
[da1bafb]152 irq_spinlock_lock(&target->lock, false);
153 target->ticks -= timeout->ticks;
154 irq_spinlock_unlock(&target->lock, false);
[f761f1eb]155 }
[a35b458]156
[da1bafb]157 irq_spinlock_unlock(&timeout->lock, false);
158 irq_spinlock_unlock(&CPU->timeoutlock, true);
[f761f1eb]159}
160
[ba1b2194]161/** Unregister timeout
[70527f1]162 *
163 * Remove timeout from timeout list.
164 *
[da1bafb]165 * @param timeout Timeout to unregister.
166 *
167 * @return True on success, false on failure.
[70527f1]168 *
169 */
[da1bafb]170bool timeout_unregister(timeout_t *timeout)
[f761f1eb]171{
[31d8e10]172 DEADLOCK_PROBE_INIT(p_tolock);
[a35b458]173
[f761f1eb]174grab_locks:
[da1bafb]175 irq_spinlock_lock(&timeout->lock, true);
176 if (!timeout->cpu) {
177 irq_spinlock_unlock(&timeout->lock, true);
[ba1b2194]178 return false;
[f761f1eb]179 }
[a35b458]180
[da1bafb]181 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {
182 irq_spinlock_unlock(&timeout->lock, true);
[31d8e10]183 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD);
[f761f1eb]184 goto grab_locks;
185 }
[a35b458]186
[f761f1eb]187 /*
[da1bafb]188 * Now we know for sure that timeout hasn't been activated yet
[55b77d9]189 * and is lurking in timeout->cpu->timeout_active_list.
[f761f1eb]190 */
[a35b458]191
[583c2a3]192 link_t *cur = list_next(&timeout->link,
193 &timeout->cpu->timeout_active_list);
194 if (cur != NULL) {
[da1bafb]195 timeout_t *tmp = list_get_instance(cur, timeout_t, link);
196 irq_spinlock_lock(&tmp->lock, false);
197 tmp->ticks += timeout->ticks;
198 irq_spinlock_unlock(&tmp->lock, false);
[f761f1eb]199 }
[a35b458]200
[da1bafb]201 list_remove(&timeout->link);
202 irq_spinlock_unlock(&timeout->cpu->timeoutlock, false);
[a35b458]203
[da1bafb]204 timeout_reinitialize(timeout);
205 irq_spinlock_unlock(&timeout->lock, true);
[a35b458]206
[ba1b2194]207 return true;
[f761f1eb]208}
[b45c443]209
[1bb2e7a]210/** @}
[b45c443]211 */
Note: See TracBrowser for help on using the repository browser.