static void stasis_message_sink_dtor(void *obj) { struct stasis_message_sink *sink = obj; { SCOPED_MUTEX(lock, &sink->lock); while (!sink->is_done) { /* Normally waiting forever is bad, but if we're not * done, we're not done. */ ast_cond_wait(&sink->cond, &sink->lock); } } ast_mutex_destroy(&sink->lock); ast_cond_destroy(&sink->cond); while (sink->num_messages > 0) { ao2_cleanup(sink->messages[--sink->num_messages]); } ast_free(sink->messages); sink->messages = NULL; sink->max_messages = 0; }
/*! * \brief Idle function for worker threads * * The worker waits here until it gets told by the threadpool * to wake up. * * worker is locked before entering this function. * * \param worker The idle worker * \retval 0 The thread is being woken up so that it can conclude. * \retval non-zero The thread is being woken up to do more work. */ static int worker_idle(struct worker_thread *worker) { struct timeval start = ast_tvnow(); struct timespec end = { .tv_sec = start.tv_sec + worker->options.idle_timeout, .tv_nsec = start.tv_usec * 1000, }; while (!worker->wake_up) { if (worker->options.idle_timeout <= 0) { ast_cond_wait(&worker->cond, &worker->lock); } else if (ast_cond_timedwait(&worker->cond, &worker->lock, &end) == ETIMEDOUT) { break; } } if (!worker->wake_up) { ast_debug(1, "Worker thread idle timeout reached. Dying.\n"); threadpool_idle_thread_dead(worker->pool, worker); worker->state = DEAD; } worker->wake_up = 0; return worker->state == ALIVE; } /*! * \brief Change a worker's state * * The threadpool calls into this function in order to let a worker know * how it should proceed. */ static void worker_set_state(struct worker_thread *worker, enum worker_state state) { SCOPED_MUTEX(lock, &worker->lock); worker->state = state; worker->wake_up = 1; ast_cond_signal(&worker->cond); }
int ast_sem_wait(struct ast_sem *sem) { int res; SCOPED_MUTEX(lock, &sem->mutex); ast_assert(sem->count >= 0); /* Wait for a non-zero count */ ++sem->waiters; while (sem->count == 0) { res = ast_cond_wait(&sem->cond, &sem->mutex); /* Give up on error */ if (res != 0) { --sem->waiters; return res; } } --sem->waiters; /* Take it! */ --sem->count; return 0; }
static void *mixmonitor_thread(void *obj) { struct mixmonitor *mixmonitor = obj; struct ast_filestream **fs = NULL; struct ast_filestream **fs_read = NULL; struct ast_filestream **fs_write = NULL; unsigned int oflags; int errflag = 0; struct ast_format format_slin; ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); fs = &mixmonitor->mixmonitor_ds->fs; fs_read = &mixmonitor->mixmonitor_ds->fs_read; fs_write = &mixmonitor->mixmonitor_ds->fs_write; ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag); mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag); mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag); ast_format_set(&format_slin, ast_format_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate), 0); ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* The audiohook must enter and exit the loop locked */ ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { struct ast_frame *fr = NULL; struct ast_frame *fr_read = NULL; struct ast_frame *fr_write = NULL; if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, &format_slin, &fr_read, &fr_write))) { ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) { break; } continue; } /* audiohook lock is not required for the next block. * Unlock it, but remember to lock it before looping or exiting */ ast_audiohook_unlock(&mixmonitor->audiohook); if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->autochan->chan && ast_bridged_channel(mixmonitor->autochan->chan))) { ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); /* Write out the frame(s) */ if ((*fs_read) && (fr_read)) { struct ast_frame *cur; for (cur = fr_read; cur; cur = AST_LIST_NEXT(cur, frame_list)) { ast_writestream(*fs_read, cur); } } if ((*fs_write) && (fr_write)) { struct ast_frame *cur; for (cur = fr_write; cur; cur = AST_LIST_NEXT(cur, frame_list)) { ast_writestream(*fs_write, cur); } } if ((*fs) && (fr)) { struct ast_frame *cur; for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) { ast_writestream(*fs, cur); } } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); } /* All done! free it. */ if (fr) { ast_frame_free(fr, 0); } if (fr_read) { ast_frame_free(fr_read, 0); } if (fr_write) { ast_frame_free(fr_write, 0); } fr = NULL; fr_write = NULL; fr_read = NULL; ast_audiohook_lock(&mixmonitor->audiohook); } ast_audiohook_unlock(&mixmonitor->audiohook); ast_autochan_destroy(mixmonitor->autochan); /* Datastore cleanup. close the filestream and wait for ds destruction */ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds); if (!mixmonitor->mixmonitor_ds->destruction_ok) { ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* kill the audiohook */ destroy_monitor_audiohook(mixmonitor); if (mixmonitor->post_process) { ast_verb(2, "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name); mixmonitor_free(mixmonitor); return NULL; }
static void *mixmonitor_thread(void *obj) { struct mixmonitor *mixmonitor = obj; struct ast_filestream **fs = NULL; unsigned int oflags; char *ext; int errflag = 0; ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); fs = &mixmonitor->mixmonitor_ds->fs; /* The audiohook must enter and exit the loop locked */ ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { struct ast_frame *fr = NULL; ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) break; if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) continue; /* audiohook lock is not required for the next block. * Unlock it, but remember to lock it before looping or exiting */ ast_audiohook_unlock(&mixmonitor->audiohook); ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) { /* Initialize the file if not already done so */ if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) { oflags = O_CREAT | O_WRONLY; oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC; if ((ext = strrchr(mixmonitor->filename, '.'))) *(ext++) = '\0'; else ext = "raw"; if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) { ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext); errflag = 1; } } /* Write out the frame(s) */ if (*fs) { struct ast_frame *cur; for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) { ast_writestream(*fs, cur); } } } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* All done! free it. */ ast_frame_free(fr, 0); ast_audiohook_lock(&mixmonitor->audiohook); } ast_audiohook_unlock(&mixmonitor->audiohook); /* Datastore cleanup. close the filestream and wait for ds destruction */ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds); if (!mixmonitor->mixmonitor_ds->destruction_ok) { ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* kill the audiohook */ destroy_monitor_audiohook(mixmonitor); if (mixmonitor->post_process) { ast_verb(2, "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name); mixmonitor_free(mixmonitor); return NULL; }
static void *mixmonitor_thread(void *obj) { struct mixmonitor *mixmonitor = obj; struct ast_filestream *fs = NULL; unsigned int oflags; char *ext; int errflag = 0; if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name); ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) { struct ast_frame *fr = NULL; ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) break; if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) continue; ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) { ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* Initialize the file if not already done so */ if (!fs && !errflag) { oflags = O_CREAT | O_WRONLY; oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC; if ((ext = strrchr(mixmonitor->filename, '.'))) *(ext++) = '\0'; else ext = "raw"; if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) { ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext); errflag = 1; } } /* Write out the frame */ if (fs) ast_writestream(fs, fr); } else { ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); } /* All done! free it. */ ast_frame_free(fr, 0); } ast_audiohook_detach(&mixmonitor->audiohook); ast_audiohook_unlock(&mixmonitor->audiohook); ast_audiohook_destroy(&mixmonitor->audiohook); if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name); if (fs) ast_closestream(fs); if (mixmonitor->post_process) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!mixmonitor->mixmonitor_ds->destruction_ok) { ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition); ast_free(mixmonitor->mixmonitor_ds); free(mixmonitor); return NULL; }