Esempio n. 1
0
PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads,
                                PRUint32 stacksize)
{
PRThreadPool *tp;
PRThread *thr;
int i;
wthread *wthrp;

	tp = alloc_threadpool();
	if (NULL == tp)
		return NULL;

	tp->init_threads = initial_threads;
	tp->max_threads = max_threads;
	tp->stacksize = stacksize;
	PR_INIT_CLIST(&tp->jobq.list);
	PR_INIT_CLIST(&tp->ioq.list);
	PR_INIT_CLIST(&tp->timerq.list);
	PR_INIT_CLIST(&tp->jobq.wthreads);
	PR_INIT_CLIST(&tp->ioq.wthreads);
	PR_INIT_CLIST(&tp->timerq.wthreads);
	tp->shutdown = PR_FALSE;

	PR_Lock(tp->jobq.lock);
	for(i=0; i < initial_threads; ++i) {

		thr = PR_CreateThread(PR_USER_THREAD, wstart,
						tp, PR_PRIORITY_NORMAL,
						PR_GLOBAL_THREAD, PR_JOINABLE_THREAD,stacksize);
		PR_ASSERT(thr);
		wthrp = PR_NEWZAP(wthread);
		PR_ASSERT(wthrp);
		wthrp->thread = thr;
		PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads);
	}
	tp->current_threads = initial_threads;

	thr = PR_CreateThread(PR_USER_THREAD, io_wstart,
					tp, PR_PRIORITY_NORMAL,
					PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize);
	PR_ASSERT(thr);
	wthrp = PR_NEWZAP(wthread);
	PR_ASSERT(wthrp);
	wthrp->thread = thr;
	PR_APPEND_LINK(&wthrp->links, &tp->ioq.wthreads);

	thr = PR_CreateThread(PR_USER_THREAD, timer_wstart,
					tp, PR_PRIORITY_NORMAL,
					PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize);
	PR_ASSERT(thr);
	wthrp = PR_NEWZAP(wthread);
	PR_ASSERT(wthrp);
	wthrp->thread = thr;
	PR_APPEND_LINK(&wthrp->links, &tp->timerq.wthreads);

	PR_Unlock(tp->jobq.lock);
	return tp;
}
Esempio n. 2
0
/*
 * add a job to the work queue
 */
static void
add_to_jobq(PRThreadPool *tp, PRJob *jobp)
{
	/*
	 * add to jobq
	 */
#ifdef OPT_WINNT
	PR_Lock(tp->jobq.lock);
	tp->jobq.cnt++;
	PR_Unlock(tp->jobq.lock);
	/*
	 * notify worker thread(s)
	 */
	PostQueuedCompletionStatus(tp->jobq.nt_completion_port, 0,
            FALSE, &jobp->nt_notifier.overlapped);
#else
	PR_Lock(tp->jobq.lock);
	PR_APPEND_LINK(&jobp->links,&tp->jobq.list);
	tp->jobq.cnt++;
	if ((tp->idle_threads < tp->jobq.cnt) &&
					(tp->current_threads < tp->max_threads)) {
		wthread *wthrp;
		/*
		 * increment thread count and unlock the jobq lock
		 */
		tp->current_threads++;
		PR_Unlock(tp->jobq.lock);
		/* create new worker thread */
		wthrp = PR_NEWZAP(wthread);
		if (wthrp) {
			wthrp->thread = PR_CreateThread(PR_USER_THREAD, wstart,
						tp, PR_PRIORITY_NORMAL,
						PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,tp->stacksize);
			if (NULL == wthrp->thread) {
				PR_DELETE(wthrp);  /* this sets wthrp to NULL */
			}
		}
		PR_Lock(tp->jobq.lock);
		if (NULL == wthrp) {
			tp->current_threads--;
		} else {
			PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads);
		}
	}
	/*
	 * wakeup a worker thread
	 */
	PR_NotifyCondVar(tp->jobq.cv);
	PR_Unlock(tp->jobq.lock);
