Asterisk - The Open Source Telephony Project GIT-master-d5a0626
sched.h
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2010, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 * Russell Bryant <russell@digium.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*! \file
21 * \brief Scheduler Routines (derived from cheops)
22 */
23
24#ifndef _ASTERISK_SCHED_H
25#define _ASTERISK_SCHED_H
26
27#if defined(__cplusplus) || defined(c_plusplus)
28extern "C" {
29#endif
30
31/*!
32 * \brief Remove a scheduler entry
33 *
34 * This is a loop construct to ensure that
35 * the scheduled task get deleted. The idea is that
36 * if we loop attempting to remove the scheduled task,
37 * then whatever callback had been running will complete
38 * and reinsert the task into the scheduler.
39 *
40 * Since macro expansion essentially works like pass-by-name
41 * parameter passing, this macro will still work correctly even
42 * if the id of the task to delete changes. This holds as long as
43 * the name of the id which could change is passed to the macro
44 * and not a copy of the value of the id.
45 */
46#define AST_SCHED_DEL(sched, id) \
47 ({ \
48 int _count = 0; \
49 int _sched_res = -1; \
50 while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
51 usleep(1); \
52 if (_count == 10) { \
53 ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
54 } \
55 id = -1; \
56 (_sched_res); \
57 })
58
59#define AST_SCHED_DEL_ACCESSOR(sched, obj, getter, setter) \
60 ({ \
61 int _count = 0; \
62 int _sched_res = -1; \
63 while (getter(obj) > -1 && (_sched_res = ast_sched_del(sched, getter(obj))) && ++_count < 10) \
64 usleep(1); \
65 if (_count == 10) { \
66 ast_debug(3, "Unable to cancel schedule ID %d.\n", getter(obj)); \
67 } \
68 setter(obj, -1); \
69 (_sched_res); \
70 })
71
72/*!
73 * \brief schedule task to get deleted and call unref function
74 *
75 * Only calls the unref function if the task is actually deleted by
76 * ast_sched_del_nonrunning. If a failure occurs or the task is
77 * currently running and not rescheduled then refcall is not invoked.
78 *
79 * \sa AST_SCHED_DEL
80 * \since 1.6.1
81 */
82#define AST_SCHED_DEL_UNREF(sched, id, refcall) \
83 do { \
84 int _count = 0, _id, _ret = 0; \
85 while ((_id = id) > -1 && (( _ret = ast_sched_del_nonrunning(sched, _id)) == -1) && ++_count < 10) { \
86 usleep(1); \
87 } \
88 if (_count == 10) { \
89 ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", _id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
90 } else if (_id > -1 && _ret >-2) { \
91 refcall; \
92 id = -1; \
93 } \
94 } while (0);
95
96/*!
97 * \brief schedule task to get deleted releasing the lock between attempts
98 * \since 1.6.1
99 */
100#define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
101 ({ \
102 int _count = 0; \
103 int _sched_res = -1; \
104 while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
105 ast_mutex_unlock(lock); \
106 usleep(1); \
107 ast_mutex_lock(lock); \
108 } \
109 if (_count == 10) { \
110 ast_debug(3, "Unable to cancel schedule ID %d.\n", id); \
111 } \
112 id = -1; \
113 (_sched_res); \
114 })
115
116#define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
117 do { \
118 int _count = 0; \
119 while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
120 usleep(1); \
121 } \
122 if (_count == 10) \
123 ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
124 id = ast_sched_add_variable(sched, when, callback, data, variable); \
125 } while (0);
126
127#define AST_SCHED_REPLACE(id, sched, when, callback, data) \
128 AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
129
130/*!
131 * \note Not currently used in the source?
132 * \since 1.6.1
133 */
134#define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
135 do { \
136 int _count = 0, _res=1; \
137 void *_data = (void *)ast_sched_find_data(sched, id); \
138 while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
139 usleep(1); \
140 } \
141 if (!_res && _data && _data != data) \
142 unrefcall; /* should ref _data! */ \
143 if (_count == 10) \
144 ast_log(LOG_WARNING, "Unable to cancel schedule ID %d. This is probably a bug (%s: %s, line %d).\n", id, __FILE__, __PRETTY_FUNCTION__, __LINE__); \
145 if (_data != data) \
146 refcall; \
147 id = ast_sched_add_variable(sched, when, callback, data, variable); \
148 if (id == -1) \
149 addfailcall; \
150 } while (0);
151
152#define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
153 AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
154
155/*!
156 * \brief Create a scheduler context
157 *
158 * \retval NULL on failure
159 * \return a malloc'd sched_context structure
160 */
162
163/*!
164 * \brief destroys a schedule context
165 *
166 * \param c Context to free
167 */
169
170/*!
171 * \brief scheduler callback
172 *
173 * A scheduler callback takes a pointer with callback data and
174 *
175 * \retval 0 if the callback should not be rescheduled
176 * \retval non-zero if the callback should be scheduled again
177 */
178typedef int (*ast_sched_cb)(const void *data);
179#define AST_SCHED_CB(a) ((ast_sched_cb)(a))
180
181/*!
182 * \brief Clean all scheduled events with matching callback.
183 *
184 * \param con Scheduler Context
185 * \param match Callback to match
186 * \param cleanup_cb Callback to run
187 *
188 * \note The return of cleanup_cb is ignored. No events are rescheduled.
189 */
191
194 char *list[10];
196};
197
198/*!
199 * \brief Show statics on what it is in the schedule queue
200 * \param con Schedule context to check
201 * \param buf dynamic string to store report
202 * \param cbnames to check against
203 * \since 1.6.1
204 */
205void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
206
207/*!
208 * \brief Adds a scheduled event
209 *
210 * Schedule an event to take place at some point in the future. callback
211 * will be called with data as the argument, when milliseconds into the
212 * future (approximately)
213 *
214 * If callback returns 0, no further events will be re-scheduled
215 *
216 * \param con Scheduler context to add
217 * \param when how many milliseconds to wait for event to occur
218 * \param callback function to call when the amount of time expires
219 * \param data data to pass to the callback
220 *
221 * \retval -1 on failure
222 * \return schedule item ID
223 */
224int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
225
226/*!
227 * \brief replace a scheduler entry
228 * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
229 *
230 * This deletes the scheduler entry for old_id if it exists, and then
231 * calls ast_sched_add to create a new entry. A negative old_id will
232 * be ignored.
233 *
234 * \retval -1 on failure
235 * \return scheduled item ID
236 */
237int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
238
239/*!
240 * \brief Adds a scheduled event with rescheduling support
241 *
242 * \param con Scheduler context to add
243 * \param when how many milliseconds to wait for event to occur
244 * \param callback function to call when the amount of time expires
245 * \param data data to pass to the callback
246 * \param variable If true, the result value of callback function will be
247 * used for rescheduling
248 *
249 * Schedule an event to take place at some point in the future. Callback
250 * will be called with data as the argument, when milliseconds into the
251 * future (approximately)
252 *
253 * If callback returns 0, no further events will be re-scheduled
254 *
255 * \retval -1 on failure
256 * \return scheduled item ID
257 */
258int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
259
260/*!
261 * \brief replace a scheduler entry
262 * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
263 *
264 * This deletes the scheduler entry for old_id if it exists, and then
265 * calls ast_sched_add to create a new entry. A negative old_id will
266 * be ignored.
267 *
268 * \retval -1 on failure
269 * \return scheduled item ID
270 */
271int ast_sched_replace_variable(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
272
273/*!
274 * \brief Find a sched structure and return the data field associated with it.
275 *
276 * \param con scheduling context in which to search fro the matching id
277 * \param id ID of the scheduled item to find
278 *
279 * \retval NULL if not found
280 * \return the data field from the matching sched struct if found.
281 *
282 * \since 1.6.1
283 */
284const void *ast_sched_find_data(struct ast_sched_context *con, int id);
285
286/*!
287 * \brief Deletes a scheduled event
288 *
289 * Remove this event from being run. A procedure should not remove its own
290 * event, but return 0 instead. In most cases, you should not call this
291 * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
292 * you don't intend to do something different when it returns failure).
293 *
294 * \param con scheduling context to delete item from
295 * \param id ID of the scheduled item to delete
296 *
297 * \retval -1 on failure
298 * \retval 0 on success
299 *
300 * \deprecated in favor of ast_sched_del_nonrunning which checks if the event is running and rescheduled
301 *
302 */
304
305/*!
306 * \brief Deletes a scheduled event with care against the event running
307 *
308 * Remove this event from being run. A procedure should not remove its own
309 * event, but return 0 instead. In most cases, you should not call this
310 * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
311 * you don't intend to do something different when it returns failure).
312 *
313 * \param con scheduling context to delete item from
314 * \param id ID of the scheduled item to delete
315 *
316 * \retval -1 on failure
317 * \retval -2 event was running but was deleted because it was not rescheduled
318 * \retval 0 on success
319 */
321
322/*!
323 * \brief Determines number of seconds until the next outstanding event to take place
324 *
325 * Determine the number of seconds until the next outstanding event
326 * should take place, and return the number of milliseconds until
327 * it needs to be run. This value is perfect for passing to the poll
328 * call.
329 *
330 * \param con context to act upon
331 *
332 * \retval -1 if there is nothing there are no scheduled events
333 * (and thus the poll should not timeout)
334 */
336
337/*!
338 * \brief Runs the queue
339 *
340 * Run the queue, executing all callbacks which need to be performed
341 * at this time.
342 *
343 * \param con Scheduling context to run
344 *
345 * \return the number of events processed.
346 */
347int ast_sched_runq(struct ast_sched_context *con);
348
349/*!
350 * \brief Dumps the scheduler contents
351 *
352 * Debugging: Dump the contents of the scheduler to stderr
353 *
354 * \param con Context to dump
355 */
356void ast_sched_dump(struct ast_sched_context *con);
357
358/*!
359 * \brief Returns the number of seconds before an event takes place
360 *
361 * \param con Context to use
362 * \param id Id to dump
363 */
364long ast_sched_when(struct ast_sched_context *con,int id);
365
366/*!
367 * \brief Convenience macro for objects and reference (add)
368 *
369 */
370#define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
371
372/*!
373 * \brief Convenience macro for objects and reference (del)
374 *
375 */
376#define ast_sched_del_object(obj,destructor,con,id) do { \
377 if ((id) > -1) { \
378 ast_sched_del((con),(id)); \
379 (id) = -1; \
380 ASTOBJ_UNREF((obj),(destructor)); \
381 } \
382} while(0)
383
384/*!
385 * \brief Start a thread for processing scheduler entries
386 *
387 * \param con the scheduler context this thread will manage
388 *
389 * \retval 0 success
390 * \retval non-zero failure
391 */
393
394#if defined(__cplusplus) || defined(c_plusplus)
395}
396#endif
397
398#endif /* _ASTERISK_SCHED_H */
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2362
#define attribute_warn_unused_result
Definition: compiler.h:71
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int cleanup_cb(void *obj, void *arg, int flags)
Definition: res_stasis.c:309
const void * ast_sched_find_data(struct ast_sched_context *con, int id)
Find a sched structure and return the data field associated with it.
Definition: sched.c:589
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:614
void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames)
Show statics on what it is in the schedule queue.
Definition: sched.c:705
void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb)
Clean all scheduled events with matching callback.
Definition: sched.c:409
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:851
int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
replace a scheduler entry
Definition: sched.c:559
void ast_sched_dump(struct ast_sched_context *con)
Dumps the scheduler contents.
Definition: sched.c:743
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:567
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_del_nonrunning(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event with care against the event running.
Definition: sched.c:627
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:526
int(* ast_sched_cb)(const void *data)
scheduler callback
Definition: sched.h:178
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433
int ast_sched_replace_variable(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
replace a scheduler entry
Definition: sched.c:514
char * list[10]
Definition: sched.h:194
int numassocs
Definition: sched.h:193
ast_sched_cb cblist[10]
Definition: sched.h:195
Support for dynamic strings.
Definition: strings.h:623
static struct test_val c