Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:18 2009

## Asterisk developer's documentation

# sched.c File Reference

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

`#include <stdio.h>`
`#include <stdlib.h>`
`#include <sys/time.h>`
`#include <unistd.h>`
`#include <string.h>`
`#include "asterisk.h"`
`#include "asterisk/sched.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/utils.h"`

Include dependency graph for sched.c:

Go to the source code of this file.

## Data Structures

struct | sched
struct | sched_context

## Defines

#define | DEBUG(a)
#define | SOONER(a, b)

## Functions

int | ast_sched_add (struct sched_context *con, int when, ast_sched_cb callback, void *data)
int | ast_sched_add_variable (struct sched_context *con, int when, ast_sched_cb callback, void *data, int variable)
int | ast_sched_del (struct sched_context *con, int id)
void | ast_sched_dump (const struct sched_context *con)
int | ast_sched_runq (struct sched_context *con)
int | ast_sched_wait (struct sched_context *con)
long | ast_sched_when (struct sched_context *con, int id)
static struct sched * | sched_alloc (struct sched_context *con)
struct sched_context * | sched_context_create (void)
void | sched_context_destroy (struct sched_context *con)
static void | sched_release (struct sched_context *con, struct sched *tmp)
static int | sched_settime (struct timeval *tv, int when)
static void | schedule (struct sched_context *con, struct sched *s)

## Detailed Description

Scheduler Routines (from cheops-NG).

Definition in file sched.c.

## Define Documentation

#define DEBUG | ( | a |  | ) |

Definition at line 28 of file sched.c.

#define SOONER | ( | a,
|  | b |  | ) |

Value:

    (((b).tv_sec > (a).tv_sec) || \
                    (((b).tv_sec == (a).tv_sec) && ((b).tv_usec > (a).tv_usec)))

Definition at line 48 of file sched.c.

Referenced by ast_sched_runq(), and schedule().

## Function Documentation

int ast_sched_add | ( | struct sched_context * | con,
|  | int | when,
|  | ast_sched_cb | callback,
|  | void * | data |
| ) |  |  |

Adds a scheduled event

Parameters:

  | 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 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 Returns a schedule item ID on success, -1 on failure

Definition at line 260 of file sched.c.

References ast_sched_add_variable().