#endif
}
NS_IMETHODIMP
nsSocketTransportService::PostEvent(PLEvent *event)
{
    LOG(("nsSocketTransportService::PostEvent [event=%p]\n", event));

    NS_ASSERTION(event, "null event");

    nsAutoLock lock(mEventQLock);
    if (!mInitialized) {
        // Allow socket detach handlers to post events
        if (!mShuttingDown || (PR_GetCurrentThread() != gSocketThread)) {
            NS_WARN_IF_FALSE(PR_GetCurrentThread() != gSocketThread,
                            "Rejecting event posted to uninitialized sts");
            return NS_ERROR_OFFLINE;
        }

    }

    PR_APPEND_LINK(&event->link, &mEventQ);

    if (mThreadEvent)
        PR_SetPollableEvent(mThreadEvent);
    // else wait for Poll timeout
    return NS_OK;
}
Esempio n. 4
0
nsProfileLock& nsProfileLock::operator=(nsProfileLock& rhs)
{
    Unlock();

    mHaveLock = rhs.mHaveLock;
    rhs.mHaveLock = false;

#if defined (XP_WIN)
    mLockFileHandle = rhs.mLockFileHandle;
    rhs.mLockFileHandle = INVALID_HANDLE_VALUE;
#elif defined (XP_OS2)
    mLockFileHandle = rhs.mLockFileHandle;
    rhs.mLockFileHandle = -1;
#elif defined (XP_UNIX)
    mLockFileDesc = rhs.mLockFileDesc;
    rhs.mLockFileDesc = -1;
    mPidLockFileName = rhs.mPidLockFileName;
    rhs.mPidLockFileName = nullptr;
    if (mPidLockFileName)
    {
        // rhs had a symlink lock, therefore it was on the list.
        PR_REMOVE_LINK(&rhs);
        PR_APPEND_LINK(this, &mPidLockList);
    }
#endif

    return *this;
}
Esempio n. 5
0
nsresult
nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback)
{
  NS_ENSURE_STATE(!mShutdown);

  MaybeReloadPAC();

  PendingPACQuery *query = new PendingPACQuery(this, uri, callback);
  if (!query)
    return NS_ERROR_OUT_OF_MEMORY;
  NS_ADDREF(query);
  PR_APPEND_LINK(query, &mPendingQ);

  // If we're waiting for the PAC file to load, then delay starting the query.
  // See OnStreamComplete.  However, if this is the PAC URI then query right
  // away since we know the result will be DIRECT.  We could shortcut some code
  // in this case by issuing the callback directly from here, but that would
  // require extra code, so we just go through the usual async code path.
  int isPACURI = IsPACURI(uri);

  if (IsLoading() && !isPACURI)
    return NS_OK;

  nsresult rv = query->Start(isPACURI ? 0 : nsIDNSService::RESOLVE_SPECULATE);
  if (rv == NS_ERROR_DNS_LOOKUP_QUEUE_FULL && !isPACURI) {
    query->OnLookupComplete(NULL, NULL, NS_OK);
    rv = NS_OK;
  } else if (NS_FAILED(rv)) {
    NS_WARNING("failed to start PAC query");
    PR_REMOVE_LINK(query);
    NS_RELEASE(query);
  }

  return rv;
}
Esempio n. 6
0
/*
 * Creates the ephemeral public and private ECDH keys used by
 * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
 * For now, the elliptic curve is chosen to be the same
 * strength as the signing certificate (ECC or RSA).
 * We need an API to specify the curve. This won't be a real
 * issue until we further develop server-side support for ECC
 * cipher suites.
 */
static SECStatus
ssl_CreateECDHEphemeralKeys(sslSocket *ss, const namedGroupDef *ecGroup)
{
    sslEphemeralKeyPair *keyPair = NULL;

    /* if there's no global key for this curve, make one. */
    if (gECDHEKeyPairs[ecGroup->index].pair == NULL) {
        PRStatus status;

        status = PR_CallOnce(&gECDHEInitOnce, ssl_ECRegister);
        if (status != PR_SUCCESS) {
            PORT_SetError(gECDHEInitError);
            return SECFailure;
        }
        status = PR_CallOnceWithArg(&gECDHEKeyPairs[ecGroup->index].once,
                                    ssl_CreateECDHEphemeralKeyPairOnce,
                                    (void *)ecGroup);
        if (status != PR_SUCCESS) {
            PORT_SetError(gECDHEKeyPairs[ecGroup->index].error);
            return SECFailure;
        }
    }

    keyPair = ssl_CopyEphemeralKeyPair(gECDHEKeyPairs[ecGroup->index].pair);
    PORT_Assert(keyPair != NULL);
    if (!keyPair)
        return SECFailure;

    PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
    PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
    return SECSuccess;
}
nsresult
nsMemoryCacheDevice::BindEntry(nsCacheEntry * entry)
{
    if (!entry->IsDoomed()) {
        NS_ASSERTION(PR_CLIST_IS_EMPTY(entry),"entry is already on a list!");

        // append entry to the eviction list
        PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, 0)]);

        // add entry to hashtable of mem cache entries
        nsresult  rv = mMemCacheEntries.AddEntry(entry);
        if (NS_FAILED(rv)) {
            PR_REMOVE_AND_INIT_LINK(entry);
            return rv;
        }

        // add size of entry to memory totals
        ++mEntryCount;
        if (mMaxEntryCount < mEntryCount) mMaxEntryCount = mEntryCount;

        mTotalSize += entry->DataSize();
        EvictEntriesIfNecessary();
    }

    return NS_OK;
}
nsresult
nsMemoryCacheDevice::OnDataSizeChange( nsCacheEntry * entry, int32_t deltaSize)
{
    if (entry->IsStreamData()) {
        // we have the right to refuse or pre-evict
        uint32_t  newSize = entry->DataSize() + deltaSize;
        if (EntryIsTooBig(newSize)) {
#ifdef DEBUG
            nsresult rv =
#endif
                nsCacheService::DoomEntry(entry);
            NS_ASSERTION(NS_SUCCEEDED(rv),"DoomEntry() failed.");
            return NS_ERROR_ABORT;
        }
    }

    // adjust our totals
    mTotalSize    += deltaSize;
    
    if (!entry->IsDoomed()) {
        // move entry to the tail of the appropriate eviction list
        PR_REMOVE_AND_INIT_LINK(entry);
        PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, deltaSize)]);
    }

    EvictEntriesIfNecessary();
    return NS_OK;
}
Esempio n. 9
0
/**
 * Called from PL_HashTableEnumerateEntries
 * A pointer to a PRCList (circular linked list) is passed in. 
 * Once enumeration is complete, the PRCList will contain a lexically
 * ordered list of a copy of the keys in the hash.  
 * The caller needs to free the copies
 */ 
