dect
/
asterisk
Archived
13
0
Fork 0

Some scheduler API cleanup and improvements.

Previously, I had added the ast_sched_thread stuff that was a generic scheduler
thread implementation.  However, if you used it, it required using different
functions for modifying scheduler contents.  This patch reworks how this is
done and just allows you to optionally start a thread on the original scheduler
context structure that has always been there.  This makes it trivial to switch
to the generic scheduler thread implementation without having to touch any of
the other code that adds or removes scheduler entries.

In passing, I made some naming tweaks to add ast_ prefixes where they were not
there before.

Review: https://reviewboard.asterisk.org/r/1007/


git-svn-id: http://svn.digium.com/svn/asterisk/trunk@299091 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
russell 2010-12-20 17:15:54 +00:00
parent ef5097f780
commit c15c0120f1
28 changed files with 328 additions and 405 deletions

View File

@ -226,7 +226,7 @@ static const struct ast_channel_tech gtalk_tech = {
static struct sockaddr_in bindaddr = { 0, }; /*!< The address we bind to */
static struct sched_context *sched; /*!< The scheduling context */
static struct ast_sched_context *sched; /*!< The scheduling context */
static struct io_context *io; /*!< The IO context */
static struct in_addr __ourip;
@ -2248,7 +2248,7 @@ static int load_module(void)
return 0;
}
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
}

View File

@ -205,7 +205,7 @@ static struct h323_alias_list {
} aliasl;
/* Asterisk RTP stuff */
static struct sched_context *sched;
static struct ast_sched_context *sched;
static struct io_context *io;
AST_MUTEX_DEFINE_STATIC(iflock); /*!< Protect the interface list (oh323_pvt) */
@ -3261,7 +3261,7 @@ static enum ast_module_load_result load_module(void)
int res;
h323debug = 0;
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
return AST_MODULE_LOAD_FAILURE;
@ -3282,7 +3282,7 @@ static enum ast_module_load_result load_module(void)
ast_cli_unregister(&cli_h323_reload);
io_context_destroy(io);
io = NULL;
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROY(&peerl);
@ -3295,7 +3295,7 @@ static enum ast_module_load_result load_module(void)
ast_cli_unregister(&cli_h323_reload);
h323_end_process();
io_context_destroy(io);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
@ -3334,7 +3334,7 @@ static enum ast_module_load_result load_module(void)
ast_cli_unregister(&cli_h323_reload);
h323_end_process();
io_context_destroy(io);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
@ -3421,7 +3421,7 @@ static int unload_module(void)
if (io)
io_context_destroy(io);
if (sched)
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);

View File

