33 #ifdef DEBUG_SCHEDULER
56 #define SCHED_MAX_CACHE 128
100 unsigned int deleted:1;
102 unsigned int rescheduled:1;
124 #ifdef SCHED_MAX_CACHE
126 unsigned int schedccnt;
134 static
void *sched_run(
void *
data)
138 while (!con->sched_thread->stop) {
140 struct timespec ts = {
144 ast_mutex_lock(&con->lock);
146 if (con->sched_thread->stop) {
147 ast_mutex_unlock(&con->lock);
154 ast_cond_wait(&con->sched_thread->cond, &con->lock);
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);
163 ast_mutex_unlock(&con->lock);
165 if (con->sched_thread->stop) {
177 if (!con->sched_thread) {
181 if (con->sched_thread->thread != AST_PTHREADT_NULL) {
182 ast_mutex_lock(&con->lock);
183 con->sched_thread->stop = 1;
184 ast_cond_signal(&con->sched_thread->cond);
185 ast_mutex_unlock(&con->lock);
186 pthread_join(con->sched_thread->thread, NULL);
187 con->sched_thread->thread = AST_PTHREADT_NULL;
190 ast_cond_destroy(&con->sched_thread->cond);
192 ast_free(con->sched_thread);
194 con->sched_thread = NULL;
199 struct sched_thread *st;
201 if (con->sched_thread) {
202 ast_log(LOG_ERROR,
"Thread already started on this scheduler context\n");
210 ast_cond_init(&st->cond, NULL);
212 st->thread = AST_PTHREADT_NULL;
214 con->sched_thread = st;
216 if (ast_pthread_create_background(&st->thread, NULL, sched_run, con)) {
217 ast_log(LOG_ERROR,
"Failed to create scheduler thread\n");
218 sched_thread_destroy(con);
225 static int sched_time_cmp(
void *va,
void *vb)
227 struct sched *a = va;
228 struct sched *b = vb;
246 ast_mutex_init(&tmp->lock);
252 offsetof(
struct sched, __heap_index)))) {
260 static void sched_free(
struct sched *
task)
267 ast_cond_destroy(&task->
cond);
276 sched_thread_destroy(con);
277 con->sched_thread = NULL;
279 ast_mutex_lock(&con->lock);
281 #ifdef SCHED_MAX_CACHE
287 if (con->sched_heap) {
292 con->sched_heap = NULL;
299 ast_mutex_unlock(&con->lock);
300 ast_mutex_destroy(&con->lock);
305 #define ID_QUEUE_INCREMENT 16
323 new_size = original_size + ID_QUEUE_INCREMENT;
328 for (i = original_size; i < new_size; ++i) {
371 #ifdef SCHED_MAX_CACHE
388 #ifdef SCHED_MAX_CACHE
398 ast_cond_init(&tmp->
cond, NULL);
401 if (set_sched_id(con, tmp)) {
402 sched_release(con, tmp);
412 struct sched *current;
414 ast_mutex_lock(&con->lock);
423 cleanup_cb(current->
data);
424 sched_release(con, current);
426 ast_mutex_unlock(&con->lock);
438 DEBUG(
ast_debug(1,
"ast_sched_wait()\n"));
440 ast_mutex_lock(&con->lock);
449 ast_mutex_unlock(&con->lock);
500 "Bug likely: Negative time interval %d (interpreted as %u ms) requested!\n",
501 when, (
unsigned int) when);
531 DEBUG(
ast_debug(1,
"ast_sched_add()\n"));
533 ast_mutex_lock(&con->lock);
534 if ((tmp = sched_alloc(con))) {
547 #ifdef DUMP_SCHEDULER
551 if (con->sched_thread) {
552 ast_cond_signal(&con->sched_thread->cond);
554 ast_mutex_unlock(&con->lock);
578 for (x = 1; x <= heap_size; x++) {
592 const void *
data = NULL;
594 ast_mutex_lock(&con->lock);
596 s = sched_find(con,
id);
601 ast_mutex_unlock(&con->lock);
629 struct sched *s = NULL;
633 DEBUG(
ast_debug(1,
"ast_sched_del(%d)\n",
id));
639 ast_mutex_lock(&con->lock);
641 s = sched_find(con,
id);
644 ast_log(LOG_WARNING,
"sched entry %d not in the sched heap?\n", s->
sched_id->
id);
646 sched_release(con, s);
652 "BUG! Trying to delete sched %d from within the callback %p. "
653 "Ignoring so we don't deadlock\n",
664 ast_cond_wait(&s->
cond, &con->lock);
675 sched_release(con, s);
680 #ifdef DUMP_SCHEDULER
684 if (con->sched_thread) {
685 ast_cond_signal(&con->sched_thread->cond);
687 ast_mutex_unlock(&con->lock);
692 else if (!s && *last_id !=
id) {
693 ast_debug(1,
"Attempted to delete nonexistent schedule entry %d!\n",
id);
709 int countlist[cbnames->numassocs + 1];
712 memset(countlist, 0,
sizeof(countlist));
715 ast_mutex_lock(&con->lock);
718 for (x = 1; x <= heap_size; x++) {
721 for (i = 0; i < cbnames->numassocs; i++) {
722 if (cur->
callback == cbnames->cblist[i]) {
726 if (i < cbnames->numassocs) {
729 countlist[cbnames->numassocs]++;
733 ast_mutex_unlock(&con->lock);
735 for (i = 0; i < cbnames->numassocs; i++) {
736 ast_str_append(buf, 0,
" %s : %d\n", cbnames->list[i], countlist[i]);
739 ast_str_append(buf, 0,
" <unknown> : %d\n", countlist[cbnames->numassocs]);
750 if (!DEBUG_ATLEAST(1)) {
755 #ifdef SCHED_MAX_CACHE
756 ast_log(LOG_DEBUG,
"Asterisk Schedule Dump (%zu in Q, %u Total, %u Cache, %u high-water)\n",
759 ast_log(LOG_DEBUG,
"Asterisk Schedule Dump (%zu in Q, %u Total, %u high-water)\n",
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);
768 for (x = 1; x <= heap_size; x++) {
769 struct timeval delta;
772 ast_log(LOG_DEBUG,
"|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
777 (
long int)delta.tv_usec);
779 ast_mutex_unlock(&con->lock);
780 ast_log(LOG_DEBUG,
"=============================================================\n");
788 struct sched *current;
793 DEBUG(
ast_debug(1,
"ast_sched_runq()\n"));
795 ast_mutex_lock(&con->lock);
798 for (numevents = 0; (current =
ast_heap_peek(con->sched_heap, 1)); numevents++) {
821 ast_mutex_unlock(&con->lock);
823 ast_mutex_lock(&con->lock);
825 ast_cond_signal(¤t->
cond);
842 sched_release(con, current);
846 ast_mutex_unlock(&con->lock);
855 DEBUG(
ast_debug(1,
"ast_sched_when()\n"));
857 ast_mutex_lock(&con->lock);
859 s = sched_find(con,
id);
862 secs = s->
when.tv_sec - now.tv_sec;
865 ast_mutex_unlock(&con->lock);
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
struct sched_id * sched_id
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
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.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
static void sched_settime(struct timeval *t, int when)
given the last event *tv and the offset in milliseconds 'when', computes the next value...
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.
static int add_ids(struct ast_sched_context *con)
Add new scheduler IDs to the queue.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
Adds a scheduled event.
struct ast_heap * ast_heap_destroy(struct ast_heap *h)
Destroy a max heap.
void ast_sched_context_destroy(struct ast_sched_context *con)
destroys a schedule context
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
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.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
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
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definitions to aid in the use of thread local storage.
void * ast_heap_pop(struct ast_heap *h)
Pop the max element off of the heap.
#define SCHED_MAX_CACHE
Max num of schedule structs.
struct ast_sched_context::@394 id_queue
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.
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
static int task(void *data)
Queued task for baseline test.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
pthread_t executing_thread_id
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
#define ast_heap_push(h, elm)
Push an element on to a heap.
General Asterisk PBX channel definitions.
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...
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Scheduler Routines (derived from cheops)
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 ...
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_sched_runq(struct ast_sched_context *con)
Launch all events which need to be run at this time.
int ast_sched_wait(struct ast_sched_context *con)
Return the number of milliseconds until the next scheduled event.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Support for dynamic strings.
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
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...
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
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
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define ast_calloc(num, len)
A wrapper for calloc()
void ast_sched_dump(struct ast_sched_context *con)
Dump the contents of the scheduler to LOG_DEBUG.
int(* ast_sched_cb)(const void *data)
scheduler callback
struct sched * currently_executing
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.
#define ast_heap_create(init_height, cmp_fn, index_offset)
Create a max heap.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
void * ast_heap_remove(struct ast_heap *h, void *elm)
Remove a specific element from a heap.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
size_t ast_heap_size(struct ast_heap *h)
Get the current size of a heap.
void * ast_heap_peek(struct ast_heap *h, unsigned int index)
Peek at an element on a heap.
struct ast_sched_context::@393 schedc
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
unsigned int tie_breaker
Tie breaker in case the when is the same for multiple entries.
Structure for mutex and tracking information.