sem.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. SCOPED_MUTEX(lock, &sem->mutex);
  72. ast_assert(sem->count >= 0);
  73. /* Wait for a non-zero count */
  74. ++sem->waiters;
  75. while (sem->count == 0) {
  76. ast_cond_wait(&sem->cond, &sem->mutex);
  77. }
  78. --sem->waiters;
  79. /* Take it! */
  80. --sem->count;
  81. return 0;
  82. }
  83. int ast_sem_getvalue(struct ast_sem *sem, int *sval)
  84. {
  85. SCOPED_MUTEX(lock, &sem->mutex);
  86. ast_assert(sem->count >= 0);
  87. *sval = sem->count;
  88. return 0;
  89. }
  90. #endif