static PRIntn OrderLoop(PLHashEntry *he, PRIntn index, void *arg)
{
    PRCList *qp = (PRCList *)arg;
    OrderedEntry_t *entry;

    if (he != NULL) {
        entry = (OrderedEntry_t *) PR_Malloc(sizeof(OrderedEntry_t));
        entry->key = PL_strdup((char *) he->key);
        if (index ==0) {
            PR_APPEND_LINK((PRCList *)entry, qp);
            return HT_ENUMERATE_NEXT;
        }
        PRCList *head = PR_LIST_HEAD(qp);
        PRCList *next;
        while (head != qp) {
            OrderedEntry_t *current = (OrderedEntry_t *) head;
            if (strcmp((char *) he->key, (char *) current->key) <=0) 
                break;
            next = PR_NEXT_LINK(head);
            head = next;
        }
        PR_INSERT_BEFORE((PRCList*) entry, head);
        return HT_ENUMERATE_NEXT;
    } else {
        return HT_ENUMERATE_STOP;
    }
}
Esempio n. 10
0
int
jobLoop(PRFileDesc *a, PRFileDesc *b, int c)
{
    PRCList *myLink = 0;
    JOB *myJob;

    PZ_Lock(qLock);
    do {
        myLink = 0;
        while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
            PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
        }
        if (!PR_CLIST_IS_EMPTY(&jobQ)) {
            myLink = PR_LIST_HEAD(&jobQ);
            PR_REMOVE_AND_INIT_LINK(myLink);
        }
        PZ_Unlock(qLock);
        myJob = (JOB *)myLink;
        /* myJob will be null when stopping is true and jobQ is empty */
        if (!myJob)
            break;
        handle_connection(myJob->tcp_sock, myJob->model_sock,
                          myJob->requestCert);
        PZ_Lock(qLock);
        PR_APPEND_LINK(myLink, &freeJobs);
        PZ_NotifyCondVar(freeListNotEmptyCv);
    } while (PR_TRUE);
    return 0;
}
Esempio n. 11
0
SECStatus
SSLExp_InstallExtensionHooks(PRFileDesc *fd, PRUint16 extension,
                             SSLExtensionWriter writer, void *writerArg,
                             SSLExtensionHandler handler, void *handlerArg)
{
    sslSocket *ss = ssl_FindSocket(fd);
    PRCList *cursor;
    sslCustomExtensionHooks *hook;

    if (!ss) {
        return SECFailure; /* Code already set. */
    }

    /* Need to specify both or neither, but not just one. */
    if ((writer && !handler) || (!writer && handler)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ssl_GetExtensionSupport(extension) == ssl_ext_native_only) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (ss->firstHsDone || ((ss->ssl3.hs.ws != idle_handshake) &&
                            (ss->ssl3.hs.ws != wait_client_hello))) {
        PORT_SetError(PR_INVALID_STATE_ERROR);
        return SECFailure;
    }

    /* Remove any old handler. */
    for (cursor = PR_NEXT_LINK(&ss->extensionHooks);
         cursor != &ss->extensionHooks;
         cursor = PR_NEXT_LINK(cursor)) {
        hook = (sslCustomExtensionHooks *)cursor;
        if (hook->type == extension) {
            PR_REMOVE_LINK(&hook->link);
            PORT_Free(hook);
            break;
        }
    }

    if (!writer && !handler) {
        return SECSuccess;
    }

    hook = PORT_ZNew(sslCustomExtensionHooks);
    if (!hook) {
        return SECFailure; /* This removed the old one, oh well. */
    }

    hook->type = extension;
    hook->writer = writer;
    hook->writerArg = writerArg;
    hook->handler = handler;
    hook->handlerArg = handlerArg;
    PR_APPEND_LINK(&hook->link, &ss->extensionHooks);
    return SECSuccess;
}
Esempio n. 12
0
nsresult
nsCacheEntry::RequestAccess(nsCacheRequest * request, nsCacheAccessMode *accessGranted)
{
    nsresult  rv = NS_OK;
    
    if (!IsInitialized()) {
        // brand new, unbound entry
        request->mKey = nsnull;  // steal ownership of the key string
        if (request->IsStreamBased())  MarkStreamBased();
        MarkInitialized();

        *accessGranted = request->AccessRequested() & nsICache::ACCESS_WRITE;
        NS_ASSERTION(*accessGranted, "new cache entry for READ-ONLY request");
        PR_APPEND_LINK(request, &mRequestQ);
        return rv;
    }
    
    if (IsDoomed()) return NS_ERROR_CACHE_ENTRY_DOOMED;

    if (IsStreamData() != request->IsStreamBased()) {
        *accessGranted = nsICache::ACCESS_NONE;
        return request->IsStreamBased() ?
            NS_ERROR_CACHE_DATA_IS_NOT_STREAM : NS_ERROR_CACHE_DATA_IS_STREAM;
    }

    if (PR_CLIST_IS_EMPTY(&mDescriptorQ)) {
        // 1st descriptor for existing bound entry
        *accessGranted = request->AccessRequested();
        if (*accessGranted & nsICache::ACCESS_WRITE) {
            MarkInvalid();
        } else {
            MarkValid();
        }
    } else {
        // nth request for existing, bound entry
        *accessGranted = request->AccessRequested() & ~nsICache::ACCESS_WRITE;
        if (!IsValid())
            rv = NS_ERROR_CACHE_WAIT_FOR_VALIDATION;
    }
    PR_APPEND_LINK(request,&mRequestQ);

    return rv;
}
Esempio n. 13
0
/* Go through hello extensions in |b| and deserialize
 * them into the list in |ss->ssl3.hs.remoteExtensions|.
 * The only checking we do in this point is for duplicates.
 *
 * IMPORTANT: This list just contains pointers to the incoming
 * buffer so they can only be used during ClientHello processing.
 */
