Changes in kernel/generic/src/time/timeout.c [da1bafb:d99c1d2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/time/timeout.c
rda1bafb rd99c1d2 33 33 /** 34 34 * @file 35 * @brief 35 * @brief Timeout management functions. 36 36 */ 37 37 … … 53 53 void timeout_init(void) 54 54 { 55 irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");55 spinlock_initialize(&CPU->timeoutlock, "timeout_lock"); 56 56 list_initialize(&CPU->timeout_active_head); 57 57 } 58 58 59 /** Reinitialize timeout 59 60 /** Reinitialize timeout 60 61 * 61 62 * Initialize all members except the lock. 62 63 * 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 } 64 * @param t Timeout to be initialized. 65 * 66 */ 67 void timeout_reinitialize(timeout_t *t) 68 { 69 t->cpu = NULL; 70 t->ticks = 0; 71 t->handler = NULL; 72 t->arg = NULL; 73 link_initialize(&t->link); 74 } 75 74 76 75 77 /** Initialize timeout … … 77 79 * Initialize all members including the lock. 78 80 * 79 * @param timeout Timeout to be initialized. 80 * 81 */ 82 void timeout_initialize(timeout_t *timeout) 83 { 84 irq_spinlock_initialize(&timeout->lock, "timeout_t_lock"); 85 timeout_reinitialize(timeout); 86 } 81 * @param t Timeout to be initialized. 82 * 83 */ 84 void timeout_initialize(timeout_t *t) 85 { 86 spinlock_initialize(&t->lock, "timeout_t_lock"); 87 timeout_reinitialize(t); 88 } 89 87 90 88 91 /** Register timeout … … 92 95 * time microseconds (or slightly more). 93 96 * 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 */ 100 void 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); 97 * @param t Timeout structure. 98 * @param time Number of usec in the future to execute the handler. 99 * @param f Timeout handler function. 100 * @param arg Timeout handler argument. 101 * 102 */ 103 void 104 timeout_register(timeout_t *t, uint64_t time, timeout_handler_t f, void *arg) 105 { 106 timeout_t *hlp = NULL; 107 link_t *l, *m; 108 ipl_t ipl; 109 uint64_t sum; 110 111 ipl = interrupts_disable(); 112 spinlock_lock(&CPU->timeoutlock); 113 spinlock_lock(&t->lock); 114 115 if (t->cpu) 116 panic("Unexpected: t->cpu != 0."); 117 118 t->cpu = CPU; 119 t->ticks = us2ticks(time); 105 120 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_head.next; 122 cur != &CPU->timeout_active_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); 121 t->handler = f; 122 t->arg = arg; 123 124 /* 125 * Insert t into the active timeouts list according to t->ticks. 126 */ 127 sum = 0; 128 l = CPU->timeout_active_head.next; 129 while (l != &CPU->timeout_active_head) { 130 hlp = list_get_instance(l, timeout_t, link); 131 spinlock_lock(&hlp->lock); 132 if (t->ticks < sum + hlp->ticks) { 133 spinlock_unlock(&hlp->lock); 128 134 break; 129 135 } 130 131 s um += target->ticks;132 irq_spinlock_unlock(&target->lock, false);133 } 134 135 /* Avoid using cur->prev directly */136 li nk_t *prev = cur->prev;137 list_prepend(&timeout->link, prev); 138 139 /*140 * Adjust timeout->ticks according to ticks141 * 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_head) {149 irq_spinlock_lock(&target->lock, false);150 target->ticks -= timeout->ticks;151 irq_spinlock_unlock(&target->lock, false); 152 }153 154 i rq_spinlock_unlock(&timeout->lock, false);155 irq_spinlock_unlock(&CPU->timeoutlock, true); 156 } 136 sum += hlp->ticks; 137 spinlock_unlock(&hlp->lock); 138 l = l->next; 139 } 140 141 m = l->prev; 142 list_prepend(&t->link, m); /* avoid using l->prev */ 143 144 /* 145 * Adjust t->ticks according to ticks accumulated in h's predecessors. 146 */ 147 t->ticks -= sum; 148 149 /* 150 * Decrease ticks of t's immediate succesor by t->ticks. 151 */ 152 if (l != &CPU->timeout_active_head) { 153 spinlock_lock(&hlp->lock); 154 hlp->ticks -= t->ticks; 155 spinlock_unlock(&hlp->lock); 156 } 157 158 spinlock_unlock(&t->lock); 159 spinlock_unlock(&CPU->timeoutlock); 160 interrupts_restore(ipl); 161 } 162 157 163 158 164 /** Unregister timeout … … 160 166 * Remove timeout from timeout list. 161 167 * 162 * @param timeout Timeout to unregister. 163 * 164 * @return True on success, false on failure. 165 * 166 */ 167 bool timeout_unregister(timeout_t *timeout) 168 { 168 * @param t Timeout to unregister. 169 * 170 * @return True on success, false on failure. 171 */ 172 bool timeout_unregister(timeout_t *t) 173 { 174 timeout_t *hlp; 175 link_t *l; 176 ipl_t ipl; 169 177 DEADLOCK_PROBE_INIT(p_tolock); 170 178 171 179 grab_locks: 172 irq_spinlock_lock(&timeout->lock, true); 173 if (!timeout->cpu) { 174 irq_spinlock_unlock(&timeout->lock, true); 180 ipl = interrupts_disable(); 181 spinlock_lock(&t->lock); 182 if (!t->cpu) { 183 spinlock_unlock(&t->lock); 184 interrupts_restore(ipl); 175 185 return false; 176 186 } 177 178 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) {179 i rq_spinlock_unlock(&timeout->lock, true);187 if (!spinlock_trylock(&t->cpu->timeoutlock)) { 188 spinlock_unlock(&t->lock); 189 interrupts_restore(ipl); 180 190 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD); 181 191 goto grab_locks; … … 183 193 184 194 /* 185 * Now we know for sure that timeout hasn't been activated yet 186 * and is lurking in timeout->cpu->timeout_active_head queue. 187 */ 195 * Now we know for sure that t hasn't been activated yet 196 * and is lurking in t->cpu->timeout_active_head queue. 197 */ 198 199 l = t->link.next; 200 if (l != &t->cpu->timeout_active_head) { 201 hlp = list_get_instance(l, timeout_t, link); 202 spinlock_lock(&hlp->lock); 203 hlp->ticks += t->ticks; 204 spinlock_unlock(&hlp->lock); 205 } 188 206 189 link_t *cur = timeout->link.next; 190 if (cur != &timeout->cpu->timeout_active_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 207 list_remove(&t->link); 208 spinlock_unlock(&t->cpu->timeoutlock); 209 210 timeout_reinitialize(t); 211 spinlock_unlock(&t->lock); 212 213 interrupts_restore(ipl); 203 214 return true; 204 215 }
Note:
See TracChangeset
for help on using the changeset viewer.