Ejemplo n.º 1
0
SECStatus 
sslMutex_Unlock(sslMutex *pMutex)
{
    PRInt32 newValue;
    if (PR_FALSE == pMutex->isMultiProcess) {
        return single_process_sslMutex_Unlock(pMutex);
    }

    if (pMutex->u.pipeStr.mPipes[2] != SSL_MUTEX_MAGIC) {
	PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
	return SECFailure;
    }
    /* Do Memory Barrier here. */
    newValue = PR_ATOMIC_DECREMENT(&pMutex->u.pipeStr.nWaiters);
    if (newValue > 0) {
	int  cc;
	char c  = 1;
	do {
	    cc = write(pMutex->u.pipeStr.mPipes[1], &c, 1);
	} while (cc < 0 && (errno == EINTR || errno == EAGAIN));
	if (cc != 1) {
	    if (cc < 0)
		nss_MD_unix_map_default_error(errno);
	    else
		PORT_SetError(PR_UNKNOWN_ERROR);
	    return SECFailure;
	}
    }
    return SECSuccess;
}
Ejemplo n.º 2
0
int32_t
gfxMemorySharedReadLock::ReadUnlock()
{
  int32_t readCount = PR_ATOMIC_DECREMENT(&mReadCount);
  NS_ASSERTION(readCount >= 0, "ReadUnlock called without ReadLock.");

  return readCount;
}
Ejemplo n.º 3
0
SECStatus
SECMOD_UnloadModule(SECMODModule *mod) {
    PRLibrary *library;
    char *disableUnload = NULL;

    if (!mod->loaded) {
	return SECFailure;
    }
    if (finalizeModules) {
        if (mod->functionList &&!mod->moduleDBOnly) {
	    PK11_GETTAB(mod)->C_Finalize(NULL);
	}
    }
    mod->moduleID = 0;
    mod->loaded = PR_FALSE;
    
    /* do we want the semantics to allow unloading the internal library?
     * if not, we should change this to SECFailure and move it above the
     * mod->loaded = PR_FALSE; */
    if (mod->internal && (mod->dllName == NULL)) {
#ifndef NSS_STATIC
        if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
          if (softokenLib) {
              disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
              if (!disableUnload) {
#ifdef DEBUG
                  PRStatus status = PR_UnloadLibrary(softokenLib);
                  PORT_Assert(PR_SUCCESS == status);
#else
                  PR_UnloadLibrary(softokenLib);
#endif
              }
              softokenLib = NULL;
          }
          loadSoftokenOnce = pristineCallOnce;
        }
#endif
	return SECSuccess;
    }

    library = (PRLibrary *)mod->library;
    /* paranoia */
    if (library == NULL) {
#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS)
	if (strstr(mod->dllName, "nssckbi") != NULL) {
	    return SECSuccess;
	}
#endif
	return SECFailure;
    }

    disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
    if (!disableUnload) {
        PR_UnloadLibrary(library);
    }
    return SECSuccess;
}
nsSystemPrincipal::Release()
{
  NS_PRECONDITION(0 != refcount, "dup release");
  nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount);
  NS_LOG_RELEASE(this, count, "nsSystemPrincipal");
  if (count == 0) {
    delete this;
  }

  return count;
}
Ejemplo n.º 5
0
void
nsStringBuffer::Release()
  {
    int32_t count = PR_ATOMIC_DECREMENT(&mRefCount);
    NS_LOG_RELEASE(this, count, "nsStringBuffer");
    if (count == 0)
      {
        STRING_STAT_INCREMENT(Free);
        free(this); // we were allocated with |malloc|
      }
  }