SECStatus
ssl3_ParseExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length)
{
    /* Clean out the extensions list. */
    ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions);

    while (*length) {
        SECStatus rv;
        PRUint32 extension_type;
        SECItem extension_data = { siBuffer, NULL, 0 };
        TLSExtension *extension;
        PRCList *cursor;

        /* Get the extension's type field */
        rv = ssl3_ConsumeHandshakeNumber(ss, &extension_type, 2, b, length);
        if (rv != SECSuccess) {
            return SECFailure; /* alert already sent */
        }

        /* Check whether an extension has been sent multiple times. */
        for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions);
             cursor != &ss->ssl3.hs.remoteExtensions;
             cursor = PR_NEXT_LINK(cursor)) {
            if (((TLSExtension *)cursor)->type == extension_type) {
                (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
                PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
                return SECFailure;
            }
        }

        /* Get the data for this extension, so we can pass it or skip it. */
        rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
        if (rv != SECSuccess) {
            return rv; /* alert already sent */
        }

        SSL_TRC(10, ("%d: SSL3[%d]: parsed extension %d len=%u",
                     SSL_GETPID(), ss->fd, extension_type, extension_data.len));

        extension = PORT_ZNew(TLSExtension);
        if (!extension) {
            return SECFailure;
        }

        extension->type = (PRUint16)extension_type;
        extension->data = extension_data;
        PR_APPEND_LINK(&extension->link, &ss->ssl3.hs.remoteExtensions);
    }

    return SECSuccess;
}
Esempio n. 14
0
PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */)
{
    PRWaitGroup *wg = NULL;
    if (PR_FAILURE == MW_Init()) goto failed;

    if (NULL == (wg = PR_NEWZAP(PRWaitGroup))) goto failed;
    /* the wait group itself */
    wg->ml = PR_NewLock();
    if (NULL == wg->ml) goto failed_lock;
    wg->io_taken = PR_NewCondVar(wg->ml);
    if (NULL == wg->io_taken) goto failed_cvar0;
    wg->io_complete = PR_NewCondVar(wg->ml);
    if (NULL == wg->io_complete) goto failed_cvar1;
    wg->new_business = PR_NewCondVar(wg->ml);
    if (NULL == wg->new_business) goto failed_cvar2;
    wg->mw_manage = PR_NewCondVar(wg->ml);
    if (NULL == wg->mw_manage) goto failed_cvar3;

    PR_INIT_CLIST(&wg->group_link);
    PR_INIT_CLIST(&wg->io_ready);

    /* the waiters sequence */
    wg->waiter = (_PRWaiterHash*)PR_CALLOC(
        sizeof(_PRWaiterHash) +
        (_PR_DEFAULT_HASH_LENGTH * sizeof(PRRecvWait*)));
    if (NULL == wg->waiter) goto failed_waiter;
    wg->waiter->count = 0;
    wg->waiter->length = _PR_DEFAULT_HASH_LENGTH;

    PR_Lock(mw_lock);
    PR_APPEND_LINK(&wg->group_link, &mw_state->group_list);
    PR_Unlock(mw_lock);
    return wg;

failed_waiter:
    PR_DestroyCondVar(wg->mw_manage);
failed_cvar3:
    PR_DestroyCondVar(wg->new_business);
failed_cvar2:
    PR_DestroyCondVar(wg->io_taken);
failed_cvar1:
    PR_DestroyCondVar(wg->io_complete);
failed_cvar0:
    PR_DestroyLock(wg->ml);
failed_lock:
    PR_DELETE(wg);

failed:
    return wg;
}  /* MW_CreateWaitGroup */
Esempio n. 15
0
nsCacheEntry *
nsMemoryCacheDevice::FindEntry(nsCString * key, bool *collision)
{
    mozilla::Telemetry::AutoTimer<mozilla::Telemetry::CACHE_MEMORY_SEARCH_2> timer;
    nsCacheEntry * entry = mMemCacheEntries.GetEntry(key);
    if (!entry)  return nullptr;

    // move entry to the tail of an eviction list
    PR_REMOVE_AND_INIT_LINK(entry);
    PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, 0)]);
    
    mInactiveSize -= entry->DataSize();

    return entry;
}
nsresult
nsSocketTransportService::NotifyWhenCanAttachSocket(PLEvent *event)
{
    LOG(("nsSocketTransportService::NotifyWhenCanAttachSocket\n"));

    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");

    if (CanAttachSocket()) {
        NS_WARNING("should have called CanAttachSocket");
        return PostEvent(event);
    }

    PR_APPEND_LINK(&event->link, &mPendingSocketQ);
    return NS_OK;
}
/*
** Test and then lock the lock if it's not already locked by some other
** thread. Return PR_FALSE if some other thread owned the lock at the
** time of the call.
*/
PR_IMPLEMENT(PRBool) PR_TestAndLock(PRLock *lock)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRBool rv = PR_FALSE;
    PRIntn is;