Referenced by ast_readaudio_callback(), ast_readvideo_callback(), attempt_transmit(), auth_fail(), build_peer(), do_register(), do_reload(), dundi_discover(), dundi_query(), dundi_send(), find_callno(), handle_command_response(), handle_response_peerpoke(), handle_response_register(), iax2_ack_registry(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_provision(), make_trunk(), mgcp_postrequest(), network_thread(), parse_register_contact(), populate_addr(), precache_trans(), qualify_peer(), realtime_peer(), reg_source_db(), sched_delay_remove(), schedule_delivery(), sip_call(), sip_poke_noanswer(), sip_poke_peer(), sip_scheddestroy(), sip_send_all_registers(), socket_read(), submit_scheduled_batch(), submit_unscheduled_batch(), transmit_register(), update_jbsched(), and update_registry().

    00261 {
    00262    return ast_sched_add_variable(con, when, callback, data, 0);
    00263 }

int ast_sched_add_variable | ( | struct sched_context * | con,
|  | int | when,
|  | ast_sched_cb | callback,
|  | void * | data,
|  | int | variable |
| ) |  |  |

Adds a scheduled event

Parameters:

  | 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 Returns a schedule item ID on success, -1 on failure

Definition at line 225 of file sched.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_dump(), sched::callback, sched::data, DEBUG, sched_context::eventcnt, sched::id, sched_context::lock, LOG_DEBUG, LOG_NOTICE, sched::resched, sched_alloc(), sched_release(), sched_settime(), schedule(), sched::variable, and sched::when.

Referenced by __sip_reliable_xmit(), _misdn_tasks_add_variable(), ast_sched_add(), dnsmgr_start_refresh(), and do_reload().

    00226 {
    00227    /*
    00228     * Schedule callback(data) to happen when ms into the future
    00229     */
    00230    struct sched *tmp;
    00231    int res = -1;
    00232    DEBUG(ast_log(LOG_DEBUG, "ast_sched_add()\n"));
    00233    if (!when) {
    00234       ast_log(LOG_NOTICE, "Scheduled event in 0 ms?\n");
    00235       return -1;
    00236    }
    00237    ast_mutex_lock(&con->lock);
    00238    if ((tmp = sched_alloc(con))) {
    00239       tmp->id = con->eventcnt++;
    00240       tmp->callback = callback;
    00241       tmp->data = data;
    00242       tmp->resched = when;
    00243       tmp->variable = variable;
    00244       tmp->when = ast_tv(0, 0);
    00245       if (sched_settime(&tmp->when, when)) {
    00246          sched_release(con, tmp);
    00247       } else {
    00248          schedule(con, tmp);
    00249          res = tmp->id;
    00250       }
    00251    }
    00252 #ifdef DUMP_SCHEDULER
    00253    /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
    00254    ast_sched_dump(con);
    00255 #endif
    00256    ast_mutex_unlock(&con->lock);
    00257    return res;
    00258 }

int ast_sched_del | ( | struct sched_context * | con,
|  | int | id |
| ) |  |  |

Deletes a scheduled event

Parameters:

  | con | scheduling context to delete item from
  | id | ID of the scheduled item to delete Remove this event from being run. A procedure should not remove its own event, but return 0 instead. Returns 0 on success, -1 on failure

Definition at line 265 of file sched.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_dump(), CRASH, DEBUG, last, sched_context::lock, LOG_DEBUG, LOG_NOTICE, sched::next, s, sched_release(), sched_context::schedcnt, and sched_context::schedq.

Referenced by __sip_ack(), __sip_destroy(), __sip_semi_ack(), ack_trans(), ast_closestream(), auth_fail(), build_gateway(), build_peer(), delete_users(), destroy_packet(), destroy_packets(), destroy_peer(), destroy_trans(), dnsmgr_start_refresh(), do_reload(), handle_command_response(), handle_response(), handle_response_peerpoke(), handle_response_register(), iax2_ack_registry(), iax2_destroy_helper(), iax2_do_register(), iax2_dprequest(), iax2_frame_free(), iax2_poke_peer(), iax2_predestroy(), iax2_provision(), make_trunk(), mgcpsock_read(), misdn_tasks_remove(), parse_register_contact(), qualify_peer(), realtime_peer(), reg_source_db(), schedule_delivery(), sip_cancel_destroy(), sip_destroy_peer(), sip_poke_peer(), sip_registry_destroy(), sip_scheddestroy(), sip_send_all_registers(), socket_read(), stop_stuff(), submit_unscheduled_batch(), transmit_register(), update_jbsched(), and update_registry().

    00266 {
    00267    /*
    00268     * Delete the schedule entry with number
    00269     * "id".  It's nearly impossible that there
    00270     * would be two or more in the list with that
    00271     * id.
    00272     */
    00273    struct sched *last=NULL, *s;
    00274    DEBUG(ast_log(LOG_DEBUG, "ast_sched_del()\n"));
    00275    ast_mutex_lock(&con->lock);
    00276    s = con->schedq;
    00277    while(s) {
    00278       if (s->id == id) {
    00279          if (last)
    00280             last->next = s->next;
    00281          else
    00282             con->schedq = s->next;
    00283          con->schedcnt--;
    00284          sched_release(con, s);
    00285          break;
    00286       }
    00287       last = s;
    00288       s = s->next;
    00289    }
    00290 #ifdef DUMP_SCHEDULER
    00291    /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
    00292    ast_sched_dump(con);
    00293 #endif
    00294    ast_mutex_unlock(&con->lock);
    00295    if (!s) {
    00296       ast_log(LOG_NOTICE, "Attempted to delete nonexistent schedule entry %d!\n", id);
    00297 #ifdef DO_CRASH
    00298       CRASH;
    00299 #endif
    00300       return -1;
    00301    } else
    00302       return 0;
    00303 }

void ast_sched_dump | ( | const struct sched_context * | con | ) |

Dumps the scheduler contents

Parameters:

  | con | Context to dump Debugging: Dump the contents of the scheduler to stderr

Definition at line 305 of file sched.c.

References ast_log(), ast_tvsub(), sched::callback, sched::data, sched_context::eventcnt, sched::id, LOG_DEBUG, sched::next, sched_context::schedcnt, sched_context::schedq, and sched::when.

Referenced by ast_sched_add_variable(), and ast_sched_del().

    00306 {
    00307    /*
    00308     * Dump the contents of the scheduler to
    00309     * stderr
    00310     */
    00311    struct sched *q;
    00312    struct timeval tv = ast_tvnow();
    00313 #ifdef SCHED_MAX_CACHE
    00314    ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt);
    00315 #else
    00316    ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total)\n", con->schedcnt, con->eventcnt - 1);
    00317 #endif
    00318
    00319    ast_log(LOG_DEBUG, "=============================================================\n");
    00320    ast_log(LOG_DEBUG, "|ID    Callback          Data              Time  (sec:ms)   |\n");
    00321    ast_log(LOG_DEBUG, "+-----+-----------------+-----------------+-----------------+\n");
    00322    for (q = con->schedq; q; q = q->next) {
    00323       struct timeval delta =  ast_tvsub(q->when, tv);
    00324
    00325       ast_log(LOG_DEBUG, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
    00326          q->id,
    00327          q->callback,
    00328          q->data,
    00329          delta.tv_sec,
    00330          (long int)delta.tv_usec);
    00331    }
    00332    ast_log(LOG_DEBUG, "=============================================================\n");
    00333
    00334 }

