michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "seccomon.h" michael@0: /* This ifdef should match the one in sslsnce.c */ michael@0: #if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS) michael@0: michael@0: #include "sslmutex.h" michael@0: #include "prerr.h" michael@0: michael@0: static SECStatus single_process_sslMutex_Init(sslMutex* pMutex) michael@0: { michael@0: PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0 ); michael@0: michael@0: pMutex->u.sslLock = PR_NewLock(); michael@0: if (!pMutex->u.sslLock) { michael@0: return SECFailure; michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: static SECStatus single_process_sslMutex_Destroy(sslMutex* pMutex) michael@0: { michael@0: PR_ASSERT(pMutex != 0); michael@0: PR_ASSERT(pMutex->u.sslLock!= 0); michael@0: if (!pMutex->u.sslLock) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: PR_DestroyLock(pMutex->u.sslLock); michael@0: return SECSuccess; michael@0: } michael@0: michael@0: static SECStatus single_process_sslMutex_Unlock(sslMutex* pMutex) michael@0: { michael@0: PR_ASSERT(pMutex != 0 ); michael@0: PR_ASSERT(pMutex->u.sslLock !=0); michael@0: if (!pMutex->u.sslLock) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: PR_Unlock(pMutex->u.sslLock); michael@0: return SECSuccess; michael@0: } michael@0: michael@0: static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex) michael@0: { michael@0: PR_ASSERT(pMutex != 0); michael@0: PR_ASSERT(pMutex->u.sslLock != 0 ); michael@0: if (!pMutex->u.sslLock) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: PR_Lock(pMutex->u.sslLock); michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #if defined(LINUX) || defined(AIX) || defined(BEOS) || defined(BSDI) || (defined(NETBSD) && __NetBSD_Version__ < 500000000) || defined(OPENBSD) michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include "unix_err.h" michael@0: #include "pratom.h" michael@0: michael@0: #define SSL_MUTEX_MAGIC 0xfeedfd michael@0: #define NONBLOCKING_POSTS 1 /* maybe this is faster */ michael@0: michael@0: #if NONBLOCKING_POSTS michael@0: michael@0: #ifndef FNONBLOCK michael@0: #define FNONBLOCK O_NONBLOCK michael@0: #endif michael@0: michael@0: static int michael@0: setNonBlocking(int fd, int nonBlocking) michael@0: { michael@0: int flags; michael@0: int err; michael@0: michael@0: flags = fcntl(fd, F_GETFL, 0); michael@0: if (0 > flags) michael@0: return flags; michael@0: if (nonBlocking) michael@0: flags |= FNONBLOCK; michael@0: else michael@0: flags &= ~FNONBLOCK; michael@0: err = fcntl(fd, F_SETFL, flags); michael@0: return err; michael@0: } michael@0: #endif michael@0: michael@0: SECStatus michael@0: sslMutex_Init(sslMutex *pMutex, int shared) michael@0: { michael@0: int err; michael@0: PR_ASSERT(pMutex); michael@0: pMutex->isMultiProcess = (PRBool)(shared != 0); michael@0: if (!shared) { michael@0: return single_process_sslMutex_Init(pMutex); michael@0: } michael@0: pMutex->u.pipeStr.mPipes[0] = -1; michael@0: pMutex->u.pipeStr.mPipes[1] = -1; michael@0: pMutex->u.pipeStr.mPipes[2] = -1; michael@0: pMutex->u.pipeStr.nWaiters = 0; michael@0: michael@0: err = pipe(pMutex->u.pipeStr.mPipes); michael@0: if (err) { michael@0: nss_MD_unix_map_default_error(errno); michael@0: return err; michael@0: } michael@0: #if NONBLOCKING_POSTS michael@0: err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1); michael@0: if (err) michael@0: goto loser; michael@0: #endif michael@0: michael@0: pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC; michael@0: michael@0: #if defined(LINUX) && defined(i386) michael@0: /* Pipe starts out empty */ michael@0: return SECSuccess; michael@0: #else michael@0: /* Pipe starts with one byte. */ michael@0: return sslMutex_Unlock(pMutex); michael@0: #endif michael@0: michael@0: loser: michael@0: nss_MD_unix_map_default_error(errno); michael@0: close(pMutex->u.pipeStr.mPipes[0]); michael@0: close(pMutex->u.pipeStr.mPipes[1]); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) michael@0: { michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Destroy(pMutex); michael@0: } michael@0: if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: close(pMutex->u.pipeStr.mPipes[0]); michael@0: close(pMutex->u.pipeStr.mPipes[1]); michael@0: michael@0: if (processLocal) { michael@0: return SECSuccess; michael@0: } michael@0: michael@0: pMutex->u.pipeStr.mPipes[0] = -1; michael@0: pMutex->u.pipeStr.mPipes[1] = -1; michael@0: pMutex->u.pipeStr.mPipes[2] = -1; michael@0: pMutex->u.pipeStr.nWaiters = 0; michael@0: michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #if defined(LINUX) && defined(i386) michael@0: /* No memory barrier needed for this platform */ michael@0: michael@0: /* nWaiters includes the holder of the lock (if any) and the number michael@0: ** threads waiting for it. After incrementing nWaiters, if the count michael@0: ** is exactly 1, then you have the lock and may proceed. If the michael@0: ** count is greater than 1, then you must wait on the pipe. michael@0: */ michael@0: michael@0: michael@0: SECStatus michael@0: sslMutex_Unlock(sslMutex *pMutex) michael@0: { michael@0: PRInt32 newValue; michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: } michael@0: michael@0: if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: /* Do Memory Barrier here. */ michael@0: newValue = PR_ATOMIC_DECREMENT(&pMutex->u.pipeStr.nWaiters); michael@0: if (newValue > 0) { michael@0: int cc; michael@0: char c = 1; michael@0: do { michael@0: cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1); michael@0: } while (cc < 0 && (errno == EINTR || errno == EAGAIN)); michael@0: if (cc != 1) { michael@0: if (cc < 0) michael@0: nss_MD_unix_map_default_error(errno); michael@0: else michael@0: PORT_SetError(PR_UNKNOWN_ERROR); michael@0: return SECFailure; michael@0: } michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Lock(sslMutex *pMutex) michael@0: { michael@0: PRInt32 newValue; michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Lock(pMutex); michael@0: } michael@0: michael@0: if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: newValue = PR_ATOMIC_INCREMENT(&pMutex->u.pipeStr.nWaiters); michael@0: /* Do Memory Barrier here. */ michael@0: if (newValue > 1) { michael@0: int cc; michael@0: char c; michael@0: do { michael@0: cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1); michael@0: } while (cc < 0 && errno == EINTR); michael@0: if (cc != 1) { michael@0: if (cc < 0) michael@0: nss_MD_unix_map_default_error(errno); michael@0: else michael@0: PORT_SetError(PR_UNKNOWN_ERROR); michael@0: return SECFailure; michael@0: } michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #else michael@0: michael@0: /* Using Atomic operations requires the use of a memory barrier instruction michael@0: ** on PowerPC, Sparc, and Alpha. NSPR's PR_Atomic functions do not perform michael@0: ** them, and NSPR does not provide a function that does them (e.g. PR_Barrier). michael@0: ** So, we don't use them on those platforms. michael@0: */ michael@0: michael@0: SECStatus michael@0: sslMutex_Unlock(sslMutex *pMutex) michael@0: { michael@0: int cc; michael@0: char c = 1; michael@0: michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: } michael@0: michael@0: if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: do { michael@0: cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1); michael@0: } while (cc < 0 && (errno == EINTR || errno == EAGAIN)); michael@0: if (cc != 1) { michael@0: if (cc < 0) michael@0: nss_MD_unix_map_default_error(errno); michael@0: else michael@0: PORT_SetError(PR_UNKNOWN_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Lock(sslMutex *pMutex) michael@0: { michael@0: int cc; michael@0: char c; michael@0: michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Lock(pMutex); michael@0: } michael@0: michael@0: if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: do { michael@0: cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1); michael@0: } while (cc < 0 && errno == EINTR); michael@0: if (cc != 1) { michael@0: if (cc < 0) michael@0: nss_MD_unix_map_default_error(errno); michael@0: else michael@0: PORT_SetError(PR_UNKNOWN_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: #elif defined(WIN32) michael@0: michael@0: #include "win32err.h" michael@0: michael@0: /* on Windows, we need to find the optimal type of locking mechanism to use michael@0: for the sslMutex. michael@0: michael@0: There are 3 cases : michael@0: 1) single-process, use a PRLock, as for all other platforms michael@0: 2) Win95 multi-process, use a Win32 mutex michael@0: 3) on WINNT multi-process, use a PRLock + a Win32 mutex michael@0: michael@0: */ michael@0: michael@0: #ifdef WINNT michael@0: michael@0: SECStatus sslMutex_2LevelInit(sslMutex *sem) michael@0: { michael@0: /* the following adds a PRLock to sslMutex . This is done in each michael@0: process of a multi-process server and is only needed on WINNT, if michael@0: using fibers. We can't tell if native threads or fibers are used, so michael@0: we always do it on WINNT michael@0: */ michael@0: PR_ASSERT(sem); michael@0: if (sem) { michael@0: /* we need to reset the sslLock in the children or the single_process init michael@0: function below will assert */ michael@0: sem->u.sslLock = NULL; michael@0: } michael@0: return single_process_sslMutex_Init(sem); michael@0: } michael@0: michael@0: static SECStatus sslMutex_2LevelDestroy(sslMutex *sem) michael@0: { michael@0: return single_process_sslMutex_Destroy(sem); michael@0: } michael@0: michael@0: #endif michael@0: michael@0: SECStatus michael@0: sslMutex_Init(sslMutex *pMutex, int shared) michael@0: { michael@0: #ifdef WINNT michael@0: SECStatus retvalue; michael@0: #endif michael@0: HANDLE hMutex; michael@0: SECURITY_ATTRIBUTES attributes = michael@0: { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; michael@0: michael@0: PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 || michael@0: pMutex->u.sslMutx == INVALID_HANDLE_VALUE) ); michael@0: michael@0: pMutex->isMultiProcess = (PRBool)(shared != 0); michael@0: michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Init(pMutex); michael@0: } michael@0: michael@0: #ifdef WINNT michael@0: /* we need a lock on WINNT for fibers in the parent process */ michael@0: retvalue = sslMutex_2LevelInit(pMutex); michael@0: if (SECSuccess != retvalue) michael@0: return SECFailure; michael@0: #endif michael@0: michael@0: if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 && michael@0: hMutex != INVALID_HANDLE_VALUE)) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: attributes.bInheritHandle = (shared ? TRUE : FALSE); michael@0: hMutex = CreateMutex(&attributes, FALSE, NULL); michael@0: if (hMutex == NULL) { michael@0: hMutex = INVALID_HANDLE_VALUE; michael@0: nss_MD_win32_map_default_error(GetLastError()); michael@0: return SECFailure; michael@0: } michael@0: pMutex->u.sslMutx = hMutex; michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) michael@0: { michael@0: HANDLE hMutex; michael@0: int rv; michael@0: int retvalue = SECSuccess; michael@0: michael@0: PR_ASSERT(pMutex != 0); michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Destroy(pMutex); michael@0: } michael@0: michael@0: /* multi-process mode */ michael@0: #ifdef WINNT michael@0: /* on NT, get rid of the PRLock used for fibers within a process */ michael@0: retvalue = sslMutex_2LevelDestroy(pMutex); michael@0: #endif michael@0: michael@0: PR_ASSERT( pMutex->u.sslMutx != 0 && michael@0: pMutex->u.sslMutx != INVALID_HANDLE_VALUE); michael@0: if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 michael@0: || hMutex == INVALID_HANDLE_VALUE) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: rv = CloseHandle(hMutex); /* ignore error */ michael@0: if (!processLocal && rv) { michael@0: pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE; michael@0: } michael@0: if (!rv) { michael@0: nss_MD_win32_map_default_error(GetLastError()); michael@0: retvalue = SECFailure; michael@0: } michael@0: return retvalue; michael@0: } michael@0: michael@0: int michael@0: sslMutex_Unlock(sslMutex *pMutex) michael@0: { michael@0: BOOL success = FALSE; michael@0: HANDLE hMutex; michael@0: michael@0: PR_ASSERT(pMutex != 0 ); michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: } michael@0: michael@0: PR_ASSERT(pMutex->u.sslMutx != 0 && michael@0: pMutex->u.sslMutx != INVALID_HANDLE_VALUE); michael@0: if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 || michael@0: hMutex == INVALID_HANDLE_VALUE) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; michael@0: } michael@0: success = ReleaseMutex(hMutex); michael@0: if (!success) { michael@0: nss_MD_win32_map_default_error(GetLastError()); michael@0: return SECFailure; michael@0: } michael@0: #ifdef WINNT michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: /* release PRLock for other fibers in the process */ michael@0: #else michael@0: return SECSuccess; michael@0: #endif michael@0: } michael@0: michael@0: int michael@0: sslMutex_Lock(sslMutex *pMutex) michael@0: { michael@0: HANDLE hMutex; michael@0: DWORD event; michael@0: DWORD lastError; michael@0: SECStatus rv; michael@0: SECStatus retvalue = SECSuccess; michael@0: PR_ASSERT(pMutex != 0); michael@0: michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Lock(pMutex); michael@0: } michael@0: #ifdef WINNT michael@0: /* lock first to preserve from other threads/fibers michael@0: in the same process */ michael@0: retvalue = single_process_sslMutex_Lock(pMutex); michael@0: #endif michael@0: PR_ASSERT(pMutex->u.sslMutx != 0 && michael@0: pMutex->u.sslMutx != INVALID_HANDLE_VALUE); michael@0: if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 || michael@0: hMutex == INVALID_HANDLE_VALUE) { michael@0: PORT_SetError(PR_INVALID_ARGUMENT_ERROR); michael@0: return SECFailure; /* what else ? */ michael@0: } michael@0: /* acquire the mutex to be the only owner accross all other processes */ michael@0: event = WaitForSingleObject(hMutex, INFINITE); michael@0: switch (event) { michael@0: case WAIT_OBJECT_0: michael@0: case WAIT_ABANDONED: michael@0: rv = SECSuccess; michael@0: break; michael@0: michael@0: case WAIT_TIMEOUT: michael@0: #if defined(WAIT_IO_COMPLETION) michael@0: case WAIT_IO_COMPLETION: michael@0: #endif michael@0: default: /* should never happen. nothing we can do. */ michael@0: PR_ASSERT(!("WaitForSingleObject returned invalid value.")); michael@0: PORT_SetError(PR_UNKNOWN_ERROR); michael@0: rv = SECFailure; michael@0: break; michael@0: michael@0: case WAIT_FAILED: /* failure returns this */ michael@0: rv = SECFailure; michael@0: lastError = GetLastError(); /* for debugging */ michael@0: nss_MD_win32_map_default_error(lastError); michael@0: break; michael@0: } michael@0: michael@0: if (! (SECSuccess == retvalue && SECSuccess == rv)) { michael@0: return SECFailure; michael@0: } michael@0: michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #elif defined(XP_UNIX) michael@0: michael@0: #include michael@0: #include "unix_err.h" michael@0: michael@0: SECStatus michael@0: sslMutex_Init(sslMutex *pMutex, int shared) michael@0: { michael@0: int rv; michael@0: PR_ASSERT(pMutex); michael@0: pMutex->isMultiProcess = (PRBool)(shared != 0); michael@0: if (!shared) { michael@0: return single_process_sslMutex_Init(pMutex); michael@0: } michael@0: do { michael@0: rv = sem_init(&pMutex->u.sem, shared, 1); michael@0: } while (rv < 0 && errno == EINTR); michael@0: if (rv < 0) { michael@0: nss_MD_unix_map_default_error(errno); michael@0: return SECFailure; michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) michael@0: { michael@0: int rv; michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Destroy(pMutex); michael@0: } michael@0: michael@0: /* semaphores are global resources. See SEM_DESTROY(3) man page */ michael@0: if (processLocal) { michael@0: return SECSuccess; michael@0: } michael@0: do { michael@0: rv = sem_destroy(&pMutex->u.sem); michael@0: } while (rv < 0 && errno == EINTR); michael@0: if (rv < 0) { michael@0: nss_MD_unix_map_default_error(errno); michael@0: return SECFailure; michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Unlock(sslMutex *pMutex) michael@0: { michael@0: int rv; michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: } michael@0: do { michael@0: rv = sem_post(&pMutex->u.sem); michael@0: } while (rv < 0 && errno == EINTR); michael@0: if (rv < 0) { michael@0: nss_MD_unix_map_default_error(errno); michael@0: return SECFailure; michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Lock(sslMutex *pMutex) michael@0: { michael@0: int rv; michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Lock(pMutex); michael@0: } michael@0: do { michael@0: rv = sem_wait(&pMutex->u.sem); michael@0: } while (rv < 0 && errno == EINTR); michael@0: if (rv < 0) { michael@0: nss_MD_unix_map_default_error(errno); michael@0: return SECFailure; michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #else michael@0: michael@0: SECStatus michael@0: sslMutex_Init(sslMutex *pMutex, int shared) michael@0: { michael@0: PR_ASSERT(pMutex); michael@0: pMutex->isMultiProcess = (PRBool)(shared != 0); michael@0: if (!shared) { michael@0: return single_process_sslMutex_Init(pMutex); michael@0: } michael@0: PORT_Assert(!("sslMutex_Init not implemented for multi-process applications !")); michael@0: PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Destroy(sslMutex *pMutex, PRBool processLocal) michael@0: { michael@0: PR_ASSERT(pMutex); michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Destroy(pMutex); michael@0: } michael@0: PORT_Assert(!("sslMutex_Destroy not implemented for multi-process applications !")); michael@0: PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Unlock(sslMutex *pMutex) michael@0: { michael@0: PR_ASSERT(pMutex); michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Unlock(pMutex); michael@0: } michael@0: PORT_Assert(!("sslMutex_Unlock not implemented for multi-process applications !")); michael@0: PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: SECStatus michael@0: sslMutex_Lock(sslMutex *pMutex) michael@0: { michael@0: PR_ASSERT(pMutex); michael@0: if (PR_FALSE == pMutex->isMultiProcess) { michael@0: return single_process_sslMutex_Lock(pMutex); michael@0: } michael@0: PORT_Assert(!("sslMutex_Lock not implemented for multi-process applications !")); michael@0: PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); michael@0: return SECFailure; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: #endif