Asterisk - The Open Source Telephony Project GIT-master-0bf3178
Data Structures | Macros | Functions | Variables
sched.c File Reference

Scheduler Routines (from cheops-NG) More...

#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/heap.h"
#include "asterisk/threadstorage.h"
Include dependency graph for sched.c:

Go to the source code of this file.

Data Structures

struct  ast_sched_context
 
struct  sched
 
struct  sched_id
 Scheduler ID holder. More...
 
struct  sched_thread
 

Macros

#define DEBUG(a)
 
#define ID_QUEUE_INCREMENT   16
 
#define SCHED_MAX_CACHE   128
 Max num of schedule structs. More...
 

Functions

static void __init_last_del_id (void)
 
static int add_ids (struct ast_sched_context *con)
 Add new scheduler IDs to the queue. More...
 
int ast_sched_add (struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
 Adds a scheduled event. More...
 
int ast_sched_add_variable (struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
 Schedule callback(data) to happen when ms into the future. More...
 
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. More...
 
struct ast_sched_contextast_sched_context_create (void)
 Create a scheduler context. More...
 
void ast_sched_context_destroy (struct ast_sched_context *con)
 destroys a schedule context More...
 
int ast_sched_del (struct ast_sched_context *con, int id)
 Delete the schedule entry with number "id". It's nearly impossible that there would be two or more in the list with that id. Deprecated in favor of ast_sched_del_nonrunning which checks running event status. More...
 
int ast_sched_del_nonrunning (struct ast_sched_context *con, int id)
 Delete the schedule entry with number "id". If running, wait for the task to complete, check to see if it is rescheduled then schedule the release. It's nearly impossible that there would be two or more in the list with that id. More...
 
void ast_sched_dump (struct ast_sched_context *con)
 Dump the contents of the scheduler to LOG_DEBUG. More...
 
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. More...
 
int ast_sched_replace (int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
 replace a scheduler entry More...
 
int ast_sched_replace_variable (int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
 replace a scheduler entry More...
 
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. More...
 
int ast_sched_runq (struct ast_sched_context *con)
 Launch all events which need to be run at this time. More...
 
int ast_sched_start_thread (struct ast_sched_context *con)
 Start a thread for processing scheduler entries. More...
 
int ast_sched_wait (struct ast_sched_context *con)
 Return the number of milliseconds until the next scheduled event. More...
 
long ast_sched_when (struct ast_sched_context *con, int id)
 Returns the number of seconds before an event takes place. More...
 
static struct schedsched_alloc (struct ast_sched_context *con)
 
static struct schedsched_find (struct ast_sched_context *con, int id)
 
static void sched_free (struct sched *task)
 
static void sched_release (struct ast_sched_context *con, struct sched *tmp)
 
static void * sched_run (void *data)
 
static void sched_settime (struct timeval *t, int when)
 given the last event *tv and the offset in milliseconds 'when', computes the next value, More...
 
static void sched_thread_destroy (struct ast_sched_context *con)
 
static int sched_time_cmp (void *va, void *vb)
 
static void schedule (struct ast_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. More...
 
static int set_sched_id (struct ast_sched_context *con, struct sched *new_sched)
 

Variables

static struct ast_threadstorage last_del_id = { .once = PTHREAD_ONCE_INIT , .key_init = __init_last_del_id , .custom_init = NULL , }
 

Detailed Description

Scheduler Routines (from cheops-NG)

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file sched.c.

Macro Definition Documentation

◆ DEBUG

#define DEBUG (   a)

Definition at line 36 of file sched.c.

◆ ID_QUEUE_INCREMENT

#define ID_QUEUE_INCREMENT   16

Definition at line 305 of file sched.c.

◆ SCHED_MAX_CACHE

#define SCHED_MAX_CACHE   128

Max num of schedule structs.

Note
The max number of schedule structs to keep around for use. Undefine to disable schedule structure caching. (Only disable this on very low memory machines)

Definition at line 56 of file sched.c.

Function Documentation

◆ __init_last_del_id()

static void __init_last_del_id ( void  )
static

Definition at line 58 of file sched.c.

70{

◆ add_ids()

static int add_ids ( struct ast_sched_context con)
static

Add new scheduler IDs to the queue.

Return values
Thenumber of IDs added to the queue

Definition at line 312 of file sched.c.

313{
314 int new_size;
315 int original_size;
316 int i;
317
318 original_size = con->id_queue_size;
319 /* So we don't go overboard with the mallocs here, we'll just up
320 * the size of the list by a fixed amount each time instead of
321 * multiplying the size by any particular factor
322 */
323 new_size = original_size + ID_QUEUE_INCREMENT;
324 if (new_size < 0) {
325 /* Overflow. Cap it at INT_MAX. */
326 new_size = INT_MAX;
327 }
328 for (i = original_size; i < new_size; ++i) {
329 struct sched_id *new_id;
330
331 new_id = ast_calloc(1, sizeof(*new_id));
332 if (!new_id) {
333 break;
334 }
335
336 /*
337 * According to the API doxygen a sched ID of 0 is valid.
338 * Unfortunately, 0 was never returned historically and
339 * several users incorrectly coded usage of the returned
340 * sched ID assuming that 0 was invalid.
341 */
342 new_id->id = ++con->id_queue_size;
343
344 AST_LIST_INSERT_TAIL(&con->id_queue, new_id, list);
345 }
346
347 return con->id_queue_size - original_size;
348}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ID_QUEUE_INCREMENT
Definition: sched.c:305
struct ast_sched_context::@388 id_queue
int id_queue_size
Definition: sched.c:131
Scheduler ID holder.
Definition: sched.c:70
int id
Definition: sched.c:72
struct sched_id::@385 list

References ast_calloc, AST_LIST_INSERT_TAIL, sched_id::id, ast_sched_context::id_queue, ID_QUEUE_INCREMENT, ast_sched_context::id_queue_size, and sched_id::list.

Referenced by set_sched_id().

◆ ast_sched_add()

int ast_sched_add ( struct ast_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

Parameters
conScheduler context to add
whenhow many milliseconds to wait for event to occur
callbackfunction to call when the amount of time expires
datadata to pass to the callback
Return values
-1on failure
Returns
schedule item ID

Definition at line 567 of file sched.c.

568{
569 return ast_sched_add_variable(con, when, callback, data, 0);
570}
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
Schedule callback(data) to happen when ms into the future.
Definition: sched.c:526

References ast_sched_add_variable(), sched::callback, sched::data, and sched::when.

Referenced by ast_readaudio_callback(), ast_readvideo_callback(), ast_rtp_interpret(), ast_sched_replace(), ast_sip_schedule_task(), AST_TEST_DEFINE(), build_peer(), cc_generic_agent_start_offer_timer(), cc_generic_monitor_request_cc(), dns_query_recurring_resolution_callback(), do_register(), dundi_discover(), dundi_query(), dundi_send(), handle_cli_sched_bench(), handle_command_response(), iax2_hangup(), iax2_key_rotate(), iax2_sched_add(), mbl_call(), memory_cache_stale_update_full(), memory_cache_stale_update_object(), populate_addr(), precache_trans(), qualify_peer(), rtp_instance_parse_transport_wide_cc(), rtp_raw_write(), rtp_red_init(), run_task(), schedule_cache_expiration(), schedule_notification(), and transaction_sched_timer().

◆ ast_sched_add_variable()

int ast_sched_add_variable ( struct ast_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.

Definition at line 526 of file sched.c.

527{
528 struct sched *tmp;
529 int res = -1;
530
531 DEBUG(ast_debug(1, "ast_sched_add()\n"));
532
533 ast_mutex_lock(&con->lock);
534 if ((tmp = sched_alloc(con))) {
535 con->eventcnt++;
536 tmp->callback = callback;
537 tmp->data = data;
538 tmp->resched = when;
539 tmp->variable = variable;
540 tmp->when = ast_tv(0, 0);
541 tmp->deleted = 0;
542
543 sched_settime(&tmp->when, when);
544 schedule(con, tmp);
545 res = tmp->sched_id->id;
546 }
547#ifdef DUMP_SCHEDULER
548 /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
549 ast_sched_dump(con);
550#endif
551 if (con->sched_thread) {
553 }
554 ast_mutex_unlock(&con->lock);
555
556 return res;
557}
static int tmp()
Definition: bt_open.c:389
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
#define ast_cond_signal(cond)
Definition: lock.h:203
static struct sched * sched_alloc(struct ast_sched_context *con)
Definition: sched.c:380
static void sched_settime(struct timeval *t, int when)
given the last event *tv and the offset in milliseconds 'when', computes the next value,
Definition: sched.c:490
void ast_sched_dump(struct ast_sched_context *con)
Dump the contents of the scheduler to LOG_DEBUG.
Definition: sched.c:743
#define DEBUG(a)
Definition: sched.c:36
static void schedule(struct ast_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: sched.c:460
unsigned int eventcnt
Definition: sched.c:113
struct sched_thread * sched_thread
Definition: sched.c:118
ast_mutex_t lock
Definition: sched.c:112
ast_cond_t cond
Definition: sched.c:107
Definition: sched.c:76
const void * data
Definition: sched.c:91
struct timeval when
Definition: sched.c:80
int variable
Definition: sched.c:90
ast_sched_cb callback
Definition: sched.c:92
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References ast_cond_signal, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_sched_dump(), ast_tv(), sched::callback, sched_thread::cond, sched::data, DEBUG, ast_sched_context::eventcnt, ast_sched_context::lock, sched_alloc(), sched_settime(), ast_sched_context::sched_thread, schedule(), tmp(), sched::variable, and sched::when.

Referenced by apply_negotiated_sdp_stream(), ast_sched_add(), ast_sched_replace_variable(), dnsmgr_start_refresh(), do_reload(), global_loaded(), monitored_transport_state_callback(), start_batch_mode(), and stun_start_monitor().

◆ ast_sched_clean_by_callback()

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.

Parameters
conScheduler Context
matchCallback to match
cleanup_cbCallback to run
Note
The return of cleanup_cb is ignored. No events are rescheduled.

Definition at line 409 of file sched.c.

410{
411 int i = 1;
412 struct sched *current;
413
414 ast_mutex_lock(&con->lock);
415 while ((current = ast_heap_peek(con->sched_heap, i))) {
416 if (current->callback != match) {
417 i++;
418 continue;
419 }
420
422
423 cleanup_cb(current->data);
425 }
426 ast_mutex_unlock(&con->lock);
427}
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
void * ast_heap_remove(struct ast_heap *h, void *elm)
Remove a specific element from a heap.
Definition: heap.c:251
void * ast_heap_peek(struct ast_heap *h, unsigned int index)
Peek at an element on a heap.
Definition: heap.c:267
size_t current
Definition: main/cli.c:113
static int cleanup_cb(void *obj, void *arg, int flags)
Definition: res_stasis.c:309
static void sched_release(struct ast_sched_context *con, struct sched *tmp)
Definition: sched.c:360
struct ast_heap * sched_heap
Definition: sched.c:117

References ast_heap_peek(), ast_heap_remove(), ast_mutex_lock, ast_mutex_unlock, cleanup_cb(), current, ast_sched_context::lock, match(), ast_sched_context::sched_heap, and sched_release().

Referenced by __unload_module(), ast_sip_destroy_transport_management(), and global_loaded().

◆ ast_sched_context_create()

struct ast_sched_context * ast_sched_context_create ( void  )

Create a scheduler context.

Return values
NULLon failure
Returns
a malloc'd sched_context structure

Definition at line 238 of file sched.c.

239{
240 struct ast_sched_context *tmp;
241
242 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
243 return NULL;
244 }
245
246 ast_mutex_init(&tmp->lock);
247 tmp->eventcnt = 1;
248
249 AST_LIST_HEAD_INIT_NOLOCK(&tmp->id_queue);
250
251 if (!(tmp->sched_heap = ast_heap_create(8, sched_time_cmp,
252 offsetof(struct sched, __heap_index)))) {
254 return NULL;
255 }
256
257 return tmp;
258}
#define ast_heap_create(init_height, cmp_fn, index_offset)
Create a max heap.
Definition: heap.h:100
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define NULL
Definition: resample.c:96
static int sched_time_cmp(void *va, void *vb)
Definition: sched.c:225
void ast_sched_context_destroy(struct ast_sched_context *con)
destroys a schedule context
Definition: sched.c:271

References ast_calloc, ast_heap_create, AST_LIST_HEAD_INIT_NOLOCK, ast_mutex_init, ast_sched_context_destroy(), NULL, sched_time_cmp(), and tmp().

Referenced by __ast_channel_alloc_ap(), aeap_general_initialize(), ast_sip_initialize_distributor(), ast_sip_initialize_scheduler(), ast_sip_initialize_transport_management(), AST_TEST_DEFINE(), dns_core_init(), handle_cli_sched_bench(), load_module(), mbl_load_device(), and stun_start_monitor().

◆ ast_sched_context_destroy()

void ast_sched_context_destroy ( struct ast_sched_context c)

destroys a schedule context

Parameters
cContext to free

Definition at line 271 of file sched.c.

272{
273 struct sched *s;
274 struct sched_id *sid;
275
277 con->sched_thread = NULL;
278
279 ast_mutex_lock(&con->lock);
280
281#ifdef SCHED_MAX_CACHE
282 while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list))) {
283 sched_free(s);
284 }
285#endif
286
287 if (con->sched_heap) {
288 while ((s = ast_heap_pop(con->sched_heap))) {
289 sched_free(s);
290 }
292 con->sched_heap = NULL;
293 }
294
295 while ((sid = AST_LIST_REMOVE_HEAD(&con->id_queue, list))) {
296 ast_free(sid);
297 }
298
299 ast_mutex_unlock(&con->lock);
300 ast_mutex_destroy(&con->lock);
301
302 ast_free(con);
303}
#define ast_free(a)
Definition: astmm.h:180
struct ast_heap * ast_heap_destroy(struct ast_heap *h)
Destroy a max heap.
Definition: heap.c:146
void * ast_heap_pop(struct ast_heap *h)
Pop the max element off of the heap.
Definition: heap.c:262
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_mutex_destroy(a)
Definition: lock.h:188
static void sched_free(struct sched *task)
Definition: sched.c:260
static void sched_thread_destroy(struct ast_sched_context *con)
Definition: sched.c:175
struct ast_sched_context::@387 schedc

References ast_free, ast_heap_destroy(), ast_heap_pop(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_sched_context::id_queue, sched_id::list, ast_sched_context::lock, NULL, sched_free(), ast_sched_context::sched_heap, ast_sched_context::sched_thread, sched_thread_destroy(), and ast_sched_context::schedc.

Referenced by __unload_module(), aeap_general_finalize(), ast_channel_destructor(), ast_hangup(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), ast_sip_destroy_distributor(), ast_sip_destroy_scheduler(), ast_sip_destroy_transport_management(), ast_sip_initialize_scheduler(), ast_sip_initialize_transport_management(), AST_TEST_DEFINE(), cdr_engine_shutdown(), dns_shutdown(), handle_cli_sched_bench(), load_module(), mbl_load_device(), stun_start_monitor(), stun_stop_monitor(), and unload_module().

◆ ast_sched_del()

int ast_sched_del ( struct ast_sched_context con,
int  id 
)

Delete the schedule entry with number "id". It's nearly impossible that there would be two or more in the list with that id. Deprecated in favor of ast_sched_del_nonrunning which checks running event status.

Deletes a scheduled event.

Definition at line 614 of file sched.c.

615{
616 return ast_sched_del_nonrunning(con, id) ? -1 : 0;
617}
int ast_sched_del_nonrunning(struct ast_sched_context *con, int id)
Delete the schedule entry with number "id". If running, wait for the task to complete,...
Definition: sched.c:627

References ast_sched_del_nonrunning().

Referenced by ast_rtp_prop_set(), ast_rtp_stop(), ast_sip_sched_task_cancel(), AST_TEST_DEFINE(), cc_generic_agent_stop_offer_timer(), cc_generic_monitor_cancel_available_timer(), destroy_event(), and handle_cli_sched_bench().

◆ ast_sched_del_nonrunning()

int ast_sched_del_nonrunning ( struct ast_sched_context con,
int  id 
)

Delete the schedule entry with number "id". If running, wait for the task to complete, check to see if it is rescheduled then schedule the release. It's nearly impossible that there would be two or more in the list with that id.

Deletes a scheduled event with care against the event running.

Definition at line 627 of file sched.c.

628{
629 struct sched *s = NULL;
630 int *last_id = ast_threadstorage_get(&last_del_id, sizeof(int));
631 int res = 0;
632
633 DEBUG(ast_debug(1, "ast_sched_del(%d)\n", id));
634
635 if (id < 0) {
636 return 0;
637 }
638
639 ast_mutex_lock(&con->lock);
640
641 s = sched_find(con, id);
642 if (s) {
643 if (!ast_heap_remove(con->sched_heap, s)) {
644 ast_log(LOG_WARNING,"sched entry %d not in the sched heap?\n", s->sched_id->id);
645 }
646 sched_release(con, s);
647 } else if (con->currently_executing && (id == con->currently_executing->sched_id->id)) {
648 if (con->executing_thread_id == pthread_self()) {
649 /* The scheduled callback is trying to delete itself.
650 * Not good as that is a deadlock. */
652 "BUG! Trying to delete sched %d from within the callback %p. "
653 "Ignoring so we don't deadlock\n",
654 id, con->currently_executing->callback);
656 /* We'll return -1 below because s is NULL.
657 * The caller will rightly assume that the unscheduling failed. */
658 } else {
659 s = con->currently_executing;
660 s->deleted = 1;
661 /* Wait for executing task to complete so that the caller of
662 * ast_sched_del() does not free memory out from under the task. */
663 while (con->currently_executing && (id == con->currently_executing->sched_id->id)) {
664 ast_cond_wait(&s->cond, &con->lock);
665 }
666 /* This is not rescheduled so the caller of ast_sched_del_nonrunning needs to know
667 * that it was still deleted
668 */
669 if (!s->rescheduled) {
670 res = -2;
671 }
672 /* ast_sched_runq knows we are waiting on this item and is passing responsibility for
673 * its destruction to us
674 */
675 sched_release(con, s);
676 s = NULL;
677 }
678 }
679
680#ifdef DUMP_SCHEDULER
681 /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
682 ast_sched_dump(con);
683#endif
684 if (con->sched_thread) {
686 }
687 ast_mutex_unlock(&con->lock);
688
689 if(res == -2){
690 return res;
691 }
692 else if (!s && *last_id != id) {
693 ast_debug(1, "Attempted to delete nonexistent schedule entry %d!\n", id);
694 /* Removing nonexistent schedule entry shouldn't trigger assert (it was enabled in DEV_MODE);
695 * because in many places entries is deleted without having valid id. */
696 *last_id = id;
697 return -1;
698 } else if (!s) {
699 return -1;
700 }
701
702 return res;
703}
enum queue_result id
Definition: app_queue.c:1667
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define LOG_WARNING
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
Definition: logger.c:2510
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
static struct ast_threadstorage last_del_id
Definition: sched.c:58
static struct sched * sched_find(struct ast_sched_context *con, int id)
Definition: sched.c:572
pthread_t executing_thread_id
Definition: sched.c:122
struct sched * currently_executing
Definition: sched.c:120
ast_cond_t cond
Definition: sched.c:98
unsigned int rescheduled
Definition: sched.c:102
struct sched_id * sched_id
Definition: sched.c:79
unsigned int deleted
Definition: sched.c:100
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

References ast_cond_signal, ast_cond_wait, ast_debug, ast_heap_remove(), ast_log, ast_log_backtrace(), ast_mutex_lock, ast_mutex_unlock, ast_sched_dump(), ast_threadstorage_get(), sched::callback, sched::cond, sched_thread::cond, ast_sched_context::currently_executing, DEBUG, sched::deleted, ast_sched_context::executing_thread_id, id, sched_id::id, last_del_id, ast_sched_context::lock, LOG_ERROR, LOG_WARNING, NULL, sched::rescheduled, sched_find(), ast_sched_context::sched_heap, sched::sched_id, sched_release(), and ast_sched_context::sched_thread.

Referenced by ast_sched_del().

◆ ast_sched_dump()

void ast_sched_dump ( struct ast_sched_context con)

Dump the contents of the scheduler to LOG_DEBUG.

Dumps the scheduler contents.

Definition at line 743 of file sched.c.

744{
745 struct sched *q;
746 struct timeval when;
747 int x;
748 size_t heap_size;
749
750 if (!DEBUG_ATLEAST(1)) {
751 return;
752 }
753
754 when = ast_tvnow();
755#ifdef SCHED_MAX_CACHE
756 ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%zu in Q, %u Total, %u Cache, %u high-water)\n",
757 ast_heap_size(con->sched_heap), con->eventcnt - 1, con->schedccnt, con->highwater);
758#else
759 ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%zu in Q, %u Total, %u high-water)\n",
760 ast_heap_size(con->sched_heap), con->eventcnt - 1, con->highwater);
761#endif
762
763 ast_log(LOG_DEBUG, "=============================================================\n");
764 ast_log(LOG_DEBUG, "|ID Callback Data Time (sec:ms) |\n");
765 ast_log(LOG_DEBUG, "+-----+-----------------+-----------------+-----------------+\n");
766 ast_mutex_lock(&con->lock);
767 heap_size = ast_heap_size(con->sched_heap);
768 for (x = 1; x <= heap_size; x++) {
769 struct timeval delta;
770 q = ast_heap_peek(con->sched_heap, x);
771 delta = ast_tvsub(q->when, when);
772 ast_log(LOG_DEBUG, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
773 q->sched_id->id,
774 q->callback,
775 q->data,
776 (long)delta.tv_sec,
777 (long int)delta.tv_usec);
778 }
779 ast_mutex_unlock(&con->lock);
780 ast_log(LOG_DEBUG, "=============================================================\n");
781}
size_t ast_heap_size(struct ast_heap *h)
Get the current size of a heap.
Definition: heap.c:276
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
unsigned int schedccnt
Definition: sched.c:126
unsigned int highwater
Definition: sched.c:114
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_heap_peek(), ast_heap_size(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), ast_tvsub(), DEBUG_ATLEAST, ast_sched_context::eventcnt, ast_sched_context::highwater, ast_sched_context::lock, LOG_DEBUG, ast_sched_context::sched_heap, and ast_sched_context::schedccnt.

Referenced by ast_sched_add_variable(), ast_sched_del_nonrunning(), and handle_dump_sched().

◆ ast_sched_find_data()

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.

Parameters
conscheduling context in which to search fro the matching id
idID of the scheduled item to find
Return values
NULLif not found
Returns
the data field from the matching sched struct if found.
Since
1.6.1

Definition at line 589 of file sched.c.

590{
591 struct sched *s;
592 const void *data = NULL;
593
594 ast_mutex_lock(&con->lock);
595
596 s = sched_find(con, id);
597 if (s) {
598 data = s->data;
599 }
600
601 ast_mutex_unlock(&con->lock);
602
603 return data;
604}

References ast_mutex_lock, ast_mutex_unlock, sched::data, ast_sched_context::lock, NULL, and sched_find().

◆ ast_sched_replace()

int ast_sched_replace ( int  old_id,
struct ast_sched_context con,
int  when,
ast_sched_cb  callback,
const void *  data 
)

replace a scheduler entry

Deprecated:
You should use the AST_SCHED_REPLACE() macro instead.

This deletes the scheduler entry for old_id if it exists, and then calls ast_sched_add to create a new entry. A negative old_id will be ignored.

Return values
-1on failure
Returns
scheduled item ID

Definition at line 559 of file sched.c.

560{
561 if (old_id > -1) {
562 AST_SCHED_DEL(con, old_id);
563 }
564 return ast_sched_add(con, when, callback, data);
565}
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
Adds a scheduled event.
Definition: sched.c:567
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46

References ast_sched_add(), AST_SCHED_DEL, sched::callback, sched::data, and sched::when.

Referenced by iax2_sched_replace().

◆ ast_sched_replace_variable()

int ast_sched_replace_variable ( int  old_id,
struct ast_sched_context con,
int  when,
ast_sched_cb  callback,
const void *  data,
int  variable 
)

replace a scheduler entry

Deprecated:
You should use the AST_SCHED_REPLACE_VARIABLE() macro instead.

This deletes the scheduler entry for old_id if it exists, and then calls ast_sched_add to create a new entry. A negative old_id will be ignored.

Return values
-1on failure
Returns
scheduled item ID

Definition at line 514 of file sched.c.

515{
516 /* 0 means the schedule item is new; do not delete */
517 if (old_id > 0) {
518 AST_SCHED_DEL(con, old_id);
519 }
520 return ast_sched_add_variable(con, when, callback, data, variable);
521}

References ast_sched_add_variable(), and AST_SCHED_DEL.

◆ ast_sched_report()

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.

Parameters
conSchedule context to check
bufdynamic string to store report
cbnamesto check against
Since
1.6.1

Definition at line 705 of file sched.c.

706{
707 int i, x;
708 struct sched *cur;
709 int countlist[cbnames->numassocs + 1];
710 size_t heap_size;
711
712 memset(countlist, 0, sizeof(countlist));
713 ast_str_set(buf, 0, " Highwater = %u\n schedcnt = %zu\n", con->highwater, ast_heap_size(con->sched_heap));
714
715 ast_mutex_lock(&con->lock);
716
717 heap_size = ast_heap_size(con->sched_heap);
718 for (x = 1; x <= heap_size; x++) {
719 cur = ast_heap_peek(con->sched_heap, x);
720 /* match the callback to the cblist */
721 for (i = 0; i < cbnames->numassocs; i++) {
722 if (cur->callback == cbnames->cblist[i]) {
723 break;
724 }
725 }
726 if (i < cbnames->numassocs) {
727 countlist[i]++;
728 } else {
729 countlist[cbnames->numassocs]++;
730 }
731 }
732
733 ast_mutex_unlock(&con->lock);
734
735 for (i = 0; i < cbnames->numassocs; i++) {
736 ast_str_append(buf, 0, " %s : %d\n", cbnames->list[i], countlist[i]);
737 }
738
739 ast_str_append(buf, 0, " <unknown> : %d\n", countlist[cbnames->numassocs]);
740}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
char * list[10]
Definition: sched.h:194
int numassocs
Definition: sched.h:193
ast_sched_cb cblist[10]
Definition: sched.h:195

References ast_heap_peek(), ast_heap_size(), ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_set(), buf, sched::callback, ast_cb_names::cblist, ast_sched_context::highwater, ast_cb_names::list, ast_sched_context::lock, ast_cb_names::numassocs, and ast_sched_context::sched_heap.

◆ ast_sched_runq()

int ast_sched_runq ( struct ast_sched_context con)

Launch all events which need to be run at this time.

Runs the queue.

Definition at line 786 of file sched.c.

787{
788 struct sched *current;
789 struct timeval when;
790 int numevents;
791 int res;
792
793 DEBUG(ast_debug(1, "ast_sched_runq()\n"));
794
795 ast_mutex_lock(&con->lock);
796
797 when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
798 for (numevents = 0; (current = ast_heap_peek(con->sched_heap, 1)); numevents++) {
799 /* schedule all events which are going to expire within 1ms.
800 * We only care about millisecond accuracy anyway, so this will
801 * help us get more than one event at one time if they are very
802 * close together.
803 */
804 if (ast_tvcmp(current->when, when) != -1) {
805 break;
806 }
807
809
810 /*
811 * At this point, the schedule queue is still intact. We
812 * have removed the first event and the rest is still there,
813 * so it's permissible for the callback to add new events, but
814 * trying to delete itself won't work because it isn't in
815 * the schedule queue. If that's what it wants to do, it
816 * should return 0.
817 */
818
820 con->executing_thread_id = pthread_self();
821 ast_mutex_unlock(&con->lock);
822 res = current->callback(current->data);
823 ast_mutex_lock(&con->lock);
825 ast_cond_signal(&current->cond);
826
827 if (current->deleted) {
828 /*
829 * Another thread is waiting on this scheduled item. That thread
830 * will be responsible for it's destruction
831 */
832 current->rescheduled = res ? 1 : 0;
833 } else if (res) {
834 /*
835 * If they return non-zero, we should schedule them to be
836 * run again.
837 */
838 sched_settime(&current->when, current->variable ? res : current->resched);
839 schedule(con, current);
840 } else {
841 /* No longer needed, so release it */
843 }
844 }
845
846 ast_mutex_unlock(&con->lock);
847
848 return numevents;
849}
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282

References ast_cond_signal, ast_debug, ast_heap_peek(), ast_heap_pop(), ast_mutex_lock, ast_mutex_unlock, ast_tv(), ast_tvadd(), ast_tvcmp(), ast_tvnow(), current, ast_sched_context::currently_executing, DEBUG, ast_sched_context::executing_thread_id, ast_sched_context::lock, NULL, ast_sched_context::sched_heap, sched_release(), sched_settime(), and schedule().

Referenced by AST_TEST_DEFINE(), background_detect_exec(), dial_exec_full(), do_cdr(), do_monitor(), do_monitor_headset(), do_refresh(), handle_speechrecognize(), network_thread(), sched_run(), speech_background(), wait_for_winner(), and waitstream_core().

◆ ast_sched_start_thread()

int ast_sched_start_thread ( struct ast_sched_context con)

Start a thread for processing scheduler entries.

Parameters
conthe scheduler context this thread will manage
Return values
0success
non-zerofailure

Definition at line 197 of file sched.c.

198{
199 struct sched_thread *st;
200
201 if (con->sched_thread) {
202 ast_log(LOG_ERROR, "Thread already started on this scheduler context\n");
203 return -1;
204 }
205
206 if (!(st = ast_calloc(1, sizeof(*st)))) {
207 return -1;
208 }
209
210 ast_cond_init(&st->cond, NULL);
211
213
214 con->sched_thread = st;
215
217 ast_log(LOG_ERROR, "Failed to create scheduler thread\n");
219 return -1;
220 }
221
222 return 0;
223}
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
static void * sched_run(void *data)
Definition: sched.c:134
pthread_t thread
Definition: sched.c:106
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

References ast_calloc, ast_cond_init, ast_log, ast_pthread_create_background, AST_PTHREADT_NULL, sched_thread::cond, LOG_ERROR, NULL, sched_run(), ast_sched_context::sched_thread, sched_thread_destroy(), and sched_thread::thread.

Referenced by aeap_general_initialize(), ast_sip_initialize_distributor(), ast_sip_initialize_scheduler(), ast_sip_initialize_transport_management(), AST_TEST_DEFINE(), dns_core_init(), load_module(), and stun_start_monitor().

◆ ast_sched_wait()

int ast_sched_wait ( struct ast_sched_context con)

Return the number of milliseconds until the next scheduled event.

Determines number of seconds until the next outstanding event to take place.

Definition at line 433 of file sched.c.

434{
435 int ms;
436 struct sched *s;
437
438 DEBUG(ast_debug(1, "ast_sched_wait()\n"));
439
440 ast_mutex_lock(&con->lock);
441 if ((s = ast_heap_peek(con->sched_heap, 1))) {
442 ms = ast_tvdiff_ms(s->when, ast_tvnow());
443 if (ms < 0) {
444 ms = 0;
445 }
446 } else {
447 ms = -1;
448 }
449 ast_mutex_unlock(&con->lock);
450
451 return ms;
452}
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107

