|
|
|
@ -755,11 +755,58 @@ int call_init() { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void __call_iterator_remove(struct call *c) { |
|
|
|
for (unsigned int i = 0; i < NUM_CALL_ITERATORS; i++) { |
|
|
|
struct call *prev_call, *next_call; |
|
|
|
while (1) { |
|
|
|
mutex_lock(&rtpe_call_iterators[i].lock); |
|
|
|
// lock this entry |
|
|
|
mutex_lock(&c->iterator[i].next_lock); |
|
|
|
mutex_lock(&c->iterator[i].prev_lock); |
|
|
|
// try lock adjacent entries |
|
|
|
prev_call = c->iterator[i].link.prev ? c->iterator[i].link.prev->data : NULL; |
|
|
|
next_call = c->iterator[i].link.next ? c->iterator[i].link.next->data : NULL; |
|
|
|
if (prev_call) { |
|
|
|
if (mutex_trylock(&prev_call->iterator[i].next_lock)) { |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
continue; // try again |
|
|
|
} |
|
|
|
} |
|
|
|
if (next_call) { |
|
|
|
if (mutex_trylock(&next_call->iterator[i].prev_lock)) { |
|
|
|
if (prev_call) |
|
|
|
mutex_unlock(&prev_call->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
continue; // try again |
|
|
|
} |
|
|
|
} |
|
|
|
break; // we can remove now |
|
|
|
} |
|
|
|
if (c->iterator[i].link.data) |
|
|
|
obj_put_o(c->iterator[i].link.data); |
|
|
|
rtpe_call_iterators[i].first = g_list_remove_link(rtpe_call_iterators[i].first, |
|
|
|
&c->iterator[i].link); |
|
|
|
ZERO(c->iterator[i].link); |
|
|
|
if (prev_call) |
|
|
|
mutex_unlock(&prev_call->iterator[i].next_lock); |
|
|
|
if (next_call) |
|
|
|
mutex_unlock(&next_call->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
void call_free(void) { |
|
|
|
mqtt_timer_stop(&global_mqtt_timer); |
|
|
|
GList *ll = g_hash_table_get_values(rtpe_callhash); |
|
|
|
for (GList *l = ll; l; l = l->next) { |
|
|
|
struct call *c = l->data; |
|
|
|
__call_iterator_remove(c); |
|
|
|
__call_cleanup(c); |
|
|
|
obj_put(c); |
|
|
|
} |
|
|
|
@ -3107,50 +3154,7 @@ void call_destroy(struct call *c) { |
|
|
|
|
|
|
|
redis_delete(c, rtpe_redis_write); |
|
|
|
|
|
|
|
for (int i = 0; i < NUM_CALL_ITERATORS; i++) { |
|
|
|
struct call *prev_call, *next_call; |
|
|
|
while (1) { |
|
|
|
mutex_lock(&rtpe_call_iterators[i].lock); |
|
|
|
// lock this entry |
|
|
|
mutex_lock(&c->iterator[i].next_lock); |
|
|
|
mutex_lock(&c->iterator[i].prev_lock); |
|
|
|
// try lock adjacent entries |
|
|
|
prev_call = c->iterator[i].link.prev ? c->iterator[i].link.prev->data : NULL; |
|
|
|
next_call = c->iterator[i].link.next ? c->iterator[i].link.next->data : NULL; |
|
|
|
if (prev_call) { |
|
|
|
if (mutex_trylock(&prev_call->iterator[i].next_lock)) { |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
continue; // try again |
|
|
|
} |
|
|
|
} |
|
|
|
if (next_call) { |
|
|
|
if (mutex_trylock(&next_call->iterator[i].prev_lock)) { |
|
|
|
if (prev_call) |
|
|
|
mutex_unlock(&prev_call->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
continue; // try again |
|
|
|
} |
|
|
|
} |
|
|
|
break; // we can remove now |
|
|
|
} |
|
|
|
if (c->iterator[i].link.data) |
|
|
|
obj_put_o(c->iterator[i].link.data); |
|
|
|
rtpe_call_iterators[i].first = g_list_remove_link(rtpe_call_iterators[i].first, |
|
|
|
&c->iterator[i].link); |
|
|
|
ZERO(c->iterator[i].link); |
|
|
|
if (prev_call) |
|
|
|
mutex_unlock(&prev_call->iterator[i].next_lock); |
|
|
|
if (next_call) |
|
|
|
mutex_unlock(&next_call->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&c->iterator[i].next_lock); |
|
|
|
mutex_unlock(&c->iterator[i].prev_lock); |
|
|
|
mutex_unlock(&rtpe_call_iterators[i].lock); |
|
|
|
} |
|
|
|
|
|
|
|
__call_iterator_remove(c); |
|
|
|
|
|
|
|
rwlock_lock_w(&c->master_lock); |
|
|
|
/* at this point, no more packet streams can be added */ |
|
|
|
|