timeout.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2004 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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          * Insert t into the active timeouts list according to t->ticks.
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); /* avoid using l->prev */
00145 
00146         /*
00147          * Adjust t->ticks according to ticks accumulated in h's predecessors.
00148          */
00149         t->ticks -= sum;
00150 
00151         /*
00152          * Decrease ticks of t's immediate succesor by t->ticks.
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          * Now we know for sure that t hasn't been activated yet
00196          * and is lurking in t->cpu->timeout_active_head queue.
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 

Generated on Sun Jun 18 17:28:04 2006 for HelenOS Kernel (ppc64) by  doxygen 1.4.6