diff options
-rw-r--r-- | channels/chan_gtalk.c | 4 | ||||
-rw-r--r-- | channels/chan_h323.c | 12 | ||||
-rw-r--r-- | channels/chan_iax2.c | 107 | ||||
-rw-r--r-- | channels/chan_jingle.c | 4 | ||||
-rw-r--r-- | channels/chan_mgcp.c | 10 | ||||
-rw-r--r-- | channels/chan_sip.c | 10 | ||||
-rw-r--r-- | channels/chan_skinny.c | 9 | ||||
-rw-r--r-- | channels/chan_unistim.c | 11 | ||||
-rw-r--r-- | channels/sip/dialplan_functions.c | 2 | ||||
-rw-r--r-- | channels/sip/include/globals.h | 2 | ||||
-rw-r--r-- | include/asterisk.h | 1 | ||||
-rw-r--r-- | include/asterisk/channel.h | 3 | ||||
-rw-r--r-- | include/asterisk/rtp_engine.h | 4 | ||||
-rw-r--r-- | include/asterisk/sched.h | 222 | ||||
-rw-r--r-- | include/asterisk/udptl.h | 2 | ||||
-rw-r--r-- | main/ccss.c | 19 | ||||
-rw-r--r-- | main/cdr.c | 4 | ||||
-rw-r--r-- | main/channel.c | 9 | ||||
-rw-r--r-- | main/dnsmgr.c | 4 | ||||
-rw-r--r-- | main/rtp_engine.c | 2 | ||||
-rw-r--r-- | main/sched.c | 234 | ||||
-rw-r--r-- | main/udptl.c | 4 | ||||
-rw-r--r-- | pbx/pbx_dundi.c | 6 | ||||
-rw-r--r-- | res/res_calendar.c | 4 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 6 | ||||
-rw-r--r-- | res/res_rtp_multicast.c | 4 | ||||
-rw-r--r-- | res/res_stun_monitor.c | 22 | ||||
-rw-r--r-- | tests/test_sched.c | 12 |
28 files changed, 328 insertions, 405 deletions
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 9b7dd80af..280cac4b5 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -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"); } diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 89b452dbc..e549d4299 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -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); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index abd158c01..a6d716b3c 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -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(®istrations); while ((reg = AST_LIST_REMOVE_HEAD(®istrations, 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); diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index c12704835..fd84f1f27 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -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"); } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 499b5e55e..723849785 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -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; } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 691514ddc..c292d448a 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -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(®l); /* 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"); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index e1c903512..0d75888ba 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -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) diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 3c307a682..155890250 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -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)); diff --git a/channels/sip/dialplan_functions.c b/channels/sip/dialplan_functions.c index e14975d5d..abf83e7d4 100644 --- a/channels/sip/dialplan_functions.c +++ b/channels/sip/dialplan_functions.c @@ -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); diff --git a/channels/sip/include/globals.h b/channels/sip/include/globals.h index 414d2189b..0bd2f4d2d 100644 --- a/channels/sip/include/globals.h +++ b/channels/sip/include/globals.h @@ -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; diff --git a/include/asterisk.h b/include/asterisk.h index 9e5814a25..1e9f076eb 100644 --- a/include/asterisk.h +++ b/include/asterisk.h @@ -211,6 +211,7 @@ struct ast_frame; struct ast_module; struct ast_variable; struct ast_str; +struct ast_sched_context; #ifdef bzero #undef bzero diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index f23fab286..78fda54b9 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -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); diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h index 39633c84c..cd9179be1 100644 --- a/include/asterisk/rtp_engine.h +++ b/include/asterisk/rtp_engine.h @@ -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); /*! diff --git a/include/asterisk/sched.h b/include/asterisk/sched.h index 4f5fb4217..c5581fb09 100644 --- a/include/asterisk/sched.h +++ b/include/asterisk/sched.h @@ -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 - * - * 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 + * \brief Start a thread for processing scheduler entries * - * \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) } diff --git a/include/asterisk/udptl.h b/include/asterisk/udptl.h index af80681ac..ae5c5a596 100644 --- a/include/asterisk/udptl.h +++ b/include/asterisk/udptl.h @@ -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. diff --git a/main/ccss.c b/main/ccss.c index 4dcacd360..0b703b4cb 100644 --- a/main/ccss.c +++ b/main/ccss.c @@ -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); diff --git a/main/cdr.c b/main/cdr.c index f2ade2192..1677b1ba3 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -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; diff --git a/main/channel.c b/main/channel.c index 0e5b72308..723d60ef6 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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; } diff --git a/main/dnsmgr.c b/main/dnsmgr.c index 7fb5f8803..23e1ab6ef 100644 --- a/main/dnsmgr.c +++ b/main/dnsmgr.c @@ -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; } diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 0fecff8cf..4a4dbf595 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -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,}}; diff --git a/main/sched.c b/main/sched.c index 8a3602a39..bab8cfbe6 100644 --- a/main/sched.c +++ b/main/sched.c @@ -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) -{ - 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) +static void sched_thread_destroy(struct ast_sched_context *con) { - 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)) { - ast_log(LOG_ERROR, "Failed to create scheduler thread\n"); - ast_sched_thread_destroy(st); - return NULL; - } + con->sched_thread = st; - return st; -} - -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); + if (ast_pthread_create_background(&st->thread, NULL, sched_run, con)) { + ast_log(LOG_ERROR, "Failed to create scheduler thread\n"); + sched_thread_destroy(con); + return -1; } - ast_mutex_unlock(&st->lock); - return res; + return 0; } -/* 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; } diff --git a/main/udptl.c b/main/udptl.c index 100044919..6fbf3784c 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -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; diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index ef482df2c..c9dd3973e 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -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; diff --git a/res/res_calendar.c b/res/res_calendar.c index 5457f86f8..f95c17de2 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -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; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 72032de60..785b4040d 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -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; diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c index 56a8cd23c..4ec71f26e 100644 --- a/res/res_rtp_multicast.c +++ b/res/res_rtp_multicast.c @@ -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; diff --git a/res/res_stun_monitor.c b/res/res_stun_monitor.c index bec76c826..8ce77141d 100644 --- a/res/res_stun_monitor.c +++ b/res/res_stun_monitor.c @@ -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; } diff --git a/tests/test_sched.c b/tests/test_sched.c index 1090e5b48..0062afb09 100644 --- a/tests/test_sched.c +++ b/tests/test_sched.c @@ -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); } |