00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <time/timeout.h>
00039 #include <typedefs.h>
00040 #include <arch/types.h>
00041 #include <config.h>
00042 #include <panic.h>
00043 #include <synch/spinlock.h>
00044 #include <func.h>
00045 #include <cpu.h>
00046 #include <arch/asm.h>
00047 #include <arch.h>
00048
00049
00055 void timeout_init(void)
00056 {
00057 spinlock_initialize(&CPU->timeoutlock, "timeout_lock");
00058 list_initialize(&CPU->timeout_active_head);
00059 }
00060
00061
00069 void timeout_reinitialize(timeout_t *t)
00070 {
00071 t->cpu = NULL;
00072 t->ticks = 0;
00073 t->handler = NULL;
00074 t->arg = NULL;
00075 link_initialize(&t->link);
00076 }
00077
00078
00086 void timeout_initialize(timeout_t *t)
00087 {
00088 spinlock_initialize(&t->lock, "timeout_t_lock");
00089 timeout_reinitialize(t);
00090 }
00091
00092
00106 void timeout_register(timeout_t *t, __u64 time, timeout_handler_t f, void *arg)
00107 {
00108 timeout_t *hlp = NULL;
00109 link_t *l, *m;
00110 ipl_t ipl;
00111 __u64 sum;
00112
00113 ipl = interrupts_disable();
00114 spinlock_lock(&CPU->timeoutlock);
00115 spinlock_lock(&t->lock);
00116
00117 if (t->cpu)
00118 panic("t->cpu != 0");
00119
00120 t->cpu = CPU;
00121 t->ticks = us2ticks(time);
00122
00123 t->handler = f;
00124 t->arg = arg;
00125
00126
00127
00128
00129 sum = 0;
00130 l = CPU->timeout_active_head.next;
00131 while (l != &CPU->timeout_active_head) {
00132 hlp = list_get_instance(l, timeout_t, link);
00133 spinlock_lock(&hlp->lock);
00134 if (t->ticks < sum + hlp->ticks) {
00135 spinlock_unlock(&hlp->lock);
00136 break;
00137 }
00138 sum += hlp->ticks;
00139 spinlock_unlock(&hlp->lock);
00140 l = l->next;
00141 }
00142
00143 m = l->prev;
00144 list_prepend(&t->link, m);
00145
00146
00147
00148
00149 t->ticks -= sum;
00150
00151
00152
00153
00154 if (l != &CPU->timeout_active_head) {
00155 spinlock_lock(&hlp->lock);
00156 hlp->ticks -= t->ticks;
00157 spinlock_unlock(&hlp->lock);
00158 }
00159
00160 spinlock_unlock(&t->lock);
00161 spinlock_unlock(&CPU->timeoutlock);
00162 interrupts_restore(ipl);
00163 }
00164
00165
00174 bool timeout_unregister(timeout_t *t)
00175 {
00176 timeout_t *hlp;
00177 link_t *l;
00178 ipl_t ipl;
00179
00180 grab_locks:
00181 ipl = interrupts_disable();
00182 spinlock_lock(&t->lock);
00183 if (!t->cpu) {
00184 spinlock_unlock(&t->lock);
00185 interrupts_restore(ipl);
00186 return false;
00187 }
00188 if (!spinlock_trylock(&t->cpu->timeoutlock)) {
00189 spinlock_unlock(&t->lock);
00190 interrupts_restore(ipl);
00191 goto grab_locks;
00192 }
00193
00194
00195
00196
00197
00198
00199 l = t->link.next;
00200 if (l != &t->cpu->timeout_active_head) {
00201 hlp = list_get_instance(l, timeout_t, link);
00202 spinlock_lock(&hlp->lock);
00203 hlp->ticks += t->ticks;
00204 spinlock_unlock(&hlp->lock);
00205 }
00206
00207 list_remove(&t->link);
00208 spinlock_unlock(&t->cpu->timeoutlock);
00209
00210 timeout_reinitialize(t);
00211 spinlock_unlock(&t->lock);
00212
00213 interrupts_restore(ipl);
00214 return true;
00215 }
00216