References ast_debug, ast_heap_peek(), ast_mutex_lock, ast_mutex_unlock, ast_tvdiff_ms(), ast_tvnow(), DEBUG, ast_sched_context::lock, ast_sched_context::sched_heap, and sched::when.

Referenced by AST_TEST_DEFINE(), background_detect_exec(), dial_exec_full(), do_cdr(), do_monitor(), do_monitor_headset(), do_refresh(), handle_speechrecognize(), network_thread(), sched_run(), speech_background(), wait_for_winner(), and waitstream_core().

◆ ast_sched_when()

long ast_sched_when ( struct ast_sched_context con,
int  id 
)

Returns the number of seconds before an event takes place.

Parameters
conContext to use
idId to dump

Definition at line 851 of file sched.c.

852{
853 struct sched *s;
854 long secs = -1;
855 DEBUG(ast_debug(1, "ast_sched_when()\n"));
856
857 ast_mutex_lock(&con->lock);
858
859 s = sched_find(con, id);
860 if (s) {
861 struct timeval now = ast_tvnow();
862 secs = s->when.tv_sec - now.tv_sec;
863 }
864
865 ast_mutex_unlock(&con->lock);
866
867 return secs;
868}

References ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), DEBUG, ast_sched_context::lock, sched_find(), and sched::when.

