PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( PRCallOnceType *once, PRCallOnceWithArgFN func, void *arg) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (!once->initialized) { if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) { once->status = (*func)(arg); PR_Lock(mod_init.ml); once->initialized = 1; PR_NotifyAllCondVar(mod_init.cv); PR_Unlock(mod_init.ml); } else { PR_Lock(mod_init.ml); while (!once->initialized) { PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(mod_init.ml); } } else { if (PR_SUCCESS != once->status) { PR_SetError(PR_CALL_ONCE_ERROR, 0); } } return once->status; }
/* * When we notice we're using too much memory for decoded images, we enqueue a * DiscardRunnable, which runs this code. */ NS_IMETHODIMP DiscardTracker::DiscardRunnable::Run() { PR_ATOMIC_SET(&sDiscardRunnablePending, 0); DiscardTracker::DiscardNow(); return NS_OK; }
void nsDOMWorkerTimeout::ReleaseSpinlock() { #ifdef DEBUG PRInt32 suspended = #endif PR_ATOMIC_SET(&mSuspendSpinlock, 0); NS_ASSERTION(suspended == 1, "Huh?!"); }
void DiscardTracker::MaybeDiscardSoon() { // Are we carrying around too much decoded image data? If so, enqueue an // event to try to get us down under our limit. if (sCurrentDecodedImageBytes > sMaxDecodedImageKB * 1024 && !sDiscardableImages.isEmpty()) { // Check if the value of sDiscardRunnablePending used to be false if (!PR_ATOMIC_SET(&sDiscardRunnablePending, 1)) { nsRefPtr<DiscardRunnable> runnable = new DiscardRunnable(); NS_DispatchToMainThread(runnable); } } }
// Called from any thread NS_IMETHODIMP nsBaseAppShell::OnDispatchedEvent(nsIThreadInternal *thr) { if (mBlockNativeEvent) return NS_OK; int32_t lastVal = PR_ATOMIC_SET(&mNativeEventPending, 1); if (lastVal == 1) return NS_OK; // Returns on the main thread in NativeEventCallback above ScheduleNativeEventCallback(); return NS_OK; }
// Called by nsAppShell's native event callback void nsBaseAppShell::NativeEventCallback() { int32_t hasPending = PR_ATOMIC_SET(&mNativeEventPending, 0); if (hasPending == 0) return; // If DoProcessNextNativeEvent is on the stack, then we assume that we can // just unwind and let nsThread::ProcessNextEvent process the next event. // However, if we are called from a nested native event loop (maybe via some // plug-in or library function), then go ahead and process Gecko events now. if (mEventloopNestingState == eEventloopXPCOM) { mEventloopNestingState = eEventloopOther; // XXX there is a tiny risk we will never get a new NativeEventCallback, // XXX see discussion in bug 389931. return; } // nsBaseAppShell::Run is not being used to pump events, so this may be // our only opportunity to process pending gecko events. nsIThread *thread = NS_GetCurrentThread(); bool prevBlockNativeEvent = mBlockNativeEvent; if (mEventloopNestingState == eEventloopOther) { if (!NS_HasPendingEvents(thread)) return; // We're in a nested native event loop and have some gecko events to // process. While doing that we block processing native events from the // appshell - instead, we want to get back to the nested native event // loop ASAP (bug 420148). mBlockNativeEvent = true; } ++mEventloopNestingLevel; EventloopNestingState prevVal = mEventloopNestingState; NS_ProcessPendingEvents(thread, THREAD_EVENT_STARVATION_LIMIT); mProcessedGeckoEvents = true; mEventloopNestingState = prevVal; mBlockNativeEvent = prevBlockNativeEvent; // Continue processing pending events later (we don't want to starve the // embedders event loop). if (NS_HasPendingEvents(thread)) DoProcessMoreGeckoEvents(); --mEventloopNestingLevel; }
void nsDOMWorkerTimeout::AcquireSpinlock() { PRUint32 loopCount = 0; while (PR_ATOMIC_SET(&mSuspendSpinlock, 1) == 1) { if (++loopCount > SUSPEND_SPINLOCK_COUNT) { LOG(("AcquireSpinlock taking too long (looped %u times), yielding.", loopCount)); loopCount = 0; PR_Sleep(PR_INTERVAL_NO_WAIT); } } #ifdef PR_LOGGING if (loopCount) { LOG(("AcquireSpinlock needed %u loops", loopCount)); } #endif }
static void fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced) { CERTCertTrust* trust = NULL; NSSTrust *nssTrust; NSSCryptoContext *context = c->object.cryptoContext; nssCryptokiInstance *instance; NSSUTF8 *stanNick = NULL; /* We are holding the base class object's lock on entry of this function * This lock protects writes to fields of the CERTCertificate . * It is also needed by some functions to compute values such as trust. */ instance = get_cert_instance(c); if (instance) { stanNick = instance->label; } else if (context) { stanNick = c->object.tempName; } /* fill other fields needed by NSS3 functions using CERTCertificate */ if ((!cc->nickname && stanNick) || forced) { PRStatus nssrv; int nicklen, tokenlen, len; NSSUTF8 *tokenName = NULL; char *nick; if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) || (stanNick && PORT_Strchr(stanNick, ':') != NULL))) { tokenName = nssToken_GetName(instance->token); tokenlen = nssUTF8_Size(tokenName, &nssrv); } else { /* don't use token name for internal slot; 3.3 didn't */ tokenlen = 0; } if (stanNick) { nicklen = nssUTF8_Size(stanNick, &nssrv); len = tokenlen + nicklen; nick = PORT_ArenaAlloc(cc->arena, len); if (tokenName) { memcpy(nick, tokenName, tokenlen-1); nick[tokenlen-1] = ':'; memcpy(nick+tokenlen, stanNick, nicklen-1); } else { memcpy(nick, stanNick, nicklen-1); } nick[len-1] = '\0'; cc->nickname = nick; } else { cc->nickname = NULL; } } if (context) { /* trust */ nssTrust = nssCryptoContext_FindTrustForCertificate(context, c); if (!nssTrust) { /* chicken and egg issue: * * c->issuer and c->serial are empty at this point, but * nssTrustDomain_FindTrustForCertificate use them to look up * up the trust object, so we point them to cc->derIssuer and * cc->serialNumber. * * Our caller will fill these in with proper arena copies when we * return. */ c->issuer.data = cc->derIssuer.data; c->issuer.size = cc->derIssuer.len; c->serial.data = cc->serialNumber.data; c->serial.size = cc->serialNumber.len; nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c); } if (nssTrust) { trust = cert_trust_from_stan_trust(nssTrust, cc->arena); if (trust) { /* we should destroy cc->trust before replacing it, but it's allocated in cc->arena, so memory growth will occur on each refresh */ CERT_LockCertTrust(cc); cc->trust = trust; CERT_UnlockCertTrust(cc); } nssTrust_Destroy(nssTrust); } } else if (instance) { /* slot */ if (cc->slot != instance->token->pk11slot) { if (cc->slot) { PK11_FreeSlot(cc->slot); } cc->slot = PK11_ReferenceSlot(instance->token->pk11slot); } cc->ownSlot = PR_TRUE; /* pkcs11ID */ cc->pkcs11ID = instance->handle; /* trust */ trust = nssTrust_GetCERTCertTrustForCert(c, cc); if (trust) { /* we should destroy cc->trust before replacing it, but it's allocated in cc->arena, so memory growth will occur on each refresh */ CERT_LockCertTrust(cc); cc->trust = trust; CERT_UnlockCertTrust(cc); } nssCryptokiObject_Destroy(instance); } /* database handle is now the trust domain */ cc->dbhandle = c->object.trustDomain; /* subjectList ? */ /* istemp and isperm are supported in NSS 3.4 */ cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */ cc->isperm = PR_TRUE; /* by default */ /* pointer back */ cc->nssCertificate = c; if (trust) { /* force the cert type to be recomputed to include trust info */ PRUint32 nsCertType = cert_ComputeCertType(cc); /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */ PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32)); PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType); } }
/* * It's important that this function not acquire any locks, nor do anything * which might cause malloc to run. */ void ScheduleMemoryPressureEvent() { PR_ATOMIC_SET(&sMemoryPressurePending, 1); }
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 */