Back to index

lightning-sunbird  0.9+nobinonly
sslmutex.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 /* $Id: sslmutex.c,v 1.19.28.1 2006/06/07 18:40:57 nelson%bolyard.com Exp $ */
00037 
00038 #include "seccomon.h"
00039 /* This ifdef should match the one in sslsnce.c */
00040 #if (defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
00041 
00042 #include "sslmutex.h"
00043 #include "prerr.h"
00044 
00045 static SECStatus single_process_sslMutex_Init(sslMutex* pMutex)
00046 {
00047     PR_ASSERT(pMutex != 0 && pMutex->u.sslLock == 0 );
00048     
00049     pMutex->u.sslLock = PR_NewLock();
00050     if (!pMutex->u.sslLock) {
00051         return SECFailure;
00052     }
00053     return SECSuccess;
00054 }
00055 
00056 static SECStatus single_process_sslMutex_Destroy(sslMutex* pMutex)
00057 {
00058     PR_ASSERT(pMutex != 0);
00059     PR_ASSERT(pMutex->u.sslLock!= 0);
00060     if (!pMutex->u.sslLock) {
00061         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00062         return SECFailure;
00063     }
00064     PR_DestroyLock(pMutex->u.sslLock);
00065     return SECSuccess;
00066 }
00067 
00068 static SECStatus single_process_sslMutex_Unlock(sslMutex* pMutex)
00069 {
00070     PR_ASSERT(pMutex != 0 );
00071     PR_ASSERT(pMutex->u.sslLock !=0);
00072     if (!pMutex->u.sslLock) {
00073         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00074         return SECFailure;
00075     }
00076     PR_Unlock(pMutex->u.sslLock);
00077     return SECSuccess;
00078 }
00079 
00080 static SECStatus single_process_sslMutex_Lock(sslMutex* pMutex)
00081 {
00082     PR_ASSERT(pMutex != 0);
00083     PR_ASSERT(pMutex->u.sslLock != 0 );
00084     if (!pMutex->u.sslLock) {
00085         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00086         return SECFailure;
00087     }
00088     PR_Lock(pMutex->u.sslLock);
00089     return SECSuccess;
00090 }
00091 
00092 #if defined(LINUX) || defined(AIX) || defined(VMS) || defined(BEOS) || defined(BSDI) || defined(NETBSD) || defined(OPENBSD)
00093 
00094 #include <unistd.h>
00095 #include <fcntl.h>
00096 #include <string.h>
00097 #include <errno.h>
00098 #include "unix_err.h"
00099 #include "pratom.h"
00100 
00101 #define SSL_MUTEX_MAGIC 0xfeedfd
00102 #define NONBLOCKING_POSTS 1 /* maybe this is faster */
00103 
00104 #if NONBLOCKING_POSTS
00105 
00106 #ifndef FNONBLOCK
00107 #define FNONBLOCK O_NONBLOCK
00108 #endif
00109 
00110 static int
00111 setNonBlocking(int fd, int nonBlocking)
00112 {
00113     int flags;
00114     int err;
00115 
00116     flags = fcntl(fd, F_GETFL, 0);
00117     if (0 > flags)
00118        return flags;
00119     if (nonBlocking)
00120        flags |= FNONBLOCK;
00121     else
00122        flags &= ~FNONBLOCK;
00123     err = fcntl(fd, F_SETFL, flags);
00124     return err;
00125 }
00126 #endif
00127 
00128 SECStatus
00129 sslMutex_Init(sslMutex *pMutex, int shared)
00130 {
00131     int  err;
00132     PR_ASSERT(pMutex);
00133     pMutex->isMultiProcess = (PRBool)(shared != 0);
00134     if (!shared) {
00135         return single_process_sslMutex_Init(pMutex);
00136     }
00137     pMutex->u.pipeStr.mPipes[0] = -1;
00138     pMutex->u.pipeStr.mPipes[1] = -1;
00139     pMutex->u.pipeStr.mPipes[2] = -1;
00140     pMutex->u.pipeStr.nWaiters  =  0;
00141 
00142     err = pipe(pMutex->u.pipeStr.mPipes);
00143     if (err) {
00144        return err;
00145     }
00146 #if NONBLOCKING_POSTS
00147     err = setNonBlocking(pMutex->u.pipeStr.mPipes[1], 1);
00148     if (err)
00149        goto loser;
00150 #endif
00151 
00152     pMutex->u.pipeStr.mPipes[2] = SSL_MUTEX_MAGIC;
00153 
00154 #if defined(LINUX) && defined(i386)
00155     /* Pipe starts out empty */
00156     return SECSuccess;
00157 #else
00158     /* Pipe starts with one byte. */
00159     return sslMutex_Unlock(pMutex);
00160 #endif
00161 
00162 loser:
00163     nss_MD_unix_map_default_error(errno);
00164     close(pMutex->u.pipeStr.mPipes[0]);
00165     close(pMutex->u.pipeStr.mPipes[1]);
00166     return SECFailure;
00167 }
00168 
00169 SECStatus
00170 sslMutex_Destroy(sslMutex *pMutex)
00171 {
00172     if (PR_FALSE == pMutex->isMultiProcess) {
00173         return single_process_sslMutex_Destroy(pMutex);
00174     }
00175     if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
00176        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00177        return SECFailure;
00178     }
00179     close(pMutex->u.pipeStr.mPipes[0]);
00180     close(pMutex->u.pipeStr.mPipes[1]);
00181 
00182     pMutex->u.pipeStr.mPipes[0] = -1;
00183     pMutex->u.pipeStr.mPipes[1] = -1;
00184     pMutex->u.pipeStr.mPipes[2] = -1;
00185     pMutex->u.pipeStr.nWaiters  =  0;
00186 
00187     return SECSuccess;
00188 }
00189 
00190 #if defined(LINUX) && defined(i386)
00191 /* No memory barrier needed for this platform */
00192 
00193 /* nWaiters includes the holder of the lock (if any) and the number
00194 ** threads waiting for it.  After incrementing nWaiters, if the count
00195 ** is exactly 1, then you have the lock and may proceed.  If the 
00196 ** count is greater than 1, then you must wait on the pipe.
00197 */ 
00198 
00199 
00200 SECStatus 
00201 sslMutex_Unlock(sslMutex *pMutex)
00202 {
00203     PRInt32 newValue;
00204     if (PR_FALSE == pMutex->isMultiProcess) {
00205         return single_process_sslMutex_Unlock(pMutex);
00206     }
00207 
00208     if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
00209        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00210        return SECFailure;
00211     }
00212     /* Do Memory Barrier here. */
00213     newValue = PR_AtomicDecrement(&pMutex->u.pipeStr.nWaiters);
00214     if (newValue > 0) {
00215        int  cc;
00216        char c  = 1;
00217        do {
00218            cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
00219        } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
00220        if (cc != 1) {
00221            if (cc < 0)
00222               nss_MD_unix_map_default_error(errno);
00223            else
00224               PORT_SetError(PR_UNKNOWN_ERROR);
00225            return SECFailure;
00226        }
00227     }
00228     return SECSuccess;
00229 }
00230 
00231 SECStatus 
00232 sslMutex_Lock(sslMutex *pMutex)
00233 {
00234     PRInt32 newValue;
00235     if (PR_FALSE == pMutex->isMultiProcess) {
00236         return single_process_sslMutex_Lock(pMutex);
00237     }
00238 
00239     if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
00240        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00241        return SECFailure;
00242     }
00243     newValue = PR_AtomicIncrement(&pMutex->u.pipeStr.nWaiters);
00244     /* Do Memory Barrier here. */
00245     if (newValue > 1) {
00246        int   cc;
00247        char  c;
00248        do {
00249            cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
00250        } while (cc < 0 && errno == EINTR);
00251        if (cc != 1) {
00252            if (cc < 0)
00253               nss_MD_unix_map_default_error(errno);
00254            else
00255               PORT_SetError(PR_UNKNOWN_ERROR);
00256            return SECFailure;
00257        }
00258     }
00259     return SECSuccess;
00260 }
00261 
00262 #else
00263 
00264 /* Using Atomic operations requires the use of a memory barrier instruction 
00265 ** on PowerPC, Sparc, and Alpha.  NSPR's PR_Atomic functions do not perform
00266 ** them, and NSPR does not provide a function that does them (e.g. PR_Barrier).
00267 ** So, we don't use them on those platforms. 
00268 */
00269 
00270 SECStatus 
00271 sslMutex_Unlock(sslMutex *pMutex)
00272 {
00273     int  cc;
00274     char c  = 1;
00275 
00276     if (PR_FALSE == pMutex->isMultiProcess) {
00277         return single_process_sslMutex_Unlock(pMutex);
00278     }
00279 
00280     if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
00281        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00282        return SECFailure;
00283     }
00284     do {
00285        cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
00286     } while (cc < 0 && (errno == EINTR || errno == EAGAIN));
00287     if (cc != 1) {
00288        if (cc < 0)
00289            nss_MD_unix_map_default_error(errno);
00290        else
00291            PORT_SetError(PR_UNKNOWN_ERROR);
00292        return SECFailure;
00293     }
00294 
00295     return SECSuccess;
00296 }
00297 
00298 SECStatus 
00299 sslMutex_Lock(sslMutex *pMutex)
00300 {
00301     int   cc;
00302     char  c;
00303 
00304     if (PR_FALSE == pMutex->isMultiProcess) {
00305         return single_process_sslMutex_Lock(pMutex);
00306     }
00307  
00308     if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
00309        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00310        return SECFailure;
00311     }
00312 
00313     do {
00314        cc = read(pMutex->u.pipeStr.mPipes[0], &c, 1);
00315     } while (cc < 0 && errno == EINTR);
00316     if (cc != 1) {
00317        if (cc < 0)
00318            nss_MD_unix_map_default_error(errno);
00319        else
00320            PORT_SetError(PR_UNKNOWN_ERROR);
00321        return SECFailure;
00322     }
00323 
00324     return SECSuccess;
00325 }
00326 
00327 #endif
00328 
00329 #elif defined(WIN32)
00330 
00331 #include "win32err.h"
00332 
00333 /* on Windows, we need to find the optimal type of locking mechanism to use
00334  for the sslMutex.
00335 
00336  There are 3 cases :
00337  1) single-process, use a PRLock, as for all other platforms
00338  2) Win95 multi-process, use a Win32 mutex
00339  3) on WINNT multi-process, use a PRLock + a Win32 mutex
00340 
00341 */
00342 
00343 #ifdef WINNT
00344 
00345 SECStatus sslMutex_2LevelInit(sslMutex *sem)
00346 {
00347     /*  the following adds a PRLock to sslMutex . This is done in each
00348         process of a multi-process server and is only needed on WINNT, if
00349         using fibers. We can't tell if native threads or fibers are used, so
00350         we always do it on WINNT
00351     */
00352     PR_ASSERT(sem);
00353     if (sem) {
00354         /* we need to reset the sslLock in the children or the single_process init
00355            function below will assert */
00356         sem->u.sslLock = NULL;
00357     }
00358     return single_process_sslMutex_Init(sem);
00359 }
00360 
00361 static SECStatus sslMutex_2LevelDestroy(sslMutex *sem)
00362 {
00363     return single_process_sslMutex_Destroy(sem);
00364 }
00365 
00366 #endif
00367 
00368 SECStatus
00369 sslMutex_Init(sslMutex *pMutex, int shared)
00370 {
00371 #ifdef WINNT
00372     SECStatus retvalue;
00373 #endif
00374     HANDLE hMutex;
00375     SECURITY_ATTRIBUTES attributes =
00376                                 { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
00377 
00378     PR_ASSERT(pMutex != 0 && (pMutex->u.sslMutx == 0 || 
00379               pMutex->u.sslMutx == INVALID_HANDLE_VALUE) );
00380     
00381     pMutex->isMultiProcess = (PRBool)(shared != 0);
00382     
00383     if (PR_FALSE == pMutex->isMultiProcess) {
00384         return single_process_sslMutex_Init(pMutex);
00385     }
00386     
00387 #ifdef WINNT
00388     /*  we need a lock on WINNT for fibers in the parent process */
00389     retvalue = sslMutex_2LevelInit(pMutex);
00390     if (SECSuccess != retvalue)
00391         return SECFailure;
00392 #endif
00393     
00394     if (!pMutex || ((hMutex = pMutex->u.sslMutx) != 0 && 
00395         hMutex != INVALID_HANDLE_VALUE)) {
00396         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00397         return SECFailure;
00398     }
00399     attributes.bInheritHandle = (shared ? TRUE : FALSE);
00400     hMutex = CreateMutex(&attributes, FALSE, NULL);
00401     if (hMutex == NULL) {
00402         hMutex = INVALID_HANDLE_VALUE;
00403         nss_MD_win32_map_default_error(GetLastError());
00404         return SECFailure;
00405     }
00406     pMutex->u.sslMutx = hMutex;
00407     return SECSuccess;
00408 }
00409 
00410 SECStatus
00411 sslMutex_Destroy(sslMutex *pMutex)
00412 {
00413     HANDLE hMutex;
00414     int    rv;
00415     int retvalue = SECSuccess;
00416 
00417     PR_ASSERT(pMutex != 0);
00418     if (PR_FALSE == pMutex->isMultiProcess) {
00419         return single_process_sslMutex_Destroy(pMutex);
00420     }
00421 
00422     /*  multi-process mode */    
00423 #ifdef WINNT
00424     /* on NT, get rid of the PRLock used for fibers within a process */
00425     retvalue = sslMutex_2LevelDestroy(pMutex);
00426 #endif
00427     
00428     PR_ASSERT( pMutex->u.sslMutx != 0 && 
00429                pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
00430     if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 
00431         || hMutex == INVALID_HANDLE_VALUE) {
00432         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00433         return SECFailure;
00434     }
00435     
00436     rv = CloseHandle(hMutex); /* ignore error */
00437     if (rv) {
00438         pMutex->u.sslMutx = hMutex = INVALID_HANDLE_VALUE;
00439     } else {
00440         nss_MD_win32_map_default_error(GetLastError());
00441         retvalue = SECFailure;
00442     }
00443     return retvalue;
00444 }
00445 
00446 int 
00447 sslMutex_Unlock(sslMutex *pMutex)
00448 {
00449     BOOL   success = FALSE;
00450     HANDLE hMutex;
00451 
00452     PR_ASSERT(pMutex != 0 );
00453     if (PR_FALSE == pMutex->isMultiProcess) {
00454         return single_process_sslMutex_Unlock(pMutex);
00455     }
00456     
00457     PR_ASSERT(pMutex->u.sslMutx != 0 && 
00458               pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
00459     if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 ||
00460         hMutex == INVALID_HANDLE_VALUE) {
00461         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00462         return SECFailure;
00463     }
00464     success = ReleaseMutex(hMutex);
00465     if (!success) {
00466         nss_MD_win32_map_default_error(GetLastError());
00467         return SECFailure;
00468     }
00469 #ifdef WINNT
00470     return single_process_sslMutex_Unlock(pMutex);
00471     /* release PRLock for other fibers in the process */
00472 #else
00473     return SECSuccess;
00474 #endif
00475 }
00476 
00477 int 
00478 sslMutex_Lock(sslMutex *pMutex)
00479 {
00480     HANDLE    hMutex;
00481     DWORD     event;
00482     DWORD     lastError;
00483     SECStatus rv;
00484     SECStatus retvalue = SECSuccess;
00485     PR_ASSERT(pMutex != 0);
00486 
00487     if (PR_FALSE == pMutex->isMultiProcess) {
00488         return single_process_sslMutex_Lock(pMutex);
00489     }
00490 #ifdef WINNT
00491     /* lock first to preserve from other threads/fibers
00492        in the same process */
00493     retvalue = single_process_sslMutex_Lock(pMutex);
00494 #endif
00495     PR_ASSERT(pMutex->u.sslMutx != 0 && 
00496               pMutex->u.sslMutx != INVALID_HANDLE_VALUE);
00497     if (!pMutex || (hMutex = pMutex->u.sslMutx) == 0 || 
00498         hMutex == INVALID_HANDLE_VALUE) {
00499         PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00500         return SECFailure;      /* what else ? */
00501     }
00502     /* acquire the mutex to be the only owner accross all other processes */
00503     event = WaitForSingleObject(hMutex, INFINITE);
00504     switch (event) {
00505     case WAIT_OBJECT_0:
00506     case WAIT_ABANDONED:
00507         rv = SECSuccess;
00508         break;
00509 
00510     case WAIT_TIMEOUT:
00511 #if defined(WAIT_IO_COMPLETION)
00512     case WAIT_IO_COMPLETION:
00513 #endif
00514     default:            /* should never happen. nothing we can do. */
00515         PR_ASSERT(!("WaitForSingleObject returned invalid value."));
00516        PORT_SetError(PR_UNKNOWN_ERROR);
00517        rv = SECFailure;
00518        break;
00519 
00520     case WAIT_FAILED:           /* failure returns this */
00521         rv = SECFailure;
00522         lastError = GetLastError();     /* for debugging */
00523         nss_MD_win32_map_default_error(lastError);
00524         break;
00525     }
00526 
00527     if (! (SECSuccess == retvalue && SECSuccess == rv)) {
00528         return SECFailure;
00529     }
00530     
00531     return SECSuccess;
00532 }
00533 
00534 #elif defined(XP_UNIX)
00535 
00536 #include <errno.h>
00537 #include "unix_err.h"
00538 
00539 SECStatus 
00540 sslMutex_Init(sslMutex *pMutex, int shared)
00541 {
00542     int rv;
00543     PR_ASSERT(pMutex);
00544     pMutex->isMultiProcess = (PRBool)(shared != 0);
00545     if (!shared) {
00546         return single_process_sslMutex_Init(pMutex);
00547     }
00548     do {
00549         rv = sem_init(&pMutex->u.sem, shared, 1);
00550     } while (rv < 0 && errno == EINTR);
00551     if (rv < 0) {
00552         nss_MD_unix_map_default_error(errno);
00553         return SECFailure;
00554     }
00555     return SECSuccess;
00556 }
00557 
00558 SECStatus 
00559 sslMutex_Destroy(sslMutex *pMutex)
00560 {
00561     int rv;
00562     if (PR_FALSE == pMutex->isMultiProcess) {
00563         return single_process_sslMutex_Destroy(pMutex);
00564     }
00565     do {
00566        rv = sem_destroy(&pMutex->u.sem);
00567     } while (rv < 0 && errno == EINTR);
00568     if (rv < 0) {
00569        nss_MD_unix_map_default_error(errno);
00570        return SECFailure;
00571     }
00572     return SECSuccess;
00573 }
00574 
00575 SECStatus 
00576 sslMutex_Unlock(sslMutex *pMutex)
00577 {
00578     int rv;
00579     if (PR_FALSE == pMutex->isMultiProcess) {
00580         return single_process_sslMutex_Unlock(pMutex);
00581     }
00582     do {
00583        rv = sem_post(&pMutex->u.sem);
00584     } while (rv < 0 && errno == EINTR);
00585     if (rv < 0) {
00586        nss_MD_unix_map_default_error(errno);
00587        return SECFailure;
00588     }
00589     return SECSuccess;
00590 }
00591 
00592 SECStatus 
00593 sslMutex_Lock(sslMutex *pMutex)
00594 {
00595     int rv;
00596     if (PR_FALSE == pMutex->isMultiProcess) {
00597         return single_process_sslMutex_Lock(pMutex);
00598     }
00599     do {
00600        rv = sem_wait(&pMutex->u.sem);
00601     } while (rv < 0 && errno == EINTR);
00602     if (rv < 0) {
00603        nss_MD_unix_map_default_error(errno);
00604        return SECFailure;
00605     }
00606     return SECSuccess;
00607 }
00608 
00609 #else
00610 
00611 SECStatus 
00612 sslMutex_Init(sslMutex *pMutex, int shared)
00613 {
00614     PR_ASSERT(pMutex);
00615     pMutex->isMultiProcess = (PRBool)(shared != 0);
00616     if (!shared) {
00617         return single_process_sslMutex_Init(pMutex);
00618     }
00619     PORT_Assert(!("sslMutex_Init not implemented for multi-process applications !"));
00620     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
00621     return SECFailure;
00622 }
00623 
00624 SECStatus 
00625 sslMutex_Destroy(sslMutex *pMutex)
00626 {
00627     PR_ASSERT(pMutex);
00628     if (PR_FALSE == pMutex->isMultiProcess) {
00629         return single_process_sslMutex_Destroy(pMutex);
00630     }
00631     PORT_Assert(!("sslMutex_Destroy not implemented for multi-process applications !"));
00632     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
00633     return SECFailure;
00634 }
00635 
00636 SECStatus 
00637 sslMutex_Unlock(sslMutex *pMutex)
00638 {
00639     PR_ASSERT(pMutex);
00640     if (PR_FALSE == pMutex->isMultiProcess) {
00641         return single_process_sslMutex_Unlock(pMutex);
00642     }
00643     PORT_Assert(!("sslMutex_Unlock not implemented for multi-process applications !"));
00644     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
00645     return SECFailure;
00646 }
00647 
00648 SECStatus 
00649 sslMutex_Lock(sslMutex *pMutex)
00650 {
00651     PR_ASSERT(pMutex);
00652     if (PR_FALSE == pMutex->isMultiProcess) {
00653         return single_process_sslMutex_Lock(pMutex);
00654     }
00655     PORT_Assert(!("sslMutex_Lock not implemented for multi-process applications !"));
00656     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
00657     return SECFailure;
00658 }
00659 
00660 #endif
00661 
00662 #endif