Referenced by handle_cli_status().

◆ sched_alloc()

static struct sched * sched_alloc ( struct ast_sched_context con)
static

Definition at line 380 of file sched.c.

381{
382 struct sched *tmp;
383
384 /*
385 * We keep a small cache of schedule entries
386 * to minimize the number of necessary malloc()'s
387 */
388#ifdef SCHED_MAX_CACHE
389 if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list))) {
390 con->schedccnt--;
391 } else
392#endif
393 {
394 tmp = ast_calloc(1, sizeof(*tmp));
395 if (!tmp) {
396 return NULL;
397 }
398 ast_cond_init(&tmp->cond, NULL);
399 }
400
401 if (set_sched_id(con, tmp)) {
402 sched_release(con, tmp);
403 return NULL;
404 }
405
406 return tmp;
407}
static int set_sched_id(struct ast_sched_context *con, struct sched *new_sched)
Definition: sched.c:350
struct sched::@386 list

References ast_calloc, ast_cond_init, AST_LIST_REMOVE_HEAD, sched::list, NULL, sched_release(), ast_sched_context::schedc, ast_sched_context::schedccnt, set_sched_id(), and tmp().

Referenced by ast_sched_add_variable().

◆ sched_find()

static struct sched * sched_find ( struct ast_sched_context con,
int  id 
)
static

