Changes in kernel/generic/src/time/timeout.c [583c2a3:eda43238] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/time/timeout.c
r583c2a3 reda43238 1 1 /* 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 * Copyright (c) 2022 Jiří Zárevúcky 3 4 * All rights reserved. 4 5 * … … 57 58 } 58 59 59 /** Reinitialize timeout60 *61 * Initialize all members except the lock.62 *63 * @param timeout Timeout to be initialized.64 *65 */66 void 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 60 /** Initialize timeout 76 61 * … … 82 67 void timeout_initialize(timeout_t *timeout) 83 68 { 84 irq_spinlock_initialize(&timeout->lock, "timeout_t_lock");85 timeout _reinitialize(timeout);69 link_initialize(&timeout->link); 70 timeout->cpu = NULL; 86 71 } 87 72 … … 102 87 { 103 88 irq_spinlock_lock(&CPU->timeoutlock, true); 104 irq_spinlock_lock(&timeout->lock, false);105 89 106 if (timeout->cpu) 107 panic("Unexpected: timeout->cpu != 0."); 90 assert(!link_in_use(&timeout->link)); 108 91 109 92 timeout->cpu = CPU; 110 timeout->ticks = us2ticks(time); 111 93 timeout->deadline = CPU->current_clock_tick + us2ticks(time); 112 94 timeout->handler = handler; 113 95 timeout->arg = arg; 114 96 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, *prev; 121 prev = NULL; 122 for (cur = list_first(&CPU->timeout_active_list); 123 cur != NULL; cur = list_next(cur, &CPU->timeout_active_list)) { 124 target = list_get_instance(cur, timeout_t, link); 125 irq_spinlock_lock(&target->lock, false); 97 /* Insert timeout into the active timeouts list according to timeout->deadline. */ 126 98 127 if (timeout->ticks < sum + target->ticks) { 128 irq_spinlock_unlock(&target->lock, false); 129 break; 99 link_t *last = list_last(&CPU->timeout_active_list); 100 if (last == NULL || timeout->deadline >= list_get_instance(last, timeout_t, link)->deadline) { 101 list_append(&timeout->link, &CPU->timeout_active_list); 102 } else { 103 for (link_t *cur = list_first(&CPU->timeout_active_list); cur != NULL; 104 cur = list_next(cur, &CPU->timeout_active_list)) { 105 106 if (timeout->deadline < list_get_instance(cur, timeout_t, link)->deadline) { 107 list_insert_before(&timeout->link, cur); 108 break; 109 } 130 110 } 131 132 sum += target->ticks;133 irq_spinlock_unlock(&target->lock, false);134 prev = cur;135 111 } 136 112 137 if (prev == NULL)138 list_prepend(&timeout->link, &CPU->timeout_active_list);139 else140 list_insert_after(&timeout->link, prev);141 142 /*143 * Adjust timeout->ticks according to ticks144 * accumulated in target's predecessors.145 */146 timeout->ticks -= sum;147 148 /*149 * Decrease ticks of timeout's immediate succesor by timeout->ticks.150 */151 if (cur != NULL) {152 irq_spinlock_lock(&target->lock, false);153 target->ticks -= timeout->ticks;154 irq_spinlock_unlock(&target->lock, false);155 }156 157 irq_spinlock_unlock(&timeout->lock, false);158 113 irq_spinlock_unlock(&CPU->timeoutlock, true); 159 114 } … … 170 125 bool timeout_unregister(timeout_t *timeout) 171 126 { 172 DEADLOCK_PROBE_INIT(p_tolock);127 assert(timeout->cpu); 173 128 174 grab_locks: 175 irq_spinlock_lock(&timeout->lock, true); 176 if (!timeout->cpu) {177 irq_spinlock_unlock(&timeout->lock, true);178 return false;129 irq_spinlock_lock(&timeout->cpu->timeoutlock, true); 130 131 bool success = link_in_use(&timeout->link); 132 if (success) { 133 list_remove(&timeout->link); 179 134 } 180 135 181 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) { 182 irq_spinlock_unlock(&timeout->lock, true); 183 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD); 184 goto grab_locks; 185 } 186 187 /* 188 * Now we know for sure that timeout hasn't been activated yet 189 * and is lurking in timeout->cpu->timeout_active_list. 190 */ 191 192 link_t *cur = list_next(&timeout->link, 193 &timeout->cpu->timeout_active_list); 194 if (cur != NULL) { 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); 199 } 200 201 list_remove(&timeout->link); 202 irq_spinlock_unlock(&timeout->cpu->timeoutlock, false); 203 204 timeout_reinitialize(timeout); 205 irq_spinlock_unlock(&timeout->lock, true); 206 207 return true; 136 irq_spinlock_unlock(&timeout->cpu->timeoutlock, true); 137 return success; 208 138 } 209 139
Note:
See TracChangeset
for help on using the changeset viewer.