Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Examples

etimer.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup etimer
00003  * @{
00004  */
00005 
00006 /**
00007  * \file
00008  * Event timer library implementation.
00009  * \author
00010  * Adam Dunkels <adam@sics.se>
00011  */
00012 
00013 /*
00014  * Copyright (c) 2004, Swedish Institute of Computer Science.
00015  * All rights reserved.
00016  *
00017  * Redistribution and use in source and binary forms, with or without
00018  * modification, are permitted provided that the following conditions
00019  * are met:
00020  * 1. Redistributions of source code must retain the above copyright
00021  *    notice, this list of conditions and the following disclaimer.
00022  * 2. Redistributions in binary form must reproduce the above copyright
00023  *    notice, this list of conditions and the following disclaimer in the
00024  *    documentation and/or other materials provided with the distribution.
00025  * 3. Neither the name of the Institute nor the names of its contributors
00026  *    may be used to endorse or promote products derived from this software
00027  *    without specific prior written permission.
00028  *
00029  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00030  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00031  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00032  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00033  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00034  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00035  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00036  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00037  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00038  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00039  * SUCH DAMAGE.
00040  *
00041  * This file is part of the Contiki operating system.
00042  *
00043  * Author: Adam Dunkels <adam@sics.se>
00044  *
00045  * $Id: etimer.c,v 1.1 2006/06/17 22:41:20 adamdunkels Exp $
00046  */
00047 
00048 #include "contiki-conf.h"
00049 
00050 #include "sys/etimer.h"
00051 #include "sys/process.h"
00052 
00053 static struct etimer *timerlist;
00054 static clock_time_t next_expiration;
00055 
00056 PROCESS(etimer_process, "Event timer");
00057 /*---------------------------------------------------------------------------*/
00058 static void
00059 update_time(void)
00060 {
00061   clock_time_t nextt;
00062   struct etimer *t;
00063 
00064   if (timerlist == NULL) {
00065     next_expiration = 0;
00066   } else {
00067     t = timerlist;
00068     nextt = t->timer.start + t->timer.interval;
00069     for(t = t->next; t != NULL; t = t->next) {
00070       if(t->timer.start + t->timer.interval < nextt) {
00071         nextt = t->timer.start + t->timer.interval;
00072       }
00073     }
00074     next_expiration = nextt;
00075   }
00076 }
00077 /*---------------------------------------------------------------------------*/
00078 PROCESS_THREAD(etimer_process, ev, data)
00079 {
00080   struct etimer *t, *u;
00081         
00082   PROCESS_BEGIN();
00083 
00084   timerlist = NULL;
00085   
00086   while(1) {
00087     PROCESS_YIELD();
00088 
00089     if(ev == PROCESS_EVENT_EXITED) {
00090       struct process *p = data;
00091 
00092       while(timerlist != NULL && timerlist->p == p) {
00093         timerlist = timerlist->next;
00094       }
00095 
00096       if(timerlist != NULL) {
00097         t = timerlist;
00098         while(t->next != NULL) {
00099           if(t->next->p == p) {
00100             t->next = t->next->next;
00101           } else
00102             t = t->next;
00103         }
00104       }
00105       continue;
00106     } else if(ev != PROCESS_EVENT_POLL) {
00107       continue;
00108     }
00109 
00110   again:
00111     
00112     u = NULL;
00113     
00114     for(t = timerlist; t != NULL; t = t->next) {
00115       if(timer_expired(&t->timer)) {
00116         if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
00117           
00118           /* Reset the process ID of the event timer, to signal that the
00119              etimer has expired. This is later checked in the
00120              etimer_expired() function. */
00121           t->p = PROCESS_NONE;
00122           if(u != NULL) {
00123             u->next = t->next;
00124           } else {
00125             timerlist = t->next;
00126           }
00127           t->next = NULL;
00128           update_time();
00129           goto again;
00130         } else {
00131           etimer_request_poll();
00132         }
00133       }
00134       u = t;
00135     }
00136     
00137   }
00138   
00139   PROCESS_END();
00140 }
00141 /*---------------------------------------------------------------------------*/
00142 void
00143 etimer_request_poll(void)
00144 {
00145   process_poll(&etimer_process);
00146 }
00147 /*---------------------------------------------------------------------------*/
00148 static void
00149 add_timer(struct etimer *timer)
00150 {
00151   struct etimer *t;
00152 
00153   if(timer->p != PROCESS_NONE) {
00154     /* Timer not on list. */
00155     
00156     for(t = timerlist; t != NULL; t = t->next) {
00157       if(t == timer) {
00158         /* Timer already on list, bail out. */
00159         update_time();
00160         return;
00161       }
00162     }
00163   }
00164 
00165   timer->p = PROCESS_CURRENT();
00166   timer->next = timerlist;
00167   timerlist = timer;
00168 
00169   update_time();
00170 }
00171 /*---------------------------------------------------------------------------*/
00172 void
00173 etimer_set(struct etimer *et, clock_time_t interval)
00174 {
00175   timer_set(&et->timer, interval);
00176   add_timer(et);
00177 }
00178 /*---------------------------------------------------------------------------*/
00179 void
00180 etimer_reset(struct etimer *et)
00181 {
00182   timer_reset(&et->timer);
00183   add_timer(et);
00184 }
00185 /*---------------------------------------------------------------------------*/
00186 void
00187 etimer_restart(struct etimer *et)
00188 {
00189   timer_restart(&et->timer);
00190   add_timer(et);
00191 }
00192 /*---------------------------------------------------------------------------*/
00193 void
00194 etimer_adjust(struct etimer *et, int timediff)
00195 {
00196   et->timer.start += timediff;
00197   update_time();
00198 }
00199 /*---------------------------------------------------------------------------*/
00200 int
00201 etimer_expired(struct etimer *et)
00202 {
00203   return et->p == PROCESS_NONE;
00204 }
00205 /*---------------------------------------------------------------------------*/
00206 clock_time_t
00207 etimer_expiration_time(struct etimer *et)
00208 {
00209   return et->timer.start + et->timer.interval;
00210 }
00211 /*---------------------------------------------------------------------------*/
00212 clock_time_t
00213 etimer_start_time(struct etimer *et)
00214 {
00215   return et->timer.start;
00216 }
00217 /*---------------------------------------------------------------------------*/
00218 int
00219 etimer_pending(void)
00220 {
00221   return timerlist != NULL;
00222 }
00223 /*---------------------------------------------------------------------------*/
00224 clock_time_t
00225 etimer_next_expiration_time(void)
00226 {
00227   return etimer_pending() ? next_expiration : 0;
00228 }
00229 /*---------------------------------------------------------------------------*/
00230 void
00231 etimer_stop(struct etimer *et)
00232 {
00233   struct etimer *t;
00234 
00235   /* First check if et is the first event timer on the list. */
00236   if(et == timerlist) {
00237     timerlist = timerlist->next;
00238     update_time();
00239   } else {
00240     /* Else walk through the list and try to find the item before the
00241        et timer. */
00242     for(t = timerlist; t != NULL && t->next != et; t = t->next);
00243 
00244     if(t != NULL) {
00245       /* We've found the item before the event timer that we are about
00246          to remove. We point the items next pointer to the event after
00247          the removed item. */
00248       t->next = et->next;
00249 
00250       update_time();
00251     }
00252   }
00253 
00254   /* Remove the next pointer from the item to be removed. */
00255   et->next = NULL;
00256   /* Set the timer as expired */
00257   et->p = PROCESS_NONE;
00258 }
00259 /*---------------------------------------------------------------------------*/
00260 /** @} */

Generated on Thu Jun 22 17:45:43 2006 for Contiki 2.x by  doxygen 1.4.4