diff options
Diffstat (limited to 'main/sem.c')
-rw-r--r-- | main/sem.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/main/sem.c b/main/sem.c new file mode 100644 index 000000000..e67d9c72e --- /dev/null +++ b/main/sem.c @@ -0,0 +1,116 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2013, Digium, Inc. + * + * David M. Lee, II <dlee@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Asterisk semaphore support. + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/sem.h" +#include "asterisk/utils.h" + +#ifndef HAS_WORKING_SEMAPHORE + +/* DIY semaphores! */ + +int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value) +{ + if (pshared) { + /* Don't need it... yet */ + errno = ENOSYS; + return -1; + } + + /* Since value is unsigned, this will also catch attempts to init with + * a negative value */ + if (value > AST_SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + + sem->count = value; + sem->waiters = 0; + ast_mutex_init(&sem->mutex); + ast_cond_init(&sem->cond, NULL); + return 0; +} + +int ast_sem_destroy(struct ast_sem *sem) +{ + ast_mutex_destroy(&sem->mutex); + ast_cond_destroy(&sem->cond); + return 0; +} + +int ast_sem_post(struct ast_sem *sem) +{ + SCOPED_MUTEX(lock, &sem->mutex); + + ast_assert(sem->count >= 0); + + if (sem->count == AST_SEM_VALUE_MAX) { + errno = EOVERFLOW; + return -1; + } + + /* Give it up! */ + ++sem->count; + + /* Release a waiter, if needed */ + if (sem->waiters) { + ast_cond_signal(&sem->cond); + } + + return 0; +} + +int ast_sem_wait(struct ast_sem *sem) +{ + SCOPED_MUTEX(lock, &sem->mutex); + + ast_assert(sem->count >= 0); + + /* Wait for a non-zero count */ + ++sem->waiters; + while (sem->count == 0) { + ast_cond_wait(&sem->cond, &sem->mutex); + } + --sem->waiters; + + /* Take it! */ + --sem->count; + + return 0; +} + +int ast_sem_getvalue(struct ast_sem *sem, int *sval) +{ + SCOPED_MUTEX(lock, &sem->mutex); + + ast_assert(sem->count >= 0); + + *sval = sem->count; + + return 0; +} + +#endif |