#ifdef _PR_GLOBAL_THREADS_ONLY 
    is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
    if (is == 0) {
        lock->owner = me;
        return PR_TRUE;
    }
    return PR_FALSE;
#else  /* _PR_GLOBAL_THREADS_ONLY */

#ifndef _PR_LOCAL_THREADS_ONLY
	if (_native_threads_only) {
		is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
		if (is == 0) {
			lock->owner = me;
			return PR_TRUE;
		}
    	return PR_FALSE;
	}
#endif

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);

    _PR_LOCK_LOCK(lock);
    if (lock->owner == 0) {
        /* Just got the lock */
        lock->owner = me;
        lock->priority = me->priority;
		/* Add the granted lock to this owning thread's lock list */
        PR_APPEND_LINK(&lock->links, &me->lockList);
        rv = PR_TRUE;
    }
    _PR_LOCK_UNLOCK(lock);

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSON(is);
    return rv;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}
Esempio n. 18
0
SECStatus
setupJobs(int maxJobs)
{
    int i;

    jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
    if (!jobTable)
        return SECFailure;

    PR_INIT_CLIST(&jobQ);
    PR_INIT_CLIST(&freeJobs);

    for (i = 0; i < maxJobs; ++i) {
        JOB *pJob = jobTable + i;
        PR_APPEND_LINK(&pJob->link, &freeJobs);
    }
    return SECSuccess;
}
Esempio n. 19
0
void
_PR_MD_CLEAN_THREAD(PRThread *thread)
{
    BOOL rv;

    if (thread->md.acceptex_buf) {
        PR_DELETE(thread->md.acceptex_buf);
    }

    if (thread->md.xmit_bufs) {
        PR_DELETE(thread->md.xmit_bufs);
    }

    if (thread->md.blocked_sema) {
        rv = CloseHandle(thread->md.blocked_sema);
        PR_ASSERT(rv);
        thread->md.blocked_sema = 0;
    }
	if (_native_threads_only) {
		if (thread->md.thr_event) {
			rv = CloseHandle(thread->md.thr_event);
			PR_ASSERT(rv);
			thread->md.thr_event = 0;
		}
	}

    if (thread->md.handle) {
        rv = CloseHandle(thread->md.handle);
        PR_ASSERT(rv);
        thread->md.handle = 0;
    }

    /* Don't call DeleteFiber on current fiber or we'll kill the whole thread.
     * Don't call free(thread) until we've switched off the thread.
     * So put this fiber (or thread) on a list to be deleted by the idle
     * fiber next time we have a chance.
     */
    if (!(thread->flags & (_PR_ATTACHED|_PR_GLOBAL_SCOPE))) {
        _MD_LOCK(&_nt_idleLock);
        _nt_idleCount++;
        PR_APPEND_LINK(&thread->links, &_nt_idleList);
        _MD_UNLOCK(&_nt_idleLock);
    }
}
Esempio n. 20
0
static SECStatus
tls13_HandleKeyShareEntry(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data)
{
    SECStatus rv;
    PRUint32 group;
    const sslNamedGroupDef *groupDef;
    TLS13KeyShareEntry *ks = NULL;
    SECItem share = { siBuffer, NULL, 0 };

    rv = ssl3_ExtConsumeHandshakeNumber(ss, &group, 2, &data->data, &data->len);
    if (rv != SECSuccess) {
        PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE);
        goto loser;
    }
    groupDef = ssl_LookupNamedGroup(group);
    rv = ssl3_ExtConsumeHandshakeVariable(ss, &share, 2, &data->data,
                                          &data->len);
    if (rv != SECSuccess) {
        goto loser;
    }
    /* If the group is disabled, continue. */
    if (!groupDef) {
        return SECSuccess;
    }

    ks = PORT_ZNew(TLS13KeyShareEntry);
    if (!ks)
        goto loser;
    ks->group = groupDef;

    rv = SECITEM_CopyItem(NULL, &ks->key_exchange, &share);
    if (rv != SECSuccess)
        goto loser;

    PR_APPEND_LINK(&ks->link, &xtnData->remoteKeyShares);
    return SECSuccess;

