Wed Jan 8 2020 09:49:51

Asterisk developer's documentation


sched.h
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  * \brief Scheduler Routines (derived from cheops)
21  */
22 
23 #ifndef _ASTERISK_SCHED_H
24 #define _ASTERISK_SCHED_H
25 
26 #if defined(__cplusplus) || defined(c_plusplus)
27 extern "C" {
28 #endif
29 
30 
31 /*! \brief Max num of schedule structs
32  * \note The max number of schedule structs to keep around
33  * for use. Undefine to disable schedule structure
34  * caching. (Only disable this on very low memory
35  * machines)
36  */
37 #define SCHED_MAX_CACHE 128
38 
39 /*! \brief a loop construct to ensure that
40  * the scheduled task get deleted. The idea is that
41  * if we loop attempting to remove the scheduled task,
42  * then whatever callback had been running will complete
43  * and reinsert the task into the scheduler.
44  *
45  * Since macro expansion essentially works like pass-by-name
46  * parameter passing, this macro will still work correctly even
47  * if the id of the task to delete changes. This holds as long as
48  * the name of the id which could change is passed to the macro
49  * and not a copy of the value of the id.
50  */
51 #define AST_SCHED_DEL(sched, id) \
52  ({ \
53  int _count = 0; \
54  int _sched_res = -1; \
55  while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \
56  usleep(1); \
57  if (_count == 10 && option_debug > 2) { \
58  ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \
59  } \
60  id = -1; \
61  (_sched_res); \
62  })
63 
64 /*!
65  * \brief schedule task to get deleted and call unref function
66  * \sa AST_SCHED_DEL
67  * \since 1.6.1
68  */
69 #define AST_SCHED_DEL_UNREF(sched, id, refcall) \
70  do { \
71  int _count = 0; \
72  while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
73  usleep(1); \
74  } \
75  if (_count == 10) \
76  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__); \
77  if (id > -1) \
78  refcall; \
79  id = -1; \
80  } while (0);
81 
82 /*!
83  * \brief schedule task to get deleted releasing the lock between attempts
84  * \since 1.6.1
85  */
86 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \
87  ({ \
88  int _count = 0; \
89  int _sched_res = -1; \
90  while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \
91  ast_mutex_unlock(lock); \
92  usleep(1); \
93  ast_mutex_lock(lock); \
94  } \
95  if (_count == 10 && option_debug > 2) { \
96  ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \
97  } \
98  id = -1; \
99  (_sched_res); \
100  })
101 
102 #define AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, variable) \
103  do { \
104  int _count = 0; \
105  while (id > -1 && ast_sched_del(sched, id) && ++_count < 10) { \
106  usleep(1); \
107  } \
108  if (_count == 10) \
109  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__); \
110  id = ast_sched_add_variable(sched, when, callback, data, variable); \
111  } while (0);
112 
113 #define AST_SCHED_REPLACE(id, sched, when, callback, data) \
114  AST_SCHED_REPLACE_VARIABLE(id, sched, when, callback, data, 0)
115 
116 /*!
117  * \note Not currently used in the source?
118  * \since 1.6.1
119  */
120 #define AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, variable, unrefcall, addfailcall, refcall) \
121  do { \
122  int _count = 0, _res=1; \
123  void *_data = (void *)ast_sched_find_data(sched, id); \
124  while (id > -1 && (_res = ast_sched_del(sched, id) && _count++ < 10)) { \
125  usleep(1); \
126  } \
127  if (!_res && _data) \
128  unrefcall; /* should ref _data! */ \
129  if (_count == 10) \
130  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__); \
131  refcall; \
132  id = ast_sched_add_variable(sched, when, callback, data, variable); \
133  if (id == -1) \
134  addfailcall; \
135  } while (0);
136 
137 #define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
138  AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
139 
140 struct sched_context;
141 
142 /*! \brief New schedule context
143  * \note Create a scheduling context
144  * \return Returns a malloc'd sched_context structure, NULL on failure
145  */
146 struct sched_context *sched_context_create(void);
147 
148 /*! \brief destroys a schedule context
149  * Destroys (free's) the given sched_context structure
150  * \param c Context to free
151  * \return Returns 0 on success, -1 on failure
152  */
153 void sched_context_destroy(struct sched_context *c);
154 
155 /*! \brief callback for a cheops scheduler
156  * A cheops scheduler callback takes a pointer with callback data and
157  * \return returns a 0 if it should not be run again, or non-zero if it should be
158  * rescheduled to run again
159  */
160 typedef int (*ast_sched_cb)(const void *data);
161 #define AST_SCHED_CB(a) ((ast_sched_cb)(a))
162 
163 struct ast_cb_names {
165  char *list[10];
167 };
168 
169 /*!
170  * \brief Show statics on what it is in the schedule queue
171  * \param con Schedule context to check
172  * \param buf dynamic string to store report
173  * \param cbnames to check against
174  * \since 1.6.1
175  */
176 void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
177 
178 /*! \brief Adds a scheduled event
179  * Schedule an event to take place at some point in the future. callback
180  * will be called with data as the argument, when milliseconds into the
181  * future (approximately)
182  * If callback returns 0, no further events will be re-scheduled
183  * \param con Scheduler context to add
184  * \param when how many milliseconds to wait for event to occur
185  * \param callback function to call when the amount of time expires
186  * \param data data to pass to the callback
187  * \return Returns a schedule item ID on success, -1 on failure
188  */
189 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
190 
191 /*!
192  * \brief replace a scheduler entry
193  * \deprecated You should use the AST_SCHED_REPLACE() macro instead.
194  *
195  * This deletes the scheduler entry for old_id if it exists, and then
196  * calls ast_sched_add to create a new entry. A negative old_id will
197  * be ignored.
198  *
199  * \retval -1 failure
200  * \retval otherwise, returns scheduled item ID
201  */
202 int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
203 
204 /*!Adds a scheduled event with rescheduling support
205  * \param con Scheduler context to add
206  * \param when how many milliseconds to wait for event to occur
207  * \param callback function to call when the amount of time expires
208  * \param data data to pass to the callback
209  * \param variable If true, the result value of callback function will be
210  * used for rescheduling
211  * Schedule an event to take place at some point in the future. Callback
212  * will be called with data as the argument, when milliseconds into the
213  * future (approximately)
214  * If callback returns 0, no further events will be re-scheduled
215  * \return Returns a schedule item ID on success, -1 on failure
216  */
217 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
218 
219 /*!
220  * \brief replace a scheduler entry
221  * \deprecated You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.
222  *
223  * This deletes the scheduler entry for old_id if it exists, and then
224  * calls ast_sched_add to create a new entry. A negative old_id will
225  * be ignored.
226  *
227  * \retval -1 failure
228  * \retval otherwise, returns scheduled item ID
229  */
230 int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
231 
232 
233 /*!
234  * \brief Find a sched structure and return the data field associated with it.
235  * \param con scheduling context in which to search fro the matching id
236  * \param id ID of the scheduled item to find
237  * \return the data field from the matching sched struct if found; else return NULL if not found.
238  * \since 1.6.1
239  */
240 
241 const void *ast_sched_find_data(struct sched_context *con, int id);
242 
243 /*! \brief Deletes a scheduled event
244  * Remove this event from being run. A procedure should not remove its own
245  * event, but return 0 instead. In most cases, you should not call this
246  * routine directly, but use the AST_SCHED_DEL() macro instead (especially if
247  * you don't intend to do something different when it returns failure).
248  * \param con scheduling context to delete item from
249  * \param id ID of the scheduled item to delete
250  * \return Returns 0 on success, -1 on failure
251  */
252 #ifndef AST_DEVMODE
254 #else
255 int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
256 #define ast_sched_del(a, b) _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
257 #endif
258 
259 /*! \brief Determines number of seconds until the next outstanding event to take place
260  * Determine the number of seconds until the next outstanding event
261  * should take place, and return the number of milliseconds until
262  * it needs to be run. This value is perfect for passing to the poll
263  * call.
264  * \param con context to act upon
265  * \return Returns "-1" if there is nothing there are no scheduled events
266  * (and thus the poll should not timeout)
267  */
269 
270 /*! \brief Runs the queue
271  * \param con Scheduling context to run
272  * Run the queue, executing all callbacks which need to be performed
273  * at this time.
274  * \param con context to act upon
275  * \return Returns the number of events processed.
276  */
277 int ast_sched_runq(struct sched_context *con);
278 
279 /*! \brief Dumps the scheduler contents
280  * Debugging: Dump the contents of the scheduler to stderr
281  * \param con Context to dump
282  */
283 void ast_sched_dump(struct sched_context *con);
284 
285 /*! \brief Returns the number of seconds before an event takes place
286  * \param con Context to use
287  * \param id Id to dump
288  */
289 long ast_sched_when(struct sched_context *con,int id);
290 
291 /*!
292  * \brief Convenience macro for objects and reference (add)
293  *
294  */
295 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj)))
296 
297 /*!
298  * \brief Convenience macro for objects and reference (del)
299  *
300  */
301 #define ast_sched_del_object(obj,destructor,con,id) do { \
302  if ((id) > -1) { \
303  ast_sched_del((con),(id)); \
304  (id) = -1; \
305  ASTOBJ_UNREF((obj),(destructor)); \
306  } \
307 } while(0)
308 
309 /*!
310  * \brief An opaque type representing a scheduler thread
311  *
312  * The purpose of the ast_sched_thread API is to provide a common implementation
313  * of the case where a module wants to have a dedicated thread for handling the
314  * scheduler.
315  */
316 struct ast_sched_thread;
317 
318 /*!
319  * \brief Create a scheduler with a dedicated thread
320  *
321  * This function should be used to allocate a scheduler context and a dedicated
322  * thread for processing scheduler entries. The thread is started immediately.
323  *
324  * \retval NULL error
325  * \retval non-NULL a handle to the scheduler and its dedicated thread.
326  */
328 
329 /*!
330  * \brief Destroy a scheduler and its thread
331  *
332  * This function is used to destroy a scheduler context and the dedicated thread
333  * that was created for handling scheduler entries. Any entries in the scheduler
334  * that have not yet been processed will be thrown away. Once this function is
335  * called, the handle must not be used again.
336  *
337  * \param st the handle to the scheduler and thread
338  *
339  * \return NULL for convenience
340  */
342 
343 /*!
344  * \brief Add a scheduler entry
345  *
346  * \param st the handle to the scheduler and thread
347  * \param when the number of ms in the future to run the task. A value <= 0
348  * is treated as "run now".
349  * \param cb the function to call when the scheduled time arrives
350  * \param data the parameter to pass to the scheduler callback
351  *
352  * \retval -1 Failure
353  * \retval >=0 Sched ID of added task
354  */
355 int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb,
356  const void *data);
357 
358 /*!
359  * \brief Add a variable reschedule time scheduler entry
360  *
361  * \param st the handle to the scheduler and thread
362  * \param when the number of ms in the future to run the task. A value <= 0
363  * is treated as "run now".
364  * \param cb the function to call when the scheduled time arrives
365  * \param data the parameter to pass to the scheduler callback
366  * \param variable If this value is non-zero, then the scheduler will use the return
367  * value of the scheduler as the amount of time in the future to run the
368  * task again. Normally, a return value of 0 means do not re-schedule, and
369  * non-zero means re-schedule using the time provided when the scheduler
370  * entry was first created.
371  *
372  * \retval -1 Failure
373  * \retval >=0 Sched ID of added task
374  */
375 int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb,
376  const void *data, int variable);
377 
378 /*!
379  * \brief Get the scheduler context for a given ast_sched_thread
380  *
381  * This function should be used only when direct access to the scheduler context
382  * is required. Its use is discouraged unless necessary. The cases where
383  * this is currently required is when you want to take advantage of one of the
384  * AST_SCHED macros.
385  *
386  * \param st the handle to the scheduler and thread
387  *
388  * \return the sched_context associated with an ast_sched_thread
389  */
391 
392 /*!
393  * \brief Delete a scheduler entry
394  *
395  * This uses the AST_SCHED_DEL macro internally.
396  *
397  * \param st the handle to the scheduler and thread
398  * \param id scheduler entry id to delete
399  *
400  * \retval 0 success
401  * \retval non-zero failure
402  */
403 #define ast_sched_thread_del(st, id) ({ \
404  struct sched_context *__tmp_context = ast_sched_thread_get_context(st); \
405  AST_SCHED_DEL(__tmp_context, id); \
406 })
407 
408 /*!
409  * \brief Force re-processing of the scheduler context
410  *
411  * \param st the handle to the scheduler and thread
412  *
413  * \return nothing
414  */
415 void ast_sched_thread_poke(struct ast_sched_thread *st);
416 
417 #if defined(__cplusplus) || defined(c_plusplus)
418 }
419 #endif
420 
421 #endif /* _ASTERISK_SCHED_H */
char * list[10]
Definition: sched.h:165
int ast_sched_del(struct sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event Remove this event from being run. A procedure should not remove its own eve...
Definition: sched.c:468
struct ast_sched_thread * ast_sched_thread_destroy(struct ast_sched_thread *st)
Destroy a scheduler and its thread.
Definition: sched.c:143
struct ast_sched_thread * ast_sched_thread_create(void)
Create a scheduler with a dedicated thread.
Definition: sched.c:167
int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb, const void *data, int variable)
Add a variable reschedule time scheduler entry.
Definition: sched.c:195
int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Schedule callback(data) to happen when ms into the future.
Definition: sched.c:406
ast_sched_cb cblist[10]
Definition: sched.h:166
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event Schedule an event to take place at some point in the future. callback will be called with data as the argument, when milliseconds into the future (approximately) If callback returns 0, no further events will be re-scheduled.
Definition: sched.c:446
void ast_sched_dump(struct sched_context *con)
Dumps the scheduler contents Debugging: Dump the contents of the scheduler to stderr.
Definition: sched.c:565
int numassocs
Definition: sched.h:164
void ast_sched_report(struct 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:527
int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
replace a scheduler entry
Definition: sched.c:438
const void * ast_sched_find_data(struct sched_context *con, int id)
Find a sched structure and return the data field associated with it.
Definition: sched.c:451
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free&#39;s) the given sched_context structure
Definition: sched.c:267
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
long ast_sched_when(struct sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:664
int ast_sched_replace_variable(int old_id, struct 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:394
struct sched_context * ast_sched_thread_get_context(struct ast_sched_thread *st)
Get the scheduler context for a given ast_sched_thread.
Definition: sched.c:138
#define attribute_warn_unused_result
Definition: compiler.h:71
void ast_sched_thread_poke(struct ast_sched_thread *st)
Force re-processing of the scheduler context.
Definition: sched.c:131
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
int(* ast_sched_cb)(const void *data)
callback for a cheops scheduler A cheops scheduler callback takes a pointer with callback data and ...
Definition: sched.h:160
int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb, const void *data)
Add a scheduler entry.
Definition: sched.c:210