]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/unix_semaphore.cc
Include config.h only in .cc files
[thirdparty/pdns.git] / pdns / unix_semaphore.cc
1 /*
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 - 2005 PowerDNS.COM BV
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
8
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #include "utility.hh"
28 #include <cstring>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include "pdnsexception.hh"
33 #include "logger.hh"
34 #include "misc.hh"
35 #include <pwd.h>
36 #include <grp.h>
37 #include <sys/types.h>
38
39
40 #if defined(_AIX) || defined(__APPLE__)
41
42 // Darwin 6.0 Compatible implementation, uses pthreads so it portable across more platforms.
43
44 #define SEM_VALUE_MAX 32767
45 #define SEM_MAGIC ((uint32_t) 0x09fa4012)
46
47 Semaphore::Semaphore(unsigned int value)
48 {
49 if (value > SEM_VALUE_MAX) {
50 throw PDNSException("Cannot create semaphore: value too large");
51 }
52
53 // Initialize
54
55 if (pthread_mutex_init(&m_lock, NULL) != 0) {
56 throw PDNSException("Cannot create semaphore: cannot allocate mutex");
57 }
58
59 if (pthread_cond_init(&m_gtzero, NULL) != 0) {
60 pthread_mutex_destroy(&m_lock);
61 throw PDNSException("Cannot create semaphore: cannot allocate condition");
62 }
63
64 m_count = (uint32_t) value;
65 m_nwaiters = 0;
66 m_magic = SEM_MAGIC;
67 }
68
69 int Semaphore::post()
70 {
71 pthread_mutex_lock(&m_lock);
72
73 m_count++;
74 if (m_nwaiters > 0) {
75 pthread_cond_signal(&m_gtzero);
76 }
77
78 pthread_mutex_unlock(&m_lock);
79
80 return 0;
81 }
82
83 int Semaphore::wait()
84 {
85 pthread_mutex_lock(&m_lock);
86
87 while (m_count == 0) {
88 m_nwaiters++;
89 pthread_cond_wait(&m_gtzero, &m_lock);
90 m_nwaiters--;
91 }
92
93 m_count--;
94
95 pthread_mutex_unlock(&m_lock);
96
97 return 0;
98 }
99
100 int Semaphore::tryWait()
101 {
102 int retval = 0;
103
104 pthread_mutex_lock(&m_lock);
105
106 if (m_count > 0) {
107 m_count--;
108 } else {
109 errno = EAGAIN;
110 retval = -1;
111 }
112
113 pthread_mutex_unlock(&m_lock);
114
115 return retval;
116 }
117
118 int Semaphore::getValue(Semaphore::sem_value_t *sval)
119 {
120 pthread_mutex_lock(&m_lock);
121 *sval = m_count;
122 pthread_mutex_unlock(&m_lock);
123
124 return 0;
125 }
126
127 Semaphore::~Semaphore()
128 {
129 // Make sure there are no waiters.
130
131 pthread_mutex_lock(&m_lock);
132 if (m_nwaiters > 0) {
133 pthread_mutex_unlock(&m_lock);
134 //errno = EBUSY;
135 //return -1;
136 }
137 pthread_mutex_unlock(&m_lock);
138
139 // Destroy it.
140
141 pthread_mutex_destroy(&m_lock);
142 pthread_cond_destroy(&m_gtzero);
143 m_magic = 0;
144
145 //return 0;
146 }
147
148 #else /* not DARWIN from here on */
149
150
151 Semaphore::Semaphore(unsigned int value)
152 {
153 m_pSemaphore=new sem_t;
154 if (sem_init(m_pSemaphore, 0, value) == -1) {
155 theL() << Logger::Error << "Cannot create semaphore: " << stringerror() << endl;
156 exit(1);
157 }
158 }
159
160 int Semaphore::post()
161 {
162 return sem_post(m_pSemaphore);
163 }
164
165 int Semaphore::wait()
166 {
167 int ret;
168 do
169 ret = sem_wait(m_pSemaphore);
170 while (ret == -1 && errno == EINTR);
171 return ret;
172 }
173 int Semaphore::tryWait()
174 {
175 return sem_trywait(m_pSemaphore);
176 }
177
178 int Semaphore::getValue(Semaphore::sem_value_t *sval)
179 {
180 return sem_getvalue(m_pSemaphore, sval);
181 }
182
183 Semaphore::~Semaphore()
184 {
185 }
186
187 #endif