/src/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) |
8 | | |
9 | | #include "sslmutex.h" |
10 | | #include "prerr.h" |
11 | | |
12 | | static SECStatus |
13 | | single_process_sslMutex_Init(sslMutex* pMutex) |
14 | 11 | { |
15 | 11 | PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0); |
16 | | |
17 | 11 | pMutex->u.sslLock = PR_NewLock(); |
18 | 11 | if (!pMutex->u.sslLock) { |
19 | 0 | return SECFailure; |
20 | 0 | } |
21 | 11 | return SECSuccess; |
22 | 11 | } |
23 | | |
24 | | static SECStatus |
25 | | single_process_sslMutex_Destroy(sslMutex* pMutex) |
26 | 11 | { |
27 | 11 | PR_ASSERT(pMutex != 0); |
28 | 11 | PR_ASSERT(pMutex->u.sslLock != 0); |
29 | 11 | if (!pMutex->u.sslLock) { |
30 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
31 | 0 | return SECFailure; |
32 | 0 | } |
33 | 11 | PR_DestroyLock(pMutex->u.sslLock); |
34 | 11 | return SECSuccess; |
35 | 11 | } |
36 | | |
37 | | static SECStatus |
38 | | single_process_sslMutex_Unlock(sslMutex* pMutex) |
39 | 5.20k | { |
40 | 5.20k | PR_ASSERT(pMutex != 0); |
41 | 5.20k | PR_ASSERT(pMutex->u.sslLock != 0); |
42 | 5.20k | if (!pMutex->u.sslLock) { |
43 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
44 | 0 | return SECFailure; |
45 | 0 | } |
46 | 5.20k | PR_Unlock(pMutex->u.sslLock); |
47 | 5.20k | return SECSuccess; |
48 | 5.20k | } |
49 | | |
50 | | static SECStatus |
51 | | single_process_sslMutex_Lock(sslMutex* pMutex) |
52 | 5.20k | { |
53 | 5.20k | PR_ASSERT(pMutex != 0); |
54 | 5.20k | PR_ASSERT(pMutex->u.sslLock != 0); |
55 | 5.20k | if (!pMutex->u.sslLock) { |
56 | 0 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
57 | 0 | return SECFailure; |
58 | 0 | } |
59 | 5.20k | PR_Lock(pMutex->u.sslLock); |
60 | 5.20k | return SECSuccess; |
61 | 5.20k | } |
62 | | |
63 | | #if defined(LINUX) || defined(AIX) || 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 | |
|
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 | 11 | { |
103 | 11 | int err; |
104 | 11 | PR_ASSERT(pMutex); |
105 | 11 | pMutex->isMultiProcess = (PRBool)(shared != 0); |
106 | 11 | if (!shared) { |
107 | 11 | return single_process_sslMutex_Init(pMutex); |
108 | 11 | } |
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 | |
|
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 | | |
125 | 0 | pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC; |
126 | |
|
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 | | |
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 | 11 | { |
145 | 11 | if (PR_FALSE == pMutex->isMultiProcess) { |
146 | 11 | return single_process_sslMutex_Destroy(pMutex); |
147 | 11 | } |
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 | |
|
155 | 0 | if (processLocal) { |
156 | 0 | return SECSuccess; |
157 | 0 | } |
158 | | |
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 | |
|
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 | 5.20k | { |
249 | 5.20k | int cc; |
250 | 5.20k | char c = 1; |
251 | | |
252 | 5.20k | if (PR_FALSE == pMutex->isMultiProcess) { |
253 | 5.20k | return single_process_sslMutex_Unlock(pMutex); |
254 | 5.20k | } |
255 | | |
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 | | |
271 | 0 | return SECSuccess; |
272 | 0 | } |
273 | | |
274 | | SECStatus |
275 | | sslMutex_Lock(sslMutex* pMutex) |
276 | 5.20k | { |
277 | 5.20k | int cc; |
278 | 5.20k | char c; |
279 | | |
280 | 5.20k | if (PR_FALSE == pMutex->isMultiProcess) { |
281 | 5.20k | return single_process_sslMutex_Lock(pMutex); |
282 | 5.20k | } |
283 | | |
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 | | |
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 | | |
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 = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; |
354 | | |
355 | | PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 || |
356 | | pMutex->u.sslMutx == |
357 | | INVALID_HANDLE_VALUE)); |
358 | | |
359 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
360 | | |
361 | | if (PR_FALSE == pMutex->isMultiProcess) { |
362 | | return single_process_sslMutex_Init(pMutex); |
363 | | } |
364 | | |
365 | | #ifdef WINNT |
366 | | /* we need a lock on WINNT for fibers in the parent process */ |
367 | | retvalue = sslMutex_2LevelInit(pMutex); |
368 | | if (SECSuccess != retvalue) |
369 | | return SECFailure; |
370 | | #endif |
371 | | |
372 | | if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 && |
373 | | hMutex != |
374 | | INVALID_HANDLE_VALUE)) { |
375 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
376 | | return SECFailure; |
377 | | } |
378 | | attributes.bInheritHandle = (shared ? TRUE : FALSE); |
379 | | hMutex = CreateMutex(&attributes, FALSE, NULL); |
380 | | if (hMutex == NULL) { |
381 | | hMutex = INVALID_HANDLE_VALUE; |
382 | | nss_MD_win32_map_default_error(GetLastError()); |
383 | | return SECFailure; |
384 | | } |
385 | | pMutex->u.sslMutx = hMutex; |
386 | | return SECSuccess; |
387 | | } |
388 | | |
389 | | SECStatus |
390 | | sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) |
391 | | { |
392 | | HANDLE hMutex; |
393 | | int rv; |
394 | | int retvalue = SECSuccess; |
395 | | |
396 | | PR_ASSERT(pMutex != 0); |
397 | | if (!pMutex) { |
398 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
399 | | return SECFailure; |
400 | | } |
401 | | |
402 | | if (PR_FALSE == pMutex->isMultiProcess) { |
403 | | return single_process_sslMutex_Destroy(pMutex); |
404 | | } |
405 | | |
406 | | /* multi-process mode */ |
407 | | #ifdef WINNT |
408 | | /* on NT, get rid of the PRLock used for fibers within a process */ |
409 | | retvalue = sslMutex_2LevelDestroy(pMutex); |
410 | | #endif |
411 | | |
412 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
413 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
414 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
415 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
416 | | return SECFailure; |
417 | | } |
418 | | |
419 | | rv = CloseHandle(hMutex); /* ignore error */ |
420 | | if (!processLocal && rv) { |
421 | | pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE; |
422 | | } |
423 | | if (!rv) { |
424 | | nss_MD_win32_map_default_error(GetLastError()); |
425 | | retvalue = SECFailure; |
426 | | } |
427 | | return retvalue; |
428 | | } |
429 | | |
430 | | int |
431 | | sslMutex_Unlock(sslMutex *pMutex) |
432 | | { |
433 | | BOOL success = FALSE; |
434 | | HANDLE hMutex; |
435 | | |
436 | | PR_ASSERT(pMutex != 0); |
437 | | if (!pMutex) { |
438 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
439 | | return SECFailure; |
440 | | } |
441 | | |
442 | | if (PR_FALSE == pMutex->isMultiProcess) { |
443 | | return single_process_sslMutex_Unlock(pMutex); |
444 | | } |
445 | | |
446 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
447 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
448 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
449 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
450 | | return SECFailure; |
451 | | } |
452 | | success = ReleaseMutex(hMutex); |
453 | | if (!success) { |
454 | | nss_MD_win32_map_default_error(GetLastError()); |
455 | | return SECFailure; |
456 | | } |
457 | | #ifdef WINNT |
458 | | return single_process_sslMutex_Unlock(pMutex); |
459 | | /* release PRLock for other fibers in the process */ |
460 | | #else |
461 | | return SECSuccess; |
462 | | #endif |
463 | | } |
464 | | |
465 | | int |
466 | | sslMutex_Lock(sslMutex *pMutex) |
467 | | { |
468 | | HANDLE hMutex; |
469 | | DWORD event; |
470 | | DWORD lastError; |
471 | | SECStatus rv; |
472 | | SECStatus retvalue = SECSuccess; |
473 | | |
474 | | PR_ASSERT(pMutex != 0); |
475 | | if (!pMutex) { |
476 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
477 | | return SECFailure; |
478 | | } |
479 | | |
480 | | if (PR_FALSE == pMutex->isMultiProcess) { |
481 | | return single_process_sslMutex_Lock(pMutex); |
482 | | } |
483 | | #ifdef WINNT |
484 | | /* lock first to preserve from other threads/fibers in the same process */ |
485 | | retvalue = single_process_sslMutex_Lock(pMutex); |
486 | | #endif |
487 | | PR_ASSERT(pMutex->u.sslMutx != 0 && |
488 | | pMutex->u.sslMutx != INVALID_HANDLE_VALUE); |
489 | | if ((hMutex = pMutex->u.sslMutx) == 0 || hMutex == INVALID_HANDLE_VALUE) { |
490 | | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
491 | | return SECFailure; /* what else ? */ |
492 | | } |
493 | | /* acquire the mutex to be the only owner accross all other processes */ |
494 | | event = WaitForSingleObject(hMutex, INFINITE); |
495 | | switch (event) { |
496 | | case WAIT_OBJECT_0: |
497 | | case WAIT_ABANDONED: |
498 | | rv = SECSuccess; |
499 | | break; |
500 | | |
501 | | case WAIT_TIMEOUT: |
502 | | #if defined(WAIT_IO_COMPLETION) |
503 | | case WAIT_IO_COMPLETION: |
504 | | #endif |
505 | | default: /* should never happen. nothing we can do. */ |
506 | | PR_ASSERT(PR_FALSE && "WaitForSingleObject returned invalid value."); |
507 | | PORT_SetError(PR_UNKNOWN_ERROR); |
508 | | rv = SECFailure; |
509 | | break; |
510 | | |
511 | | case WAIT_FAILED: /* failure returns this */ |
512 | | rv = SECFailure; |
513 | | lastError = GetLastError(); /* for debugging */ |
514 | | nss_MD_win32_map_default_error(lastError); |
515 | | break; |
516 | | } |
517 | | |
518 | | if (!(SECSuccess == retvalue && SECSuccess == rv)) { |
519 | | return SECFailure; |
520 | | } |
521 | | |
522 | | return SECSuccess; |
523 | | } |
524 | | |
525 | | #elif defined(XP_UNIX) && !defined(DARWIN) |
526 | | |
527 | | #include <errno.h> |
528 | | #include "unix_err.h" |
529 | | |
530 | | SECStatus |
531 | | sslMutex_Init(sslMutex* pMutex, int shared) |
532 | | { |
533 | | int rv; |
534 | | PR_ASSERT(pMutex); |
535 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
536 | | if (!shared) { |
537 | | return single_process_sslMutex_Init(pMutex); |
538 | | } |
539 | | do { |
540 | | rv = sem_init(&pMutex->u.sem, shared, 1); |
541 | | } while (rv < 0 && errno == EINTR); |
542 | | if (rv < 0) { |
543 | | nss_MD_unix_map_default_error(errno); |
544 | | return SECFailure; |
545 | | } |
546 | | return SECSuccess; |
547 | | } |
548 | | |
549 | | SECStatus |
550 | | sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal) |
551 | | { |
552 | | int rv; |
553 | | if (PR_FALSE == pMutex->isMultiProcess) { |
554 | | return single_process_sslMutex_Destroy(pMutex); |
555 | | } |
556 | | |
557 | | /* semaphores are global resources. See SEM_DESTROY(3) man page */ |
558 | | if (processLocal) { |
559 | | return SECSuccess; |
560 | | } |
561 | | do { |
562 | | rv = sem_destroy(&pMutex->u.sem); |
563 | | } while (rv < 0 && errno == EINTR); |
564 | | if (rv < 0) { |
565 | | nss_MD_unix_map_default_error(errno); |
566 | | return SECFailure; |
567 | | } |
568 | | return SECSuccess; |
569 | | } |
570 | | |
571 | | SECStatus |
572 | | sslMutex_Unlock(sslMutex* pMutex) |
573 | | { |
574 | | int rv; |
575 | | if (PR_FALSE == pMutex->isMultiProcess) { |
576 | | return single_process_sslMutex_Unlock(pMutex); |
577 | | } |
578 | | do { |
579 | | rv = sem_post(&pMutex->u.sem); |
580 | | } while (rv < 0 && errno == EINTR); |
581 | | if (rv < 0) { |
582 | | nss_MD_unix_map_default_error(errno); |
583 | | return SECFailure; |
584 | | } |
585 | | return SECSuccess; |
586 | | } |
587 | | |
588 | | SECStatus |
589 | | sslMutex_Lock(sslMutex* pMutex) |
590 | | { |
591 | | int rv; |
592 | | if (PR_FALSE == pMutex->isMultiProcess) { |
593 | | return single_process_sslMutex_Lock(pMutex); |
594 | | } |
595 | | do { |
596 | | rv = sem_wait(&pMutex->u.sem); |
597 | | } while (rv < 0 && errno == EINTR); |
598 | | if (rv < 0) { |
599 | | nss_MD_unix_map_default_error(errno); |
600 | | return SECFailure; |
601 | | } |
602 | | return SECSuccess; |
603 | | } |
604 | | |
605 | | #else |
606 | | |
607 | | SECStatus |
608 | | sslMutex_Init(sslMutex* pMutex, int shared) |
609 | | { |
610 | | PR_ASSERT(pMutex); |
611 | | pMutex->isMultiProcess = (PRBool)(shared != 0); |
612 | | if (!shared) { |
613 | | return single_process_sslMutex_Init(pMutex); |
614 | | } |
615 | | PORT_Assert(PR_FALSE && "sslMutex_Init not implemented for multi-process applications !"); |
616 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
617 | | return SECFailure; |
618 | | } |
619 | | |
620 | | SECStatus |
621 | | sslMutex_Destroy(sslMutex* pMutex, PRBool processLocal) |
622 | | { |
623 | | PR_ASSERT(pMutex); |
624 | | if (PR_FALSE == pMutex->isMultiProcess) { |
625 | | return single_process_sslMutex_Destroy(pMutex); |
626 | | } |
627 | | PORT_Assert(PR_FALSE && "sslMutex_Destroy not implemented for multi-process applications !"); |
628 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
629 | | return SECFailure; |
630 | | } |
631 | | |
632 | | SECStatus |
633 | | sslMutex_Unlock(sslMutex* pMutex) |
634 | | { |
635 | | PR_ASSERT(pMutex); |
636 | | if (PR_FALSE == pMutex->isMultiProcess) { |
637 | | return single_process_sslMutex_Unlock(pMutex); |
638 | | } |
639 | | PORT_Assert(PR_FALSE && "sslMutex_Unlock not implemented for multi-process applications !"); |
640 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
641 | | return SECFailure; |
642 | | } |
643 | | |
644 | | SECStatus |
645 | | sslMutex_Lock(sslMutex* pMutex) |
646 | | { |
647 | | PR_ASSERT(pMutex); |
648 | | if (PR_FALSE == pMutex->isMultiProcess) { |
649 | | return single_process_sslMutex_Lock(pMutex); |
650 | | } |
651 | | PORT_Assert(PR_FALSE && "sslMutex_Lock not implemented for multi-process applications !"); |
652 | | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
653 | | return SECFailure; |
654 | | } |
655 | | |
656 | | #endif |
657 | | |
658 | | #endif |