int ast_sched_runq | ( | struct sched_context * | con | ) |

Runs the queue

Parameters:

  | con | Scheduling context to run Run the queue, executing all callbacks which need to be performed at this time. Returns the number of events processed.

Definition at line 336 of file sched.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), sched::callback, sched::data, DEBUG, sched_context::lock, LOG_DEBUG, sched::next, sched::resched, sched_release(), sched_settime(), sched_context::schedcnt, sched_context::schedq, schedule(), SOONER, sched::variable, and sched::when.

Referenced by ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), ast_waitstream_full(), background_detect_exec(), do_cdr(), do_monitor(), do_refresh(), misdn_tasks_thread_func(), network_thread(), and reload_config().

    00337 {
    00338    /*
    00339     * Launch all events which need to be run at this time.
    00340     */
    00341    struct sched *current;
    00342    struct timeval tv;
    00343    int x=0;
    00344    int res;
    00345    DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n"));
    00346
    00347    ast_mutex_lock(&con->lock);
    00348    for(;;) {
    00349       if (!con->schedq)
    00350          break;
    00351
    00352       /* schedule all events which are going to expire within 1ms.
    00353        * We only care about millisecond accuracy anyway, so this will
    00354        * help us get more than one event at one time if they are very
    00355        * close together.
    00356        */
    00357       tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
    00358       if (SOONER(con->schedq->when, tv)) {
    00359          current = con->schedq;
    00360          con->schedq = con->schedq->next;
    00361          con->schedcnt--;
    00362
    00363          /*
    00364           * At this point, the schedule queue is still intact.  We
    00365           * have removed the first event and the rest is still there,
    00366           * so it's permissible for the callback to add new events, but
    00367           * trying to delete itself won't work because it isn't in
    00368           * the schedule queue.  If that's what it wants to do, it
    00369           * should return 0.
    00370           */
    00371
    00372          ast_mutex_unlock(&con->lock);
    00373          res = current->callback(current->data);
    00374          ast_mutex_lock(&con->lock);
    00375
    00376          if (res) {
    00377             /*
    00378              * If they return non-zero, we should schedule them to be
    00379              * run again.
    00380              */
    00381             if (sched_settime(&current->when, current->variable? res : current->resched)) {
    00382                sched_release(con, current);
    00383             } else
    00384                schedule(con, current);
    00385          } else {
    00386             /* No longer needed, so release it */
    00387             sched_release(con, current);
    00388          }
    00389          x++;
    00390       } else
    00391          break;
    00392    }
    00393    ast_mutex_unlock(&con->lock);
    00394    return x;
    00395 }

