EVE 1.0
etimer.c
Go to the documentation of this file.
1 /**
2  * \addtogroup etimer
3  * @{
4  */
5 
6 /**
7  * \file
8  * Event timer library implementation.
9  * \author
10  * Adam Dunkels <adam@sics.se>
11  */
12 
13 /*
14  * Copyright (c) 2004, Swedish Institute of Computer Science.
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the Institute nor the names of its contributors
26  * may be used to endorse or promote products derived from this software
27  * without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  * This file is part of the Contiki operating system.
42  *
43  * Author: Adam Dunkels <adam@sics.se>
44  *
45  */
46 #include <stddef.h>
47 #include "contiki-conf.h"
48 
49 #include "sys/etimer.h"
50 #include "sys/process.h"
51 
52 #ifndef ETIMER_CONF_SYNC
53 #define ETIMER_CONF_SYNC 0
54 #endif
55 
56 static struct etimer *timerlist;
57 static clock_time_t next_expiration;
58 
59 PROCESS(etimer_process, "Event timer");
60 /*---------------------------------------------------------------------------*/
61 static void
62 update_time(void)
63 {
64  clock_time_t tdist;
65  clock_time_t now;
66  struct etimer *t;
67 
68  if (timerlist == NULL) {
69  next_expiration = 0;
70  } else {
71  now = clock_time();
72  t = timerlist;
73  /* Must calculate distance to next time into account due to wraps */
74  tdist = t->timer.start + t->timer.interval - now;
75  for(t = t->next; t != NULL; t = t->next) {
76  if(t->timer.start + t->timer.interval - now < tdist) {
77  tdist = t->timer.start + t->timer.interval - now;
78  }
79  }
80  next_expiration = now + tdist;
81  if (next_expiration == 0)
82  next_expiration = 1;
83  }
84 #ifdef CLOCK_CONF_TICKLESS
85  arch_update_time();
86 #endif
87 }
88 /*---------------------------------------------------------------------------*/
89 PROCESS_THREAD(etimer_process, ev, data)
90 {
91  struct etimer *t, *u;
92 
93  PROCESS_BEGIN();
94 
95  timerlist = NULL;
96 
97  while(1) {
98  PROCESS_YIELD();
99 
100  if(ev == PROCESS_EVENT_EXITED) {
101  struct process *p = data;
102 
103  while(timerlist != NULL && timerlist->p == p) {
104  timerlist = timerlist->next;
105  }
106 
107  if(timerlist != NULL) {
108  t = timerlist;
109  while(t->next != NULL) {
110  if(t->next->p == p) {
111  t->next = t->next->next;
112  } else
113  t = t->next;
114  }
115  }
116  continue;
117  } else if(ev != PROCESS_EVENT_POLL) {
118  continue;
119  }
120 
121  again:
122 
123  u = NULL;
124 
125  for(t = timerlist; t != NULL; t = t->next) {
126  if(timer_expired(&t->timer)) {
127 #if !(ETIMER_CONF_SYNC)
128  if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
129 
130  /* Reset the process ID of the event timer, to signal that the
131  etimer has expired. This is later checked in the
132  etimer_expired() function. */
133  t->p = PROCESS_NONE;
134  if(u != NULL) {
135  u->next = t->next;
136  } else {
137  timerlist = t->next;
138  }
139  t->next = NULL;
140  update_time();
141  goto again;
142  } else {
144  }
145 #else /* ETIMER_CONF_SYNC */
146  struct process *p = t->p;
147  t->p = PROCESS_NONE;
148  if (u != NULL) {
149  u->next = t->next;
150  } else {
151  timerlist = t->next;
152  }
153  t->next = NULL;
154  update_time();
155 
156  process_post_synch(p, PROCESS_EVENT_TIMER, t);
157 
158  goto again;
159 #endif /* ETIMER_CONF_SYNC */
160  }
161  u = t;
162  }
163 
164  }
165 
166  PROCESS_END();
167 #ifdef ECLIPSE_STUB_CODE_ANALYSE
168  return PT_ENDED;
169 #endif /* ECLIPSE_STUB_CODE_ANALYSE */
170 }
171 /*---------------------------------------------------------------------------*/
172 void
174 {
175  process_poll(&etimer_process);
176 }
177 /*---------------------------------------------------------------------------*/
178 static void
179 add_timer(struct etimer *timer)
180 {
181  struct etimer *t;
182 
184 
185  if(timer->p != PROCESS_NONE) {
186  for(t = timerlist; t != NULL; t = t->next) {
187  if(t == timer) {
188  /* Timer already on list, bail out. */
189  timer->p = PROCESS_CURRENT();
190  update_time();
191  return;
192  }
193  }
194  }
195 
196  /* Timer not on list. */
197  timer->p = PROCESS_CURRENT();
198  timer->next = timerlist;
199  timerlist = timer;
200 
201  update_time();
202 }
203 /*---------------------------------------------------------------------------*/
204 void
205 etimer_set(struct etimer *et, clock_time_t interval)
206 {
207  timer_set(&et->timer, interval);
208  add_timer(et);
209 }
210 /*---------------------------------------------------------------------------*/
211 void
212 etimer_reset(struct etimer *et)
213 {
214  timer_reset(&et->timer);
215  add_timer(et);
216 }
217 /*---------------------------------------------------------------------------*/
218 void
220 {
221  timer_restart(&et->timer);
222  add_timer(et);
223 }
224 /*---------------------------------------------------------------------------*/
225 void
226 etimer_adjust(struct etimer *et, int timediff)
227 {
228  et->timer.start += timediff;
229  update_time();
230 }
231 /*---------------------------------------------------------------------------*/
232 int
234 {
235  return et->p == PROCESS_NONE;
236 }
237 /*---------------------------------------------------------------------------*/
238 clock_time_t
240 {
241  return et->timer.start + et->timer.interval;
242 }
243 /*---------------------------------------------------------------------------*/
244 clock_time_t
246 {
247  return et->timer.start;
248 }
249 /*---------------------------------------------------------------------------*/
250 int
252 {
253  return timerlist != NULL;
254 }
255 /*---------------------------------------------------------------------------*/
256 clock_time_t
258 {
259  return etimer_pending() ? next_expiration : 0;
260 }
261 /*---------------------------------------------------------------------------*/
262 void
263 etimer_stop(struct etimer *et)
264 {
265  struct etimer *t;
266 
267  /* First check if et is the first event timer on the list. */
268  if(et == timerlist) {
269  timerlist = timerlist->next;
270  update_time();
271  } else {
272  /* Else walk through the list and try to find the item before the
273  et timer. */
274  for(t = timerlist; t != NULL && t->next != et; t = t->next);
275 
276  if(t != NULL) {
277  /* We've found the item before the event timer that we are about
278  to remove. We point the items next pointer to the event after
279  the removed item. */
280  t->next = et->next;
281 
282  update_time();
283  }
284  }
285 
286  /* Remove the next pointer from the item to be removed. */
287  et->next = NULL;
288  /* Set the timer as expired */
289  et->p = PROCESS_NONE;
290 }
291 /*---------------------------------------------------------------------------*/
292 /** @} */
#define PROCESS_END()
Definition: process.h:140
#define PROCESS(name, strname)
Definition: process.h:316
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition: etimer.c:263
CCIF clock_time_t clock_time(void)
Definition: clock.c:195
void process_poll(struct process *p)
Definition: process.c:416
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition: etimer.c:219
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:173
clock_time_t etimer_start_time(struct etimer *et)
Get the start time for the event timer.
Definition: etimer.c:245
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:212
void timer_reset(struct timer *t)
Definition: timer.c:84
void timer_set(struct timer *t, clock_time_t interval)
Definition: timer.c:64
Definition: timer.h:86
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition: etimer.c:257
#define PROCESS_ERR_OK
Return value indicating that an operation was successful.
Definition: process.h:74
#define PROCESS_CURRENT()
Definition: process.h:437
int process_post(struct process *p, process_event_t ev, process_data_t data)
Definition: process.c:327
#define PROCESS_BEGIN()
Definition: process.h:129
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:233
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:251
void timer_restart(struct timer *t)
Definition: timer.c:104
void etimer_adjust(struct etimer *et, int timediff)
Adjust the expiration time for an event timer.
Definition: etimer.c:226
Definition: etimer.h:77
#define PROCESS_YIELD()
Definition: process.h:173
uint8_t data[USBNET_RX_BUF_SIZE]
Definition: usbnet.h:140
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:205
#define PROCESS_THREAD(name, ev, data)
Definition: process.h:282
int timer_expired(struct timer *t)
Definition: timer.c:121
void process_post_synch(struct process *p, process_event_t ev, process_data_t data)
Definition: process.c:374
clock_time_t etimer_expiration_time(struct etimer *et)
Get the expiration time for the event timer.
Definition: etimer.c:239