loser:
    if (ks)
        tls13_DestroyKeyShareEntry(ks);
    return SECFailure;
}
Esempio n. 21
0
static SECStatus
ssl_SetSignedTimestampsInSlot(sslSocket *ss, SSLAuthType authType,
                              const SECItem *scts)
{
    sslServerCert *sc;
    SECStatus rv;

    sc = ssl_FindOrMakeCertType(ss, authType);
    if (!sc) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return SECFailure;
    }
    rv = ssl_PopulateSignedCertTimestamps(sc, scts);
    if (rv == SECSuccess) {
        PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    } else {
        ssl_FreeServerCert(sc);
    }
    return rv;
}
Esempio n. 22
0
static void _MW_DoneInternal(
    PRWaitGroup *group, PRRecvWait **waiter, PRMWStatus outcome)
{
    /*
    ** Add this receive wait object to the list of finished I/O
    ** operations for this particular group. If there are other
    ** threads waiting on the group, notify one. If not, arrange
    ** for this thread to return.
    */

#if 0
    printf("Removing 0x%x->0x%x\n", *waiter, (*waiter)->fd);
#endif
    (*waiter)->outcome = outcome;
    PR_APPEND_LINK(&((*waiter)->internal), &group->io_ready);
    PR_NotifyCondVar(group->io_complete);
    PR_ASSERT(0 != group->waiter->count);
    group->waiter->count -= 1;
    *waiter = NULL;
}  /* _MW_DoneInternal */
Esempio n. 23
0
NS_IMETHODIMP
nsIOThreadPool::PostEvent(PLEvent *event)
{
    LOG(("nsIOThreadPool::PostEvent [event=%p]\n", event));

    nsAutoLock lock(mLock);

    // if we are shutting down, then prevent additional events from being
    // added to the queue...
    if (mShutdown)
        return NS_ERROR_UNEXPECTED;
    
    nsresult rv = NS_OK;

    PR_APPEND_LINK(&event->link, &mEventQ);

    // now, look for an available idle thread...
    if (mNumIdleThreads)
        PR_NotifyCondVar(mIdleThreadCV); // wake up an idle thread

    // or, try to create a new thread unless we have reached our maximum...
    else if (mNumThreads < MAX_THREADS) {
        NS_ADDREF_THIS(); // the thread owns a reference to us
        mNumThreads++;
        PRThread *thread = PR_CreateThread(PR_USER_THREAD,
                                           ThreadFunc,
                                           this,
                                           PR_PRIORITY_NORMAL,
                                           PR_GLOBAL_THREAD,
                                           PR_UNJOINABLE_THREAD,
                                           0);
        if (!thread) {
            NS_RELEASE_THIS();
            mNumThreads--;
            rv = NS_ERROR_OUT_OF_MEMORY;
        }
    }
    // else, we expect one of the active threads to process the event queue.

    return rv;
}
Esempio n. 24
0
nsresult
nsCacheEntry::CreateDescriptor(nsCacheRequest *           request,
                               nsCacheAccessMode          accessGranted,
                               nsICacheEntryDescriptor ** result)
{
    NS_ENSURE_ARG_POINTER(request && result);

    nsCacheEntryDescriptor * descriptor =
        new nsCacheEntryDescriptor(this, accessGranted);

    // XXX check request is on q
    PR_REMOVE_AND_INIT_LINK(request); // remove request regardless of success

    if (descriptor == nsnull)
        return NS_ERROR_OUT_OF_MEMORY;

    PR_APPEND_LINK(descriptor, &mDescriptorQ);

    NS_ADDREF(*result = descriptor);
    return NS_OK;
}
Esempio n. 25
0
static SECStatus
ssl_AddCertAndKeyByAuthType(sslSocket *ss, SSLAuthType authType,
                            CERTCertificate *cert,
                            const CERTCertificateList *certChainOpt,
                            sslKeyPair *keyPair)
{
    sslServerCert *sc;
    SECStatus rv;

    if (!ssl_CertSuitableForAuthType(cert, authType)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    sc = ssl_FindOrMakeCertType(ss, authType);
    if (!sc) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        return SECFailure;
    }
    rv = ssl_PopulateKeyPair(sc, keyPair);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto loser;
    }
    /* Now that we have a key pair, update the details of the slot. Many of the
     * legacy functions create a slot with a namedCurve of NULL, which
     * makes the slot unusable; this corrects that. */
    ssl_PopulateCertType(&sc->certType, authType, cert, keyPair);
    rv = ssl_PopulateServerCert(sc, cert, certChainOpt);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }
    PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    return ssl_OneTimeCertSetup(ss, sc);
loser:
    ssl_FreeServerCert(sc);
    return SECFailure;
}
Esempio n. 26
0
/*
** Free the stack for the current thread
*/
void _PR_FreeStack(PRThreadStack *ts)
{
    if (!ts) {
	return;
    }
    if (ts->flags & _PR_STACK_PRIMORDIAL) {
	PR_DELETE(ts);
	return;
    }

    /*
    ** Put the stack on the free list. This is done because we are still
    ** using the stack. Next time a thread is created we will trim the
    ** list down; it's safe to do it then because we will have had to
    ** context switch to a live stack before another thread can be
    ** created.
    */
    PR_Lock(_pr_stackLock);
    PR_APPEND_LINK(&ts->links, _pr_freeStacks.prev);
    _pr_numFreeStacks++;
    PR_Unlock(_pr_stackLock);
}
Esempio n. 27
0
JSContext *
js_NewContext(JSRuntime *rt, size_t stacksize)
{
    JSContext *cx;

    cx = malloc(sizeof *cx);
    if (!cx)
	return NULL;
    memset(cx, 0, sizeof *cx);

    cx->runtime = rt;
    if (rt->contextList.next == (PRCList *)&rt->contextList) {
	/* First context on this runtime: initialize atoms and keywords. */
	if (!js_InitAtomState(cx, &rt->atomState) ||
	    !js_InitScanner(cx)) {
	    free(cx);
	    return NULL;
	}
    }

    PR_APPEND_LINK(&cx->links, &rt->contextList);
    cx->version = JSVERSION_DEFAULT;
    cx->jsop_eq = JSOP_EQ;
    cx->jsop_ne = JSOP_NE;
    PR_InitArenaPool(&cx->stackPool, "stack", stacksize, sizeof(jsval));
    PR_InitArenaPool(&cx->codePool, "code", 1024, sizeof(jsbytecode));
    PR_InitArenaPool(&cx->tempPool, "temp", 1024, sizeof(jsdouble));

#if JS_HAS_REGEXPS
    if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
	js_DestroyContext(cx);
	return 0;
    }
