CI: Various updates to buildAsterisk.sh
[asterisk/asterisk.git] / main / sem.c
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
19 /*! \file
20  *
21  * \brief Asterisk semaphore support.
22  */
23
24 #include "asterisk.h"
25
26 #include "asterisk/sem.h"
27 #include "asterisk/utils.h"
28
29 #ifndef HAS_WORKING_SEMAPHORE
30
31 /* DIY semaphores! */
32
33 int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value)
34 {
35         if (pshared) {
36                 /* Don't need it... yet */
37                 errno = ENOSYS;
38                 return -1;
39         }
40
41         /* Since value is unsigned, this will also catch attempts to init with
42          * a negative value */
43         if (value > AST_SEM_VALUE_MAX) {
44                 errno = EINVAL;
45                 return -1;
46         }
47
48         sem->count = value;
49         sem->waiters = 0;
50         ast_mutex_init(&sem->mutex);
51         ast_cond_init(&sem->cond, NULL);
52         return 0;
53 }
54
55 int ast_sem_destroy(struct ast_sem *sem)
56 {
57         ast_mutex_destroy(&sem->mutex);
58         ast_cond_destroy(&sem->cond);
59         return 0;
60 }
61
62 int ast_sem_post(struct ast_sem *sem)
63 {
64         SCOPED_MUTEX(lock, &sem->mutex);
65
66         ast_assert(sem->count >= 0);
67
68         if (sem->count == AST_SEM_VALUE_MAX) {
69                 errno = EOVERFLOW;
70                 return -1;
71         }
72
73         /* Give it up! */
74         ++sem->count;
75
76         /* Release a waiter, if needed */
77         if (sem->waiters) {
78                 ast_cond_signal(&sem->cond);
79         }
80
81         return 0;
82 }
83
84 int ast_sem_wait(struct ast_sem *sem)
85 {
86         int res;
87         SCOPED_MUTEX(lock, &sem->mutex);
88
89         ast_assert(sem->count >= 0);
90
91         /* Wait for a non-zero count */
92         ++sem->waiters;
93         while (sem->count == 0) {
94                 res = ast_cond_wait(&sem->cond, &sem->mutex);
95                 /* Give up on error */
96                 if (res != 0) {
97                         --sem->waiters;
98                         return res;
99                 }
100         }
101         --sem->waiters;
102
103         /* Take it! */
104         --sem->count;
105
106         return 0;
107 }
108
109 int ast_sem_timedwait(struct ast_sem *sem, const struct timespec *abs_timeout)
110 {
111         int res;
112         SCOPED_MUTEX(lock, &sem->mutex);
113
114         ast_assert(sem->count >= 0);
115
116         /* Wait for a non-zero count */
117         ++sem->waiters;
118         while (sem->count == 0) {
119                 res = ast_cond_timedwait(&sem->cond, &sem->mutex, abs_timeout);
120                 /* Give up on error */
121                 if (res != 0) {
122                         --sem->waiters;
123                         return res;
124                 }
125         }
126         --sem->waiters;
127
128         /* Take it! */
129         --sem->count;
130
131         return 0;
132 }
133
134 int ast_sem_getvalue(struct ast_sem *sem, int *sval)
135 {
136         SCOPED_MUTEX(lock, &sem->mutex);
137
138         ast_assert(sem->count >= 0);
139
140         *sval = sem->count;
141
142         return 0;
143 }
144
145 #endif