/*! \brief ast_context: An extension context */
struct ast_context {
- ast_mutex_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
+ ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
struct ast_exten *root; /*!< The root of the list of extensions */
struct ast_context *next; /*!< Link them together */
struct ast_include *includes; /*!< Include other contexts */
};
static struct ast_context *contexts;
-AST_MUTEX_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
+AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
static AST_RWLIST_HEAD_STATIC(apps, ast_app);
struct ast_context *ast_context_find(const char *name)
{
struct ast_context *tmp = NULL;
- ast_mutex_lock(&conlock);
+ ast_rdlock_contexts();
while ( (tmp = ast_walk_contexts(tmp)) ) {
if (!name || !strcasecmp(name, tmp->name))
break;
}
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return tmp;
}
int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
- ast_mutex_lock(&conlock);
+ ast_rdlock_contexts();
e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
if (e) {
if (matching_action) {
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return -1; /* success, we found it */
} else if (action == E_FINDLABEL) { /* map the label to a priority */
res = e->priority;
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return res; /* the priority we were looking for */
} else { /* spawn */
if (!e->cached_app)
e->cached_app = pbx_findapp(e->app);
app = e->cached_app;
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
if (!app) {
ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
return -1;
return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
}
} else if (q.swo) { /* not found here, but in another switch */
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
if (matching_action)
return -1;
else {
return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
}
} else { /* not found anywhere, see what happened */
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
switch (q.status) {
case STATUS_NO_CONTEXT:
if (!matching_action)
struct ast_exten *e;
struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
- ast_mutex_lock(&conlock);
+ ast_rdlock_contexts();
e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return e;
}
{
struct ast_context *c = NULL;
- ast_lock_contexts();
+ ast_rdlock_contexts();
while ( (c = ast_walk_contexts(c)) ) {
if (!strcmp(ast_get_context_name(c), context))
return c;
struct ast_include *i, *pi = NULL;
int ret = -1;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
/* find our include */
for (i = con->includes; i; pi = i, i = i->next) {
}
}
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
+
return ret;
}
struct ast_sw *i;
int ret = -1;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
/* walk switches */
AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
}
AST_LIST_TRAVERSE_SAFE_END
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return ret;
}
struct ast_exten *exten, *prev_exten = NULL;
struct ast_exten *peer;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
/* scan the extension list to find matching extension-registrar */
for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
}
if (!exten) {
/* we can't find right extension */
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return -1;
}
break; /* found our priority */
}
if (!peer) { /* not found */
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return -1;
}
/* we are first priority extension? */
destroy_exten(peer);
/* XXX should we return -1 ? */
}
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return 0;
}
struct ast_context *c = NULL;
int ret = -1;
- ast_lock_contexts();
+ ast_rdlock_contexts();
while ((c = ast_walk_contexts(c))) {
if (!strcmp(ast_get_context_name(c), context)) {
struct ast_context *c = NULL;
int ret = -1;
- ast_lock_contexts();
+ ast_rdlock_contexts();
while ((c = ast_walk_contexts(c))) {
if (!strcmp(ast_get_context_name(c), context)) {
if (pos != 2)
return NULL;
- ast_lock_contexts();
+ ast_rdlock_contexts();
wordlen = strlen(word);
struct ast_context *c = NULL;
int res = 0, old_total_exten = dpc->total_exten;
- ast_lock_contexts();
+ ast_rdlock_contexts();
/* walk all contexts ... */
while ( (c = ast_walk_contexts(c)) ) {
dpc->context_existence = 1;
- ast_lock_context(c);
+ ast_rdlock_context(c);
/* are we looking for exten too? if yes, we print context
* only if we find our extension.
ast_log(LOG_DEBUG, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
/* try to lock contexts */
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
astman_send_error(s, m, "Failed to lock contexts\r\n");
ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
return -1;
if (option_debug > 2)
ast_log(LOG_DEBUG, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
- if (ast_lock_context(c)) { /* failed to lock */
+ if (ast_rdlock_context(c)) { /* failed to lock */
if (option_debug > 2)
ast_log(LOG_DEBUG, "manager_show_dialplan: Failed to lock context\n");
continue;
struct ast_context *context = NULL;
struct ast_exten *eroot = NULL, *e = NULL;
- ast_lock_contexts();
+ ast_rdlock_contexts();
while ((context = ast_walk_contexts(context))) {
while ((eroot = ast_walk_context_extensions(context, eroot))) {
while ((e = ast_walk_extension_priorities(eroot, e))) {
int length = sizeof(struct ast_context) + strlen(name) + 1;
if (!extcontexts) {
- ast_mutex_lock(&conlock);
+ ast_wrlock_contexts();
local_contexts = &contexts;
} else
local_contexts = extcontexts;
tmp = NULL;
}
if (!extcontexts)
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return tmp;
}
}
if ((tmp = ast_calloc(1, length))) {
- ast_mutex_init(&tmp->lock);
+ ast_rwlock_init(&tmp->lock);
ast_mutex_init(&tmp->macrolock);
strcpy(tmp->name, name);
tmp->root = NULL;
}
if (!extcontexts)
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return tmp;
}
in addition, the locks _must_ be taken in this order, because there are already
other code paths that use this order
*/
- ast_mutex_lock(&conlock);
+ ast_wrlock_contexts();
AST_RWLIST_WRLOCK(&hints);
/* preserve all watchers for hints associated with this registrar */
}
AST_RWLIST_UNLOCK(&hints);
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
return;
}
new_include->next = NULL;
new_include->registrar = registrar;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
/* ... go to last include and check if context is already included too... */
for (i = con->includes; i; i = i->next) {
if (!strcasecmp(i->name, new_include->name)) {
free(new_include);
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
errno = EEXIST;
return -1;
}
con->includes = new_include;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
- ast_mutex_unlock(&con->lock);
+
+ ast_unlock_context(con);
return 0;
}
new_sw->registrar = registrar;
/* ... try to lock this context ... */
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
/* ... go to last sw and check if context is already swd too... */
AST_LIST_TRAVERSE(&con->alts, i, list) {
if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
free(new_sw);
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
errno = EEXIST;
return -1;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return 0;
}
{
struct ast_ignorepat *ip, *ipl = NULL;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
for (ip = con->ignorepats; ip; ip = ip->next) {
if (!strcmp(ip->pattern, ignorepat) &&
con->ignorepats = ip->next;
free(ip);
}
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return 0;
}
ipl = ip;
}
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
errno = EINVAL;
return -1;
}
strcpy((char *)ignorepat->pattern, value);
ignorepat->next = NULL;
ignorepat->registrar = registrar;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
ignorepatl = ignorepatc;
if (!strcasecmp(ignorepatc->pattern, value)) {
/* Already there */
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
errno = EEXIST;
return -1;
}
ignorepatl->next = ignorepat;
else
con->ignorepats = ignorepat;
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
return 0;
}
tmp->datad = datad;
tmp->registrar = registrar;
- ast_mutex_lock(&con->lock);
+ ast_wrlock_context(con);
res = 0; /* some compilers will think it is uninitialized otherwise */
for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
res = ext_cmp(e->exten, extension);
}
if (e && res == 0) { /* exact match, insert in the pri chain */
res = add_pri(con, tmp, el, e, replace);
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
if (res < 0) {
errno = EEXIST; /* XXX do we care ? */
return 0; /* XXX should we return -1 maybe ? */
el->next = tmp;
else
con->root = tmp;
- ast_mutex_unlock(&con->lock);
+ ast_unlock_context(con);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
}
struct ast_exten *e, *el, *en;
struct ast_ignorepat *ipi;
- ast_mutex_lock(&conlock);
+ ast_wrlock_contexts();
for (tmp = contexts; tmp; ) {
struct ast_context *next; /* next starting point */
for (; tmp; tmpl = tmp, tmp = tmp->next) {
}
if (!tmp) /* not found, we are done */
break;
- ast_mutex_lock(&tmp->lock);
+ ast_wrlock_context(tmp);
if (option_debug)
ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
next = tmp->next;
contexts = next;
/* Okay, now we're safe to let it go -- in a sense, we were
ready to let it go as soon as we locked it. */
- ast_mutex_unlock(&tmp->lock);
+ ast_unlock_context(tmp);
for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
struct ast_include *tmpil = tmpi;
tmpi = tmpi->next;
e = e->next;
destroy_exten(el);
}
- ast_mutex_destroy(&tmp->lock);
+ ast_rwlock_destroy(&tmp->lock);
free(tmp);
/* if we have a specific match, we are done, otherwise continue */
tmp = con ? NULL : next;
}
- ast_mutex_unlock(&conlock);
+ ast_unlock_contexts();
}
void ast_context_destroy(struct ast_context *con, const char *registrar)
/*
* Lock context list functions ...
*/
-int ast_lock_contexts()
+int ast_wrlock_contexts()
+{
+ return ast_rwlock_wrlock(&conlock);
+}
+
+int ast_rdlock_contexts()
{
- return ast_mutex_lock(&conlock);
+ return ast_rwlock_rdlock(&conlock);
}
int ast_unlock_contexts()
{
- return ast_mutex_unlock(&conlock);
+ return ast_rwlock_unlock(&conlock);
}
/*
* Lock context ...
*/
-int ast_lock_context(struct ast_context *con)
+int ast_wrlock_context(struct ast_context *con)
+{
+ return ast_rwlock_wrlock(&con->lock);
+}
+
+int ast_rdlock_context(struct ast_context *con)
{
- return ast_mutex_lock(&con->lock);
+ return ast_rwlock_rdlock(&con->lock);
}
int ast_unlock_context(struct ast_context *con)
{
- return ast_mutex_unlock(&con->lock);
+ return ast_rwlock_unlock(&con->lock);
}
/*
{
struct ast_include *i = NULL;
- if (ast_lock_context(c)) /* error, skip */
+ if (ast_rdlock_context(c)) /* error, skip */
return 0;
while ( (i = ast_walk_context_includes(c, i)) )
if (!strcmp(name, ast_get_include_name(i)))
{
struct ast_ignorepat *ip = NULL;
- if (ast_lock_context(c)) /* error, skip */
+ if (ast_rdlock_context(c)) /* error, skip */
return 0;
while ( (ip = ast_walk_context_ignorepats(c, ip)) )
if (!strcmp(name, ast_get_ignorepat_name(ip)))
struct ast_context *c = NULL;
if (pos == 3) { /* "dialplan remove include _X_" */
- if (ast_lock_contexts()) {
+ if (ast_wrlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
return NULL;
}
while (!res && (c = ast_walk_contexts(c))) {
struct ast_include *i = NULL;
- if (ast_lock_context(c)) /* error ? skip this one */
+ if (ast_rdlock_context(c)) /* error ? skip this one */
continue;
while ( !res && (i = ast_walk_context_includes(c, i)) ) {
}
strsep(&dupline, " ");
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock contexts list\n");
free(context);
return NULL;
return NULL;
}
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
free(context);
return NULL;
le = strlen(exten);
lc = strlen(context);
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
goto error2;
}
if (le == 0 || lc == 0)
goto error3;
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
goto error3;
}
int len = strlen(word);
if (pos == 3) { /* 'dialplan add include _X_' (context) ... */
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
return NULL;
}
strsep(&dupline, " ");
/* check for context existence ... */
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
/* our fault, we can't check, so complete 'into' ... */
ret = strdup("into");
goto error3;
}
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock context list\n");
goto error3;
}
cfg = ast_config_load("extensions.conf");
/* try to lock contexts list */
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_cli(fd, "Failed to lock contexts list\n");
ast_mutex_unlock(&save_dialplan_lock);
ast_config_destroy(cfg);
struct ast_sw *sw;
/* try to lock context and fireout all info */
- if (ast_lock_context(c)) { /* lock failure */
+ if (ast_rdlock_context(c)) { /* lock failure */
incomplete = 1;
continue;
}
char *res = NULL;
/* try to lock contexts list ... */
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
return NULL;
}
}
ignorepat = strsep(&dupline, " ");
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock contexts list\n");
return NULL;
}
if (pos == 3) {
int len = strlen(word);
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
return NULL;
}
for (c = NULL; !ret && (c = ast_walk_contexts(c));) {
struct ast_ignorepat *ip;
- if (ast_lock_context(c)) /* error, skip it */
+ if (ast_rdlock_context(c)) /* error, skip it */
continue;
for (ip = NULL; !ret && (ip = ast_walk_context_ignorepats(c, ip));) {
return NULL;
}
- if (ast_lock_contexts()) {
+ if (ast_rdlock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
free(dupline);
return NULL;
}
for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
- if (ast_lock_context(c)) /* fail, skip it */
+ if (ast_rdlock_context(c)) /* fail, skip it */
continue;
if (!partial_match(ast_get_context_name(c), word, len))
continue;