Changes in kernel/generic/src/time/timeout.c [d99c1d2:da1bafb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/time/timeout.c
rd99c1d2 rda1bafb 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 spinlock_initialize(&CPU->timeoutlock, "timeout_lock");55 irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock"); 56 56 list_initialize(&CPU->timeout_active_head); 57 57 } 58 58 59 60 /** Reinitialize timeout 59 /** Reinitialize timeout 61 60 * 62 61 * Initialize all members except the lock. 63 62 * 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 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 } 76 74 77 75 /** Initialize timeout … … 79 77 * Initialize all members including the lock. 80 78 * 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 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 } 90 87 91 88 /** Register timeout … … 95 92 * time microseconds (or slightly more). 96 93 * 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); 120 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); 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); 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; 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); 134 128 break; 135 129 } 136 sum += hlp->ticks;137 s pinlock_unlock(&hlp->lock);138 l = l->next;139 } 140 141 m = l->prev;142 li st_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 i nterrupts_restore(ipl);161 } 162 130 131 sum += target->ticks; 132 irq_spinlock_unlock(&target->lock, false); 133 } 134 135 /* Avoid using cur->prev directly */ 136 link_t *prev = cur->prev; 137 list_prepend(&timeout->link, prev); 138 139 /* 140 * Adjust timeout->ticks according to ticks 141 * 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 irq_spinlock_unlock(&timeout->lock, false); 155 irq_spinlock_unlock(&CPU->timeoutlock, true); 156 } 163 157 164 158 /** Unregister timeout … … 166 160 * Remove timeout from timeout list. 167 161 * 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; 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 { 177 169 DEADLOCK_PROBE_INIT(p_tolock); 178 170 179 171 grab_locks: 180 ipl = interrupts_disable(); 181 spinlock_lock(&t->lock); 182 if (!t->cpu) { 183 spinlock_unlock(&t->lock); 184 interrupts_restore(ipl); 172 irq_spinlock_lock(&timeout->lock, true); 173 if (!timeout->cpu) { 174 irq_spinlock_unlock(&timeout->lock, true); 185 175 return false; 186 176 } 187 if (!spinlock_trylock(&t->cpu->timeoutlock)) {188 spinlock_unlock(&t->lock);189 i nterrupts_restore(ipl);177 178 if (!irq_spinlock_trylock(&timeout->cpu->timeoutlock)) { 179 irq_spinlock_unlock(&timeout->lock, true); 190 180 DEADLOCK_PROBE(p_tolock, DEADLOCK_THRESHOLD); 191 181 goto grab_locks; … … 193 183 194 184 /* 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 } 206 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); 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 */ 188 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 214 203 return true; 215 204 }
Note:
See TracChangeset
for help on using the changeset viewer.