#endif
    return cx;
}
Esempio n. 28
0
nsresult nsProfileLock::LockWithSymlink(nsIFile *aLockFile, bool aHaveFcntlLock)
{
    nsresult rv;
    nsAutoCString lockFilePath;
    rv = aLockFile->GetNativePath(lockFilePath);
    if (NS_FAILED(rv)) {
        NS_ERROR("Could not get native path");
        return rv;
    }

    // don't replace an existing lock time if fcntl already got one
    if (!mReplacedLockTime)
        aLockFile->GetLastModifiedTimeOfLink(&mReplacedLockTime);

    struct in_addr inaddr;
    inaddr.s_addr = htonl(INADDR_LOOPBACK);

    char hostname[256];
    PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
    if (status == PR_SUCCESS)
    {
        char netdbbuf[PR_NETDB_BUF_SIZE];
        PRHostEnt hostent;
        status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
        if (status == PR_SUCCESS)
            memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
    }

    char *signature =
        PR_smprintf("%s:%s%lu", inet_ntoa(inaddr), aHaveFcntlLock ? "+" : "",
                    (unsigned long)getpid());
    const char *fileName = lockFilePath.get();
    int symlink_rv, symlink_errno = 0, tries = 0;

    // use ns4.x-compatible symlinks if the FS supports them
    while ((symlink_rv = symlink(signature, fileName)) < 0)
    {
        symlink_errno = errno;
        if (symlink_errno != EEXIST)
            break;

        if (!IsSymlinkStaleLock(&inaddr, fileName, aHaveFcntlLock))
            break;

        // Lock seems to be bogus: try to claim it.  Give up after a large
        // number of attempts (100 comes from the 4.x codebase).
        (void) unlink(fileName);
        if (++tries > 100)
            break;
    }

    PR_smprintf_free(signature);
    signature = nullptr;

    if (symlink_rv == 0)
    {
        // We exclusively created the symlink: record its name for eventual
        // unlock-via-unlink.
        rv = NS_OK;
        mHaveLock = true;
        mPidLockFileName = strdup(fileName);
        if (mPidLockFileName)
        {
            PR_APPEND_LINK(this, &mPidLockList);
            if (!setupPidLockCleanup++)
            {
                // Clean up on normal termination.
                // This instanciates a dummy class, and will trigger the class
                // destructor when libxul is unloaded. This is equivalent to atexit(),
                // but gracefully handles dlclose().
                static RemovePidLockFilesExiting r;

                // Clean up on abnormal termination, using POSIX sigaction.
                // Don't arm a handler if the signal is being ignored, e.g.,
                // because mozilla is run via nohup.
                if (!sDisableSignalHandling) {
                    struct sigaction act, oldact;
#ifdef SA_SIGINFO
                    act.sa_sigaction = FatalSignalHandler;
                    act.sa_flags = SA_SIGINFO;
#else
                    act.sa_handler = FatalSignalHandler;
#endif
                    sigfillset(&act.sa_mask);

#define CATCH_SIGNAL(signame)                                           \
PR_BEGIN_MACRO                                                          \
  if (sigaction(signame, nullptr, &oldact) == 0 &&                      \
      oldact.sa_handler != SIG_IGN)                                     \
  {                                                                     \
      sigaction(signame, &act, &signame##_oldact);                      \
  }                                                                     \
  PR_END_MACRO

                    CATCH_SIGNAL(SIGHUP);
                    CATCH_SIGNAL(SIGINT);
                    CATCH_SIGNAL(SIGQUIT);
                    CATCH_SIGNAL(SIGILL);
                    CATCH_SIGNAL(SIGABRT);
                    CATCH_SIGNAL(SIGSEGV);
                    CATCH_SIGNAL(SIGTERM);

#undef CATCH_SIGNAL
                }
            }
        }
    }
    else if (symlink_errno == EEXIST)
        rv = NS_ERROR_FILE_ACCESS_DENIED;
    else
    {
#ifdef DEBUG
        printf("symlink() failed. errno = %d\n", errno);
#endif
        rv = NS_ERROR_FAILURE;
    }
    return rv;
}
/*
** Lock the lock.
*/
PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRIntn is;
    PRThread *t;
    PRCList *q;

    PR_ASSERT(me != suspendAllThread); 
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
    PR_ASSERT(lock != NULL);
#ifdef _PR_GLOBAL_THREADS_ONLY 
    _PR_MD_LOCK(&lock->ilock);
    PR_ASSERT(lock->owner == 0);
    lock->owner = me;
    return;
#else  /* _PR_GLOBAL_THREADS_ONLY */

	if (_native_threads_only) {
		_PR_MD_LOCK(&lock->ilock);
		PR_ASSERT(lock->owner == 0);
		lock->owner = me;
		return;
	}

    if (!_PR_IS_NATIVE_THREAD(me))
    	_PR_INTSOFF(is);

    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

retry:
    _PR_LOCK_LOCK(lock);
    if (lock->owner == 0) {
        /* Just got the lock */
        lock->owner = me;
        lock->priority = me->priority;
		/* Add the granted lock to this owning thread's lock list */
        PR_APPEND_LINK(&lock->links, &me->lockList);
        _PR_LOCK_UNLOCK(lock);
    	if (!_PR_IS_NATIVE_THREAD(me))
        	_PR_FAST_INTSON(is);
        return;
    }

    /* If this thread already owns this lock, then it is a deadlock */
    PR_ASSERT(lock->owner != me);

    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);

