]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/unix_semaphore.cc
Merge pull request #7908 from omoerbeek/rec-4.1.14-changelog
[thirdparty/pdns.git] / pdns / unix_semaphore.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "utility.hh"
26 #include <cstring>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include "pdnsexception.hh"
31 #include "logger.hh"
32 #include "misc.hh"
33 #include <pwd.h>
34 #include <grp.h>
35 #include <sys/types.h>
36
37
38 #if defined(_AIX) || defined(__APPLE__)
39
40 // Darwin 6.0 Compatible implementation, uses pthreads so it portable across more platforms.
41
42 #define SEM_VALUE_MAX 32767
43 #define SEM_MAGIC ((uint32_t) 0x09fa4012)
44
45 Semaphore::Semaphore(unsigned int value)
46 {
47 if (value > SEM_VALUE_MAX) {
48 throw PDNSException("Cannot create semaphore: value too large");
49 }
50
51 // Initialize
52
53 if (pthread_mutex_init(&m_lock, NULL) != 0) {
54 throw PDNSException("Cannot create semaphore: cannot allocate mutex");
55 }
56
57 if (pthread_cond_init(&m_gtzero, NULL) != 0) {
58 pthread_mutex_destroy(&m_lock);
59 throw PDNSException("Cannot create semaphore: cannot allocate condition");
60 }
61
62 m_count = (uint32_t) value;
63 m_nwaiters = 0;
64 m_magic = SEM_MAGIC;
65 }
66
67 int Semaphore::post()
68 {
69 pthread_mutex_lock(&m_lock);
70
71 m_count++;
72 if (m_nwaiters > 0) {
73 pthread_cond_signal(&m_gtzero);
74 }
75
76 pthread_mutex_unlock(&m_lock);
77
78 return 0;
79 }
80
81 int Semaphore::wait()
82 {
83 pthread_mutex_lock(&m_lock);
84
85 while (m_count == 0) {
86 m_nwaiters++;
87 pthread_cond_wait(&m_gtzero, &m_lock);
88 m_nwaiters--;
89 }
90
91 m_count--;
92
93 pthread_mutex_unlock(&m_lock);
94
95 return 0;
96 }
97
98 int Semaphore::tryWait()
99 {
100 int retval = 0;
101
102 pthread_mutex_lock(&m_lock);
103
104 if (m_count > 0) {
105 m_count--;
106 } else {
107 errno = EAGAIN;
108 retval = -1;
109 }
110
111 pthread_mutex_unlock(&m_lock);
112
113 return retval;
114 }
115
116 int Semaphore::getValue(Semaphore::sem_value_t *sval)
117 {
118 pthread_mutex_lock(&m_lock);
119 *sval = m_count;
120 pthread_mutex_unlock(&m_lock);
121
122 return 0;
123 }
124
125 Semaphore::~Semaphore()
126 {
127 // Make sure there are no waiters.
128
129 pthread_mutex_lock(&m_lock);
130 if (m_nwaiters > 0) {
131 pthread_mutex_unlock(&m_lock);
132 //errno = EBUSY;
133 //return -1;
134 }
135 pthread_mutex_unlock(&m_lock);
136
137 // Destroy it.
138
139 pthread_mutex_destroy(&m_lock);
140 pthread_cond_destroy(&m_gtzero);
141 m_magic = 0;
142
143 //return 0;
144 }
145
146 #else /* not DARWIN from here on */
147
148
149 Semaphore::Semaphore(unsigned int value)
150 {
151 m_pSemaphore=new sem_t;
152 if (sem_init(m_pSemaphore, 0, value) == -1) {
153 g_log << Logger::Error << "Cannot create semaphore: " << stringerror() << endl;
154 exit(1);
155 }
156 }
157
158 int Semaphore::post()
159 {
160 return sem_post(m_pSemaphore);
161 }
162
163 int Semaphore::wait()
164 {
165 int ret;
166 do
167 ret = sem_wait(m_pSemaphore);
168 while (ret == -1 && errno == EINTR);
169 return ret;
170 }
171 int Semaphore::tryWait()
172 {
173 return sem_trywait(m_pSemaphore);
174 }
175
176 int Semaphore::getValue(Semaphore::sem_value_t *sval)
177 {
178 return sem_getvalue(m_pSemaphore, sval);
179 }
180
181 Semaphore::~Semaphore()
182 {
183 delete m_pSemaphore;
184 }
185
186 #endif