Definition at line 572 of file sched.c.

573{
574 int x;
575 size_t heap_size;
576
577 heap_size = ast_heap_size(con->sched_heap);
578 for (x = 1; x <= heap_size; x++) {
579 struct sched *cur = ast_heap_peek(con->sched_heap, x);
580
581 if (cur->sched_id->id == id) {
582 return cur;
583 }
584 }
585
586 return NULL;
587}

References ast_heap_peek(), ast_heap_size(), sched_id::id, NULL, ast_sched_context::sched_heap, and sched::sched_id.

Referenced by ast_sched_del_nonrunning(), ast_sched_find_data(), and ast_sched_when().

◆ sched_free()

static void sched_free ( struct sched task)
static

Definition at line 260 of file sched.c.

261{
262 /* task->sched_id will be NULL most of the time, but when the
263 * scheduler context shuts down, it will free all scheduled
264 * tasks, and in that case, the task->sched_id will be non-NULL
265 */
266 ast_free(task->sched_id);
267 ast_cond_destroy(&task->cond);
268 ast_free(task);
269}
#define ast_cond_destroy(cond)
Definition: lock.h:202
static int task(void *data)
Queued task for baseline test.

References ast_cond_destroy, ast_free, and task().

Referenced by ast_sched_context_destroy(), and sched_release().

