Contiki-NG
coap-timer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, SICS, Swedish ICT AB.
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 
30 /**
31  * \file
32  * CoAP timer implementation.
33  * \author
34  * Niclas Finne <nfi@sics.se>
35  * Joakim Eriksson <joakime@sics.se>
36  */
37 
38 /**
39  * \addtogroup coap-timer
40  * @{
41  */
42 
43 #include "coap-timer.h"
44 #include "lib/list.h"
45 #include "sys/cc.h"
46 
47 /* Log configuration */
48 #include "coap-log.h"
49 #define LOG_MODULE "coap-timer"
50 #define LOG_LEVEL LOG_LEVEL_NONE
51 
52 LIST(timer_list);
53 static uint8_t is_initialized;
54 /*---------------------------------------------------------------------------*/
55 static void
56 add_timer(coap_timer_t *timer)
57 {
58  coap_timer_t *n, *l, *p;
59 
60  if(!is_initialized) {
61  /* The coap_timer system has not yet been initialized */
63  }
64 
65  LOG_DBG("adding timer %p at %lu\n", timer,
66  (unsigned long)timer->expiration_time);
67 
68  p = list_head(timer_list);
69 
70  /* Make sure the timer is not already added to the timer list */
71  list_remove(timer_list, timer);
72 
73  for(l = NULL, n = list_head(timer_list); n != NULL; l = n, n = n->next) {
74  if(timer->expiration_time < n->expiration_time) {
75  list_insert(timer_list, l, timer);
76  timer = NULL;
77  break;
78  }
79  }
80 
81  if(timer != NULL) {
82  list_insert(timer_list, l, timer);
83  }
84 
85  if(p != list_head(timer_list)) {
86  /* The next timer to expire has changed so we need to notify the driver */
87  COAP_TIMER_DRIVER.update();
88  }
89 }
90 /*---------------------------------------------------------------------------*/
91 void
92 coap_timer_stop(coap_timer_t *timer)
93 {
94  LOG_DBG("stopping timer %p\n", timer);
95 
96  /* Mark timer as expired right now */
97  timer->expiration_time = coap_timer_uptime();
98 
99  list_remove(timer_list, timer);
100 }
101 /*---------------------------------------------------------------------------*/
102 void
103 coap_timer_set(coap_timer_t *timer, uint64_t time)
104 {
105  timer->expiration_time = coap_timer_uptime() + time;
106  add_timer(timer);
107 }
108 /*---------------------------------------------------------------------------*/
109 void
110 coap_timer_reset(coap_timer_t *timer, uint64_t time)
111 {
112  timer->expiration_time += time;
113  add_timer(timer);
114 }
115 /*---------------------------------------------------------------------------*/
116 uint64_t
118 {
119  uint64_t now;
120  coap_timer_t *next;
121 
122  next = list_head(timer_list);
123  if(next == NULL) {
124  /* No pending timers - return a time in the future */
125  return 60000;
126  }
127 
128  now = coap_timer_uptime();
129  if(now < next->expiration_time) {
130  return next->expiration_time - now;
131  }
132  /* The next timer should already have expired */
133  return 0;
134 }
135 /*---------------------------------------------------------------------------*/
136 int
138 {
139  uint64_t now;
140  coap_timer_t *next;
141 
142  /* Always get the current time because it might trigger clock updates */
143  now = coap_timer_uptime();
144 
145  next = list_head(timer_list);
146  if(next == NULL) {
147  /* No pending timers */
148  return 0;
149  }
150 
151  if(next->expiration_time <= now) {
152  LOG_DBG("timer %p expired at %lu\n", next, (unsigned long)now);
153 
154  /* This timer should expire now */
155  list_remove(timer_list, next);
156 
157  if(next->callback) {
158  next->callback(next);
159  }
160 
161  /* The next timer has changed */
162  COAP_TIMER_DRIVER.update();
163 
164  /* Check if there is another pending timer */
165  next = list_head(timer_list);
166  if(next != NULL && next->expiration_time <= coap_timer_uptime()) {
167  /* Need to run again */
168  return 1;
169  }
170  }
171 
172  return 0;
173 }
174 /*---------------------------------------------------------------------------*/
175 void
177 {
178  if(is_initialized) {
179  return;
180  }
181  is_initialized = 1;
182  list_init(timer_list);
183  if(COAP_TIMER_DRIVER.init) {
184  COAP_TIMER_DRIVER.init();
185  }
186 }
187 /*---------------------------------------------------------------------------*/
188 /** @} */
Log support for CoAP
CoAP timer API.
void list_insert(list_t list, void *previtem, void *newitem)
Insert an item after a specified item on the list.
Definition: list.c:300
A timer.
Definition: timer.h:82
uint64_t coap_timer_time_to_next_expiration(void)
Get the time until next CoAP timer expires or 0 if there already exists expired timers that have not ...
Definition: coap-timer.c:117
void coap_timer_reset(coap_timer_t *timer, uint64_t time)
Reset a CoAP timer to expire a specified time after the last expiration time.
Definition: coap-timer.c:110
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
static uint64_t coap_timer_uptime(void)
Get the time since boot in milliseconds.
Definition: coap-timer.h:83
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
void coap_timer_init(void)
This function initializes the CoAP timer library.
Definition: coap-timer.c:176
#define LIST(name)
Declare a linked list.
Definition: list.h:88
void coap_timer_stop(coap_timer_t *timer)
Stop a pending CoAP timer.
Definition: coap-timer.c:92
void coap_timer_set(coap_timer_t *timer, uint64_t time)
Set a CoAP timer to expire after the specified time.
Definition: coap-timer.c:103
Default definitions of C compiler quirk work-arounds.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
int coap_timer_run(void)
This function must be called periodically by the CoAP timer driver to process any expired CoAP timers...
Definition: coap-timer.c:137