Contiki 2.6
|
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.3 2007/10/07 19:59:27 joxe 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 tdist; 00062 clock_time_t now; 00063 struct etimer *t; 00064 00065 if (timerlist == NULL) { 00066 next_expiration = 0; 00067 } else { 00068 now = clock_time(); 00069 t = timerlist; 00070 /* Must calculate distance to next time into account due to wraps */ 00071 tdist = t->timer.start + t->timer.interval - now; 00072 for(t = t->next; t != NULL; t = t->next) { 00073 if(t->timer.start + t->timer.interval - now < tdist) { 00074 tdist = t->timer.start + t->timer.interval - now; 00075 } 00076 } 00077 next_expiration = now + tdist; 00078 } 00079 } 00080 /*---------------------------------------------------------------------------*/ 00081 PROCESS_THREAD(etimer_process, ev, data) 00082 { 00083 struct etimer *t, *u; 00084 00085 PROCESS_BEGIN(); 00086 00087 timerlist = NULL; 00088 00089 while(1) { 00090 PROCESS_YIELD(); 00091 00092 if(ev == PROCESS_EVENT_EXITED) { 00093 struct process *p = data; 00094 00095 while(timerlist != NULL && timerlist->p == p) { 00096 timerlist = timerlist->next; 00097 } 00098 00099 if(timerlist != NULL) { 00100 t = timerlist; 00101 while(t->next != NULL) { 00102 if(t->next->p == p) { 00103 t->next = t->next->next; 00104 } else 00105 t = t->next; 00106 } 00107 } 00108 continue; 00109 } else if(ev != PROCESS_EVENT_POLL) { 00110 continue; 00111 } 00112 00113 again: 00114 00115 u = NULL; 00116 00117 for(t = timerlist; t != NULL; t = t->next) { 00118 if(timer_expired(&t->timer)) { 00119 if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) { 00120 00121 /* Reset the process ID of the event timer, to signal that the 00122 etimer has expired. This is later checked in the 00123 etimer_expired() function. */ 00124 t->p = PROCESS_NONE; 00125 if(u != NULL) { 00126 u->next = t->next; 00127 } else { 00128 timerlist = t->next; 00129 } 00130 t->next = NULL; 00131 update_time(); 00132 goto again; 00133 } else { 00134 etimer_request_poll(); 00135 } 00136 } 00137 u = t; 00138 } 00139 00140 } 00141 00142 PROCESS_END(); 00143 } 00144 /*---------------------------------------------------------------------------*/ 00145 void 00146 etimer_request_poll(void) 00147 { 00148 process_poll(&etimer_process); 00149 } 00150 /*---------------------------------------------------------------------------*/ 00151 static void 00152 add_timer(struct etimer *timer) 00153 { 00154 struct etimer *t; 00155 00156 etimer_request_poll(); 00157 00158 if(timer->p != PROCESS_NONE) { 00159 /* Timer not on list. */ 00160 00161 for(t = timerlist; t != NULL; t = t->next) { 00162 if(t == timer) { 00163 /* Timer already on list, bail out. */ 00164 update_time(); 00165 return; 00166 } 00167 } 00168 } 00169 00170 timer->p = PROCESS_CURRENT(); 00171 timer->next = timerlist; 00172 timerlist = timer; 00173 00174 update_time(); 00175 } 00176 /*---------------------------------------------------------------------------*/ 00177 void 00178 etimer_set(struct etimer *et, clock_time_t interval) 00179 { 00180 timer_set(&et->timer, interval); 00181 add_timer(et); 00182 } 00183 /*---------------------------------------------------------------------------*/ 00184 void 00185 etimer_reset(struct etimer *et) 00186 { 00187 timer_reset(&et->timer); 00188 add_timer(et); 00189 } 00190 /*---------------------------------------------------------------------------*/ 00191 void 00192 etimer_restart(struct etimer *et) 00193 { 00194 timer_restart(&et->timer); 00195 add_timer(et); 00196 } 00197 /*---------------------------------------------------------------------------*/ 00198 void 00199 etimer_adjust(struct etimer *et, int timediff) 00200 { 00201 et->timer.start += timediff; 00202 update_time(); 00203 } 00204 /*---------------------------------------------------------------------------*/ 00205 int 00206 etimer_expired(struct etimer *et) 00207 { 00208 return et->p == PROCESS_NONE; 00209 } 00210 /*---------------------------------------------------------------------------*/ 00211 clock_time_t 00212 etimer_expiration_time(struct etimer *et) 00213 { 00214 return et->timer.start + et->timer.interval; 00215 } 00216 /*---------------------------------------------------------------------------*/ 00217 clock_time_t 00218 etimer_start_time(struct etimer *et) 00219 { 00220 return et->timer.start; 00221 } 00222 /*---------------------------------------------------------------------------*/ 00223 int 00224 etimer_pending(void) 00225 { 00226 return timerlist != NULL; 00227 } 00228 /*---------------------------------------------------------------------------*/ 00229 clock_time_t 00230 etimer_next_expiration_time(void) 00231 { 00232 return etimer_pending() ? next_expiration : 0; 00233 } 00234 /*---------------------------------------------------------------------------*/ 00235 void 00236 etimer_stop(struct etimer *et) 00237 { 00238 struct etimer *t; 00239 00240 /* First check if et is the first event timer on the list. */ 00241 if(et == timerlist) { 00242 timerlist = timerlist->next; 00243 update_time(); 00244 } else { 00245 /* Else walk through the list and try to find the item before the 00246 et timer. */ 00247 for(t = timerlist; t != NULL && t->next != et; t = t->next); 00248 00249 if(t != NULL) { 00250 /* We've found the item before the event timer that we are about 00251 to remove. We point the items next pointer to the event after 00252 the removed item. */ 00253 t->next = et->next; 00254 00255 update_time(); 00256 } 00257 } 00258 00259 /* Remove the next pointer from the item to be removed. */ 00260 et->next = NULL; 00261 /* Set the timer as expired */ 00262 et->p = PROCESS_NONE; 00263 } 00264 /*---------------------------------------------------------------------------*/ 00265 /** @} */