int ast_sched_wait | ( | struct sched_context * | con | ) |

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

Parameters:

  | con | context to act upon 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. Returns "-1" if there is nothing there are no scheduled events (and thus the poll should not timeout)

Definition at line 158 of file sched.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DEBUG, sched_context::lock, LOG_DEBUG, sched_context::schedq, and sched::when.

Referenced by ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), ast_waitstream_full(), background_detect_exec(), do_cdr(), do_monitor(), do_refresh(), misdn_tasks_thread_func(), and network_thread().

    00159 {
    00160    /*
    00161     * Return the number of milliseconds
    00162     * until the next scheduled event
    00163     */
    00164    int ms;
    00165    DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));
    00166    ast_mutex_lock(&con->lock);
    00167    if (!con->schedq) {
    00168       ms = -1;
    00169    } else {
    00170       ms = ast_tvdiff_ms(con->schedq->when, ast_tvnow());
    00171       if (ms < 0)
    00172          ms = 0;
    00173    }
    00174    ast_mutex_unlock(&con->lock);
    00175    return ms;
    00176
    00177 }

long ast_sched_when | ( | struct sched_context * | con,
|  | int | id |
| ) |  |  |

Returns the number of seconds before an event takes place

Parameters:

  | con | Context to use
  | id | Id to dump

Definition at line 397 of file sched.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), DEBUG, sched::id, sched_context::lock, LOG_DEBUG, sched::next, s, sched_context::schedq, and sched::when.

Referenced by _sip_show_peer(), handle_cli_status(), and parse_register_contact().

    00398 {
    00399    struct sched *s;
    00400    long secs;
    00401    DEBUG(ast_log(LOG_DEBUG, "ast_sched_when()\n"));
    00402
    00403    ast_mutex_lock(&con->lock);
    00404    s=con->schedq;
    00405    while (s!=NULL) {
    00406       if (s->id==id) break;
    00407       s=s->next;
    00408    }
    00409    secs=-1;
    00410    if (s!=NULL) {
    00411       struct timeval now = ast_tvnow();
    00412       secs=s->when.tv_sec-now.tv_sec;
    00413    }
    00414    ast_mutex_unlock(&con->lock);
    00415    return secs;
    00416 }

static struct sched* sched_alloc | ( | struct sched_context * | con | ) | `[static, read]`

Definition at line 123 of file sched.c.

References malloc.

Referenced by ast_sched_add_variable().

    00124 {
    00125    /*
    00126     * We keep a small cache of schedule entries
    00127     * to minimize the number of necessary malloc()'s
    00128     */
    00129    struct sched *tmp;
    00130 #ifdef SCHED_MAX_CACHE
    00131    if (con->schedc) {
    00132       tmp = con->schedc;
    00133       con->schedc = con->schedc->next;
    00134       con->schedccnt--;
    00135    } else
    00136 #endif
    00137       tmp = malloc(sizeof(struct sched));
    00138    return tmp;
    00139 }

struct sched_context* sched_context_create | ( | void |  | ) | `[read]`

New schedule context

Definition at line 79 of file sched.c.

References ast_mutex_init(), sched_context::eventcnt, sched_context::lock, malloc, sched_context::schedcnt, and sched_context::schedq.

Referenced by ast_cdr_engine_init(), ast_channel_alloc(), dnsmgr_init(), load_module(), and misdn_tasks_init().

    00080 {
    00081    struct sched_context *tmp;
    00082    tmp = malloc(sizeof(struct sched_context));
    00083    if (tmp) {
    00084             memset(tmp, 0, sizeof(struct sched_context));
    00085       ast_mutex_init(&tmp->lock);
    00086       tmp->eventcnt = 1;
    00087       tmp->schedcnt = 0;
    00088       tmp->schedq = NULL;
    00089 #ifdef SCHED_MAX_CACHE
    00090       tmp->schedc = NULL;
    00091       tmp->schedccnt = 0;
    00092 #endif
    00093    }
    00094    return tmp;
    00095 }

