Wed Oct 28 11:46:20 2009

Asterisk developer's documentation


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/linkedlists.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)

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)
 Delete the schedule entry with number "id". It's nearly impossible that there would be two or more in the list with that id.
void ast_sched_dump (const struct sched_context *con)
 Dump the contents of the scheduler to LOG_DEBUG.
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)
 Launch all events which need to be run at this time.
int ast_sched_wait (struct sched_context *con)
 Return the number of milliseconds until the next scheduled event.
long ast_sched_when (struct sched_context *con, int id)
 Returns the number of seconds before an event takes place.
static struct schedsched_alloc (struct sched_context *con)
struct sched_contextsched_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.


Detailed Description

Scheduler Routines (from cheops-NG).

Author:
Mark Spencer <markster@digium.com>

Definition in file sched.c.


Define Documentation

#define DEBUG (  ) 

Definition at line 36 of file sched.c.


Function Documentation

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.

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

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(), build_peer(), 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(), transmit_register(), and update_provisional_keepalive().

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

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

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 
)

Delete the schedule entry with number "id". It's nearly impossible that there would be two or more in the list with that 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).

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::id, sched_context::lock, option_debug, s, sched_release(), sched_context::schedcnt, and sched_context::schedq.

Referenced by __sip_ack(), ast_sched_replace(), ast_sched_replace_variable(), handle_response_register(), iax2_poke_peer(), realtime_peer(), reg_source_db(), sip_cancel_destroy(), socket_process(), 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  ) 

Dump the contents of the scheduler to LOG_DEBUG.

Dumps the scheduler contents Debugging: Dump the contents of the scheduler to stderr.

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_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

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:
-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

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:
-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  ) 

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

Runs the queue.

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_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(&current->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  ) 

Return the number of milliseconds until the next scheduled event.

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.

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.

Parameters:
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::id, sched_context::lock, s, sched_context::schedq, and sched::when.

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, read]

Definition at line 104 of file sched.c.

References ast_calloc, AST_LIST_REMOVE_HEAD, 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   )  [read]

New schedule context.

Note:
Create a scheduling context
Returns:
Returns a malloc'd sched_context structure, NULL on failure

Definition at line 69 of file sched.c.

References ast_calloc, ast_mutex_init(), sched_context::eventcnt, and sched_context::lock.

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

Parameters:
c Context to free
Returns:
Returns 0 on success, -1 on failure

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_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_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_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 }


Generated on Wed Oct 28 11:46:20 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6