int ooh323c_start_call_thread(ooCallData *call) { char c = 'c'; struct callthread *cur = callThreads; ast_mutex_lock(&callThreadsLock); while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) { cur = cur->next; } ast_mutex_unlock(&callThreadsLock); if (cur != NULL) { if (cur->inUse || write(cur->thePipe[1], &c, 1) < 0) { ast_mutex_unlock(&cur->lock); cur = NULL; } } /* make new thread */ if (cur == NULL) { if (!(cur = ast_calloc(1, sizeof(struct callthread)))) { ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n", call->callToken); return -1; } ast_module_ref(myself); if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) { ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken); ast_free(cur); return -1; } cur->inUse = TRUE; cur->call = call; ast_mutex_init(&cur->lock); if (gH323Debug) ast_debug(1,"new call thread created for call %s\n", call->callToken); if(ast_pthread_create_detached_background(&call->callThread, NULL, ooh323c_call_thread, cur) < 0) { ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n", call->callToken); ast_mutex_destroy(&cur->lock); close(cur->thePipe[0]); close(cur->thePipe[1]); ast_free(cur); return -1; } } else { if (gH323Debug) ast_debug(1,"using existing call thread for call %s\n", call->callToken); cur->inUse = TRUE; cur->call = call; ast_mutex_unlock(&cur->lock); } return 0; }
/*! \brief Called when a frame should be written out to a channel */ static int bridge_write(struct ast_channel *ast, struct ast_frame *f) { struct bridge_pvt *p = ast->tech_pvt; struct ast_channel *other; ast_mutex_lock(&p->lock); other = (p->input == ast ? p->output : p->input); while (other && ast_channel_trylock(other)) { ast_mutex_unlock(&p->lock); do { CHANNEL_DEADLOCK_AVOIDANCE(ast); } while (ast_mutex_trylock(&p->lock)); other = (p->input == ast ? p->output : p->input); } /* We basically queue the frame up on the other channel if present */ if (other) { ast_queue_frame(other, f); ast_channel_unlock(other); } ast_mutex_unlock(&p->lock); return 0; }
int usecount(void) { /* Simplistic use count */ if (ast_mutex_trylock(&tds_lock)) { return 1; } else { ast_mutex_unlock(&tds_lock); return 0; } }
/*! \brief Helper function to not deadlock when queueing the hangup frame */ static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us) { struct ast_channel *other = (p->input == us ? p->output : p->input); while (other && ast_channel_trylock(other)) { ast_mutex_unlock(&p->lock); do { CHANNEL_DEADLOCK_AVOIDANCE(us); } while (ast_mutex_trylock(&p->lock)); other = (p->input == us ? p->output : p->input); } /* We basically queue the frame up on the other channel if present */ if (other) { ast_queue_hangup(other); ast_channel_unlock(other); } return; }