Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: net/third_party/nss/ssl/sslmutex.c

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

Powered by Google App Engine
This is Rietveld 408576698