◆ sched_release()

static void sched_release ( struct ast_sched_context con,
struct sched tmp 
)
static

Definition at line 360 of file sched.c.

361{
362 if (tmp->sched_id) {
363 AST_LIST_INSERT_TAIL(&con->id_queue, tmp->sched_id, list);
364 tmp->sched_id = NULL;
365 }
366
367 /*
368 * Add to the cache, or just free() if we
369 * already have too many cache entries
370 */
371#ifdef SCHED_MAX_CACHE
372 if (con->schedccnt < SCHED_MAX_CACHE) {
373 AST_LIST_INSERT_HEAD(&con->schedc, tmp, list);
374 con->schedccnt++;
375 } else
376#endif
378}
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define SCHED_MAX_CACHE
Max num of schedule structs.
Definition: sched.c:56

References AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_sched_context::id_queue, sched_id::list, NULL, sched_free(), SCHED_MAX_CACHE, ast_sched_context::schedc, ast_sched_context::schedccnt, and tmp().

Referenced by ast_sched_clean_by_callback(), ast_sched_del_nonrunning(), ast_sched_runq(), and sched_alloc().

◆ sched_run()

static void * sched_run ( void *  data)
static

Definition at line 134 of file sched.c.

135{
136 struct ast_sched_context *con = data;
137
138 while (!con->sched_thread->stop) {
139 int ms;
140 struct timespec ts = {
141 .tv_sec = 0,
142 };
143
144 ast_mutex_lock(&con->lock);
145
146 if (con->sched_thread->stop) {
147 ast_mutex_unlock(&con->lock);
148 return NULL;
149 }
150
151 ms = ast_sched_wait(con);
152
153 if (ms == -1) {
154 ast_cond_wait(&con->sched_thread->cond, &con->lock);
155 } else {
156 struct timeval tv;
157 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(ms, 1000));
158 ts.tv_sec = tv.tv_sec;
159 ts.tv_nsec = tv.tv_usec * 1000;
160 ast_cond_timedwait(&con->sched_thread->cond, &con->lock, &ts);
161 }
162
163 ast_mutex_unlock(&con->lock);
164
165 if (con->sched_thread->stop) {
166 return NULL;
167 }
168
169 ast_sched_runq(con);
170 }
171
172 return NULL;
173}
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
int ast_sched_runq(struct ast_sched_context *con)
Launch all events which need to be run at this time.
Definition: sched.c:786
int ast_sched_wait(struct ast_sched_context *con)
Return the number of milliseconds until the next scheduled event.
Definition: sched.c:433
unsigned int stop
Definition: sched.c:108
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282

