2 * Copyright (c) <2014-2015>, Olivier Matz <zer0@droids-corp.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * 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 * * Neither the name of the University of California, Berkeley nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /* Inspired from Intel DPDK rte_timer library */
31 * Copyright (c) <2010>, Intel Corporation
32 * All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
38 * - Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
41 * - Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in
43 * the documentation and/or other materials provided with the
46 * - Neither the name of Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
53 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
54 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
57 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
64 #ifndef UCG_CALLOUT_H_
65 #define UCG_CALLOUT_H_
67 #include <sys/queue.h>
69 #define UCG_CALLOUT_STATS
70 /* #define UCG_CALLOUT_DEBUG */
73 * This module provides a timer service. The manager function
74 * ucg_callout_manage() can be called from an interrupt or from a
75 * standard function (usually a main-loop). In the latter case, no
76 * preemption is possible.
78 * Each timer has a priority: the timers with higher priorities are
79 * scheduled before the others. This feature is mostly useful when the
80 * manager is called from an interrupt. Indeed, the callback function of
81 * a timer with a high priority cannot be preempted by a timer with a
84 * The module locks interrupts when doing critical operations, ensuring that
85 * critical data are accessed atomically.
88 * - stopped: initial state after ucg_callout_init()
89 * - scheduled: after a call to ucg_callout_schedule(), the timer is in the
90 * scheduled list of the callout manager
91 * - expired: after a call to ucg_callout_manage(), if the expire time of a
92 * timer is reached, it is moved in a local list and its state is
93 * changed to "expired".
94 * - before starting the callback, the timer goes in state "running".
96 * Once running, the associated timer is not touched anymore by
97 * ucg_callout_manage(). As a result, the timer MUST be either reloaded
98 * or stopped (and potentially freed).
102 * Maximum number of nested preemptions.
104 #define UCG_CALLOUT_MAX_RECURSION 5
106 #ifdef UCG_CALLOUT_STATS
108 * The structure that stores the timer statistics, mostly useful for debug
111 struct ucg_callout_debug_stats {
112 uint32_t schedule; /**< nb of calls to ucg_callout_(re)schedule() */
113 uint32_t stop; /**< nb of calls to ucg_callout_stop() */
114 uint32_t manage; /**< nb of calls to ucg_callout_manage() */
115 uint32_t max_recursion; /** manage() skipped due to max recursion */
116 uint32_t delayed; /** task delayed a bit due to low prio */
117 uint32_t hard_delayed; /** task recheduled later due to low priority */
119 uint8_t cur_scheduled; /**< current number of scheduled timers */
120 uint8_t cur_expired; /**< current number of expired timers */
121 uint8_t cur_running; /**< current number of running timers */
126 struct ucg_callout_mgr;
129 * The type of a callout callback function.
131 typedef void (ucg_callout_cb_t)(struct ucg_callout_mgr *cm,
132 struct ucg_callout *tim, void *arg);
135 * A callout structure, storing all data associated to a timer.
138 LIST_ENTRY(ucg_callout) next; /**< next/prev in list */
140 #define UCG_CALLOUT_STATE_STOPPED 0 /**< not scheduled */
141 #define UCG_CALLOUT_STATE_SCHEDULED 1 /**< in the scheduled list */
142 #define UCG_CALLOUT_STATE_EXPIRED 2 /**< expired, will be executed soon */
143 #define UCG_CALLOUT_STATE_RUNNING 3 /**< being executed */
144 uint8_t state; /**< stopped, scheduled, expired */
145 uint8_t priority; /**< the priority of the timer */
146 uint16_t expire; /**< time when timer should expire */
148 ucg_callout_cb_t *f; /**< callback function pointer */
149 void *arg; /**< argument given to the cb function. */
152 /* define the callout list */
153 LIST_HEAD(ucg_callout_list, ucg_callout);
155 /* static initializer for a timer structure */
156 #define UCG_CALLOUT_INITIALIZER { }
159 * Type of the function used by a callout manager to get a time reference
161 typedef uint16_t (ucg_callout_get_time_t)(void);
164 * An instance of callout manager. It is possible to have several
165 * managers. A callout is attached to one manager at a time.
167 struct ucg_callout_mgr {
168 ucg_callout_get_time_t *get_time; /**< func to get the time reference */
169 uint16_t prev_time; /**< time of previous call */
170 uint8_t cur_priority; /** priority of running event */
171 uint8_t nb_recursion; /** number of recursion */
172 struct ucg_callout_list sched_list; /**< list of scheduled timers */
174 #ifdef UCG_CALLOUT_STATS
175 struct ucg_callout_debug_stats stats; /**< stats */
180 * Initialize a callout manager
182 * The callout manager must be initialized before ucg_callout_add() or
183 * ucg_callout_manage() can be called.
186 * Pointer to the uninitialized callout manager structure.
188 * Pointer to a function that returns a time reference (unsigned 16 bits).
190 void ucg_callout_mgr_init(struct ucg_callout_mgr *cm,
191 ucg_callout_get_time_t *get_time);
194 * Initialize a callout structure and set callback function
196 * Before doing any operation on the callout structure, it has to be
197 * initialized with this function. It is possible to reinitialize a
198 * timer that has been previously scheduled, but it must be stopped.
201 * The timer to initialize.
203 * The priority of the callout (high value means higher priority)
205 * The callback function of the timer.
207 * The user argument of the callback function.
209 void ucg_callout_init(struct ucg_callout *tim, ucg_callout_cb_t f, void *arg,
215 * The ucg_callout_schedule() function adds the timer in the scheduled
216 * list. After the specified amount of ticks are elapsed, the callback
217 * function of the timer previously given to ucg_callout_init() will be
218 * invoked with its argument.
220 * The given "tick" value is relative to the current time, and is 16 bits
221 * wide. As it internally uses signed 16 bits comparison, the max value for
225 * The callout manager where the timer should be scheduled
229 * The number of ticks before the callback function is called, relative to now
230 * (the reference is given by the get_time() function of the callout manager).
232 * 0 on success, negative on error
234 int ucg_callout_schedule(struct ucg_callout_mgr *cm, struct ucg_callout *tim,
238 * Reschedule a callout
240 * This function does exactly the same than ucg_callout_schedule()
241 * except that the given time "ticks" is not relative to the current
242 * time but to the "expire" field of the timer.
244 * Using this function is advised to avoid drift if you want to have periodic
247 * This function should preferably be called from the callback function of
248 * the timer. Indeed, if the "expire" field should be a known value or it
249 * can result in an undefined behavior
251 * The given "tick" value is relative to the "expire" field of the
252 * timer, and is 16 bits wide. As it internally uses signed 16 bits
253 * comparison, the max value for ticks is 32767.
256 * The callout manager where the timer should be scheduled
260 * The number of ticks before the callback function is called, relative to
261 * the "expire" value of the timer
263 * 0 on success, negative on error
265 int ucg_callout_reschedule(struct ucg_callout_mgr *cm, struct ucg_callout *tim,
271 * The ucg_callout_stop() function stops a timer associated with the
274 * If the timer is scheduled or expired, it is removed from the list:
275 * the callback function won't be invoked. If the timer is stopped or
276 * running the function does nothing.
278 * If a timer structure is dynamically allocated, invoking
279 * ucg_callout_stop() is needed before freeing the structure, even if
280 * the freeing occurs in a callback. Indeed, this function can be called
281 * safely from a timer callback. If it succeeds, the timer is not
282 * referenced anymore by the callout manager.
285 * The callout manager where the timer is or was scheduled
289 * 0 on success, negative on error
291 void ucg_callout_stop(struct ucg_callout_mgr *cm, struct ucg_callout *tim);
294 * Return the state of a timer
299 * - UCG_CALLOUT_STATE_STOPPED: the timer is stopped
300 * - UCG_CALLOUT_STATE_SCHEDULED: the timer is scheduled
301 * - UCG_CALLOUT_STATE_EXPIRED: the timer was moved in a local list before
304 static inline uint8_t ucg_callout_state(struct ucg_callout *tim)
310 * Manage the timer list and execute callback functions.
312 * This function must be called periodically, either from a loop of from
313 * an interrupt. It browses the list of scheduled timers and runs all
314 * timers that are expired.
316 * This function must be called at least every 16384 reference ticks of
317 * cm->get_time(), but calling it more often is recommanded to avoid
318 * delaying task abusively.
320 * The function must be called with IRQ allowed.
322 void ucg_callout_manage(struct ucg_callout_mgr *cm);
325 * Dump statistics about timers.
327 void ucg_callout_dump_stats(struct ucg_callout_mgr *cm);
330 * Set the current priority level
332 * Prevent callout with a priority lower than "new_prio" to be executed.
333 * If the current priority of the callout manager is already lower higher
334 * than "new_prio", the function won't change the running priority.
336 * The returned value should be stored by the caller and restored with
337 * ucg_callout_mgr_restore_prio(), preferably in the same function.
340 * The callout manager
342 * The new running priority
345 * The value of the running priority before the call og this function
347 uint8_t ucg_callout_mgr_set_prio(struct ucg_callout_mgr *cm, uint8_t new_prio);
350 * Restore the current priority level
352 * Used after a call to ucg_callout_mgr_set_prio().
355 * The callout manager
357 * The old running priority
359 void ucg_callout_mgr_restore_prio(struct ucg_callout_mgr *cm, uint8_t old_prio);
361 #endif /* UCG_CALLOUT_H_ */