main: replace printf printf_P
[protos/xbee-avr.git] / callout.h
1 /*-
2  * Copyright (c) <2010>, Intel Corporation
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  *
9  * - Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  *
17  * - Neither the name of Intel Corporation nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32  * OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #ifndef _CALLOUT_H_
36 #define _CALLOUT_H_
37
38 #define CALLOUT_STATS
39 //#define CALLOUT_DEBUG
40
41 /**
42  * @file
43  * Callout
44  *
45  * This library provides a timer service to Aversive. Instead of beeing
46  * called from interrupt (like the scheduler lib does), these kind of timers
47  * are not preemptive and should (for instance) be called from a main-loop.
48  *
49  * - Timers can be periodic or single (one-shot).
50  *
51  * This library provides an interface to add, delete and restart a
52  * timer. The API is based on the BSD callout(9) with few
53  * differences.
54  *
55  */
56
57 #ifdef CALLOUT_STATS
58 /**
59  * A structure that stores the timer statistics (per-lcore).
60  */
61 struct callout_debug_stats {
62         uint16_t reset;   /**< Number of success calls to callout_reset(). */
63         uint16_t stop;    /**< Number of success calls to callout_stop(). */
64         uint16_t manage;  /**< Number of calls to callout_manage(). */
65         uint16_t pending; /**< Number of pending timers. */
66         uint16_t running; /**< Number of running timers. */
67 };
68 extern struct callout_debug_stats callout_debug_stats;
69 #endif
70
71 struct callout;
72 struct callout_manager;
73
74 /**
75  * Callback function for the timer.
76  */
77 typedef void (callout_cb_t)(struct callout_manager *, struct callout *, void *);
78
79 /**
80  * A structure describing a timer in RTE.
81  */
82 struct callout
83 {
84         TAILQ_ENTRY(callout) next; /**< Next and prev in list. */
85
86         uint8_t periodical: 1;     /**< timer is periodical or not */
87         uint8_t scheduled: 1;      /**< true if timer is scheduled */
88         uint8_t running: 1;        /**< true if cb func is beeing executed */
89         uint8_t reserved: 5;
90
91         uint16_t period;           /**< Period of timer (0 if not periodic). */
92         uint16_t expire;           /**< Time when timer expire. */
93         callout_cb_t *f;           /**< Callback function. */
94         void *arg;                 /**< Argument to callback function. */
95 };
96
97 /**
98  * a list of timers
99  */
100 TAILQ_HEAD(callout_list, callout);
101
102 /**
103  * A static initializer for a timer structure.
104  */
105 #define CALLOUT_INITIALIZER { }
106
107 /**
108  * Function used by a callout manager to get a time reference
109  */
110 typedef uint16_t (get_time_t)(void);
111
112 /**
113  * A instance of callout manager (it is possible to have several)
114  */
115 struct callout_manager {
116         get_time_t *get_time;
117         uint8_t updated: 1;
118         uint8_t reserved: 7;
119         uint16_t prev_time;
120         struct callout_list pending_list;
121 #ifdef CALLOUT_STATS
122         /* statistics */
123         struct callout_debug_stats stats;
124 #endif
125 };
126
127 /**
128  * Initialize a callout manager
129  *
130  * @param cm
131  *   The uninitialized callout manager structure.
132  * @param get_time
133  *   Pointer to a function that returns a time reference (unsigned 16 bits)
134  * @return
135  *   - 0 on success
136  *   - negative on error
137  */
138 int
139 callout_manager_init(struct callout_manager *cm, get_time_t *get_time);
140
141 /**
142  * Initialize a timer handle.
143  *
144  * The callout_init() function initializes the timer handle tim
145  * for use. No operations can be performed on the timer before it is
146  * initialized.
147  *
148  * @param tim
149  *   The timer to initialize.
150  */
151 void callout_init(struct callout *tim);
152
153 /**
154  * Timer type: Periodic or single (one-shot).
155  */
156 enum callout_type {
157         SINGLE,
158         PERIODICAL
159 };
160
161 /**
162  * Reset and start the timer associated with the timer handle.
163  *
164  * The callout_reset() function resets and starts the timer
165  * associated with the timer handle tim. When the timer expires after
166  * ticks/hz seconds, the function specified by *fct* will be called
167  * with the argument *arg* on core *tim_lcore*.
168  *
169  * If the timer associated with the timer handle is already running
170  * (in the RUNNING state), the function will fail. The user has to check
171  * the return value of the function to see if there is a chance that the
172  * timer is in the RUNNING state.
173  *
174  * If the timer is being configured on another core (the CONFIG state),
175  * it will also fail.
176  *
177  * If the timer is pending or stopped, it will be rescheduled with the
178  * new parameters.
179  *
180  * @param tim
181  *   The timer handle.
182  * @param ticks
183  *   The number of cycles (see rte_get_hpet_hz()) before the callback
184  *   function is called.
185  * @param type
186  *   The type can be either:
187  *   - PERIODICAL: The timer is automatically reloaded after execution
188  *     (returns to the PENDING state)
189  *   - SINGLE: The timer is one-shot, that is, the timer goes to a
190  *     STOPPED state after execution.
191  * @param tim_lcore
192  *   The ID of the lcore where the timer callback function has to be
193  *   executed. If tim_lcore is LCORE_ID_ANY, the timer library will
194  *   launch it on a different core for each call (round-robin).
195  * @param fct
196  *   The callback function of the timer.
197  * @param arg
198  *   The user argument of the callback function.
199  * @return
200  *   - 0: Success; the timer is scheduled.
201  *   - (-1): Timer is in the RUNNING or CONFIG state.
202  */
203 int callout_reset(struct callout_manager *cm, struct callout *tim,
204                   uint16_t ticks, enum callout_type type,
205                   callout_cb_t fct, void *arg);
206
207
208 /**
209  * Stop a timer.
210  *
211  * The callout_stop() function stops the timer associated with the
212  * timer handle tim. It may fail if the timer is currently running or
213  * being configured.
214  *
215  * If the timer is pending or stopped (for instance, already expired),
216  * the function will succeed. The timer handle tim must have been
217  * initialized using callout_init(), otherwise, undefined behavior
218  * will occur.
219  *
220  * This function can be called safely from a timer callback. If it
221  * succeeds, the timer is not referenced anymore by the timer library
222  * and the timer structure can be freed (even in the callback
223  * function).
224  *
225  * @param tim
226  *   The timer handle.
227  */
228 void callout_stop(struct callout_manager *cm, struct callout *tim);
229
230
231 /**
232  * Test if a timer is pending.
233  *
234  * The callout_pending() function tests the PENDING status
235  * of the timer handle tim. A PENDING timer is one that has been
236  * scheduled and whose function has not yet been called.
237  *
238  * @param tim
239  *   The timer handle.
240  * @return
241  *   - 0: The timer is not pending.
242  *   - 1: The timer is pending.
243  */
244 int callout_pending(struct callout *tim);
245
246 /**
247  * Manage the timer list and execute callback functions.
248  *
249  * This function must be called periodically from all cores
250  * main_loop(). It browses the list of pending timers and runs all
251  * timers that are expired.
252  *
253  * The precision of the timer depends on the call frequency of this
254  * function. However, the more often the function is called, the more
255  * it will use CPU resources.
256  */
257 void callout_manage(struct callout_manager *cm);
258
259 /**
260  * Dump statistics about timers.
261  */
262 void callout_dump_stats(struct callout_manager *cm);
263
264 #endif /* _CALLOUT_H_ */