#if 0
    if (me->priority > lock->owner->priority) {
        /*
        ** Give the lock owner a priority boost until we get the
        ** lock. Record the priority we boosted it to.
        */
        lock->boostPriority = me->priority;
        _PR_SetThreadPriority(lock->owner, me->priority);
    }
#endif

    /* 
    Add this thread to the asked for lock's list of waiting threads.  We
    add this thread thread in the right priority order so when the unlock
    occurs, the thread with the higher priority will get the lock.
    */
    q = lock->waitQ.next;
    if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority ==
      	_PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) {
		/*
		 * If all the threads in the lock waitQ have the same priority,
		 * then avoid scanning the list:  insert the element at the end.
		 */
		q = &lock->waitQ;
    } else {
		/* Sort thread into lock's waitQ at appropriate point */
		/* Now scan the list for where to insert this entry */
		while (q != &lock->waitQ) {
			t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next);
			if (me->priority > t->priority) {
				/* Found a lower priority thread to insert in front of */
				break;
			}
			q = q->next;
		}
	}
    PR_INSERT_BEFORE(&me->waitQLinks, q);

	/* 
	Now grab the threadLock since we are about to change the state.  We have
	to do this since a PR_Suspend or PR_SetThreadPriority type call that takes
	a PRThread* as an argument could be changing the state of this thread from
	a thread running on a different cpu.
	*/

    _PR_THREAD_LOCK(me);
    me->state = _PR_LOCK_WAIT;
    me->wait.lock = lock;
    _PR_THREAD_UNLOCK(me);

    _PR_LOCK_UNLOCK(lock);

    _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
	goto retry;

#endif  /* _PR_GLOBAL_THREADS_ONLY */
}
Esempio n. 30
0
SECStatus
ssl3_SendECDHServerKeyExchange(
    sslSocket *ss,
    const SSLSignatureAndHashAlg *sigAndHash)
{
    SECStatus rv = SECFailure;
    int length;
    PRBool isTLS, isTLS12;
    SECItem signed_hash = { siBuffer, NULL, 0 };
    SSL3Hashes hashes;

    SECItem ec_params = { siBuffer, NULL, 0 };
    unsigned char paramBuf[3];
    const namedGroupDef *ecGroup;
    sslEphemeralKeyPair *keyPair;
    SECKEYPublicKey *pubKey;

    /* Generate ephemeral ECDH key pair and send the public key */
    ecGroup = ssl_GetECGroupForServerSocket(ss);
    if (!ecGroup) {
        goto loser;
    }

    PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
    if (ss->opt.reuseServerECDHEKey) {
        rv = ssl_CreateECDHEphemeralKeys(ss, ecGroup);
        if (rv != SECSuccess) {
            goto loser;
        }
        keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
    } else {
        rv = ssl_CreateECDHEphemeralKeyPair(ecGroup, &keyPair);
        if (rv != SECSuccess) {
            goto loser;
        }
        PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
    }

    PORT_Assert(keyPair);
    if (!keyPair) {
        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        return SECFailure;
    }

    ec_params.len = sizeof(paramBuf);
    ec_params.data = paramBuf;
    PORT_Assert(keyPair->group);
    PORT_Assert(keyPair->group->type == group_type_ec);
    ec_params.data[0] = ec_type_named;
    ec_params.data[1] = keyPair->group->name >> 8;
    ec_params.data[2] = keyPair->group->name & 0xff;

    pubKey = keyPair->keys->pubKey;
    rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg,
                                 ec_params,
                                 pubKey->u.ec.publicValue,
                                 &ss->ssl3.hs.client_random,
                                 &ss->ssl3.hs.server_random,
                                 &hashes, ss->opt.bypassPKCS11);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        goto loser;
    }

    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);

    rv = ssl3_SignHashes(&hashes, ss->sec.serverCert->serverKeyPair->privKey,
                         &signed_hash, isTLS);
    if (rv != SECSuccess) {
        goto loser; /* ssl3_SignHashes has set err. */
    }
    if (signed_hash.data == NULL) {
        /* how can this happen and rv == SECSuccess ?? */
        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
        goto loser;
    }

    length = ec_params.len +
             1 + pubKey->u.ec.publicValue.len +
             (isTLS12 ? 2 : 0) + 2 + signed_hash.len;

    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
    if (rv != SECSuccess) {
        goto loser; /* err set by AppendHandshake. */
    }

    rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
    if (rv != SECSuccess) {
        goto loser; /* err set by AppendHandshake. */
    }

    rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.ec.publicValue.data,
                                      pubKey->u.ec.publicValue.len, 1);
    if (rv != SECSuccess) {
        goto loser; /* err set by AppendHandshake. */
    }

    if (isTLS12) {
        rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash);
        if (rv != SECSuccess) {
            goto loser; /* err set by AppendHandshake. */
        }
    }

    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
                                      signed_hash.len, 2);
    if (rv != SECSuccess) {
        goto loser; /* err set by AppendHandshake. */
    }

    PORT_Free(signed_hash.data);
    return SECSuccess;

loser:
    if (signed_hash.data != NULL)
        PORT_Free(signed_hash.data);
    return SECFailure;
}