Index: /branches/1.8/apps/app_queue.c =================================================================== --- /branches/1.8/apps/app_queue.c (revision 335786) +++ /branches/1.8/apps/app_queue.c (working copy) @@ -2366,13 +2366,11 @@ queue_t_unref(q, "Need to find realtime queue"); } - ao2_lock(queues); - q = find_queue_by_name_rt(queuename, queue_vars, member_config); ast_config_destroy(member_config); ast_variables_destroy(queue_vars); - /* update the use_weight value if the queue's has gained or lost a weight */ + /* update the use_weight value if the queue's has gained or lost a weight */ if (q) { if (!q->weight && prev_weight) { ast_atomic_fetchadd_int(&use_weight, -1); @@ -2382,8 +2380,6 @@ } } /* Other cases will end up with the proper value for use_weight */ - ao2_unlock(queues); - } else { update_realtime_members(q); } @@ -2417,10 +2413,9 @@ return; } - ao2_lock(queues); ao2_lock(q); - - /* Temporarily set realtime members dead so we can detect deleted ones.*/ + + /* Temporarily set realtime members dead so we can detect deleted ones.*/ mem_iter = ao2_iterator_init(q->members, 0); while ((m = ao2_iterator_next(&mem_iter))) { if (m->realtime) @@ -2450,7 +2445,6 @@ } ao2_iterator_destroy(&mem_iter); ao2_unlock(q); - ao2_unlock(queues); ast_config_destroy(member_config); } @@ -2465,7 +2459,6 @@ if (!(q = load_realtime_queue(queuename))) return res; - ao2_lock(queues); ao2_lock(q); /* This is our one */ @@ -2474,7 +2467,6 @@ if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) { *reason = QUEUE_JOINEMPTY; ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Done with realtime queue"); return res; } @@ -2538,7 +2530,6 @@ ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos ); } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Done with realtime queue"); return res; @@ -2923,9 +2914,7 @@ struct member *mem; int found = 0; struct ao2_iterator queue_iter; - - /* q's lock and rq's lock already set by try_calling() - * to solve deadlock */ + queue_iter = ao2_iterator_init(queues, 0); while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) { if (q == rq) { /* don't check myself, could deadlock */ @@ -4360,7 +4349,6 @@ struct ao2_iterator memi; struct ast_datastore *datastore, *transfer_ds; struct queue_end_bridge *queue_end_bridge = NULL; - const int need_weight = use_weight; ast_channel_lock(qe->chan); datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL); @@ -4443,9 +4431,6 @@ qe->cancel_answered_elsewhere = 1; } - /* Hold the lock while we setup the outgoing calls */ - if (need_weight) - ao2_lock(queues); ao2_lock(qe->parent); ast_debug(1, "%s is trying to call a queue member.\n", qe->chan->name); @@ -4464,8 +4449,6 @@ ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) - ao2_unlock(queues); goto out; } if (!datastore) { @@ -4473,8 +4456,6 @@ ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4483,8 +4464,6 @@ ao2_ref(cur, -1); ao2_unlock(&qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4521,8 +4500,6 @@ ao2_ref(cur, -1); ao2_unlock(qe->parent); ao2_iterator_destroy(&memi); - if (need_weight) - ao2_unlock(queues); callattempt_free(tmp); goto out; } @@ -4585,8 +4562,6 @@ ++qe->pending; ao2_unlock(qe->parent); ring_one(qe, outgoing, &numbusies); - if (need_weight) - ao2_unlock(queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline); /* The ast_channel_datastore_remove() function could fail here if the * datastore was moved to another channel during a masquerade. If this is @@ -5188,7 +5163,6 @@ ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface)); if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) { - ao2_lock(queues); ao2_lock(q); if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) { /* XXX future changes should beware of this assumption!! */ @@ -5196,7 +5170,6 @@ ao2_ref(mem, -1); ao2_unlock(q); queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference"); - ao2_unlock(queues); return RES_NOT_DYNAMIC; } q->membercount--; @@ -5216,7 +5189,6 @@ res = RES_EXISTS; } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Expiring temporary reference"); } @@ -5241,8 +5213,6 @@ if (!(q = load_realtime_queue(queuename))) return res; - ao2_lock(queues); - ao2_lock(q); if ((old_member = interface_exists(q, interface)) == NULL) { if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) { @@ -5279,7 +5249,6 @@ res = RES_EXISTS; } ao2_unlock(q); - ao2_unlock(queues); queue_t_unref(q, "Expiring temporary reference"); return res; @@ -5460,8 +5429,6 @@ struct call_queue *cur_queue; char queue_data[PM_MAX_LEN]; - ao2_lock(queues); - /* Each key in 'pm_family' is the name of a queue */ db_tree = ast_db_gettree(pm_family, NULL); for (entry = db_tree; entry; entry = entry->next) { @@ -5532,7 +5499,6 @@ queue_t_unref(cur_queue, "Expire reload reference"); } - ao2_unlock(queues); if (db_tree) { ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n"); ast_db_freetree(db_tree); @@ -6810,12 +6776,12 @@ /* We've made it here, so it looks like we're doing operations on all queues. */ ao2_lock(queues); - + /* Mark all queues as dead for the moment if we're reloading queues. * For clarity, we could just be reloading members, in which case we don't want to mess * with the other queue parameters at all*/ if (queue_reload) { - ao2_callback(queues, OBJ_NODATA, mark_dead_and_unfound, (char *) queuename); + ao2_callback(queues, OBJ_NODATA | OBJ_NOLOCK, mark_dead_and_unfound, (char *) queuename); } /* Chug through config file */ @@ -6832,17 +6798,17 @@ ast_config_destroy(cfg); /* Unref all the dead queues if we were reloading queues */ if (queue_reload) { - ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename); + ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_dead_queues, (char *) queuename); } ao2_unlock(queues); return 0; } - + /*! \brief Facilitates resetting statistics for a queue * * This function actually does not reset any statistics, but * rather finds a call_queue struct which corresponds to the - * passed-in queue name and passes that structure to the + * passed-in queue name and passes that structure to the * clear_queue function. If no queuename is passed in, then * all queues will have their statistics reset. *