References ast_cond_timedwait, ast_cond_wait, ast_mutex_lock, ast_mutex_unlock, ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), sched_thread::cond, ast_sched_context::lock, NULL, ast_sched_context::sched_thread, and sched_thread::stop.

Referenced by ast_sched_start_thread().

◆ sched_settime()

static void sched_settime ( struct timeval *  t,
int  when 
)
static

given the last event *tv and the offset in milliseconds 'when', computes the next value,

Definition at line 490 of file sched.c.

491{
492 struct timeval now = ast_tvnow();
493
494 if (when < 0) {
495 /*
496 * A negative when value is likely a bug as it
497 * represents a VERY large timeout time.
498 */
500 "Bug likely: Negative time interval %d (interpreted as %u ms) requested!\n",
501 when, (unsigned int) when);
502 ast_assert(0);
503 }
504
505 /*ast_debug(1, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/
506 if (ast_tvzero(*t)) /* not supplied, default to now */
507 *t = now;
508 *t = ast_tvadd(*t, ast_samp2tv(when, 1000));
509 if (ast_tvcmp(*t, now) < 0) {
510 *t = now;
511 }
512}
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_log, ast_samp2tv(), ast_tvadd(), ast_tvcmp(), ast_tvnow(), ast_tvzero(), and LOG_WARNING.