void sched_context_destroy | ( | struct sched_context * | c | ) |

destroys a schedule context

Parameters:

  | c | Context to free Destroys (free's) the given sched_context structure Returns 0 on success, -1 on failure

Definition at line 97 of file sched.c.

References ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), free, sched_context::lock, sched::next, s, and sched_context::schedq.

Referenced by __unload_module(), ast_channel_free(), ast_hangup(), misdn_tasks_destroy(), and unload_module().

    00098 {
    00099    struct sched *s, *sl;
    00100    ast_mutex_lock(&con->lock);
    00101 #ifdef SCHED_MAX_CACHE
    00102    /* Eliminate the cache */
    00103    s = con->schedc;
    00104    while(s) {
    00105       sl = s;
    00106       s = s->next;
    00107       free(sl);
    00108    }
    00109 #endif
    00110    /* And the queue */
    00111    s = con->schedq;
    00112    while(s) {
    00113       sl = s;
    00114       s = s->next;
    00115       free(sl);
    00116    }
    00117    /* And the context */
    00118    ast_mutex_unlock(&con->lock);
    00119    ast_mutex_destroy(&con->lock);
    00120    free(con);
    00121 }

static void sched_release | ( | struct sched_context * | con,
|  | struct sched * | tmp |
| ) |  |  | `[static]`

Definition at line 141 of file sched.c.

References free, sched::next, and SCHED_MAX_CACHE.

Referenced by ast_sched_add_variable(), ast_sched_del(), and ast_sched_runq().

    00142 {
    00143    /*
    00144     * Add to the cache, or just free() if we
    00145     * already have too many cache entries
    00146     */
    00147
    00148 #ifdef SCHED_MAX_CACHE
    00149    if (con->schedccnt < SCHED_MAX_CACHE) {
    00150       tmp->next = con->schedc;
    00151       con->schedc = tmp;
    00152       con->schedccnt++;
    00153    } else
    00154 #endif
    00155       free(tmp);
    00156 }

static int sched_settime | ( | struct timeval * | tv,
|  | int | when |
| ) |  |  | `[static]`

Definition at line 209 of file sched.c.

References ast_log(), ast_tvadd(), and LOG_DEBUG.

Referenced by ast_sched_add_variable(), and ast_sched_runq().

    00210 {
    00211    struct timeval now = ast_tvnow();
    00212
    00213    /*ast_log(LOG_DEBUG, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/
    00214    if (ast_tvzero(*tv)) /* not supplied, default to now */
    00215       *tv = now;
    00216    *tv = ast_tvadd(*tv, ast_samp2tv(when, 1000));
    00217    if (ast_tvcmp(*tv, now) < 0) {
    00218       ast_log(LOG_DEBUG, "Request to schedule in the past?!?!\n");
    00219       *tv = now;
    00220    }
    00221    return 0;
    00222 }

static void schedule | ( | struct sched_context * | con,
|  | struct sched * | s |
| ) |  |  | `[static]`

Definition at line 180 of file sched.c.

References last, sched::next, sched_context::schedcnt, sched_context::schedq, SOONER, and sched::when.

Referenced by ast_sched_add_variable(), and ast_sched_runq().

    00181 {
    00182    /*
    00183     * Take a sched structure and put it in the
    00184     * queue, such that the soonest event is
    00185     * first in the list.
    00186     */
    00187
    00188    struct sched *last=NULL;
    00189    struct sched *current=con->schedq;
    00190    while(current) {
    00191       if (SOONER(s->when, current->when))
    00192          break;
    00193       last = current;
    00194       current = current->next;
    00195    }
    00196    /* Insert this event into the schedule */
    00197    s->next = current;
    00198    if (last)
    00199       last->next = s;
    00200    else
    00201       con->schedq = s;
    00202    con->schedcnt++;
    00203 }