@ -356,8 +356,8 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
ast_log(LOG_NOTICE, msg " IAX_COMMAND_RTKEY to rotate key to '%s'\n", digest); \
} while(0)
static struct io_context *io;
static struct ast_sched_thread *sched;
static struct io_context *io;
static struct ast_sched_context *sched;
#define DONT_RESCHEDULE -2
@ -1183,7 +1183,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
static int iax2_queryoption(struct ast_channel *c, int option, void *data, int *datalen);
static int iax2_transfer(struct ast_channel *c, const char *dest);
static int iax2_write(struct ast_channel *c, struct ast_frame *f);
static int iax2_sched_add(struct ast_sched_thread *st, int when, ast_sched_cb callback, const void *data);
static int iax2_sched_add(struct ast_sched_context *sched, int when, ast_sched_cb callback, const void *data);
static int send_trunk(struct iax2_trunk_peer *tpeer, struct timeval *now);
static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
@ -1487,18 +1487,16 @@ static int __schedule_action(void (*func)(const void *data), const void *data, c
#define schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__)
#endif
static int iax2_sched_replace(int id, struct ast_sched_thread *st, int when,
static int iax2_sched_replace(int id, struct ast_sched_context *con, int when,
ast_sched_cb callback, const void *data)
{
ast_sched_thread_del(st, id);
return ast_sched_thread_add(st, when, callback, data);
return ast_sched_replace(id, con, when, callback, data);
}
static int iax2_sched_add(struct ast_sched_thread *st, int when,
static int iax2_sched_add(struct ast_sched_context *con, int when,
ast_sched_cb callback, const void *data)
{
return ast_sched_thread_add(st, when, callback, data);
return ast_sched_add(con, when, callback, data);
}
static int send_ping(const void *data);
@ -1787,20 +1785,20 @@ static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
ast_clear_flag64(pvt, IAX_MAXAUTHREQ);
}
/* No more pings or lagrq's */
AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->pingid, &iaxsl[pvt->callno]);
AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]);
pvt->pingid = DONT_RESCHEDULE;
AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->lagid, &iaxsl[pvt->callno]);
AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]);
pvt->lagid = DONT_RESCHEDULE;
ast_sched_thread_del(sched, pvt->autoid);
ast_sched_thread_del(sched, pvt->authid);
ast_sched_thread_del(sched, pvt->initid);
ast_sched_thread_del(sched, pvt->jbid);
ast_sched_thread_del(sched, pvt->keyrotateid);
AST_SCHED_DEL(sched, pvt->autoid);
AST_SCHED_DEL(sched, pvt->authid);
AST_SCHED_DEL(sched, pvt->initid);
AST_SCHED_DEL(sched, pvt->jbid);
AST_SCHED_DEL(sched, pvt->keyrotateid);
}
static void iax2_frame_free(struct iax_frame *fr)
{
ast_sched_thread_del(sched, fr->retrans);
AST_SCHED_DEL(sched, fr->retrans);
iax_frame_free(fr);
}
@ -2058,8 +2056,8 @@ static int make_trunk(unsigned short callno, int locked)
* \note We delete these before switching the slot, because if
* they fire in the meantime, they will generate a warning.
*/
ast_sched_thread_del(sched, iaxs[callno]->pingid);
ast_sched_thread_del(sched, iaxs[callno]->lagid);
AST_SCHED_DEL(sched, iaxs[callno]->pingid);
AST_SCHED_DEL(sched, iaxs[callno]->lagid);
iaxs[callno]->lagid = iaxs[callno]->pingid = -1;
iaxs[x] = iaxs[callno];
iaxs[x]->callno = x;
@ -4194,7 +4192,7 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
jb_reset(iaxs[fr->callno]->jb);
ast_sched_thread_del(sched, iaxs[fr->callno]->jbid);
AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
/* deliver this frame now */
if (tsout)
@ -4389,7 +4387,7 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in
ast_copy_flags64(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
if (ast_test_flag64(peer, IAX_RTAUTOCLEAR)) {
if (peer->expire > -1) {
if (!ast_sched_thread_del(sched, peer->expire)) {
if (!AST_SCHED_DEL(sched, peer->expire)) {
peer->expire = -1;
peer_unref(peer);
}
@ -5217,7 +5215,7 @@ static int iax2_hangup(struct ast_channel *c)
ast_debug(1, "Really destroying %s now...\n", c->name);
iax2_destroy(callno);
} else if (iaxs[callno]) {
if (ast_sched_thread_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) {
if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) {
ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!! Destroying immediately.\n", callno);
iax2_destroy(callno);
}
@ -5348,12 +5346,11 @@ static int iax2_key_rotate(const void *vpvt)
struct MD5Context md5;
char key[17] = "";
struct iax_ie_data ied = {
.pos = 0,
.pos = 0,
};
ast_mutex_lock(&iaxsl[pvt->callno]);
pvt->keyrotateid =
ast_sched_thread_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt);
pvt->keyrotateid = ast_sched_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt);
snprintf(key, sizeof(key), "%lX", ast_random());
@ -8543,14 +8540,14 @@ static void prune_peers(void);
static void unlink_peer(struct iax2_peer *peer)
{
if (peer->expire > -1) {
if (!ast_sched_thread_del(sched, peer->expire)) {
if (!AST_SCHED_DEL(sched, peer->expire)) {
peer->expire = -1;
peer_unref(peer);
}
}
if (peer->pokeexpire > -1) {
if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
peer->pokeexpire = -1;
peer_unref(peer);
}
@ -8629,7 +8626,7 @@ static void reg_source_db(struct iax2_peer *p)
iax2_poke_peer(p, 0);
if (p->expire > -1) {
if (!ast_sched_thread_del(sched, p->expire)) {
if (!AST_SCHED_DEL(sched, p->expire)) {
p->expire = -1;
peer_unref(p);
}
@ -8741,7 +8738,7 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i
p->sockfd = fd;
/* Setup the expiry */
if (p->expire > -1) {
if (!ast_sched_thread_del(sched, p->expire)) {
if (!AST_SCHED_DEL(sched, p->expire)) {
p->expire = -1;
peer_unref(p);
}
@ -10297,7 +10294,7 @@ static int socket_process(struct iax2_thread *thread)
}
}
if (f.frametype == AST_FRAME_IAX) {
ast_sched_thread_del(sched, iaxs[fr->callno]->initid);
AST_SCHED_DEL(sched, iaxs[fr->callno]->initid);
/* Handle the IAX pseudo frame itself */
if (iaxdebug)
ast_debug(1, "IAX subclass %d received\n", f.subclass.integer);
@ -10823,7 +10820,7 @@ static int socket_process(struct iax2_thread *thread)
/* Remove scheduled iax2_poke_noanswer */
if (peer->pokeexpire > -1) {
if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
peer_unref(peer);
peer->pokeexpire = -1;
}
@ -11943,22 +11940,22 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
iaxs[peer->callno]->peerpoke = peer;
if (peer->pokeexpire > -1) {
if (!ast_sched_thread_del(sched, peer->pokeexpire)) {
peer->pokeexpire = -1;
peer_unref(peer);
}
}
if (peer->pokeexpire > -1) {
if (!AST_SCHED_DEL(sched, peer->pokeexpire)) {
peer->pokeexpire = -1;
peer_unref(peer);
}
}
/* Queue up a new task to handle no reply */
/* If the host is already unreachable then use the unreachable interval instead */
if (peer->lastms < 0)
peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
else
peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
if (peer->pokeexpire == -1)
peer_unref(peer);
if (peer->pokeexpire == -1)
peer_unref(peer);
/* And send the poke */
ast_mutex_lock(&iaxsl[callno]);
@ -12391,7 +12388,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
}
} else {
/* Non-dynamic. Make sure we become that way if we're not */
ast_sched_thread_del(sched, peer->expire);
AST_SCHED_DEL(sched, peer->expire);
ast_clear_flag64(peer, IAX_DYNAMIC);
if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
return peer_unref(peer);
@ -12835,7 +12832,7 @@ static void delete_users(void)
AST_LIST_LOCK(&registrations);
while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
if (sched) {
ast_sched_thread_del(sched, reg->expire);
AST_SCHED_DEL(sched, reg->expire);
}
if (reg->callno) {
int callno = reg->callno;
@ -14269,7 +14266,8 @@ static int __unload_module(void)
ast_timer_close(timer);
}
transmit_processor = ast_taskprocessor_unreference(transmit_processor);
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
con = ast_context_find(regcontext);
if (con)
@ -14588,21 +14586,29 @@ static int load_module(void)
ast_mutex_init(&iaxsl[x]);
}
if (!(sched = ast_sched_thread_create())) {
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Failed to create scheduler thread\n");
return AST_MODULE_LOAD_FAILURE;
}
if (ast_sched_start_thread(sched)) {
ast_sched_context_destroy(sched);
sched = NULL;
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_ERROR, "Failed to create I/O context\n");
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
return AST_MODULE_LOAD_FAILURE;
}
if (!(netsock = ast_netsock_list_alloc())) {
ast_log(LOG_ERROR, "Failed to create netsock list\n");
io_context_destroy(io);
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
return AST_MODULE_LOAD_FAILURE;
}
ast_netsock_init(netsock);
@ -14611,7 +14617,8 @@ static int load_module(void)
if (!outsock) {
ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
io_context_destroy(io);
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
return AST_MODULE_LOAD_FAILURE;
}
ast_netsock_init(outsock);

View File

@ -210,7 +210,7 @@ static const struct ast_channel_tech jingle_tech = {
static struct sockaddr_in bindaddr = { 0, }; /*!< The address we bind to */
static struct sched_context *sched; /*!< The scheduling context */
static struct ast_sched_context *sched; /*!< The scheduling context */
static struct io_context *io; /*!< The IO context */
static struct in_addr __ourip;
@ -1903,7 +1903,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
}

View File

@ -231,7 +231,7 @@ static int ourport;
static int mgcpdebug = 0;
static struct sched_context *sched;
static struct ast_sched_context *sched;
static struct io_context *io;
/*! The private structures of the mgcp channels are linked for
* selecting outgoing channels
@ -4776,14 +4776,14 @@ static int reload_config(int reload)
/*! \brief load_module: PBX load module - initialization ---*/
static int load_module(void)
{
if (!(sched = sched_context_create())) {
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_WARNING, "Unable to create I/O context\n");
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
return AST_MODULE_LOAD_FAILURE;
}
@ -4794,7 +4794,7 @@ static int load_module(void)
if (ast_channel_register(&mgcp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
io_context_destroy(io);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
return AST_MODULE_LOAD_FAILURE;
}
@ -4905,7 +4905,7 @@ static int unload_module(void)
close(mgcpsock);
ast_rtp_glue_unregister(&mgcp_rtp_glue);
ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
return 0;
}

View File

@ -782,7 +782,7 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL;
static int sip_reloading = FALSE; /*!< Flag for avoiding multiple reloads at the same time */
static enum channelreloadreason sip_reloadreason; /*!< Reason for last reload/load of configuration */
struct sched_context *sched; /*!< The scheduling context */
struct ast_sched_context *sched; /*!< The scheduling context */
static struct io_context *io; /*!< The IO context */
static int *sipsock_read_id; /*!< ID of IO entry for sipsock FD */
struct sip_pkt;
@ -28901,14 +28901,14 @@ static int load_module(void)
ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
if (!(sched = sched_context_create())) {
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context\n");
return AST_MODULE_LOAD_FAILURE;
}
if (!(io = io_context_create())) {
ast_log(LOG_ERROR, "Unable to create I/O context\n");
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
return AST_MODULE_LOAD_FAILURE;
}
@ -28930,7 +28930,7 @@ static int load_module(void)
if (ast_channel_register(&sip_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
io_context_destroy(io);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
return AST_MODULE_LOAD_FAILURE;
}
@ -29151,7 +29151,7 @@ static int unload_module(void)
clear_sip_domains();
ast_free_ha(sip_cfg.contact_ha);
close(sipsock);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
con = ast_context_find(used_context);
if (con) {
ast_context_destroy(con, "SIP");

View File

@ -1151,7 +1151,7 @@ static const char * const skinny_cxmodes[] = {
#endif
/* driver scheduler */
static struct sched_context *sched = NULL;
static struct ast_sched_context *sched = NULL;
static struct io_context *io;
/* Protect the monitoring thread, so only one process can kill or start it, and not
@ -7368,7 +7368,7 @@ static int load_module(void)
ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
}
@ -7449,8 +7449,9 @@ static int unload_module(void)
ast_mutex_unlock(&netlock);
close(skinnysock);
if (sched)
sched_context_destroy(sched);
if (sched) {
ast_sched_context_destroy(sched);
}
con = ast_context_find(used_context);
if (con)

View File

@ -217,7 +217,7 @@ static struct {
} qos = { 0, 0, 0, 0 };
static struct io_context *io;
static struct sched_context *sched;
static struct ast_sched_context *sched;
static struct sockaddr_in public_ip = { 0, };
/*! give the IP address for the last packet received */
static struct sockaddr_in address_from;
@ -5645,7 +5645,7 @@ int load_module(void)
goto io_failed;
}
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
goto sched_failed;
@ -5671,7 +5671,7 @@ int load_module(void)
chanreg_failed:
/*! XXX \todo Leaking anything allocated by reload_config() ... */
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
sched_failed:
io_context_destroy(io);
@ -5686,8 +5686,9 @@ buff_failed:
static int unload_module(void)
{
/* First, take us out of the channel loop */
if (sched)
sched_context_destroy(sched);
if (sched) {
ast_sched_context_destroy(sched);
}
ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));

View File

@ -225,7 +225,7 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
}
#ifdef TEST_FRAMEWORK
static int test_sip_rtpqos_1_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
static int test_sip_rtpqos_1_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
{
/* Needed to pass sanity checks */
ast_rtp_instance_set_data(instance, data);

View File

@ -25,7 +25,7 @@
#define _SIP_GLOBALS_H
extern struct ast_sockaddr bindaddr; /*!< UDP: The address we bind to */
extern struct sched_context *sched; /*!< The scheduling context */
extern struct ast_sched_context *sched; /*!< The scheduling context */
/*! \brief Definition of this channel for PBX channel registration */
extern const struct ast_channel_tech sip_tech;

View File

@ -211,6 +211,7 @@ struct ast_frame;
struct ast_module;
struct ast_variable;
struct ast_str;
struct ast_sched_context;
#ifdef bzero
#undef bzero

View File

@ -139,7 +139,6 @@ extern "C" {
#define MAX_MUSICCLASS 80 /*!< Max length of the music class setting */
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/chanvars.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
@ -744,7 +743,7 @@ struct ast_channel {
const char *blockproc; /*!< Procedure causing blocking */
const char *appl; /*!< Current application */
const char *data; /*!< Data passed to current application */
struct sched_context *sched; /*!< Schedule context */
struct ast_sched_context *sched; /*!< Schedule context */
struct ast_filestream *stream; /*!< Stream itself. */
struct ast_filestream *vstream; /*!< Video Stream itself. */
int (*timingfunc)(const void *data);

View File

@ -313,7 +313,7 @@ struct ast_rtp_engine {
/*! Module this RTP engine came from, used for reference counting */
struct ast_module *mod;
/*! Callback for setting up a new RTP instance */
int (*new)(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *sa, void *data);
int (*new)(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *sa, void *data);
/*! Callback for destroying an RTP instance */
int (*destroy)(struct ast_rtp_instance *instance);
/*! Callback for writing out a frame */
@ -542,7 +542,7 @@ int ast_rtp_glue_unregister(struct ast_rtp_glue *glue);
* \since 1.8
*/
struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
struct sched_context *sched, const struct ast_sockaddr *sa,
struct ast_sched_context *sched, const struct ast_sockaddr *sa,
void *data);
/*!

View File

@ -1,9 +1,10 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
* Copyright (C) 1999 - 2010, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Russell Bryant <russell@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@ -27,16 +28,10 @@
extern "C" {
#endif
/*! \brief 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)
*/
#define SCHED_MAX_CACHE 128
/*! \brief a loop construct to ensure that
/*!
* \brief Remove a scheduler entry
*
* This is a loop construct to ensure that
* the scheduled task get deleted. The idea is that
* if we loop attempting to remove the scheduled task,
* then whatever callback had been running will complete
@ -137,25 +132,27 @@ extern "C" {
#define AST_SCHED_REPLACE_UNREF(id, sched, when, callback, data, unrefcall, addfailcall, refcall) \
AST_SCHED_REPLACE_VARIABLE_UNREF(id, sched, when, callback, data, 0, unrefcall, addfailcall, refcall)
struct sched_context;
/*! \brief New schedule context
* \note Create a scheduling context
/*!
* \brief Create a scheduler context
*
* \return Returns a malloc'd sched_context structure, NULL on failure
*/
struct sched_context *sched_context_create(void);
struct ast_sched_context *ast_sched_context_create(void);
/*! \brief destroys a schedule context
* Destroys (free's) the given sched_context structure
/*!
* \brief destroys a schedule context
*
* \param c Context to free
* \return Returns 0 on success, -1 on failure
*/
void sched_context_destroy(struct sched_context *c);
void ast_sched_context_destroy(struct ast_sched_context *c);
/*! \brief callback for a cheops scheduler
* A cheops scheduler callback takes a pointer with callback data and
* \return returns a 0 if it should not be run again, or non-zero if it should be
* rescheduled to run again
/*!
* \brief scheduler callback
*
* A scheduler callback takes a pointer with callback data and
*
* \retval 0 if the callback should not be rescheduled
* \retval non-zero if the callback should be scheduled agai
*/
typedef int (*ast_sched_cb)(const void *data);
#define AST_SCHED_CB(a) ((ast_sched_cb)(a))
@ -173,20 +170,25 @@ struct ast_cb_names {
* \param cbnames to check against
* \since 1.6.1
*/
void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
/*! \brief Adds a scheduled event
void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames);
/*!
* \brief 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
*
* \param con Scheduler context to add
* \param when how many milliseconds to wait for event to occur
* \param callback function to call when the amount of time expires
* \param data data to pass to the callback
*
* \return Returns a schedule item ID on success, -1 on failure
*/
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
/*!
* \brief replace a scheduler entry
@ -199,22 +201,27 @@ int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, co
* \retval -1 failure
* \retval otherwise, returns scheduled item ID
*/
int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result;
/*!Adds a scheduled event with rescheduling support
/*!
* \brief Adds a scheduled event with rescheduling support
*
* \param con Scheduler context to add
* \param when how many milliseconds to wait for event to occur
* \param callback function to call when the amount of time expires
* \param data data to pass to the callback
* \param 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
*
* \return Returns a schedule item ID on success, -1 on failure
*/
int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
/*!
* \brief replace a scheduler entry
@ -227,66 +234,83 @@ int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb cal
* \retval -1 failure
* \retval otherwise, returns scheduled item ID
*/
int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
int ast_sched_replace_variable(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result;
/*!
* \brief Find a sched structure and return the data field associated with it.
*
* \param con scheduling context in which to search fro the matching id
* \param id ID of the scheduled item to find
* \return the data field from the matching sched struct if found; else return NULL if not found.
*
* \since 1.6.1
*/
const void *ast_sched_find_data(struct ast_sched_context *con, int id);
const void *ast_sched_find_data(struct sched_context *con, int id);
/*! \brief Deletes a scheduled event
/*!
* \brief 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).
*
* \param con scheduling context to delete item from
* \param id ID of the scheduled item to delete
*
* \return Returns 0 on success, -1 on failure
*/
#ifndef AST_DEVMODE
int ast_sched_del(struct sched_context *con, int id) attribute_warn_unused_result;
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result;
#else
int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int line, const char *function) attribute_warn_unused_result;
#define ast_sched_del(a, b) _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#endif
/*! \brief Determines number of seconds until the next outstanding event to take place
/*!
* \brief 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.
*
* \param con context to act upon
*
* \return Returns "-1" if there is nothing there are no scheduled events
* (and thus the poll should not timeout)
*/
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result;
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result;
/*! \brief Runs the queue
* \param con Scheduling context to run
/*!
* \brief Runs the queue
*
* Run the queue, executing all callbacks which need to be performed
* at this time.
*
* \param con Scheduling context to run
* \param con context to act upon
*
* \return Returns the number of events processed.
*/
int ast_sched_runq(struct sched_context *con);
int ast_sched_runq(struct ast_sched_context *con);
/*! \brief Dumps the scheduler contents
/*!
* \brief Dumps the scheduler contents
*
* Debugging: Dump the contents of the scheduler to stderr
*
* \param con Context to dump
*/
void ast_sched_dump(struct sched_context *con);
void ast_sched_dump(struct ast_sched_context *con);
/*! \brief Returns the number of seconds before an event takes place
/*!
* \brief Returns the number of seconds before an event takes place
*
* \param con Context to use
* \param id Id to dump
*/
long ast_sched_when(struct sched_context *con,int id);
long ast_sched_when(struct ast_sched_context *con,int id);
/*!
* \brief Convenience macro for objects and reference (add)
@ -307,112 +331,14 @@ long ast_sched_when(struct sched_context *con,int id);
} while(0)
/*!
* \brief An opaque type representing a scheduler thread
* \brief Start a thread for processing scheduler entries
*
* The purpose of the ast_sched_thread API is to provide a common implementation
* of the case where a module wants to have a dedicated thread for handling the
* scheduler.
*/
struct ast_sched_thread;
/*!
* \brief Create a scheduler with a dedicated thread
*
* This function should be used to allocate a scheduler context and a dedicated
* thread for processing scheduler entries. The thread is started immediately.
*
* \retval NULL error
* \retval non-NULL a handle to the scheduler and its dedicated thread.
*/
struct ast_sched_thread *ast_sched_thread_create(void);
/*!
* \brief Destroy a scheduler and its thread
*
* This function is used to destroy a scheduler context and the dedicated thread
* that was created for handling scheduler entries. Any entries in the scheduler
* that have not yet been processed will be thrown away. Once this function is
* called, the handle must not be used again.
*
* \param st the handle to the scheduler and thread
*
* \return NULL for convenience
*/
struct ast_sched_thread *ast_sched_thread_destroy(struct ast_sched_thread *st);
/*!
* \brief Add a scheduler entry
*
* \param st the handle to the scheduler and thread
* \param when the number of ms in the future to run the task. A value <= 0
* is treated as "run now".
* \param cb the function to call when the scheduled time arrives
* \param data the parameter to pass to the scheduler callback
*
* \retval -1 Failure
* \retval >=0 Sched ID of added task
*/
int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb,
const void *data);
/*!
* \brief Add a variable reschedule time scheduler entry
*
* \param st the handle to the scheduler and thread
* \param when the number of ms in the future to run the task. A value <= 0
* is treated as "run now".
* \param cb the function to call when the scheduled time arrives
* \param data the parameter to pass to the scheduler callback
* \param variable If this value is non-zero, then the scheduler will use the return
* value of the scheduler as the amount of time in the future to run the
* task again. Normally, a return value of 0 means do not re-schedule, and
* non-zero means re-schedule using the time provided when the scheduler
* entry was first created.
*
* \retval -1 Failure
* \retval >=0 Sched ID of added task
*/
int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb,
const void *data, int variable);
/*!
* \brief Get the scheduler context for a given ast_sched_thread
*
* This function should be used only when direct access to the scheduler context
* is required. Its use is discouraged unless necessary. The cases where
* this is currently required is when you want to take advantage of one of the
* AST_SCHED macros.
*
* \param st the handle to the scheduler and thread
*
* \return the sched_context associated with an ast_sched_thread
*/
struct sched_context *ast_sched_thread_get_context(struct ast_sched_thread *st);
/*!
* \brief Delete a scheduler entry
*
* This uses the AST_SCHED_DEL macro internally.
*
* \param st the handle to the scheduler and thread
* \param id scheduler entry id to delete
* \param con the scheduler context this thread will manage
*
* \retval 0 success
* \retval non-zero failure
*/
#define ast_sched_thread_del(st, id) ({ \
struct sched_context *__tmp_context = ast_sched_thread_get_context(st); \
AST_SCHED_DEL(__tmp_context, id); \
})
/*!
* \brief Force re-processing of the scheduler context
*
* \param st the handle to the scheduler and thread
*
* \return nothing
*/
void ast_sched_thread_poke(struct ast_sched_thread *st);
int ast_sched_start_thread(struct ast_sched_context *con);
#if defined(__cplusplus) || defined(c_plusplus)
}

View File

@ -57,7 +57,7 @@ struct ast_udptl;
typedef int (*ast_udptl_callback)(struct ast_udptl *udptl, struct ast_frame *f, void *data);
struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in);
struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *in);
/*!
* \brief Associates a character string 'tag' with a UDPTL session.

View File

@ -68,9 +68,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
*/
/*!
* The sched_thread ID used for all generic CC timeouts
* The ast_sched_context used for all generic CC timeouts
*/
static struct ast_sched_thread *cc_sched_thread;
static struct ast_sched_context *cc_sched_context;
/*!
* Counter used to create core IDs for CC calls. Each new
* core ID is created by atomically adding 1 to the core_id_counter
@ -1235,7 +1235,7 @@ static int cc_generic_monitor_request_cc(struct ast_cc_monitor *monitor, int *av
when = service == AST_CC_CCBS ? ast_get_ccbs_available_timer(monitor->interface->config_params) :
ast_get_ccnr_available_timer(monitor->interface->config_params);
*available_timer_id = ast_sched_thread_add(cc_sched_thread, when * 1000,
*available_timer_id = ast_sched_add(cc_sched_context, when * 1000,
ast_cc_available_timer_expire, cc_ref(monitor, "Give the scheduler a monitor reference"));
if (*available_timer_id == -1) {
cc_unref(monitor, "Failed to schedule available timer. (monitor)");
@ -1333,7 +1333,7 @@ static int cc_generic_monitor_cancel_available_timer(struct ast_cc_monitor *moni
ast_log_dynamic_level(cc_logger_level, "Core %d: Canceling generic monitor available timer for monitor %s\n",
monitor->core_id, monitor->interface->device_name);
if (!ast_sched_thread_del(cc_sched_thread, *sched_id)) {
if (!ast_sched_del(cc_sched_context, *sched_id)) {
cc_unref(monitor, "Remove scheduler's reference to the monitor");
}
*sched_id = -1;
@ -2377,13 +2377,13 @@ static int cc_generic_agent_start_offer_timer(struct ast_cc_agent *agent)
int sched_id;
struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
ast_assert(cc_sched_thread != NULL);
ast_assert(cc_sched_context != NULL);
ast_assert(agent->cc_params != NULL);
when = ast_get_cc_offer_timer(agent->cc_params) * 1000;
ast_log_dynamic_level(cc_logger_level, "Core %d: About to schedule offer timer expiration for %d ms\n",
agent->core_id, when);
if ((sched_id = ast_sched_thread_add(cc_sched_thread, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
if ((sched_id = ast_sched_add(cc_sched_context, when, offer_timer_expire, cc_ref(agent, "Give scheduler an agent ref"))) == -1) {
return -1;
}
generic_pvt->offer_timer_id = sched_id;
@ -2395,7 +2395,7 @@ static int cc_generic_agent_stop_offer_timer(struct ast_cc_agent *agent)
struct cc_generic_agent_pvt *generic_pvt = agent->private_data;
if (generic_pvt->offer_timer_id != -1) {
if (!ast_sched_thread_del(cc_sched_thread, generic_pvt->offer_timer_id)) {
if (!ast_sched_del(cc_sched_context, generic_pvt->offer_timer_id)) {
cc_unref(agent, "Remove scheduler's reference to the agent");
}
generic_pvt->offer_timer_id = -1;
@ -4192,7 +4192,10 @@ int ast_cc_init(void)
if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS core", TPS_REF_DEFAULT))) {
return -1;
}
if (!(cc_sched_thread = ast_sched_thread_create())) {
if (!(cc_sched_context = ast_sched_context_create())) {
return -1;
}
if (ast_sched_start_thread(cc_sched_context)) {
return -1;
}
res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL);

View File

@ -80,7 +80,7 @@ static int cdr_sequence = 0;
static int cdr_seq_inc(struct ast_cdr *cdr);
static struct sched_context *sched;
static struct ast_sched_context *sched;
static int cdr_sched = -1;
static pthread_t cdr_thread = AST_PTHREADT_NULL;
@ -1616,7 +1616,7 @@ int ast_cdr_engine_init(void)
{
int res;
sched = sched_context_create();
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_ERROR, "Unable to create schedule context.\n");
return -1;

View File

@ -1103,7 +1103,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
tmp->epfd = epoll_create(25);
#endif
if (!(tmp->sched = sched_context_create())) {
if (!(tmp->sched = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
return ast_channel_unref(tmp);
}
@ -2339,8 +2339,9 @@ static void ast_channel_destructor(void *obj)
ast_free(chan->tech_pvt);
}
if (chan->sched)
sched_context_destroy(chan->sched);
if (chan->sched) {
ast_sched_context_destroy(chan->sched);
}
if (chan->name) {
char *dashptr;
@ -2710,7 +2711,7 @@ int ast_hangup(struct ast_channel *chan)
chan->vstream = NULL;
}
if (chan->sched) {
sched_context_destroy(chan->sched);
ast_sched_context_destroy(chan->sched);
chan->sched = NULL;
}

View File

@ -45,7 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/manager.h"
#include "asterisk/acl.h"
static struct sched_context *sched;
static struct ast_sched_context *sched;
static int refresh_sched = -1;
static pthread_t refresh_thread = AST_PTHREADT_NULL;
@ -351,7 +351,7 @@ static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Disp
int dnsmgr_init(void)
{
if (!(sched = sched_context_create())) {
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create schedule context.\n");
return -1;
}

View File

@ -300,7 +300,7 @@ int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
}
struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
struct sched_context *sched, const struct ast_sockaddr *sa,
struct ast_sched_context *sched, const struct ast_sockaddr *sa,
void *data)
{
struct ast_sockaddr address = {{0,}};

View File

@ -1,9 +1,10 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2008, Digium, Inc.
* Copyright (C) 1999 - 2010, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Russell Bryant <russell@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@ -48,6 +49,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/heap.h"
#include "asterisk/threadstorage.h"
/*!
* \brief 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)
*/
#define SCHED_MAX_CACHE 128
AST_THREADSTORAGE(last_del_id);
struct sched {
@ -61,13 +72,20 @@ struct sched {
ssize_t __heap_index;
};
struct sched_context {
struct sched_thread {
pthread_t thread;
ast_cond_t cond;
unsigned int stop:1;
};
struct ast_sched_context {
ast_mutex_t lock;
unsigned int eventcnt; /*!< Number of events processed */
unsigned int schedcnt; /*!< Number of outstanding schedule events */
unsigned int highwater; /*!< highest count so far */
struct ast_hashtab *schedq_ht; /*!< hash table for fast searching */
struct ast_heap *sched_heap;
struct sched_thread *sched_thread;
#ifdef SCHED_MAX_CACHE
AST_LIST_HEAD_NOLOCK(, sched) schedc; /*!< Cache of unused schedule structures and how many */
@ -75,151 +93,97 @@ struct sched_context {
#endif
};
struct ast_sched_thread {
pthread_t thread;
ast_mutex_t lock;
ast_cond_t cond;
struct sched_context *context;
unsigned int stop:1;
};
static void *sched_run(void *data)
{
struct ast_sched_thread *st = data;
struct ast_sched_context *con = data;
while (!st->stop) {
while (!con->sched_thread->stop) {
int ms;
struct timespec ts = {
.tv_sec = 0,
.tv_sec = 0,
};
ast_mutex_lock(&st->lock);
ast_mutex_lock(&con->lock);
if (st->stop) {
ast_mutex_unlock(&st->lock);
if (con->sched_thread->stop) {
ast_mutex_unlock(&con->lock);
return NULL;
}
ms = ast_sched_wait(st->context);
ms = ast_sched_wait(con);
if (ms == -1) {
ast_cond_wait(&st->cond, &st->lock);
} else {
ast_cond_wait(&con->sched_thread->cond, &con->lock);
} else {
struct timeval tv;
tv = ast_tvadd(ast_tvnow(), ast_samp2tv(ms, 1000));
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
ast_cond_timedwait(&st->cond, &st->lock, &ts);
ast_cond_timedwait(&con->sched_thread->cond, &con->lock, &ts);
}
ast_mutex_unlock(&st->lock);
ast_mutex_unlock(&con->lock);
if (st->stop) {
if (con->sched_thread->stop) {
return NULL;
}
ast_sched_runq(st->context);
ast_sched_runq(con);
}
return NULL;
}
void ast_sched_thread_poke(struct ast_sched_thread *st)
static void sched_thread_destroy(struct ast_sched_context *con)
{
ast_mutex_lock(&st->lock);
ast_cond_signal(&st->cond);
ast_mutex_unlock(&st->lock);
}
struct sched_context *ast_sched_thread_get_context(struct ast_sched_thread *st)
{
return st->context;
}
struct ast_sched_thread *ast_sched_thread_destroy(struct ast_sched_thread *st)
{
if (st->thread != AST_PTHREADT_NULL) {
ast_mutex_lock(&st->lock);
st->stop = 1;
ast_cond_signal(&st->cond);
ast_mutex_unlock(&st->lock);
pthread_join(st->thread, NULL);
st->thread = AST_PTHREADT_NULL;
if (!con->sched_thread) {
return;
}
ast_mutex_destroy(&st->lock);
ast_cond_destroy(&st->cond);
if (st->context) {
sched_context_destroy(st->context);
st->context = NULL;
if (con->sched_thread->thread != AST_PTHREADT_NULL) {
ast_mutex_lock(&con->lock);
con->sched_thread->stop = 1;
ast_cond_signal(&con->sched_thread->cond);
ast_mutex_unlock(&con->lock);
pthread_join(con->sched_thread->thread, NULL);
con->sched_thread->thread = AST_PTHREADT_NULL;
}
ast_free(st);
ast_cond_destroy(&con->sched_thread->cond);
return NULL;
ast_free(con->sched_thread);
con->sched_thread = NULL;
}
struct ast_sched_thread *ast_sched_thread_create(void)
int ast_sched_start_thread(struct ast_sched_context *con)
{
struct ast_sched_thread *st;
struct sched_thread *st;
if (con->sched_thread) {
ast_log(LOG_ERROR, "Thread already started on this scheduler context\n");
return -1;
}
if (!(st = ast_calloc(1, sizeof(*st)))) {
return NULL;
return -1;
}
ast_mutex_init(&st->lock);
ast_cond_init(&st->cond, NULL);
st->thread = AST_PTHREADT_NULL;
if (!(st->context = sched_context_create())) {
ast_log(LOG_ERROR, "Failed to create scheduler\n");
ast_sched_thread_destroy(st);
return NULL;
}
if (ast_pthread_create_background(&st->thread, NULL, sched_run, st)) {
con->sched_thread = st;
if (ast_pthread_create_background(&st->thread, NULL, sched_run, con)) {
ast_log(LOG_ERROR, "Failed to create scheduler thread\n");
ast_sched_thread_destroy(st);
return NULL;
sched_thread_destroy(con);
return -1;
}
return st;
return 0;
}
int ast_sched_thread_add_variable(struct ast_sched_thread *st, int when, ast_sched_cb cb,
const void *data, int variable)
{
int res;
ast_mutex_lock(&st->lock);
res = ast_sched_add_variable(st->context, when, cb, data, variable);
if (res != -1) {
ast_cond_signal(&st->cond);
}
ast_mutex_unlock(&st->lock);
return res;
}
int ast_sched_thread_add(struct ast_sched_thread *st, int when, ast_sched_cb cb,
const void *data)
{
int res;
ast_mutex_lock(&st->lock);
res = ast_sched_add(st->context, when, cb, data);
if (res != -1) {
ast_cond_signal(&st->cond);
}
ast_mutex_unlock(&st->lock);
return res;
}
/* hash routines for sched */
static int sched_cmp(const void *a, const void *b)
{
const struct sched *as = a;
@ -239,12 +203,13 @@ static int sched_time_cmp(void *a, void *b)
return ast_tvcmp(((struct sched *) b)->when, ((struct sched *) a)->when);
}
struct sched_context *sched_context_create(void)
struct ast_sched_context *ast_sched_context_create(void)
{
struct sched_context *tmp;
struct ast_sched_context *tmp;
if (!(tmp = ast_calloc(1, sizeof(*tmp))))
if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
return NULL;
}
ast_mutex_init(&tmp->lock);
tmp->eventcnt = 1;
@ -253,23 +218,26 @@ struct sched_context *sched_context_create(void)
if (!(tmp->sched_heap = ast_heap_create(8, sched_time_cmp,
offsetof(struct sched, __heap_index)))) {
sched_context_destroy(tmp);
ast_sched_context_destroy(tmp);
return NULL;
}
return tmp;
}
void sched_context_destroy(struct sched_context *con)
void ast_sched_context_destroy(struct ast_sched_context *con)
{
struct sched *s;
sched_thread_destroy(con);
con->sched_thread = NULL;
ast_mutex_lock(&con->lock);
#ifdef SCHED_MAX_CACHE
/* Eliminate the cache */
while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list)))
while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list))) {
ast_free(s);
}
#endif
if (con->sched_heap) {
@ -282,14 +250,14 @@ void sched_context_destroy(struct sched_context *con)
ast_hashtab_destroy(con->schedq_ht, NULL);
con->schedq_ht = NULL;
/* And the context */
ast_mutex_unlock(&con->lock);
ast_mutex_destroy(&con->lock);
ast_free(con);
}
static struct sched *sched_alloc(struct sched_context *con)
static struct sched *sched_alloc(struct ast_sched_context *con)
{
struct sched *tmp;
@ -307,7 +275,7 @@ static struct sched *sched_alloc(struct sched_context *con)
return tmp;
}
static void sched_release(struct sched_context *con, struct sched *tmp)
static void sched_release(struct ast_sched_context *con, struct sched *tmp)
{
/*
* Add to the cache, or just free() if we
@ -327,7 +295,7 @@ static void sched_release(struct sched_context *con, struct sched *tmp)
* Return the number of milliseconds
* until the next scheduled event
*/
int ast_sched_wait(struct sched_context *con)
int ast_sched_wait(struct ast_sched_context *con)
{
int ms;
struct sched *s;
@ -354,7 +322,7 @@ int ast_sched_wait(struct sched_context *con)
* queue, such that the soonest event is
* first in the list.
*/
static void schedule(struct sched_context *con, struct sched *s)
static void schedule(struct ast_sched_context *con, struct sched *s)
{
ast_heap_push(con->sched_heap, s);
@ -387,7 +355,7 @@ static int sched_settime(struct timeval *t, int when)
return 0;
}
int ast_sched_replace_variable(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data, int 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)
{
/* 0 means the schedule item is new; do not delete */
if (old_id > 0) {
@ -399,7 +367,7 @@ int ast_sched_replace_variable(int old_id, struct sched_context *con, int when,
/*! \brief
* Schedule callback(data) to happen when ms into the future
*/
int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
{
struct sched *tmp;
int res = -1;
@ -426,12 +394,15 @@ int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb cal
if (option_debug)
ast_sched_dump(con);
#endif
if (con->sched_thread) {
ast_cond_signal(&con->sched_thread->cond);
}
ast_mutex_unlock(&con->lock);
return res;
}
int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched_cb callback, const void *data)
int ast_sched_replace(int old_id, struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
{
if (old_id > -1) {
AST_SCHED_DEL(con, old_id);
@ -439,12 +410,12 @@ int ast_sched_replace(int old_id, struct sched_context *con, int when, ast_sched
return ast_sched_add(con, when, callback, data);
}
int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data)
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data)
{
return ast_sched_add_variable(con, when, callback, data, 0);
}
const void *ast_sched_find_data(struct sched_context *con, int id)
const void *ast_sched_find_data(struct ast_sched_context *con, int id)
{
struct sched tmp,*res;
tmp.id = id;
@ -461,9 +432,9 @@ const void *ast_sched_find_data(struct sched_context *con, int id)
* id.
*/
#ifndef AST_DEVMODE
int ast_sched_del(struct sched_context *con, int id)
int ast_sched_del(struct ast_sched_context *con, int id)
#else
int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function)
int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int line, const char *function)
#endif
{
struct sched *s, tmp = {
@ -498,6 +469,9 @@ int _ast_sched_del(struct sched_context *con, int id, const char *file, int line
if (option_debug)
ast_sched_dump(con);
#endif
if (con->sched_thread) {
ast_cond_signal(&con->sched_thread->cond);
}
ast_mutex_unlock(&con->lock);
if (!s && *last_id != id) {
@ -520,7 +494,7 @@ int _ast_sched_del(struct sched_context *con, int id, const char *file, int line
return 0;
}
void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames)
void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames)
{
int i, x;
struct sched *cur;
@ -558,7 +532,7 @@ void ast_sched_report(struct sched_context *con, struct ast_str **buf, struct as
}
/*! \brief Dump the contents of the scheduler to LOG_DEBUG */
void ast_sched_dump(struct sched_context *con)
void ast_sched_dump(struct ast_sched_context *con)
{
struct sched *q;
struct timeval when = ast_tvnow();
@ -593,7 +567,7 @@ void ast_sched_dump(struct sched_context *con)
/*! \brief
* Launch all events which need to be run at this time.
*/
int ast_sched_runq(struct sched_context *con)
int ast_sched_runq(struct ast_sched_context *con)
{
struct sched *current;
struct timeval when;
@ -601,7 +575,7 @@ int ast_sched_runq(struct sched_context *con)
int res;
DEBUG(ast_debug(1, "ast_sched_runq()\n"));
ast_mutex_lock(&con->lock);
when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
@ -614,7 +588,7 @@ int ast_sched_runq(struct sched_context *con)
if (ast_tvcmp(current->when, when) != -1) {
break;
}
current = ast_heap_pop(con->sched_heap);
if (!ast_hashtab_remove_this_object(con->schedq_ht, current)) {
@ -631,13 +605,13 @@ int ast_sched_runq(struct sched_context *con)
* the schedule queue. If that's what it wants to do, it
* should return 0.
*/
ast_mutex_unlock(&con->lock);
res = current->callback(current->data);
ast_mutex_lock(&con->lock);
if (res) {
/*
/*
* If they return non-zero, we should schedule them to be
* run again.
*/
@ -653,27 +627,27 @@ int ast_sched_runq(struct sched_context *con)
}
ast_mutex_unlock(&con->lock);
return numevents;
}
long ast_sched_when(struct sched_context *con,int id)
long ast_sched_when(struct ast_sched_context *con,int id)
{
struct sched *s, tmp;
long secs = -1;
DEBUG(ast_debug(1, "ast_sched_when()\n"));
ast_mutex_lock(&con->lock);
/* these next 2 lines replace a lookup loop */
tmp.id = id;
s = ast_hashtab_lookup(con->schedq_ht, &tmp);
if (s) {
struct timeval now = ast_tvnow();
secs = s->when.tv_sec - now.tv_sec;
}
ast_mutex_unlock(&con->lock);
return secs;
}

View File

@ -124,7 +124,7 @@ struct ast_udptl {
struct ast_sockaddr us;
struct ast_sockaddr them;
int *ioid;
struct sched_context *sched;
struct ast_sched_context *sched;
struct io_context *io;
void *data;
char *tag;
@ -913,7 +913,7 @@ unsigned int ast_udptl_get_far_max_ifp(struct ast_udptl *udptl)
return udptl->far_max_ifp;
}
struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, struct io_context *io, int callbackmode, struct ast_sockaddr *addr)
{
struct ast_udptl *udptl;
int x;

View File

@ -173,7 +173,7 @@ enum {
#endif
static struct io_context *io;
static struct sched_context *sched;
static struct ast_sched_context *sched;
static int netsocket = -1;
static pthread_t netthreadid = AST_PTHREADT_NULL;
static pthread_t precachethreadid = AST_PTHREADT_NULL;
@ -4803,7 +4803,7 @@ static int unload_module(void)
ast_custom_function_unregister(&dundi_result_function);
close(netsocket);
io_context_destroy(io);
sched_context_destroy(sched);
ast_sched_context_destroy(sched);
mark_mappings();
prune_mappings();
@ -4836,7 +4836,7 @@ static int load_module(void)
/* Make a UDP socket */
io = io_context_create();
sched = sched_context_create();
sched = ast_sched_context_create();
if (!io || !sched)
return AST_MODULE_LOAD_DECLINE;

View File

@ -165,7 +165,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define CALENDAR_BUCKETS 19
static struct ao2_container *calendars;
static struct sched_context *sched;
static struct ast_sched_context *sched;
static pthread_t refresh_thread = AST_PTHREADT_NULL;
static ast_mutex_t refreshlock;
static ast_cond_t refresh_condition;
@ -1696,7 +1696,7 @@ static int load_module(void)
ast_cond_init(&refresh_condition, NULL);
ast_mutex_init(&reloadlock);
if (!(sched = sched_context_create())) {
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create sched context\n");
return AST_MODULE_LOAD_FAILURE;
}

View File

@ -159,7 +159,7 @@ struct ast_rtp {
int *ioid;
unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
unsigned short rxseqno;
struct sched_context *sched;
struct ast_sched_context *sched;
struct io_context *io;
void *data;
struct ast_rtcp *rtcp;
@ -251,7 +251,7 @@ struct rtp_red {
AST_LIST_HEAD_NOLOCK(frame_list, ast_frame);
/* Forward Declarations */
static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
static int ast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data);
static int ast_rtp_destroy(struct ast_rtp_instance *instance);
static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
@ -434,7 +434,7 @@ static int create_new_socket(const char *type, int af)
}
static int ast_rtp_new(struct ast_rtp_instance *instance,
struct sched_context *sched, struct ast_sockaddr *addr,
struct ast_sched_context *sched, struct ast_sockaddr *addr,
void *data)
{
struct ast_rtp *rtp = NULL;

View File

@ -89,7 +89,7 @@ struct multicast_rtp {
};
/* Forward Declarations */
static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data);
static int multicast_rtp_activate(struct ast_rtp_instance *instance);
static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
@ -106,7 +106,7 @@ static struct ast_rtp_engine multicast_rtp_engine = {
};
/*! \brief Function called to create a new multicast instance */
static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
{
struct multicast_rtp *multicast;
const char *type = data;

View File

@ -39,7 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static const int DEFAULT_MONITOR_REFRESH = 30;
static const char stun_conf_file[] = "res_stun_monitor.conf";
static struct ast_sched_thread *sched;
static struct ast_sched_context *sched;
static struct {
struct sockaddr_in stunaddr; /*!< The stun address we send requests to*/
@ -150,7 +150,8 @@ monitor_request_cleanup:
static void stun_stop_monitor(void)
{
if (sched) {
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
ast_log(LOG_NOTICE, "STUN monitor stopped\n");
}
/* it is only safe to destroy the socket without holding arg->lock
@ -188,20 +189,29 @@ static int stun_start_monitor(void)
return 0; /* already started */
}
if (!(sched = ast_sched_thread_create())) {
ast_log(LOG_ERROR, "Failed to create stun monitor scheduler thread\n");
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Failed to create stun monitor scheduler context\n");
stun_close_sock();
return -1;
}
if (ast_sched_thread_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) {
if (ast_sched_start_thread(sched)) {
ast_sched_context_destroy(sched);
sched = NULL;
stun_close_sock();
return -1;
}
if (ast_sched_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) {
ast_log(LOG_ERROR, "Unable to schedule STUN network monitor \n");
sched = ast_sched_thread_destroy(sched);
ast_sched_context_destroy(sched);
sched = NULL;
stun_close_sock();
return -1;
}
ast_log(LOG_NOTICE, "STUN monitor started\n");
return 0;
}

View File

@ -46,7 +46,7 @@ static int sched_cb(const void *data)
AST_TEST_DEFINE(sched_test_order)
{
struct sched_context *con;
struct ast_sched_context *con;
enum ast_test_result_state res = AST_TEST_FAIL;
int id1, id2, id3, wait;
@ -63,7 +63,7 @@ AST_TEST_DEFINE(sched_test_order)
break;
}
if (!(con = sched_context_create())) {
if (!(con = ast_sched_context_create())) {
ast_test_status_update(test,
"Test failed - could not create scheduler context\n");
return AST_TEST_FAIL;
@ -154,14 +154,14 @@ AST_TEST_DEFINE(sched_test_order)
res = AST_TEST_PASS;
return_cleanup:
sched_context_destroy(con);
ast_sched_context_destroy(con);
return res;
}
static char *handle_cli_sched_bench(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct sched_context *con;
struct ast_sched_context *con;
struct timeval start;
unsigned int num, i;
int *sched_ids = NULL;
@ -185,7 +185,7 @@ static char *handle_cli_sched_bench(struct ast_cli_entry *e, int cmd, struct ast
return CLI_SHOWUSAGE;
}
if (!(con = sched_context_create())) {
if (!(con = ast_sched_context_create())) {
ast_cli(a->fd, "Test failed - could not create scheduler context\n");
return CLI_FAILURE;
}
@ -225,7 +225,7 @@ static char *handle_cli_sched_bench(struct ast_cli_entry *e, int cmd, struct ast
ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
return_cleanup:
sched_context_destroy(con);
ast_sched_context_destroy(con);
if (sched_ids) {
ast_free(sched_ids);
}