Ejemplo n.º 6
0
STDMETHODIMP_(ULONG) CMapiImp::Release() 
{
    PRInt32 temp;
    temp = PR_ATOMIC_DECREMENT(&m_cRef);
    if (m_cRef == 0)
    {
        delete this;
        return 0;
    }

    return temp;
}
Ejemplo n.º 7
0
STDMETHODIMP_(ULONG) CMapiFactory::Release() 
{
    int32_t temp;
    temp = PR_ATOMIC_DECREMENT(&m_cRef);
    if (m_cRef == 0)
    {
        delete this;
        return 0;
    }

    return temp;
}
Ejemplo n.º 8
0
NSS_IMPLEMENT PRStatus
nssCertificate_Destroy (
  NSSCertificate *c
)
{
    nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
    nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};

    if (c) {
	PRUint32 i;
	nssDecodedCert *dc = c->decoding;
	NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
	NSSCryptoContext *cc = c->object.cryptoContext;

	PR_ASSERT(c->object.refCount > 0);

	/* --- LOCK storage --- */
	if (cc) {
	    nssCertificateStore_Lock(cc->certStore, &lockTrace);
	} else {
	    nssTrustDomain_LockCertCache(td);
	}
	if (PR_ATOMIC_DECREMENT(&c->object.refCount) == 0) {
	    /* --- remove cert and UNLOCK storage --- */
	    if (cc) {
		nssCertificateStore_RemoveCertLOCKED(cc->certStore, c);
		nssCertificateStore_Unlock(cc->certStore, &lockTrace,
                                           &unlockTrace);
	    } else {
		nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
		nssTrustDomain_UnlockCertCache(td);
	    }
	    /* free cert data */
	    for (i=0; i<c->object.numInstances; i++) {
		nssCryptokiObject_Destroy(c->object.instances[i]);
	    }
	    nssPKIObject_DestroyLock(&c->object);
	    nssArena_Destroy(c->object.arena);
	    nssDecodedCert_Destroy(dc);
	} else {
	    /* --- UNLOCK storage --- */
	    if (cc) {
		nssCertificateStore_Unlock(cc->certStore,
					   &lockTrace,
					   &unlockTrace);
	    } else {
		nssTrustDomain_UnlockCertCache(td);
	    }
	}
    }
    return PR_SUCCESS;
}
Ejemplo n.º 9
0
PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
{
    if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending))
    {
        PRIntn rv = pthread_cond_destroy(&cvar->cv);
        PR_ASSERT(0 == rv);
#if defined(DEBUG)
        memset(cvar, 0xaf, sizeof(PRCondVar));
        pt_debug.cvars_destroyed += 1;
#endif
        PR_Free(cvar);
    }
}  /* PR_DestroyCondVar */
Ejemplo n.º 10
0
NSS_IMPLEMENT PRStatus
nssSlot_Destroy (
  NSSSlot *slot
)
{
    if (slot) {
	if (PR_ATOMIC_DECREMENT(&slot->base.refCount) == 0) {
	    PZ_DestroyLock(slot->base.lock);
	    return nssArena_Destroy(slot->base.arena);
	}
    }
    return PR_SUCCESS;
}
Ejemplo n.º 11
0
int32_t
gfxShmSharedReadLock::ReadUnlock() {
  if (!mAllocSuccess) {
    return 0;
  }
  ShmReadLockInfo* info = GetShmReadLockInfoPtr();
  int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount);
  NS_ASSERTION(readCount >= 0, "ReadUnlock called without a ReadLock.");
  if (readCount <= 0) {
    mAllocator->FreeShmemSection(mShmemSection);
  }
  return readCount;
}
XPCWrappedNativeProto::~XPCWrappedNativeProto()
{
    NS_ASSERTION(!mJSProtoObject, "JSProtoObject still alive");

    MOZ_COUNT_DTOR(XPCWrappedNativeProto);

#ifdef DEBUG
    PR_ATOMIC_DECREMENT(&gDEBUG_LiveProtoCount);
#endif
    
    // Note that our weak ref to mScope is not to be trusted at this point.

    XPCNativeSet::ClearCacheEntryForClassInfo(mClassInfo);

    delete mScriptableInfo;
}
Ejemplo n.º 13
0
NSS_IMPLEMENT PRStatus
nssToken_Destroy (
  NSSToken *tok
)
{
    if (tok) {
	if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) {
	    PZ_DestroyLock(tok->base.lock);
	    nssTokenObjectCache_Destroy(tok->cache);
	    /* The token holds the first/last reference to the slot.
	     * When the token is actually destroyed, that ref must go too.
	     */
	    (void)nssSlot_Destroy(tok->slot);
	    return nssArena_Destroy(tok->base.arena);
	}
    }
    return PR_SUCCESS;
}
Ejemplo n.º 14
0
PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
{
    int rv;

    PR_ASSERT(mon != NULL);
    if (PR_ATOMIC_DECREMENT(&mon->refCount) == 0)
    {
        rv = pthread_cond_destroy(&mon->waitCV);
        PR_ASSERT(0 == rv);
        rv = pthread_cond_destroy(&mon->entryCV);
        PR_ASSERT(0 == rv);
        rv = pthread_mutex_destroy(&mon->lock);
        PR_ASSERT(0 == rv);
#if defined(DEBUG)
        memset(mon, 0xaf, sizeof(PRMonitor));
#endif
        PR_Free(mon);
    }
}  /* PR_DestroyMonitor */
Ejemplo n.º 15
0
static void pt_PostNotifies(PRLock *lock, PRBool unlock)
{
    PRIntn index, rv;
    _PT_Notified post;
    _PT_Notified *notified, *prev = NULL;
    /*
     * Time to actually notify any conditions that were affected
     * while the lock was held. Get a copy of the list that's in
     * the lock structure and then zero the original. If it's
     * linked to other such structures, we own that storage.
     */
    post = lock->notified;  /* a safe copy; we own the lock */

#if defined(DEBUG)
    memset(&lock->notified, 0, sizeof(_PT_Notified));  /* reset */
#else
    lock->notified.length = 0;  /* these are really sufficient */
    lock->notified.link = NULL;
#endif

    /* should (may) we release lock before notifying? */
    if (unlock)
    {
        rv = pthread_mutex_unlock(&lock->mutex);
        PR_ASSERT(0 == rv);
    }

    notified = &post;  /* this is where we start */
    do
    {
        for (index = 0; index < notified->length; ++index)
        {
            PRCondVar *cv = notified->cv[index].cv;
            PR_ASSERT(NULL != cv);
            PR_ASSERT(0 != notified->cv[index].times);
            if (-1 == notified->cv[index].times)
            {
                rv = pthread_cond_broadcast(&cv->cv);
                PR_ASSERT(0 == rv);
            }
            else
            {
                while (notified->cv[index].times-- > 0)
                {
                    rv = pthread_cond_signal(&cv->cv);
                    PR_ASSERT(0 == rv);
                }
            }
#if defined(DEBUG)
            pt_debug.cvars_notified += 1;
            if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
            {
                pt_debug.delayed_cv_deletes += 1;
                PR_DestroyCondVar(cv);
            }
#else  /* defined(DEBUG) */
            if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending))
                PR_DestroyCondVar(cv);
#endif  /* defined(DEBUG) */
        }
        prev = notified;
        notified = notified->link;
        if (&post != prev) PR_DELETE(prev);
    } while (NULL != notified);
}  /* pt_PostNotifies */
Ejemplo n.º 16
0
int main(int argc, char **argv)
{
    PRInt32 rv, oldval, test, result = 0;
    PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);

    /***********************/
    /* Test the functions. */
    /***********************/

    oldval = test = -2;
    rv = PR_AtomicIncrement(&test);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicIncrement(%d) == %d: %s\n",
        oldval, rv, (rv == -1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicIncrement(&test);
    result = result | ((rv == 0) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicIncrement(%d) == %d: %s\n",
        oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicIncrement(&test);
    result = result | ((rv == 1) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicIncrement(%d) == %d: %s\n",
        oldval, rv, (rv == 1) ? "PASSED" : "FAILED");

    oldval = test = -2;
    rv = PR_AtomicAdd(&test,1);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
        oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicAdd(&test, 4);
    result = result | ((rv == 3) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
        oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicAdd(&test, -6);
    result = result | ((rv == -3) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
        oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED");

    oldval = test = 2;
    rv = PR_AtomicDecrement(&test);
    result = result | ((rv == 1) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicDecrement(%d) == %d: %s\n",
        oldval, rv, (rv == 1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicDecrement(&test);
    result = result | ((rv == 0) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicDecrement(%d) == %d: %s\n",
        oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_AtomicDecrement(&test);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicDecrement(%d) == %d: %s\n",
        oldval, rv, (rv == -1) ? "PASSED" : "FAILED");

    /* set to a different value */
    oldval = test = -2;
    rv = PR_AtomicSet(&test, 2);
    result = result | (((rv == -2) && (test == 2)) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicSet(%d, %d) == %d: %s\n",
        oldval, 2, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED");

    /* set to the same value */
    oldval = test = -2;
    rv = PR_AtomicSet(&test, -2);
    result = result | (((rv == -2) && (test == -2)) ? 0 : 1);
    PR_fprintf(
        output, "PR_AtomicSet(%d, %d) == %d: %s\n",
        oldval, -2, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED");

    /***********************/
    /* Test the macros.    */
    /***********************/

    oldval = test = -2;
    rv = PR_ATOMIC_INCREMENT(&test);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == -1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_INCREMENT(&test);
    result = result | ((rv == 0) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_INCREMENT(&test);
    result = result | ((rv == 1) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == 1) ? "PASSED" : "FAILED");

    oldval = test = -2;
    rv = PR_ATOMIC_ADD(&test,1);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n",
        oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_ADD(&test, 4);
    result = result | ((rv == 3) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n",
        oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_ADD(&test, -6);
    result = result | ((rv == -3) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n",
        oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED");

    oldval = test = 2;
    rv = PR_ATOMIC_DECREMENT(&test);
    result = result | ((rv == 1) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == 1) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_DECREMENT(&test);
    result = result | ((rv == 0) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
    oldval = test;
    rv = PR_ATOMIC_DECREMENT(&test);
    result = result | ((rv == -1) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n",
        oldval, rv, (rv == -1) ? "PASSED" : "FAILED");

    /* set to a different value */
    oldval = test = -2;
    rv = PR_ATOMIC_SET(&test, 2);
    result = result | (((rv == -2) && (test == 2)) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_SET(%d, %d) == %d: %s\n",
        oldval, 2, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED");

    /* set to the same value */
    oldval = test = -2;
    rv = PR_ATOMIC_SET(&test, -2);
    result = result | (((rv == -2) && (test == -2)) ? 0 : 1);
    PR_fprintf(
        output, "PR_ATOMIC_SET(%d, %d) == %d: %s\n",
        oldval, -2, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED");

    PR_fprintf(
        output, "Atomic operations test %s\n",
        (result == 0) ? "PASSED" : "FAILED");
    return result;
}  /* main */
Ejemplo n.º 17
0
/*
 * destroy a symetric key
 */
void
PK11_FreeSymKey(PK11SymKey *symKey)
{
    PK11SlotInfo *slot;
    PRBool freeit = PR_TRUE;

    if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
	PK11SymKey *parent = symKey->parent;

	symKey->parent = NULL;
	if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) {
	    pk11_EnterKeyMonitor(symKey);
	    (void) PK11_GETTAB(symKey->slot)->
		C_DestroyObject(symKey->session, symKey->objectID);
	    pk11_ExitKeyMonitor(symKey);
	}
	if (symKey->data.data) {
	    PORT_Memset(symKey->data.data, 0, symKey->data.len);
	    PORT_Free(symKey->data.data);
	}
	/* free any existing data */
	if (symKey->userData && symKey->freeFunc) {
	    (*symKey->freeFunc)(symKey->userData);
	}
        slot = symKey->slot;
        PZ_Lock(slot->freeListLock);
	if (slot->keyCount < slot->maxKeyCount) {
	    /* 
             * freeSymkeysWithSessionHead contain a list of reusable
	     *  SymKey structures with valid sessions.
	     *    sessionOwner must be true.
             *    session must be valid.
             * freeSymKeysHead contain a list of SymKey structures without
             *  valid session.
             *    session must be CK_INVALID_SESSION.
	     *    though sessionOwner is false, callers should not depend on
	     *    this fact.
	     */
	    if (symKey->sessionOwner) {
		PORT_Assert (symKey->session != CK_INVALID_SESSION);
		symKey->next = slot->freeSymKeysWithSessionHead;
		slot->freeSymKeysWithSessionHead = symKey;
	    } else {
		symKey->session = CK_INVALID_SESSION;
		symKey->next = slot->freeSymKeysHead;
		slot->freeSymKeysHead = symKey;
	    }
	    slot->keyCount++;
	    symKey->slot = NULL;
	    freeit = PR_FALSE;
        }
	PZ_Unlock(slot->freeListLock);
        if (freeit) {
	    pk11_CloseSession(symKey->slot, symKey->session,
							symKey->sessionOwner);
	    PORT_Free(symKey);
	}
	PK11_FreeSlot(slot);

	if (parent) {
	    PK11_FreeSymKey(parent);
	}
    }
}
Ejemplo n.º 18
0
/*
 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
 */
PKIX_Error *
PKIX_PL_Object_DecRef(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_Int32 refCount = 0;
        PKIX_PL_Object *objectHeader = NULL;
        PKIX_PL_NssContext *context = NULL;
            
        PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
        PKIX_NULLCHECK_ONE(object);

        if (plContext){
                /* 
                 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
                 * have a header therefore we cannot verify its type before
                 * casting.
                 */  
                context = (PKIX_PL_NssContext *) plContext;
                if (context->arena != NULL) {
                        goto cleanup;
                }
        }

        if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
                goto cleanup;
        }

        /* Shift pointer from user data to object header */
        PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
                    PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);

        refCount = PR_ATOMIC_DECREMENT(&objectHeader->references);

        if (refCount == 0) {
            PKIX_PL_DestructorCallback destructor = NULL;
            pkix_ClassTable_Entry *ctEntry = NULL;
            PKIX_UInt32 objType = objectHeader->type;
            
            /* first, special handling for system types */
            if (objType >= PKIX_NUMTYPES){
#ifdef PKIX_USER_OBJECT_TYPE
                PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
                PR_Lock(classTableLock);
                pkixErrorResult = pkix_pl_PrimHashTable_Lookup
                    (classTable,
                     (void *)&objType,
                     objType,
                     NULL,
                     (void **)&ctEntry,
                     plContext);
                PKIX_OBJECT_DEBUG
                    ("\tCalling PR_Unlock).\n");
                PR_Unlock(classTableLock);
                if (pkixErrorResult){
                    PKIX_ERROR_FATAL
                        (PKIX_ERRORINGETTINGDESTRUCTOR);
                }
                
                if (ctEntry != NULL){
                    destructor = ctEntry->destructor;
                }
#else
                PORT_Assert (0);
                pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
                pkixErrorClass = PKIX_FATAL_ERROR;
                goto cleanup;
#endif /* PKIX_USER_OBJECT_TYPE */
            } else {
                ctEntry = &systemClasses[objType];
                destructor = ctEntry->destructor;
            }
            
            if (destructor != NULL){
                /* Call destructor on user data if necessary */
                pkixErrorResult = destructor(object, plContext);
                if (pkixErrorResult) {
                    pkixErrorClass = PKIX_FATAL_ERROR;
                    PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext);
                    pkixErrorResult = NULL;
                }
            }
            
            /* Atomically decrement object counter */
            PR_ATOMIC_DECREMENT(&ctEntry->objCounter);
            
            /* pkix_pl_Object_Destroy assumes the lock is held */
            /* It will call unlock and destroy the object */
            pkixErrorResult = pkix_pl_Object_Destroy(object, plContext);
            goto cleanup;
        }

        if (refCount < 0) {
            PKIX_ERROR_ALLOC_ERROR();
        }

cleanup:

        PKIX_RETURN(OBJECT);
}
nsScriptableUnicodeConverter::~nsScriptableUnicodeConverter()
{
  PR_ATOMIC_DECREMENT(&gInstanceCount);
}