andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: /* andre@0: * mutex.c andre@0: * andre@0: * This file implements a mutual-exclusion locking facility for Modules andre@0: * using the NSS Cryptoki Framework. andre@0: */ andre@0: andre@0: #ifndef CK_T andre@0: #include "ck.h" andre@0: #endif /* CK_T */ andre@0: andre@0: /* andre@0: * NSSCKFWMutex andre@0: * andre@0: * NSSCKFWMutex_Destroy andre@0: * NSSCKFWMutex_Lock andre@0: * NSSCKFWMutex_Unlock andre@0: * andre@0: * nssCKFWMutex_Create andre@0: * nssCKFWMutex_Destroy andre@0: * nssCKFWMutex_Lock andre@0: * nssCKFWMutex_Unlock andre@0: * andre@0: * -- debugging versions only -- andre@0: * nssCKFWMutex_verifyPointer andre@0: * andre@0: */ andre@0: andre@0: struct NSSCKFWMutexStr { andre@0: PRLock *lock; andre@0: }; andre@0: andre@0: #ifdef DEBUG andre@0: /* andre@0: * But first, the pointer-tracking stuff. andre@0: * andre@0: * NOTE: the pointer-tracking support in NSS/base currently relies andre@0: * upon NSPR's CallOnce support. That, however, relies upon NSPR's andre@0: * locking, which is tied into the runtime. We need a pointer-tracker andre@0: * implementation that uses the locks supplied through C_Initialize. andre@0: * That support, however, can be filled in later. So for now, I'll andre@0: * just do this routines as no-ops. andre@0: */ andre@0: andre@0: static CK_RV andre@0: mutex_add_pointer andre@0: ( andre@0: const NSSCKFWMutex *fwMutex andre@0: ) andre@0: { andre@0: return CKR_OK; andre@0: } andre@0: andre@0: static CK_RV andre@0: mutex_remove_pointer andre@0: ( andre@0: const NSSCKFWMutex *fwMutex andre@0: ) andre@0: { andre@0: return CKR_OK; andre@0: } andre@0: andre@0: NSS_IMPLEMENT CK_RV andre@0: nssCKFWMutex_verifyPointer andre@0: ( andre@0: const NSSCKFWMutex *fwMutex andre@0: ) andre@0: { andre@0: return CKR_OK; andre@0: } andre@0: andre@0: #endif /* DEBUG */ andre@0: andre@0: /* andre@0: * nssCKFWMutex_Create andre@0: * andre@0: */ andre@0: NSS_EXTERN NSSCKFWMutex * andre@0: nssCKFWMutex_Create andre@0: ( andre@0: CK_C_INITIALIZE_ARGS_PTR pInitArgs, andre@0: CryptokiLockingState LockingState, andre@0: NSSArena *arena, andre@0: CK_RV *pError andre@0: ) andre@0: { andre@0: NSSCKFWMutex *mutex; andre@0: andre@0: mutex = nss_ZNEW(arena, NSSCKFWMutex); andre@0: if (!mutex) { andre@0: *pError = CKR_HOST_MEMORY; andre@0: return (NSSCKFWMutex *)NULL; andre@0: } andre@0: *pError = CKR_OK; andre@0: mutex->lock = NULL; andre@0: if (LockingState == MultiThreaded) { andre@0: mutex->lock = PR_NewLock(); andre@0: if (!mutex->lock) { andre@0: *pError = CKR_HOST_MEMORY; /* we couldn't get the resource */ andre@0: } andre@0: } andre@0: andre@0: if( CKR_OK != *pError ) { andre@0: (void)nss_ZFreeIf(mutex); andre@0: return (NSSCKFWMutex *)NULL; andre@0: } andre@0: andre@0: #ifdef DEBUG andre@0: *pError = mutex_add_pointer(mutex); andre@0: if( CKR_OK != *pError ) { andre@0: if (mutex->lock) { andre@0: PR_DestroyLock(mutex->lock); andre@0: } andre@0: (void)nss_ZFreeIf(mutex); andre@0: return (NSSCKFWMutex *)NULL; andre@0: } andre@0: #endif /* DEBUG */ andre@0: andre@0: return mutex; andre@0: } andre@0: andre@0: /* andre@0: * nssCKFWMutex_Destroy andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: nssCKFWMutex_Destroy andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: CK_RV rv = CKR_OK; andre@0: andre@0: #ifdef NSSDEBUG andre@0: rv = nssCKFWMutex_verifyPointer(mutex); andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* NSSDEBUG */ andre@0: andre@0: if (mutex->lock) { andre@0: PR_DestroyLock(mutex->lock); andre@0: } andre@0: andre@0: #ifdef DEBUG andre@0: (void)mutex_remove_pointer(mutex); andre@0: #endif /* DEBUG */ andre@0: andre@0: (void)nss_ZFreeIf(mutex); andre@0: return rv; andre@0: } andre@0: andre@0: /* andre@0: * nssCKFWMutex_Lock andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: nssCKFWMutex_Lock andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: #ifdef NSSDEBUG andre@0: CK_RV rv = nssCKFWMutex_verifyPointer(mutex); andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* NSSDEBUG */ andre@0: if (mutex->lock) { andre@0: PR_Lock(mutex->lock); andre@0: } andre@0: andre@0: return CKR_OK; andre@0: } andre@0: andre@0: /* andre@0: * nssCKFWMutex_Unlock andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: nssCKFWMutex_Unlock andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: PRStatus nrv; andre@0: #ifdef NSSDEBUG andre@0: CK_RV rv = nssCKFWMutex_verifyPointer(mutex); andre@0: andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* NSSDEBUG */ andre@0: andre@0: if (!mutex->lock) andre@0: return CKR_OK; andre@0: andre@0: nrv = PR_Unlock(mutex->lock); andre@0: andre@0: /* if unlock fails, either we have a programming error, or we have andre@0: * some sort of hardware failure... in either case return CKR_DEVICE_ERROR. andre@0: */ andre@0: return nrv == PR_SUCCESS ? CKR_OK : CKR_DEVICE_ERROR; andre@0: } andre@0: andre@0: /* andre@0: * NSSCKFWMutex_Destroy andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: NSSCKFWMutex_Destroy andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: #ifdef DEBUG andre@0: CK_RV rv = nssCKFWMutex_verifyPointer(mutex); andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* DEBUG */ andre@0: andre@0: return nssCKFWMutex_Destroy(mutex); andre@0: } andre@0: andre@0: /* andre@0: * NSSCKFWMutex_Lock andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: NSSCKFWMutex_Lock andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: #ifdef DEBUG andre@0: CK_RV rv = nssCKFWMutex_verifyPointer(mutex); andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* DEBUG */ andre@0: andre@0: return nssCKFWMutex_Lock(mutex); andre@0: } andre@0: andre@0: /* andre@0: * NSSCKFWMutex_Unlock andre@0: * andre@0: */ andre@0: NSS_EXTERN CK_RV andre@0: NSSCKFWMutex_Unlock andre@0: ( andre@0: NSSCKFWMutex *mutex andre@0: ) andre@0: { andre@0: #ifdef DEBUG andre@0: CK_RV rv = nssCKFWMutex_verifyPointer(mutex); andre@0: if( CKR_OK != rv ) { andre@0: return rv; andre@0: } andre@0: #endif /* DEBUG */ andre@0: andre@0: return nssCKFWMutex_Unlock(mutex); andre@0: } andre@0: