/src/mozilla-central/security/nss/lib/ssl/sslmutex.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include "seccomon.h" |
6 | | /* This ifdef should match the one in sslsnce.c */ |
7 | | #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS) |
8 | | |
9 | | #include "sslmutex.h" |
10 | | #include "prerr.h" |
11 | | |
12 | | static SECStatus |
13 | | single_process_sslMutex_Init(sslMutex* pMutex) |
14 | 0 | { |
15 | 0 | PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0); |
16 | 0 |
|
17 | 0 | pMutex->u.sslLock = PR_NewLock(); |
18 | 0 | if (!pMutex->u.sslLock) { |
19 | 0 | return SECFailure; |
20 | 0 | } |
21 | 0 | return SECSuccess; |
22 | 0 | } |
23 | | |
24 | | static SECStatus |
25 | | single_process_sslMutex_Destroy(sslMutex* pMutex) |
26 | 0 | { |
27 | 0 | PR_ASSERT(pMutex != 0); |
28 | 0 | PR_ASSERT(pMutex->u.sslLock != 0); |
29 | 0 | if (!pMutex->u.sslLock) { |
30 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
31 | 0 | return SECFailure; |
32 | 0 | } |
33 | 0 | PR_DestroyLock(pMutex->u.sslLock); |
34 | 0 | return SECSuccess; |
35 | 0 | } |
36 | | |
37 | | static SECStatus |
38 | | single_process_sslMutex_Unlock(sslMutex* pMutex) |
39 | 0 | { |
40 | 0 | PR_ASSERT(pMutex != 0); |
41 | 0 | PR_ASSERT(pMutex->u.sslLock != 0); |
42 | 0 | if (!pMutex->u.sslLock) { |
43 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
44 | 0 | return SECFailure; |
45 | 0 | } |
46 | 0 | PR_Unlock(pMutex->u.sslLock); |
47 | 0 | return SECSuccess; |
48 | 0 | } |
49 | | |
50 | | static SECStatus |
51 | | single_process_sslMutex_Lock(sslMutex* pMutex) |
52 | 0 | { |
53 | 0 | PR_ASSERT(pMutex != 0); |
54 | 0 | PR_ASSERT(pMutex->u.sslLock != 0); |
55 | 0 | if (!pMutex->u.sslLock) { |
56 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
57 | 0 | return SECFailure; |
58 | 0 | } |
59 | 0 | PR_Lock(pMutex->u.sslLock); |
60 | 0 | return SECSuccess; |
61 | 0 | } |
62 | | |
63 | | #if defined(LINUX) || defined(AIX) || defined(BEOS) || defined(BSDI) || \ |
64 | | (defined(NETBSD) && __NetBSD_Version__ < 500000000) || defined(OPENBSD) || defined(__GLIBC__) |
65 | | |
66 | | #include <unistd.h> |
67 | | #include <fcntl.h> |
68 | | #include <string.h> |
69 | | #include <errno.h> |
70 | | #include "unix_err.h" |
71 | | #include "pratom.h" |
72 | | |
73 | 0 | #define SSL_MUTEX_MAGIC 0xfeedfd |
74 | | #define NONBLOCKING_POSTS 1 /* maybe this is faster */ |
75 | | |
76 | | #if NONBLOCKING_POSTS |
77 | | |
78 | | #ifndef FNONBLOCK |
79 | | #define FNONBLOCK O_NONBLOCK |
80 | | #endif |
81 | | |
82 | | static int |
83 | | setNonBlocking(int fd, int nonBlocking) |
84 | 0 | { |
85 | 0 | int flags; |
86 | 0 | int err; |
87 | 0 |
|
88 | 0 | flags = fcntl(fd, F_GETFL, 0); |
89 | 0 | if (0 > flags) |
90 | 0 | return flags; |
91 | 0 | if (nonBlocking) |
92 | 0 | flags |= FNONBLOCK; |
93 | 0 | else |
94 | 0 | flags &= ~FNONBLOCK; |
95 | 0 | err = fcntl(fd, F_SETFL, flags); |
96 | 0 | return err; |
97 | 0 | } |
98 | | #endif |
99 | | |
100 | | SECStatus |
101 | | sslMutex_Init(sslMutex* pMutex, int shared) |
102 | 0 | { |
103 | 0 | int err; |
104 | 0 | PR_ASSERT(pMutex); |
105 | 0 | pMutex->isMultiProcess = (PRBool)(shared != 0); |
106 | 0 | if (!shared) { |
107 | 0 | return single_process_sslMutex_Init(pMutex); |
108 | 0 | } |
109 | 0 | pMutex->u.pipeStr.mPipes[0] = -1; |
110 | 0 | pMutex->u.pipeStr.mPipes[1] = -1; |
111 | 0 | pMutex->u.pipeStr.mPipes[2] = -1; |
112 | 0 | pMutex->u.pipeStr.nWaiters = 0; |
113 | 0 |
|
114 | 0 | err = pipe(pMutex->u.pipeStr.mPipes); |
115 | 0 | if (err) { |
116 | 0 | nss_MD_unix_map_default_error(errno); |
117 | 0 | return err; |
118 | 0 | } |
119 | 0 | #if NONBLOCKING_POSTS |
120 | 0 | err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1); |
121 | 0 | if (err) |
122 | 0 | goto loser; |
123 | 0 | #endif |
124 | 0 | |
125 | 0 | pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC; |
126 | 0 |
|
127 | | #if defined(LINUX) && defined(i386) |
128 | | /* Pipe starts out empty */ |
129 | | return SECSuccess; |
130 | | #else |
131 | | /* Pipe starts with one byte. */ |
132 | 0 | return sslMutex_Unlock(pMutex); |
133 | 0 | #endif |
134 | 0 |
|
135 | 0 | loser: |
136 | 0 | nss_MD_unix_map_default_error(errno); |
137 | 0 | close(pMutex->u.pipeStr.mPipes[0]); |
138 | 0 | close(pMutex->u.pipeStr.mPipes[1]); |
139 | 0 | return SECFailure; |
140 | 0 | } |
141 | | |
142 | | SECStatus |
143 | | sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal) |
144 | 0 | { |
145 | 0 | if (PR_FALSE == pMutex->isMultiProcess) { |
146 | 0 | return single_process_sslMutex_Destroy(pMutex); |
147 | 0 | } |
148 | 0 | if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { |
149 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
150 | 0 | return SECFailure; |
151 | 0 | } |
152 | 0 | close(pMutex->u.pipeStr.mPipes[0]); |
153 | 0 | close(pMutex->u.pipeStr.mPipes[1]); |
154 | 0 |
|
155 | 0 | if (processLocal) { |
156 | 0 | return SECSuccess; |
157 | 0 | } |
158 | 0 | |
159 | 0 | pMutex->u.pipeStr.mPipes[0] = -1; |
160 | 0 | pMutex->u.pipeStr.mPipes[1] = -1; |
161 | 0 | pMutex->u.pipeStr.mPipes[2] = -1; |
162 | 0 | pMutex->u.pipeStr.nWaiters = 0; |
163 | 0 |
|
164 | 0 | return SECSuccess; |
165 | 0 | } |
166 | | |
167 | | #if defined(LINUX) && defined(i386) |
168 | | /* No memory barrier needed for this platform */ |
169 | | |
170 | | /* nWaiters includes the holder of the lock (if any) and the number |
171 | | ** threads waiting for it. After incrementing nWaiters, if the count |
172 | | ** is exactly 1, then you have the lock and may proceed. If the |
173 | | ** count is greater than 1, then you must wait on the pipe. |
174 | | */ |
175 | | |
176 | | SECStatus |
177 | | sslMutex_Unlock(sslMutex* pMutex) |
178 | | { |
179 | | PRInt32 newValue; |
180 | | if (PR_FALSE == pMutex->isMultiProcess) { |
181 | | return single_process_sslMutex_Unlock(pMutex); |
182 | | } |
183 | | |
184 | | if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { |
185 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
186 | | return SECFailure; |
187 | | } |
188 | | /* Do Memory Barrier here. */ |
189 | | newValue = PR_ATOMIC_DECREMENT(&pMutex->u.pipeStr.nWaiters); |
190 | | if (newValue > 0) { |
191 | | int cc; |
192 | | char c = 1; |
193 | | do { |
194 | | cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1); |
195 | | } while (cc < 0 && (errno == EINTR || errno == EAGAIN)); |
196 | | if (cc != 1) { |
197 | | if (cc < 0) |
198 | | nss_MD_unix_map_default_error(errno); |
199 | | else |
200 | | PORT_SetError(PR_UNKNOWN_ERROR); |
201 | | return SECFailure; |
202 | | } |
203 | | } |
204 | | return SECSuccess; |
205 | | } |
206 | | |
207 | | SECStatus |
208 | | sslMutex_Lock(sslMutex* pMutex) |
209 | | { |
210 | | PRInt32 newValue; |
211 | | if (PR_FALSE == pMutex->isMultiProcess) { |
212 | | return single_process_sslMutex_Lock(pMutex); |
213 | | } |
214 | | |
215 | | if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { |
216 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
217 | | return SECFailure; |
218 | | } |
219 | | newValue = PR_ATOMIC_INCREMENT(&pMutex->u.pipeStr.nWaiters); |
220 | | /* Do Memory Barrier here. */ |
221 | | if (newValue > 1) { |
222 | | int cc; |
223 | | char c; |
224 | | do { |
225 | | cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1); |
226 | | } while (cc < 0 && errno == EINTR); |
227 | | if (cc != 1) { |
228 | | if (cc < 0) |
229 | | nss_MD_unix_map_default_error(errno); |
230 | | else |
231 | | PORT_SetError(PR_UNKNOWN_ERROR); |
232 | | return SECFailure; |
233 | | } |
234 | | } |
235 | | return SECSuccess; |
236 | | } |
237 | | |
238 | | #else |
239 | | |
240 | | /* Using Atomic operations requires the use of a memory barrier instruction |
241 | | ** on PowerPC, Sparc, and Alpha. NSPR's PR_Atomic functions do not perform |
242 | | ** them, and NSPR does not provide a function that does them (e.g. PR_Barrier). |
243 | | ** So, we don't use them on those platforms. |
244 | | */ |
245 | | |
246 | | SECStatus |
247 | | sslMutex_Unlock(sslMutex* pMutex) |
248 | 0 | { |
249 | 0 | int cc; |
250 | 0 | char c = 1; |
251 | 0 |
|
252 | 0 | if (PR_FALSE == pMutex->isMultiProcess) { |
253 | 0 | return single_process_sslMutex_Unlock(pMutex); |
254 | 0 | } |
255 | 0 | |
256 | 0 | if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { |
257 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
258 | 0 | return SECFailure; |
259 | 0 | } |
260 | 0 | do { |
261 | 0 | cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1); |
262 | 0 | } while (cc < 0 && (errno == EINTR || errno == EAGAIN)); |
263 | 0 | if (cc != 1) { |
264 | 0 | if (cc < 0) |
265 | 0 | nss_MD_unix_map_default_error(errno); |
266 | 0 | else |
267 | 0 | PORT_SetError(PR_UNKNOWN_ERROR); |
268 | 0 | return SECFailure; |
269 | 0 | } |
270 | 0 |
|
271 | 0 | return SECSuccess; |
272 | 0 | } |
273 | | |
274 | | SECStatus |
275 | | sslMutex_Lock(sslMutex* pMutex) |
276 | 0 | { |
277 | 0 | int cc; |
278 | 0 | char c; |
279 | 0 |
|
280 | 0 | if (PR_FALSE == pMutex->isMultiProcess) { |
281 | 0 | return single_process_sslMutex_Lock(pMutex); |
282 | 0 | } |
283 | 0 | |
284 | 0 | if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { |
285 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
286 | 0 | return SECFailure; |
287 | 0 | } |
288 | 0 |
|
289 | 0 | do { |
290 | 0 | cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1); |
291 | 0 | } while (cc < 0 && errno == EINTR); |
292 | 0 | if (cc != 1) { |
293 | 0 | if (cc < 0) |
294 | 0 | nss_MD_unix_map_default_error(errno); |
295 | 0 | else |
296 | 0 | PORT_SetError(PR_UNKNOWN_ERROR); |
297 | 0 | return SECFailure; |
298 | 0 | } |
299 | 0 |
|
300 | 0 | return SECSuccess; |
301 | 0 | } |
302 | | |
303 | | #endif |
304 | | |
305 | | #elif defined(WIN32) |
306 | | |
307 | | #include "win32err.h" |
308 | | |
309 | | /* on Windows, we need to find the optimal type of locking mechanism to use |
310 | | for the sslMutex. |
311 | | |
312 | | There are 3 cases : |
313 | | 1) single-process, use a PRLock, as for all other platforms |
314 | | 2) Win95 multi-process, use a Win32 mutex |
315 | | 3) on WINNT multi-process, use a PRLock + a Win32 mutex |
316 | | |
317 | | */ |
318 | | |
319 | | #ifdef WINNT |
320 | | |
321 | | SECStatus |
322 | | sslMutex_2LevelInit(sslMutex *sem) |
323 | | { |
324 | | /* the following adds a PRLock to sslMutex . This is done in each |
325 | | process of a multi-process server and is only needed on WINNT, if |
326 | | using fibers. We can't tell if native threads or fibers are used, so |
327 | | we always do it on WINNT |
328 | | */ |
329 | | PR_ASSERT(sem); |
330 | | if (sem) { |
331 | | /* we need to reset the sslLock in the children or the single_process init |
332 | | function below will assert */ |
333 | | sem->u.sslLock = NULL; |
334 | | } |
335 | | return single_process_sslMutex_Init(sem); |
336 | | } |
337 | | |
338 | | static SECStatus |
339 | | sslMutex_2LevelDestroy(sslMutex *sem) |
340 | | { |
341 | | return single_process_sslMutex_Destroy(sem); |
342 | | } |
343 | | |
344 | | #endif |
345 | | |
346 | | SECStatus |
347 | | sslMutex_Init(sslMutex *pMutex, int shared) |
348 | | { |
349 | | #ifdef WINNT |
350 | | SECStatus retvalue; |
351 | | #endif |
352 | | HANDLE hMutex; |
353 | | SECURITY_ATTRIBUTES attributes = |
354 | | { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; |
355 | | |
356 | | PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 || |
357 | | pMutex->u.sslMutx == |
358 | | INVALID_HANDLE_VALUE)); |
359 | | |
360 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
361 | | |
362 | | if (PR_FALSE == pMutex->isMultiProcess) { |
363 | | return single_process_sslMutex_Init(pMutex); |
364 | | } |
365 | | |
366 | | #ifdef WINNT |
367 | | /* we need a lock on WINNT for fibers in the parent process */ |
368 | | retvalue = sslMutex_2LevelInit(pMutex); |
369 | | if (SECSuccess != retvalue) |
370 | | return SECFailure; |
371 | | #endif |
372 | | |
373 | | if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 && |
374 | | hMutex != |
375 | | INVALID_HANDLE_VALUE)) { |
376 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
377 | | return SECFailure; |
378 | | } |
379 | | attributes.bInheritHandle = (shared ? TRUE : FALSE); |
380 | | hMutex = CreateMutex(&attributes, FALSE, NULL); |
381 | | if (hMutex == NULL) { |
382 | | hMutex = INVALID_HANDLE_VALUE; |
383 | | nss_MD_win32_map_default_error(GetLastError()); |
384 | | return SECFailure; |
385 | | } |
386 | | pMutex->u.sslMutx = hMutex; |
387 | | return SECSuccess; |
388 | | } |
389 | | |
390 | | SECStatus |
391 | | sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) |
392 | | { |
393 | | HANDLE hMutex; |
394 | | int rv; |
395 | | int retvalue = SECSuccess; |
396 | | |
397 | | PR_ASSERT(pMutex != 0); |
398 | | if (!pMutex) { |
399 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
400 | | return SECFailure; |
401 | | } |
402 | | |
403 | | if (PR_FALSE == pMutex->isMultiProcess) { |
404 | | return single_process_sslMutex_Destroy(pMutex); |
405 | | } |
406 | | |
407 | | /* multi-process mode */ |
408 | | #ifdef WINNT |
409 | | /* on NT, get rid of the PRLock used for fibers within a process */ |
410 | | retvalue = sslMutex_2LevelDestroy(pMutex); |
411 | | #endif |
412 | | |
413 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
414 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
415 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
416 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
417 | | return SECFailure; |
418 | | } |
419 | | |
420 | | rv = CloseHandle(hMutex); /* ignore error */ |
421 | | if (!processLocal && rv) { |
422 | | pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE; |
423 | | } |
424 | | if (!rv) { |
425 | | nss_MD_win32_map_default_error(GetLastError()); |
426 | | retvalue = SECFailure; |
427 | | } |
428 | | return retvalue; |
429 | | } |
430 | | |
431 | | int |
432 | | sslMutex_Unlock(sslMutex *pMutex) |
433 | | { |
434 | | BOOL success = FALSE; |
435 | | HANDLE hMutex; |
436 | | |
437 | | PR_ASSERT(pMutex != 0); |
438 | | if (!pMutex) { |
439 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
440 | | return SECFailure; |
441 | | } |
442 | | |
443 | | if (PR_FALSE == pMutex->isMultiProcess) { |
444 | | return single_process_sslMutex_Unlock(pMutex); |
445 | | } |
446 | | |
447 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
448 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
449 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
450 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
451 | | return SECFailure; |
452 | | } |
453 | | success = ReleaseMutex(hMutex); |
454 | | if (!success) { |
455 | | nss_MD_win32_map_default_error(GetLastError()); |
456 | | return SECFailure; |
457 | | } |
458 | | #ifdef WINNT |
459 | | return single_process_sslMutex_Unlock(pMutex); |
460 | | /* release PRLock for other fibers in the process */ |
461 | | #else |
462 | | return SECSuccess; |
463 | | #endif |
464 | | } |
465 | | |
466 | | int |
467 | | sslMutex_Lock(sslMutex *pMutex) |
468 | | { |
469 | | HANDLE hMutex; |
470 | | DWORD event; |
471 | | DWORD lastError; |
472 | | SECStatus rv; |
473 | | SECStatus retvalue = SECSuccess; |
474 | | |
475 | | PR_ASSERT(pMutex != 0); |
476 | | if (!pMutex) { |
477 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
478 | | return SECFailure; |
479 | | } |
480 | | |
481 | | if (PR_FALSE == pMutex->isMultiProcess) { |
482 | | return single_process_sslMutex_Lock(pMutex); |
483 | | } |
484 | | #ifdef WINNT |
485 | | /* lock first to preserve from other threads/fibers in the same process */ |
486 | | retvalue = single_process_sslMutex_Lock(pMutex); |
487 | | #endif |
488 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
489 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
490 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
491 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
492 | | return SECFailure; /* what else ? */ |
493 | | } |
494 | | /* acquire the mutex to be the only owner accross all other processes */ |
495 | | event = WaitForSingleObject(hMutex, INFINITE); |
496 | | switch (event) { |
497 | | case WAIT_OBJECT_0: |
498 | | case WAIT_ABANDONED: |
499 | | rv = SECSuccess; |
500 | | break; |
501 | | |
502 | | case WAIT_TIMEOUT: |
503 | | #if defined(WAIT_IO_COMPLETION) |
504 | | case WAIT_IO_COMPLETION: |
505 | | #endif |
506 | | default: /* should never happen. nothing we can do. */ |
507 | | PR_ASSERT(!("WaitForSingleObject returned invalid value.")); |
508 | | PORT_SetError(PR_UNKNOWN_ERROR); |
509 | | rv = SECFailure; |
510 | | break; |
511 | | |
512 | | case WAIT_FAILED: /* failure returns this */ |
513 | | rv = SECFailure; |
514 | | lastError = GetLastError(); /* for debugging */ |
515 | | nss_MD_win32_map_default_error(lastError); |
516 | | break; |
517 | | } |
518 | | |
519 | | if (!(SECSuccess == retvalue && SECSuccess == rv)) { |
520 | | return SECFailure; |
521 | | } |
522 | | |
523 | | return SECSuccess; |
524 | | } |
525 | | |
526 | | #elif defined(XP_UNIX) && !defined(DARWIN) |
527 | | |
528 | | #include <errno.h> |
529 | | #include "unix_err.h" |
530 | | |
531 | | SECStatus |
532 | | sslMutex_Init(sslMutex* pMutex, int shared) |
533 | | { |
534 | | int rv; |
535 | | PR_ASSERT(pMutex); |
536 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
537 | | if (!shared) { |
538 | | return single_process_sslMutex_Init(pMutex); |
539 | | } |
540 | | do { |
541 | | rv = sem_init(&pMutex->u.sem, shared, 1); |
542 | | } while (rv < 0 && errno == EINTR); |
543 | | if (rv < 0) { |
544 | | nss_MD_unix_map_default_error(errno); |
545 | | return SECFailure; |
546 | | } |
547 | | return SECSuccess; |
548 | | } |
549 | | |
550 | | SECStatus |
551 | | sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal) |
552 | | { |
553 | | int rv; |
554 | | if (PR_FALSE == pMutex->isMultiProcess) { |
555 | | return single_process_sslMutex_Destroy(pMutex); |
556 | | } |
557 | | |
558 | | /* semaphores are global resources. See SEM_DESTROY(3) man page */ |
559 | | if (processLocal) { |
560 | | return SECSuccess; |
561 | | } |
562 | | do { |
563 | | rv = sem_destroy(&pMutex->u.sem); |
564 | | } while (rv < 0 && errno == EINTR); |
565 | | if (rv < 0) { |
566 | | nss_MD_unix_map_default_error(errno); |
567 | | return SECFailure; |
568 | | } |
569 | | return SECSuccess; |
570 | | } |
571 | | |
572 | | SECStatus |
573 | | sslMutex_Unlock(sslMutex* pMutex) |
574 | | { |
575 | | int rv; |
576 | | if (PR_FALSE == pMutex->isMultiProcess) { |
577 | | return single_process_sslMutex_Unlock(pMutex); |
578 | | } |
579 | | do { |
580 | | rv = sem_post(&pMutex->u.sem); |
581 | | } while (rv < 0 && errno == EINTR); |
582 | | if (rv < 0) { |
583 | | nss_MD_unix_map_default_error(errno); |
584 | | return SECFailure; |
585 | | } |
586 | | return SECSuccess; |
587 | | } |
588 | | |
589 | | SECStatus |
590 | | sslMutex_Lock(sslMutex* pMutex) |
591 | | { |
592 | | int rv; |
593 | | if (PR_FALSE == pMutex->isMultiProcess) { |
594 | | return single_process_sslMutex_Lock(pMutex); |
595 | | } |
596 | | do { |
597 | | rv = sem_wait(&pMutex->u.sem); |
598 | | } while (rv < 0 && errno == EINTR); |
599 | | if (rv < 0) { |
600 | | nss_MD_unix_map_default_error(errno); |
601 | | return SECFailure; |
602 | | } |
603 | | return SECSuccess; |
604 | | } |
605 | | |
606 | | #else |
607 | | |
608 | | SECStatus |
609 | | sslMutex_Init(sslMutex* pMutex, int shared) |
610 | | { |
611 | | PR_ASSERT(pMutex); |
612 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
613 | | if (!shared) { |
614 | | return single_process_sslMutex_Init(pMutex); |
615 | | } |
616 | | PORT_Assert(!("sslMutex_Init not implemented for multi-process applications !")); |
617 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
618 | | return SECFailure; |
619 | | } |
620 | | |
621 | | SECStatus |
622 | | sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal) |
623 | | { |
624 | | PR_ASSERT(pMutex); |
625 | | if (PR_FALSE == pMutex->isMultiProcess) { |
626 | | return single_process_sslMutex_Destroy(pMutex); |
627 | | } |
628 | | PORT_Assert(!("sslMutex_Destroy not implemented for multi-process applications !")); |
629 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
630 | | return SECFailure; |
631 | | } |
632 | | |
633 | | SECStatus |
634 | | sslMutex_Unlock(sslMutex* pMutex) |
635 | | { |
636 | | PR_ASSERT(pMutex); |
637 | | if (PR_FALSE == pMutex->isMultiProcess) { |
638 | | return single_process_sslMutex_Unlock(pMutex); |
639 | | } |
640 | | PORT_Assert(!("sslMutex_Unlock not implemented for multi-process applications !")); |
641 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
642 | | return SECFailure; |
643 | | } |
644 | | |
645 | | SECStatus |
646 | | sslMutex_Lock(sslMutex* pMutex) |
647 | | { |
648 | | PR_ASSERT(pMutex); |
649 | | if (PR_FALSE == pMutex->isMultiProcess) { |
650 | | return single_process_sslMutex_Lock(pMutex); |
651 | | } |
652 | | PORT_Assert(!("sslMutex_Lock not implemented for multi-process applications !")); |
653 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
654 | | return SECFailure; |
655 | | } |
656 | | |
657 | | #endif |
658 | | |
659 | | #endif |