#include "asterisk.h"
#include <sys/time.h>
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
Go to the source code of this file.
Data Structures | |
struct | sched |
struct | sched_context |
Defines | |
#define | DEBUG(a) |
Functions | |
int | ast_sched_add (struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
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. | |
int | ast_sched_add_variable (struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) |
Schedule callback(data) to happen when ms into the future. | |
int | ast_sched_del (struct sched_context *con, int id) |
Deletes a scheduled event Remove this event from being run. A procedure should not remove its own event, but return 0 instead. In most cases, you should not call this routine directly, but use the AST_SCHED_DEL() macro instead (especially if you don't intend to do something different when it returns failure). | |
void | ast_sched_dump (const struct sched_context *con) |
Dumps the scheduler contents Debugging: Dump the contents of the scheduler to stderr. | |
int | ast_sched_replace (int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
replace a scheduler entry | |
int | ast_sched_replace_variable (int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) |
replace a scheduler entry | |
int | ast_sched_runq (struct sched_context *con) |
Runs the queue. | |
int | ast_sched_wait (struct sched_context *con) |
Determines number of seconds until the next outstanding event to take place Determine the number of seconds until the next outstanding event should take place, and return the number of milliseconds until it needs to be run. This value is perfect for passing to the poll call. | |
long | ast_sched_when (struct sched_context *con, int id) |
Returns the number of seconds before an event takes place. | |
static struct sched * | sched_alloc (struct sched_context *con) |
sched_context * | sched_context_create (void) |
New schedule context. | |
void | sched_context_destroy (struct sched_context *con) |
destroys a schedule context Destroys (free's) the given sched_context structure | |
static void | sched_release (struct sched_context *con, struct sched *tmp) |
static int | sched_settime (struct timeval *tv, int when) |
given the last event *tv and the offset in milliseconds 'when', computes the next value, | |
static void | schedule (struct sched_context *con, struct sched *s) |
Take a sched structure and put it in the queue, such that the soonest event is first in the list. |
Definition in file sched.c.
int ast_sched_add | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) |
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.
con | Scheduler context to add | |
when | how many milliseconds to wait for event to occur | |
callback | function to call when the amount of time expires | |
data | data to pass to the callback |
Definition at line 253 of file sched.c.
References ast_sched_add_variable().
Referenced by __oh323_update_info(), ast_readaudio_callback(), ast_readvideo_callback(), ast_rtp_raw_write(), ast_rtp_read(), ast_sched_replace(), do_register(), do_reload(), dundi_discover(), dundi_query(), dundi_send(), handle_command_response(), handle_request_invite(), handle_response_invite(), iax2_hangup(), iax2_sched_add(), mgcp_postrequest(), parse_register_contact(), populate_addr(), precache_trans(), qualify_peer(), queue_request(), receive_digit(), sip_scheddestroy(), start_session_timer(), submit_scheduled_batch(), submit_unscheduled_batch(), and transmit_register().
00254 { 00255 return ast_sched_add_variable(con, when, callback, data, 0); 00256 }
int ast_sched_add_variable | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data, | |||
int | variable | |||
) |
Schedule callback(data) to happen when ms into the future.
Adds a scheduled event with rescheduling support
con | Scheduler context to add | |
when | how many milliseconds to wait for event to occur | |
callback | function to call when the amount of time expires | |
data | data to pass to the callback | |
variable | If true, the result value of callback function will be used for rescheduling 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 at line 214 of file sched.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_dump(), ast_tv(), sched::callback, sched::data, DEBUG, sched_context::eventcnt, sched::id, sched_context::lock, option_debug, sched::resched, sched_alloc(), sched_release(), sched_settime(), schedule(), sched::variable, and sched::when.
Referenced by _misdn_tasks_add_variable(), ast_sched_add(), ast_sched_replace_variable(), dnsmgr_start_refresh(), and do_reload().
00215 { 00216 struct sched *tmp; 00217 int res = -1; 00218 00219 DEBUG(ast_debug(1, "ast_sched_add()\n")); 00220 00221 ast_mutex_lock(&con->lock); 00222 if ((tmp = sched_alloc(con))) { 00223 tmp->id = con->eventcnt++; 00224 tmp->callback = callback; 00225 tmp->data = data; 00226 tmp->resched = when; 00227 tmp->variable = variable; 00228 tmp->when = ast_tv(0, 0); 00229 if (sched_settime(&tmp->when, when)) { 00230 sched_release(con, tmp); 00231 } else { 00232 schedule(con, tmp); 00233 res = tmp->id; 00234 } 00235 } 00236 #ifdef DUMP_SCHEDULER 00237 /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ 00238 if (option_debug) 00239 ast_sched_dump(con); 00240 #endif 00241 ast_mutex_unlock(&con->lock); 00242 00243 return res; 00244 }
int ast_sched_del | ( | struct sched_context * | con, | |
int | id | |||
) |
Deletes a scheduled event Remove this event from being run. A procedure should not remove its own event, but return 0 instead. In most cases, you should not call this routine directly, but use the AST_SCHED_DEL() macro instead (especially if you don't intend to do something different when it returns failure).
con | scheduling context to delete item from | |
id | ID of the scheduled item to delete |
Definition at line 265 of file sched.c.
References ast_assert, ast_debug, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_dump(), DEBUG, sched::list, option_debug, s, and sched_release().
Referenced by __sip_ack(), __sip_destroy(), ast_sched_replace(), ast_sched_replace_variable(), handle_response_register(), iax2_poke_peer(), reg_source_db(), restart_session_timer(), sip_cancel_destroy(), socket_process(), stop_session_timer(), unlink_peer(), and update_registry().
00269 { 00270 struct sched *s; 00271 00272 DEBUG(ast_debug(1, "ast_sched_del()\n")); 00273 00274 ast_mutex_lock(&con->lock); 00275 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, s, list) { 00276 if (s->id == id) { 00277 AST_LIST_REMOVE_CURRENT(list); 00278 con->schedcnt--; 00279 sched_release(con, s); 00280 break; 00281 } 00282 } 00283 AST_LIST_TRAVERSE_SAFE_END; 00284 00285 #ifdef DUMP_SCHEDULER 00286 /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ 00287 if (option_debug) 00288 ast_sched_dump(con); 00289 #endif 00290 ast_mutex_unlock(&con->lock); 00291 00292 if (!s) { 00293 ast_debug(1, "Attempted to delete nonexistent schedule entry %d!\n", id); 00294 #ifndef AST_DEVMODE 00295 ast_assert(s != NULL); 00296 #else 00297 _ast_assert(0, "s != NULL", file, line, function); 00298 #endif 00299 return -1; 00300 } 00301 00302 return 0; 00303 }
void ast_sched_dump | ( | const struct sched_context * | con | ) |
Dumps the scheduler contents Debugging: Dump the contents of the scheduler to stderr.
con | Context to dump |
Definition at line 306 of file sched.c.
References ast_debug, AST_LIST_TRAVERSE, ast_tvnow(), ast_tvsub(), sched::callback, sched::data, sched_context::eventcnt, sched::id, sched::list, sched_context::schedccnt, sched_context::schedcnt, sched_context::schedq, and sched::when.
Referenced by ast_sched_add_variable(), and ast_sched_del().
00307 { 00308 struct sched *q; 00309 struct timeval tv = ast_tvnow(); 00310 #ifdef SCHED_MAX_CACHE 00311 ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt); 00312 #else 00313 ast_debug(1, "Asterisk Schedule Dump (%d in Q, %d Total)\n", con->schedcnt, con->eventcnt - 1); 00314 #endif 00315 00316 ast_debug(1, "=============================================================\n"); 00317 ast_debug(1, "|ID Callback Data Time (sec:ms) |\n"); 00318 ast_debug(1, "+-----+-----------------+-----------------+-----------------+\n"); 00319 AST_LIST_TRAVERSE(&con->schedq, q, list) { 00320 struct timeval delta = ast_tvsub(q->when, tv); 00321 00322 ast_debug(1, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n", 00323 q->id, 00324 q->callback, 00325 q->data, 00326 delta.tv_sec, 00327 (long int)delta.tv_usec); 00328 } 00329 ast_debug(1, "=============================================================\n"); 00330 }
int ast_sched_replace | ( | int | old_id, | |
struct sched_context * | con, | |||
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) |
replace a scheduler entry
-1 | failure | |
otherwise,returns | scheduled item ID |
Definition at line 246 of file sched.c.
References ast_sched_add(), and ast_sched_del().
00247 { 00248 if (old_id > -1) 00249 ast_sched_del(con, old_id); 00250 return ast_sched_add(con, when, callback, data); 00251 }
int ast_sched_replace_variable | ( | int | old_id, | |
struct sched_context * | con, | |||
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data, | |||
int | variable | |||
) |
replace a scheduler entry
-1 | failure | |
otherwise,returns | scheduled item ID |
Definition at line 203 of file sched.c.
References ast_sched_add_variable(), and ast_sched_del().
00204 { 00205 /* 0 means the schedule item is new; do not delete */ 00206 if (old_id > 0) 00207 ast_sched_del(con, old_id); 00208 return ast_sched_add_variable(con, when, callback, data, variable); 00209 }
int ast_sched_runq | ( | struct sched_context * | con | ) |
Runs the queue.
con | Scheduling context to run Run the queue, executing all callbacks which need to be performed at this time. | |
con | context to act upon |
Definition at line 335 of file sched.c.
References ast_debug, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_tv(), ast_tvadd(), ast_tvcmp(), ast_tvnow(), sched::callback, sched::data, DEBUG, sched::list, sched_context::lock, sched::resched, sched_release(), sched_settime(), sched_context::schedcnt, sched_context::schedq, schedule(), sched::variable, and sched::when.
Referenced by background_detect_exec(), do_cdr(), do_monitor(), do_refresh(), handle_speechrecognize(), misdn_tasks_thread_func(), network_thread(), reload_config(), sched_thread(), speech_background(), wait_for_winner(), and waitstream_core().
00336 { 00337 struct sched *current; 00338 struct timeval tv; 00339 int numevents; 00340 int res; 00341 00342 DEBUG(ast_debug(1, "ast_sched_runq()\n")); 00343 00344 ast_mutex_lock(&con->lock); 00345 00346 for (numevents = 0; !AST_LIST_EMPTY(&con->schedq); numevents++) { 00347 /* schedule all events which are going to expire within 1ms. 00348 * We only care about millisecond accuracy anyway, so this will 00349 * help us get more than one event at one time if they are very 00350 * close together. 00351 */ 00352 tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000)); 00353 if (ast_tvcmp(AST_LIST_FIRST(&con->schedq)->when, tv) != -1) 00354 break; 00355 00356 current = AST_LIST_REMOVE_HEAD(&con->schedq, list); 00357 con->schedcnt--; 00358 00359 /* 00360 * At this point, the schedule queue is still intact. We 00361 * have removed the first event and the rest is still there, 00362 * so it's permissible for the callback to add new events, but 00363 * trying to delete itself won't work because it isn't in 00364 * the schedule queue. If that's what it wants to do, it 00365 * should return 0. 00366 */ 00367 00368 ast_mutex_unlock(&con->lock); 00369 res = current->callback(current->data); 00370 ast_mutex_lock(&con->lock); 00371 00372 if (res) { 00373 /* 00374 * If they return non-zero, we should schedule them to be 00375 * run again. 00376 */ 00377 if (sched_settime(¤t->when, current->variable? res : current->resched)) { 00378 sched_release(con, current); 00379 } else 00380 schedule(con, current); 00381 } else { 00382 /* No longer needed, so release it */ 00383 sched_release(con, current); 00384 } 00385 } 00386 00387 ast_mutex_unlock(&con->lock); 00388 00389 return numevents; 00390 }
int ast_sched_wait | ( | struct sched_context * | con | ) |
Determines number of seconds until the next outstanding event to take place Determine the number of seconds until the next outstanding event should take place, and return the number of milliseconds until it needs to be run. This value is perfect for passing to the poll call.
con | context to act upon |
Definition at line 142 of file sched.c.
References ast_debug, AST_LIST_EMPTY, AST_LIST_FIRST, ast_mutex_lock(), ast_mutex_unlock(), ast_tvdiff_ms(), ast_tvnow(), DEBUG, sched_context::lock, and sched_context::schedq.
Referenced by background_detect_exec(), do_cdr(), do_monitor(), do_refresh(), handle_speechrecognize(), misdn_tasks_thread_func(), network_thread(), sched_thread(), speech_background(), wait_for_winner(), and waitstream_core().
00143 { 00144 int ms; 00145 00146 DEBUG(ast_debug(1, "ast_sched_wait()\n")); 00147 00148 ast_mutex_lock(&con->lock); 00149 if (AST_LIST_EMPTY(&con->schedq)) { 00150 ms = -1; 00151 } else { 00152 ms = ast_tvdiff_ms(AST_LIST_FIRST(&con->schedq)->when, ast_tvnow()); 00153 if (ms < 0) 00154 ms = 0; 00155 } 00156 ast_mutex_unlock(&con->lock); 00157 00158 return ms; 00159 }
long ast_sched_when | ( | struct sched_context * | con, | |
int | id | |||
) |
Returns the number of seconds before an event takes place.
con | Context to use | |
id | Id to dump |
Definition at line 392 of file sched.c.
References ast_debug, AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_tvnow(), DEBUG, sched::list, sched_context::lock, s, and sched_context::schedq.
Referenced by _sip_show_peer(), handle_cli_status(), and parse_register_contact().
00393 { 00394 struct sched *s; 00395 long secs = -1; 00396 DEBUG(ast_debug(1, "ast_sched_when()\n")); 00397 00398 ast_mutex_lock(&con->lock); 00399 AST_LIST_TRAVERSE(&con->schedq, s, list) { 00400 if (s->id == id) 00401 break; 00402 } 00403 if (s) { 00404 struct timeval now = ast_tvnow(); 00405 secs = s->when.tv_sec - now.tv_sec; 00406 } 00407 ast_mutex_unlock(&con->lock); 00408 00409 return secs; 00410 }
static struct sched* sched_alloc | ( | struct sched_context * | con | ) | [static] |
Definition at line 104 of file sched.c.
References ast_calloc, AST_LIST_REMOVE_HEAD, sched::list, sched_context::schedc, and sched_context::schedccnt.
Referenced by ast_sched_add_variable().
00105 { 00106 struct sched *tmp; 00107 00108 /* 00109 * We keep a small cache of schedule entries 00110 * to minimize the number of necessary malloc()'s 00111 */ 00112 #ifdef SCHED_MAX_CACHE 00113 if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list))) 00114 con->schedccnt--; 00115 else 00116 #endif 00117 tmp = ast_calloc(1, sizeof(*tmp)); 00118 00119 return tmp; 00120 }
struct sched_context* sched_context_create | ( | void | ) |
New schedule context.
Definition at line 69 of file sched.c.
References ast_calloc, and ast_mutex_init().
Referenced by __ast_channel_alloc_ap(), ast_cdr_engine_init(), dnsmgr_init(), load_module(), and misdn_tasks_init().
00070 { 00071 struct sched_context *tmp; 00072 00073 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 00074 return NULL; 00075 00076 ast_mutex_init(&tmp->lock); 00077 tmp->eventcnt = 1; 00078 00079 return tmp; 00080 }
void sched_context_destroy | ( | struct sched_context * | c | ) |
destroys a schedule context Destroys (free's) the given sched_context structure
c | Context to free |
Definition at line 82 of file sched.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), sched::list, sched_context::lock, s, sched_context::schedc, and sched_context::schedq.
Referenced by __ast_channel_alloc_ap(), __unload_module(), ast_channel_free(), ast_hangup(), load_module(), misdn_tasks_destroy(), and unload_module().
00083 { 00084 struct sched *s; 00085 00086 ast_mutex_lock(&con->lock); 00087 00088 #ifdef SCHED_MAX_CACHE 00089 /* Eliminate the cache */ 00090 while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list))) 00091 ast_free(s); 00092 #endif 00093 00094 /* And the queue */ 00095 while ((s = AST_LIST_REMOVE_HEAD(&con->schedq, list))) 00096 ast_free(s); 00097 00098 /* And the context */ 00099 ast_mutex_unlock(&con->lock); 00100 ast_mutex_destroy(&con->lock); 00101 ast_free(con); 00102 }
static void sched_release | ( | struct sched_context * | con, | |
struct sched * | tmp | |||
) | [static] |
Definition at line 122 of file sched.c.
References ast_free, AST_LIST_INSERT_HEAD, sched::list, SCHED_MAX_CACHE, sched_context::schedc, and sched_context::schedccnt.
Referenced by ast_sched_add_variable(), ast_sched_del(), and ast_sched_runq().
00123 { 00124 /* 00125 * Add to the cache, or just free() if we 00126 * already have too many cache entries 00127 */ 00128 00129 #ifdef SCHED_MAX_CACHE 00130 if (con->schedccnt < SCHED_MAX_CACHE) { 00131 AST_LIST_INSERT_HEAD(&con->schedc, tmp, list); 00132 con->schedccnt++; 00133 } else 00134 #endif 00135 ast_free(tmp); 00136 }
static int sched_settime | ( | struct timeval * | tv, | |
int | when | |||
) | [static] |
given the last event *tv and the offset in milliseconds 'when', computes the next value,
Definition at line 189 of file sched.c.
References ast_samp2tv(), ast_tvadd(), ast_tvcmp(), ast_tvnow(), and ast_tvzero().
Referenced by ast_sched_add_variable(), and ast_sched_runq().
00190 { 00191 struct timeval now = ast_tvnow(); 00192 00193 /*ast_debug(1, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/ 00194 if (ast_tvzero(*tv)) /* not supplied, default to now */ 00195 *tv = now; 00196 *tv = ast_tvadd(*tv, ast_samp2tv(when, 1000)); 00197 if (ast_tvcmp(*tv, now) < 0) { 00198 *tv = now; 00199 } 00200 return 0; 00201 }
static void schedule | ( | struct sched_context * | con, | |
struct sched * | s | |||
) | [static] |
Take a sched structure and put it in the queue, such that the soonest event is first in the list.
Definition at line 167 of file sched.c.
References AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_tvcmp(), sched::list, s, sched_context::schedcnt, sched_context::schedq, and sched::when.
Referenced by ast_sched_add_variable(), and ast_sched_runq().
00168 { 00169 00170 struct sched *cur = NULL; 00171 00172 AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, cur, list) { 00173 if (ast_tvcmp(s->when, cur->when) == -1) { 00174 AST_LIST_INSERT_BEFORE_CURRENT(s, list); 00175 break; 00176 } 00177 } 00178 AST_LIST_TRAVERSE_SAFE_END; 00179 if (!cur) 00180 AST_LIST_INSERT_TAIL(&con->schedq, s, list); 00181 00182 con->schedcnt++; 00183 }