Referenced by ast_sched_add_variable(), and ast_sched_runq().

◆ sched_thread_destroy()

static void sched_thread_destroy ( struct ast_sched_context con)
static

◆ sched_time_cmp()

static int sched_time_cmp ( void *  va,
void *  vb 
)
static

Definition at line 225 of file sched.c.

226{
227 struct sched *a = va;
228 struct sched *b = vb;
229 int cmp;
230
231 cmp = ast_tvcmp(b->when, a->when);
232 if (!cmp) {
233 cmp = b->tie_breaker - a->tie_breaker;
234 }
235 return cmp;
236}
static struct test_val b
static struct test_val a

References a, ast_tvcmp(), and b.

Referenced by ast_sched_context_create().

◆ schedule()

static void schedule ( struct ast_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 460 of file sched.c.

461{
462 size_t size;
463
464 size = ast_heap_size(con->sched_heap);
465
466 /* Record the largest the scheduler heap became for reporting purposes. */
467 if (con->highwater <= size) {
468 con->highwater = size + 1;
469 }
470
471 /* Determine the tie breaker value for the new entry. */
472 if (size) {
473 ++con->tie_breaker;
474 } else {
475 /*
476 * Restart the sequence for the first entry to make integer
477 * roll over more unlikely.
478 */
479 con->tie_breaker = 0;
480 }
481 s->tie_breaker = con->tie_breaker;
482
483 ast_heap_push(con->sched_heap, s);
484}
#define ast_heap_push(h, elm)
Push an element on to a heap.
Definition: heap.h:125
unsigned int tie_breaker
Definition: sched.c:116
unsigned int tie_breaker
Tie breaker in case the when is the same for multiple entries.
Definition: sched.c:88

References ast_heap_push, ast_heap_size(), ast_sched_context::highwater, ast_sched_context::sched_heap, sched::tie_breaker, and ast_sched_context::tie_breaker.

Referenced by ast_sched_add_variable(), and ast_sched_runq().

◆ set_sched_id()

static int set_sched_id ( struct ast_sched_context con,
struct sched new_sched 
)
static

Definition at line 350 of file sched.c.

351{
352 if (AST_LIST_EMPTY(&con->id_queue) && (add_ids(con) == 0)) {
353 return -1;
354 }
355
356 new_sched->sched_id = AST_LIST_REMOVE_HEAD(&con->id_queue, list);
357 return 0;
358}
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
static int add_ids(struct ast_sched_context *con)
Add new scheduler IDs to the queue.
Definition: sched.c:312

References add_ids(), AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_sched_context::id_queue, sched_id::list, and sched::sched_id.

Referenced by sched_alloc().

Variable Documentation

◆ last_del_id

struct ast_threadstorage last_del_id = { .once = PTHREAD_ONCE_INIT , .key_init = __init_last_del_id , .custom_init = NULL , }
static

Definition at line 58 of file sched.c.

Referenced by ast_sched_del_nonrunning().