security/nss/lib/ssl/sslmutex.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial