Contiki-NG
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.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  }
108  continue;
109  } else if(ev != PROCESS_EVENT_POLL) {
110  continue;
111  }
112 
113 again:
114 
115  u = NULL;
116 
117  for(t = timerlist; t != NULL; t = t->next) {
118  if(timer_expired(&t->timer)) {
119  if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
120 
121  /* Reset the process ID of the event timer, to signal that the
122  etimer has expired. This is later checked in the
123  etimer_expired() function. */
124  t->p = PROCESS_NONE;
125  if(u != NULL) {
126  u->next = t->next;
127  } else {
128  timerlist = t->next;
129  }
130  t->next = NULL;
131  update_time();
132  goto again;
133  } else {
135  }
136  }
137  u = t;
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_with_new_interval(struct etimer *et, clock_time_t interval)
185 {
186  timer_reset(&et->timer);
187  et->timer.interval = interval;
188  add_timer(et);
189 }
190 /*---------------------------------------------------------------------------*/
191 void
192 etimer_reset(struct etimer *et)
193 {
194  timer_reset(&et->timer);
195  add_timer(et);
196 }
197 /*---------------------------------------------------------------------------*/
198 void
200 {
201  timer_restart(&et->timer);
202  add_timer(et);
203 }
204 /*---------------------------------------------------------------------------*/
205 void
206 etimer_adjust(struct etimer *et, int timediff)
207 {
208  et->timer.start += timediff;
209  update_time();
210 }
211 /*---------------------------------------------------------------------------*/
212 int
214 {
215  return et->p == PROCESS_NONE;
216 }
217 /*---------------------------------------------------------------------------*/
218 clock_time_t
220 {
221  return et->timer.start + et->timer.interval;
222 }
223 /*---------------------------------------------------------------------------*/
224 clock_time_t
226 {
227  return et->timer.start;
228 }
229 /*---------------------------------------------------------------------------*/
230 int
232 {
233  return timerlist != NULL;
234 }
235 /*---------------------------------------------------------------------------*/
236 clock_time_t
238 {
239  return etimer_pending() ? next_expiration : 0;
240 }
241 /*---------------------------------------------------------------------------*/
242 void
243 etimer_stop(struct etimer *et)
244 {
245  struct etimer *t;
246 
247  /* First check if et is the first event timer on the list. */
248  if(et == timerlist) {
249  timerlist = timerlist->next;
250  update_time();
251  } else {
252  /* Else walk through the list and try to find the item before the
253  et timer. */
254  for(t = timerlist; t != NULL && t->next != et; t = t->next) {
255  }
256 
257  if(t != NULL) {
258  /* We've found the item before the event timer that we are about
259  to remove. We point the items next pointer to the event after
260  the removed item. */
261  t->next = et->next;
262 
263  update_time();
264  }
265  }
266 
267  /* Remove the next pointer from the item to be removed. */
268  et->next = NULL;
269  /* Set the timer as expired */
270  et->p = PROCESS_NONE;
271 }
272 /*---------------------------------------------------------------------------*/
273 /** @} */
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition: etimer.c:243
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition: etimer.c:199
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
clock_time_t etimer_start_time(struct etimer *et)
Get the start time for the event timer.
Definition: etimer.c:225
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
static const nrf_drv_timer_t timer
Timer instance used for rtimer.
Definition: rtimer-arch.c:48
void timer_reset(struct timer *t)
Reset the timer with the same interval.
Definition: timer.c:84
A timer.
Definition: timer.h:82
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition: etimer.c:237
#define PROCESS_ERR_OK
Return value indicating that an operation was successful.
Definition: process.h:74
void etimer_reset_with_new_interval(struct etimer *et, clock_time_t interval)
Reset an event timer with a new interval.
Definition: etimer.c:184
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition: process.h:402
Event timer header file.
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:231
void timer_restart(struct timer *t)
Restart the timer from the current point in time.
Definition: timer.c:106
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:123
Header file for the Contiki process interface.
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:118
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:213
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
void etimer_adjust(struct etimer *et, int timediff)
Adjust the expiration time for an event timer.
Definition: etimer.c:206
A timer.
Definition: etimer.h:76
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1110
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:192
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
clock_time_t etimer_expiration_time(struct etimer *et)
Get the expiration time for the event timer.
Definition: etimer.c:219