sem.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * David M. Lee, II <dlee@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Asterisk semaphore support.
  21. */
  22. #include "asterisk.h"
  23. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  24. #include "asterisk/sem.h"
  25. #include "asterisk/utils.h"
  26. #ifndef HAS_WORKING_SEMAPHORE
  27. /* DIY semaphores! */
  28. int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value)
  29. {
  30. if (pshared) {
  31. /* Don't need it... yet */
  32. errno = ENOSYS;
  33. return -1;
  34. }
  35. /* Since value is unsigned, this will also catch attempts to init with
  36. * a negative value */
  37. if (value > AST_SEM_VALUE_MAX) {
  38. errno = EINVAL;
  39. return -1;
  40. }
  41. sem->count = value;
  42. sem->waiters = 0;
  43. ast_mutex_init(&sem->mutex);
  44. ast_cond_init(&sem->cond, NULL);
  45. return 0;
  46. }
  47. int ast_sem_destroy(struct ast_sem *sem)
  48. {
  49. ast_mutex_destroy(&sem->mutex);
  50. ast_cond_destroy(&sem->cond);
  51. return 0;
  52. }
  53. int ast_sem_post(struct ast_sem *sem)
  54. {
  55. SCOPED_MUTEX(lock, &sem->mutex);
  56. ast_assert(sem->count >= 0);
  57. if (sem->count == AST_SEM_VALUE_MAX) {
  58. errno = EOVERFLOW;
  59. return -1;
  60. }
  61. /* Give it up! */
  62. ++sem->count;
  63. /* Release a waiter, if needed */
  64. if (sem->waiters) {
  65. ast_cond_signal(&sem->cond);
  66. }
  67. return 0;
  68. }
  69. int ast_sem_wait(struct ast_sem *sem)
  70. {
  71. int res;
  72. SCOPED_MUTEX(lock, &sem->mutex);
  73. ast_assert(sem->count >= 0);
  74. /* Wait for a non-zero count */
  75. ++sem->waiters;
  76. while (sem->count == 0) {
  77. res = ast_cond_wait(&sem->cond, &sem->mutex);
  78. /* Give up on error */
  79. if (res != 0) {
  80. --sem->waiters;
  81. return res;
  82. }
  83. }
  84. --sem->waiters;
  85. /* Take it! */
  86. --sem->count;
  87. return 0;
  88. }
  89. int ast_sem_timedwait(struct ast_sem *sem, const struct timespec *abs_timeout)
  90. {
  91. int res;
  92. SCOPED_MUTEX(lock, &sem->mutex);
  93. ast_assert(sem->count >= 0);
  94. /* Wait for a non-zero count */
  95. ++sem->waiters;
  96. while (sem->count == 0) {
  97. res = ast_cond_timedwait(&sem->cond, &sem->mutex, abs_timeout);
  98. /* Give up on error */
  99. if (res != 0) {
  100. --sem->waiters;
  101. return res;
  102. }
  103. }
  104. --sem->waiters;
  105. /* Take it! */
  106. --sem->count;
  107. return 0;
  108. }
  109. int ast_sem_getvalue(struct ast_sem *sem, int *sval)
  110. {
  111. SCOPED_MUTEX(lock, &sem->mutex);
  112. ast_assert(sem->count >= 0);
  113. *sval = sem->count;
  114. return 0;
  115. }
  116. #endif