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