⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptthread.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }done:    rv = _PT_PTHREAD_ATTR_DESTROY(&tattr);    PR_ASSERT(0 == rv);    return thred;}  /* _PR_CreateThread */PR_IMPLEMENT(PRThread*) PR_CreateThread(    PRThreadType type, void (*start)(void *arg), void *arg,    PRThreadPriority priority, PRThreadScope scope,    PRThreadState state, PRUint32 stackSize){    return _PR_CreateThread(        type, start, arg, priority, scope, state, stackSize, PR_FALSE);} /* PR_CreateThread */PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(    PRThreadType type, void (*start)(void *arg), void *arg,     PRThreadPriority priority, PRThreadScope scope,    PRThreadState state, PRUint32 stackSize){    return _PR_CreateThread(        type, start, arg, priority, scope, state, stackSize, PR_TRUE);}  /* PR_CreateThreadGCAble */PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thred){    return thred->environment;}  /* GetExecutionEnvironment */ PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env){    thred->environment = env;}  /* SetExecutionEnvironment */PR_IMPLEMENT(PRThread*) PR_AttachThread(    PRThreadType type, PRThreadPriority priority, PRThreadStack *stack){    return PR_GetCurrentThread();}  /* PR_AttachThread */PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred){    int rv = -1;    void *result = NULL;    PR_ASSERT(thred != NULL);    if ((0xafafafaf == thred->state)    || (PT_THREAD_DETACHED == (PT_THREAD_DETACHED & thred->state))    || (PT_THREAD_FOREIGN == (PT_THREAD_FOREIGN & thred->state)))    {        /*         * This might be a bad address, but if it isn't, the state should         * either be an unjoinable thread or it's already had the object         * deleted. However, the client that called join on a detached         * thread deserves all the rath I can muster....         */        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);        PR_LogPrint(            "PR_JoinThread: 0x%X not joinable | already smashed\n", thred);    }    else    {        pthread_t id = thred->id;        rv = pthread_join(id, &result);        PR_ASSERT(rv == 0 && result == NULL);        if (0 == rv)        {#ifdef _PR_DCETHREADS            rv = pthread_detach(&id);            PR_ASSERT(0 == rv);#endif            _pt_thread_death(thred);        }        else        {            PRErrorCode prerror;            switch (rv)            {                case EINVAL:  /* not a joinable thread */                case ESRCH:   /* no thread with given ID */                    prerror = PR_INVALID_ARGUMENT_ERROR;                    break;                case EDEADLK: /* a thread joining with itself */                    prerror = PR_DEADLOCK_ERROR;                    break;                default:                    prerror = PR_UNKNOWN_ERROR;                    break;            }            PR_SetError(prerror, rv);        }    }    return (0 == rv) ? PR_SUCCESS : PR_FAILURE;}  /* PR_JoinThread */PR_IMPLEMENT(void) PR_DetachThread(void) { }  /* PR_DetachThread */PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void){    void *thred;    if (!_pr_initialized) _PR_ImplicitInitialization();    _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);    if (NULL == thred) thred = pt_AttachThread();    PR_ASSERT(NULL != thred);    return (PRThread*)thred;}  /* PR_GetCurrentThread */PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred){    return (thred->state & PT_THREAD_BOUND) ?        PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD;}  /* PR_GetThreadScope() */PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred){    return (thred->state & PT_THREAD_SYSTEM) ?        PR_SYSTEM_THREAD : PR_USER_THREAD;}PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thred){    return (thred->state & PT_THREAD_DETACHED) ?        PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;}  /* PR_GetThreadState */PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thred){    PR_ASSERT(thred != NULL);    return thred->priority;}  /* PR_GetThreadPriority */PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri){    PRIntn rv = -1;    PR_ASSERT(NULL != thred);    if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)newPri)        newPri = PR_PRIORITY_FIRST;    else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri)        newPri = PR_PRIORITY_LAST;#if defined(_PR_DCETHREADS)    rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));    /* pthread_setprio returns the old priority */#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)    if (EPERM != pt_schedpriv)    {        int policy;        struct sched_param schedule;        rv = pthread_getschedparam(thred->id, &policy, &schedule);        if(0 == rv) {			schedule.sched_priority = pt_PriorityMap(newPri);			rv = pthread_setschedparam(thred->id, policy, &schedule);			if (EPERM == rv)			{				pt_schedpriv = EPERM;				PR_LOG(_pr_thread_lm, PR_LOG_MIN,					("PR_SetThreadPriority: no thread scheduling privilege"));			}		}		if (rv != 0)			rv = -1;    }#endif    thred->priority = newPri;}  /* PR_SetThreadPriority */PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred){    /*    ** If the target thread indicates that it's waiting,    ** find the condition and broadcast to it. Broadcast    ** since we don't know which thread (if there are more    ** than one). This sounds risky, but clients must    ** test their invariants when resumed from a wait and    ** I don't expect very many threads to be waiting on    ** a single condition and I don't expect interrupt to    ** be used very often.    **    ** I don't know why I thought this would work. Must have    ** been one of those weaker momements after I'd been    ** smelling the vapors.    **    ** Even with the followng changes it is possible that    ** the pointer to the condition variable is pointing    ** at a bogus value. Will the unerlying code detect    ** that?    */    PRCondVar *cv;    PR_ASSERT(NULL != thred);    if (NULL == thred) return PR_FAILURE;    thred->state |= PT_THREAD_ABORTED;    cv = thred->waiting;    if ((NULL != cv) && !thred->interrupt_blocked)    {        PRIntn rv;        (void)PR_AtomicIncrement(&cv->notify_pending);        rv = pthread_cond_broadcast(&cv->cv);        PR_ASSERT(0 == rv);        if (0 > PR_AtomicDecrement(&cv->notify_pending))            PR_DestroyCondVar(cv);    }    return PR_SUCCESS;}  /* PR_Interrupt */PR_IMPLEMENT(void) PR_ClearInterrupt(void){    PRThread *me = PR_CurrentThread();    me->state &= ~PT_THREAD_ABORTED;}  /* PR_ClearInterrupt */PR_IMPLEMENT(void) PR_BlockInterrupt(void){    PRThread *me = PR_CurrentThread();    _PT_THREAD_BLOCK_INTERRUPT(me);}  /* PR_BlockInterrupt */PR_IMPLEMENT(void) PR_UnblockInterrupt(void){    PRThread *me = PR_CurrentThread();    _PT_THREAD_UNBLOCK_INTERRUPT(me);}  /* PR_UnblockInterrupt */PR_IMPLEMENT(PRStatus) PR_Yield(void){    static PRBool warning = PR_TRUE;    if (warning) warning = _PR_Obsolete(        "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)");    return PR_Sleep(PR_INTERVAL_NO_WAIT);}PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks){    PRStatus rv = PR_SUCCESS;    if (!_pr_initialized) _PR_ImplicitInitialization();    if (PR_INTERVAL_NO_WAIT == ticks)    {        _PT_PTHREAD_YIELD();    }    else    {        PRCondVar *cv;        PRIntervalTime timein;        timein = PR_IntervalNow();        cv = PR_NewCondVar(_pr_sleeplock);        PR_ASSERT(cv != NULL);        PR_Lock(_pr_sleeplock);        do        {            PRIntervalTime now = PR_IntervalNow();            PRIntervalTime delta = now - timein;            if (delta > ticks) break;            rv = PR_WaitCondVar(cv, ticks - delta);        } while (PR_SUCCESS == rv);        PR_Unlock(_pr_sleeplock);        PR_DestroyCondVar(cv);    }    return rv;}  /* PR_Sleep */static void _pt_thread_death(void *arg){    PRThread *thred = (PRThread*)arg;    if (thred->state & PT_THREAD_FOREIGN)    {        PR_Lock(pt_book.ml);        thred->prev->next = thred->next;        if (NULL == thred->next)            pt_book.last = thred->prev;        else            thred->next->prev = thred->prev;        PR_Unlock(pt_book.ml);    }    _PR_DestroyThreadPrivate(thred);    PR_Free(thred->privateData);    if (NULL != thred->errorString)        PR_Free(thred->errorString);    PR_Free(thred->stack);    if (NULL != thred->syspoll_list)        PR_Free(thred->syspoll_list);#if defined(_PR_POLL_WITH_SELECT)    if (NULL != thred->selectfd_list)        PR_Free(thred->selectfd_list);#endif#if defined(DEBUG)    memset(thred, 0xaf, sizeof(PRThread));#endif /* defined(DEBUG) */    PR_Free(thred);}  /* _pt_thread_death */void _PR_InitThreads(    PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs){    int rv;    PRThread *thred;#ifdef _PR_NEED_PTHREAD_INIT    /*     * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily     * initialized, but pthread_self() fails to initialize     * pthreads and hence returns a null thread ID if invoked     * by the primordial thread before any other pthread call.     * So we explicitly initialize pthreads here.     */    pthread_init();#endif#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)#if defined(FREEBSD)    {    pthread_attr_t attr;    int policy;    /* get the min and max priorities of the default policy */    pthread_attr_init(&attr);    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);    pthread_attr_getschedpolicy(&attr, &policy);    pt_book.minPrio = sched_get_priority_min(policy);    PR_ASSERT(-1 != pt_book.minPrio);    pt_book.maxPrio = sched_get_priority_max(policy);    PR_ASSERT(-1 != pt_book.maxPrio);    pthread_attr_destroy(&attr);    }#else    /*    ** These might be function evaluations    */    pt_book.minPrio = PT_PRIO_MIN;    pt_book.maxPrio = PT_PRIO_MAX;#endif#endif        PR_ASSERT(NULL == pt_book.ml);    pt_book.ml = PR_NewLock();    PR_ASSERT(NULL != pt_book.ml);    pt_book.cv = PR_NewCondVar(pt_book.ml);    PR_ASSERT(NULL != pt_book.cv);    thred = PR_NEWZAP(PRThread);    PR_ASSERT(NULL != thred);    thred->arg = NULL;    thred->startFunc = NULL;    thred->priority = priority;    thred->id = pthread_self();    thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);    if (PR_SYSTEM_THREAD == type)    {        thred->state |= PT_THREAD_SYSTEM;        pt_book.system += 1;	    pt_book.this_many = 0;    }    else    {	    pt_book.user += 1;	    pt_book.this_many = 1;    }    thred->next = thred->prev = NULL;    pt_book.first = pt_book.last = thred;    thred->stack = PR_NEWZAP(PRThreadStack);    PR_ASSERT(thred->stack != NULL);    thred->stack->stackSize = 0;    thred->stack->thr = thred;	_PR_InitializeStack(thred->stack);    /*     * Create a key for our use to store a backpointer in the pthread     * to our PRThread object. This object gets deleted when the thread     * returns from its root in the case of a detached thread. Other     * threads delete the objects in Join.     *     * NB: The destructor logic seems to have a bug so it isn't used.     * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998.     * More info - the problem is that pthreads calls the destructor     * eagerly as the thread returns from its root, rather than lazily     * after the thread is joined. Therefore, threads that are joining     * and holding PRThread references are actually holding pointers to     * nothing.     */    rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);    PR_ASSERT(0 == rv);    rv = pthread_setspecific(pt_book.key, thred);    PR_ASSERT(0 == rv);        PR_SetThreadPriority(thred, priority);}  /* _PR_InitThreads */PR_IMPLEMENT(PRStatus) PR_Cleanup(void){    PRThread *me = PR_CurrentThread();    PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));    PR_ASSERT(me->state & PT_THREAD_PRIMORD);    if (me->state & PT_THREAD_PRIMORD)    {        PR_Lock(pt_book.ml);        while (pt_book.user > pt_book.this_many)            PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);        PR_Unlock(pt_book.ml);        _PR_CleanupMW();        _PR_CleanupDtoa();        _PR_CleanupCallOnce();        _PR_ShutdownLinker();        _PR_LogCleanup();        _PR_CleanupNet();        /* Close all the fd's before calling _PR_CleanupIO */        _PR_CleanupIO();        /*         * I am not sure if it's safe to delete the cv and lock here,         * since there may still be "system" threads around. If this         * call isn't immediately prior to exiting, then there's a         * problem.         */        if (0 == pt_book.system)        {            PR_DestroyCondVar(pt_book.cv); pt_book.cv = NULL;            PR_DestroyLock(pt_book.ml); pt_book.ml = NULL;        }        _pt_thread_death(me);        PR_DestroyLock(_pr_sleeplock);        _pr_sleeplock = NULL;        _PR_CleanupLayerCache();        _PR_CleanupEnv();#ifdef _PR_ZONE_ALLOCATOR        _PR_DestroyZones();#endif        _pr_initialized = PR_FALSE;        return PR_SUCCESS;    }    return PR_FAILURE;}  /* PR_Cleanup */PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status){    _exit(status);}PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred){#if defined(_PR_DCETHREADS)    return (PRUint32)&thred->id;  /* this is really a sham! */#else    return (PRUint32)thred->id;  /* and I don't know what they will do with it */#endif}/* * $$$ * The following two thread-to-processor affinity functions are not * yet implemented for pthreads.  By the way, these functions should return * PRStatus rather than PRInt32 to indicate the success/failure status. * $$$ */PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask){    return 0;  /* not implemented */}PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask ){    return 0;  /* not implemented */}PR_IMPLEMENT(void)PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg){    thread->dump = dump;    thread->dumpArg = arg;}/*  * Garbage collection support follows. */#if defined(_PR_DCETHREADS)/* * statics for Garbage Collection support.  We don't need to protect these * signal masks since the garbage collector itself is protected by a lock * and multiple threads will not be garbage collecting at the same time. */static sigset_t javagc_vtalarm_sigmask;static sigset_t javagc_intsoff_sigmask;#else /* defined(_PR_DCETHREADS) *//* a bogus signal mask for forcing a timed wait *//* Not so bogus in AIX as we really do a sigwait */static sigset_t sigwait_set;static struct timespec onemillisec = {0, 1000000L};#ifndef PT_NO_SIGTIMEDWAITstatic struct timespec hundredmillisec = {0, 100000000L};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -