Changes in kernel/generic/src/time/timeout.c [eda43238:583c2a3] in mainline
- File:
-
- 1 edited
-
kernel/generic/src/time/timeout.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/time/timeout.c
reda43238 r583c2a3 1 1 /* 2 2 * Copyright (c) 2001-2004 Jakub Jermar 3 * Copyright (c) 2022 Jiří Zárevúcky4 3 * All rights reserved. 5 4 * … … 58 57 } 59 58 59 /** Reinitialize timeout 60 * 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 60 75 /** Initialize timeout 61 76 * … … 67 82 void timeout_initialize(timeout_t *timeout) 68 83 { 69 link_initialize(&timeout->link);70 timeout ->cpu = NULL;84 irq_spinlock_initialize(&timeout->lock, "timeout_t_lock"); 85 timeout_reinitialize(timeout); 71 86 } 72 87 … … 87 102 { 88 103 irq_spinlock_lock(&CPU->timeoutlock, true); 89 90 assert(!link_in_use(&timeout->link)); 104 irq_spinlock_lock(&timeout->lock, false); 105 106 if (timeout->cpu) 107 panic("Unexpected: timeout->cpu != 0."); 91 108 92 109 timeout->cpu = CPU; 93 timeout->deadline = CPU->current_clock_tick + us2ticks(time); 110 timeout->ticks = us2ticks(time); 111 94 112 timeout->handler = handler; 95 113 timeout->arg = arg; 96 114 97 /* Insert timeout into the active timeouts list according to timeout->deadline. */ 98 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 } 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); 126 127 if (timeout->ticks < sum + target->ticks) { 128 irq_spinlock_unlock(&target->lock, false); 129 break; 110 130 } 111 } 112 131 132 sum += target->ticks; 133 irq_spinlock_unlock(&target->lock, false); 134 prev = cur; 135 } 136 137 if (prev == NULL) 138 list_prepend(&timeout->link, &CPU->timeout_active_list); 139 else 140 list_insert_after(&timeout->link, prev); 141 142 /* 143 * Adjust timeout->ticks according to ticks 144 * 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); 113 158 irq_spinlock_unlock(&CPU->timeoutlock, true); 114 159 } … … 125 170 bool timeout_unregister(timeout_t *timeout) 126 171 { 127 assert(timeout->cpu); 128 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); 134 } 135 136 irq_spinlock_unlock(&timeout->cpu->timeoutlock, true); 137 return success; 172 DEADLOCK_PROBE_INIT(p_tolock); 173 174 grab_locks: 175 irq_spinlock_lock(&timeout->lock, true); 176 if (!timeout->cpu) { 177 irq_spinlock_unlock(&timeout->lock, true); 178 return false; 179 } 180 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; 138 208 } 139 209
Note:
See TracChangeset
for help on using the changeset viewer.
