Contiki-NG
Loading...
Searching...
No Matches
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
52static struct etimer *timerlist;
53static clock_time_t next_expiration;
54
55PROCESS(etimer_process, "Event timer");
56/*---------------------------------------------------------------------------*/
57static void
58update_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/*---------------------------------------------------------------------------*/
80PROCESS_THREAD(etimer_process, ev, data)
81{
82 struct etimer *t, *u;
83
85
86 timerlist = NULL;
87
88 while(1) {
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
113again:
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/*---------------------------------------------------------------------------*/
144void
146{
147 process_poll(&etimer_process);
148}
149/*---------------------------------------------------------------------------*/
150static void
151add_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/*---------------------------------------------------------------------------*/
176void
177etimer_set(struct etimer *et, clock_time_t interval)
178{
179 timer_set(&et->timer, interval);
180 add_timer(et);
181}
182/*---------------------------------------------------------------------------*/
183void
184etimer_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/*---------------------------------------------------------------------------*/
191void
193{
194 timer_reset(&et->timer);
195 add_timer(et);
196}
197/*---------------------------------------------------------------------------*/
198void
200{
201 timer_restart(&et->timer);
202 add_timer(et);
203}
204/*---------------------------------------------------------------------------*/
205void
206etimer_adjust(struct etimer *et, int timediff)
207{
208 et->timer.start += timediff;
209 update_time();
210}
211/*---------------------------------------------------------------------------*/
212clock_time_t
214{
215 return et->timer.start + et->timer.interval;
216}
217/*---------------------------------------------------------------------------*/
218clock_time_t
220{
221 return et->timer.start;
222}
223/*---------------------------------------------------------------------------*/
224int
226{
227 return timerlist != NULL;
228}
229/*---------------------------------------------------------------------------*/
230clock_time_t
232{
233 return etimer_pending() ? next_expiration : 0;
234}
235/*---------------------------------------------------------------------------*/
236void
238{
239 struct etimer *t;
240
241 /* First check if et is the first event timer on the list. */
242 if(et == timerlist) {
243 timerlist = timerlist->next;
244 update_time();
245 } else {
246 /* Else walk through the list and try to find the item before the
247 et timer. */
248 for(t = timerlist; t != NULL && t->next != et; t = t->next) {
249 }
250
251 if(t != NULL) {
252 /* We've found the item before the event timer that we are about
253 to remove. We point the items next pointer to the event after
254 the removed item. */
255 t->next = et->next;
256
257 update_time();
258 }
259 }
260
261 /* Remove the next pointer from the item to be removed. */
262 et->next = NULL;
263 /* Set the timer as expired */
264 et->p = PROCESS_NONE;
265}
266/*---------------------------------------------------------------------------*/
267/** @} */
Event timer header file.
clock_time_t clock_time(void)
Get the current clock time.
Definition clock.c:118
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition etimer.c:199
clock_time_t etimer_start_time(struct etimer *et)
Get the start time for the event timer.
Definition etimer.c:219
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition etimer.c:225
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
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition etimer.c:192
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition etimer.c:145
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition etimer.c:231
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition etimer.c:237
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:213
void etimer_adjust(struct etimer *et, int timediff)
Adjust the expiration time for an event timer.
Definition etimer.c:206
#define PROCESS(name, strname)
Declare a process.
Definition process.h:308
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition process.c:325
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition process.h:404
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition process.h:121
#define PROCESS_END()
Define the end of a process.
Definition process.h:132
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:274
#define PROCESS_ERR_OK
Return value indicating that an operation was successful.
Definition process.h:76
#define PROCESS_YIELD()
Yield the currently running process.
Definition process.h:165
void process_poll(struct process *p)
Request a process to be polled.
Definition process.c:366
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition timer.c:64
void timer_restart(struct timer *t)
Restart the timer from the current point in time.
Definition timer.c:106
bool timer_expired(struct timer *t)
Check if a timer has expired.
Definition timer.c:123
void timer_reset(struct timer *t)
Reset the timer with the same interval.
Definition timer.c:84
Header file for the Contiki process interface.
A timer.
Definition etimer.h:79
A timer.
Definition timer.h:84