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

📄 pruthr.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                goto found_thread;            }        }    }    _PR_CPU_LIST_UNLOCK();    if (wakeup_cpus == PR_TRUE)        _PR_MD_WAKEUP_CPUS();#endif        /* _PR_LOCAL_THREADS_ONLY */idle_thread:   /*    ** There are no threads to run. Switch to the idle thread    */    PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("pausing"));    thread = _PR_MD_CURRENT_CPU()->idle_thread;found_thread:    PR_ASSERT((me == thread) || ((thread->state == _PR_RUNNABLE) &&                    (!(thread->no_sched))));    /* Resume the thread */    PR_LOG(_pr_sched_lm, PR_LOG_MAX,       ("switching to %d[%p]", thread->id, thread));    PR_ASSERT(thread->state != _PR_RUNNING);    thread->state = _PR_RUNNING;     /* If we are on the runq, it just means that we went to sleep on some     * resource, and by the time we got here another real native thread had     * already given us the resource and put us back on the runqueue      */	PR_ASSERT(thread->cpu == _PR_MD_CURRENT_CPU());    if (thread != me)         _PR_MD_RESTORE_CONTEXT(thread);#if 0    /* XXXMB; with setjmp/longjmp it is impossible to land here, but      * it is not with fibers... Is this a bad thing?  I believe it is      * still safe.     */    PR_NOT_REACHED("impossible return from schedule");#endif}/*** Attaches a thread.  ** Does not set the _PR_MD_CURRENT_THREAD.  ** Does not specify the scope of the thread.*/static PRThread *_PR_AttachThread(PRThreadType type, PRThreadPriority priority,    PRThreadStack *stack){#if defined(XP_MAC)#pragma unused (type)#endif    PRThread *thread;    char *mem;    if (priority > PR_PRIORITY_LAST) {        priority = PR_PRIORITY_LAST;    } else if (priority < PR_PRIORITY_FIRST) {        priority = PR_PRIORITY_FIRST;    }    mem = (char*) PR_CALLOC(sizeof(PRThread));    if (mem) {        thread = (PRThread*) mem;        thread->priority = priority;        thread->stack = stack;        thread->state = _PR_RUNNING;        PR_INIT_CLIST(&thread->lockList);        if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {        PR_DELETE(thread);        return 0;    }        return thread;    }    return 0;}PR_IMPLEMENT(PRThread*) _PR_NativeCreateThread(PRThreadType type,                     void (*start)(void *arg),                     void *arg,                     PRThreadPriority priority,                     PRThreadScope scope,                     PRThreadState state,                     PRUint32 stackSize,                     PRUint32 flags){#if defined(XP_MAC)#pragma unused (scope)#endif    PRThread *thread;    thread = _PR_AttachThread(type, priority, NULL);    if (thread) {        PR_Lock(_pr_activeLock);        thread->flags = (flags | _PR_GLOBAL_SCOPE);        thread->id = ++_pr_utid;        if (type == PR_SYSTEM_THREAD) {            thread->flags |= _PR_SYSTEM;            _pr_systemActive++;        } else {            _pr_userActive++;        }        PR_Unlock(_pr_activeLock);        thread->stack = PR_NEWZAP(PRThreadStack);        if (!thread->stack) {            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);            goto done;        }        thread->stack->stackSize = stackSize?stackSize:_MD_DEFAULT_STACK_SIZE;        thread->stack->thr = thread;        thread->startFunc = start;        thread->arg = arg;        /*           Set thread flags related to scope and joinable state. If joinable          thread, allocate a "termination" conidition variable.         */        if (state == PR_JOINABLE_THREAD) {            thread->term = PR_NewCondVar(_pr_terminationCVLock);        if (thread->term == NULL) {        PR_DELETE(thread->stack);        goto done;        }        }    thread->state = _PR_RUNNING;        if (_PR_MD_CREATE_THREAD(thread, _PR_NativeRunThread, priority,            scope,state,stackSize) == PR_SUCCESS) {            return thread;        }        if (thread->term) {            PR_DestroyCondVar(thread->term);            thread->term = NULL;        }    PR_DELETE(thread->stack);    }done:    if (thread) {    _PR_DecrActiveThreadCount(thread);        _PR_DestroyThread(thread);    }    return NULL;}/************************************************************************/PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,                     void (*start)(void *arg),                     void *arg,                     PRThreadPriority priority,                     PRThreadScope scope,                     PRThreadState state,                     PRUint32 stackSize,                     PRUint32 flags){    PRThread *me;    PRThread *thread = NULL;    PRThreadStack *stack;    char *top;    PRIntn is;    PRIntn native = 0;    PRIntn useRecycled = 0;    PRBool status;    /*     First, pin down the priority.  Not all compilers catch passing out of    range enum here.  If we let bad values thru, priority queues won't work.    */    if (priority > PR_PRIORITY_LAST) {        priority = PR_PRIORITY_LAST;    } else if (priority < PR_PRIORITY_FIRST) {        priority = PR_PRIORITY_FIRST;    }            if (!_pr_initialized) _PR_ImplicitInitialization();    if (! (flags & _PR_IDLE_THREAD))        me = _PR_MD_CURRENT_THREAD();#if    defined(_PR_GLOBAL_THREADS_ONLY)	/*	 * can create global threads only	 */    if (scope == PR_LOCAL_THREAD)    	scope = PR_GLOBAL_THREAD;#endif	if (_native_threads_only)		scope = PR_GLOBAL_THREAD;    native = (((scope == PR_GLOBAL_THREAD)|| (scope == PR_GLOBAL_BOUND_THREAD))							&& _PR_IS_NATIVE_THREAD_SUPPORTED());    _PR_ADJUST_STACKSIZE(stackSize);    if (native) {    /*     * clear the IDLE_THREAD flag which applies to LOCAL     * threads only     */    flags &= ~_PR_IDLE_THREAD;        flags |= _PR_GLOBAL_SCOPE;        if (_PR_NUM_DEADNATIVE > 0) {            _PR_DEADQ_LOCK;            if (_PR_NUM_DEADNATIVE == 0) { /* Thread safe check */                _PR_DEADQ_UNLOCK;            } else {                thread = _PR_THREAD_PTR(_PR_DEADNATIVEQ.next);                PR_REMOVE_LINK(&thread->links);                _PR_DEC_DEADNATIVE;                _PR_DEADQ_UNLOCK;                _PR_InitializeRecycledThread(thread);                thread->startFunc = start;                thread->arg = arg;            thread->flags = (flags | _PR_GLOBAL_SCOPE);            if (type == PR_SYSTEM_THREAD)            {                thread->flags |= _PR_SYSTEM;                PR_AtomicIncrement(&_pr_systemActive);            }            else PR_AtomicIncrement(&_pr_userActive);            if (state == PR_JOINABLE_THREAD) {                if (!thread->term)                        thread->term = PR_NewCondVar(_pr_terminationCVLock);            }        else {                if(thread->term) {                    PR_DestroyCondVar(thread->term);                        thread->term = 0;            }            }                thread->priority = priority;        _PR_MD_SET_PRIORITY(&(thread->md), priority);        /* XXX what about stackSize? */        thread->state = _PR_RUNNING;                _PR_MD_WAKEUP_WAITER(thread);        return thread;            }        }        thread = _PR_NativeCreateThread(type, start, arg, priority,                                             scope, state, stackSize, flags);    } else {        if (_PR_NUM_DEADUSER > 0) {            _PR_DEADQ_LOCK;            if (_PR_NUM_DEADUSER == 0) {  /* thread safe check */                _PR_DEADQ_UNLOCK;            } else {                PRCList *ptr;                /* Go down list checking for a recycled thread with a                  * large enough stack.  XXXMB - this has a bad degenerate case.                 */                ptr = _PR_DEADUSERQ.next;                while( ptr != &_PR_DEADUSERQ ) {                    thread = _PR_THREAD_PTR(ptr);                    if ((thread->stack->stackSize >= stackSize) &&                (!thread->no_sched)) {                        PR_REMOVE_LINK(&thread->links);                        _PR_DEC_DEADUSER;                        break;                    } else {                        ptr = ptr->next;                        thread = NULL;                    }                }                 _PR_DEADQ_UNLOCK;               if (thread) {                    _PR_InitializeRecycledThread(thread);                    thread->startFunc = start;                    thread->arg = arg;                    thread->priority = priority;            if (state == PR_JOINABLE_THREAD) {            if (!thread->term)                thread->term = PR_NewCondVar(_pr_terminationCVLock);            } else {            if(thread->term) {               PR_DestroyCondVar(thread->term);                thread->term = 0;            }            }                    useRecycled++;                }            }        }         if (thread == NULL) {#ifndef HAVE_CUSTOM_USER_THREADS            stack = _PR_NewStack(stackSize);            if (!stack) {                PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);                return NULL;            }            /* Allocate thread object and per-thread data off the top of the stack*/            top = stack->stackTop;#ifdef HAVE_STACK_GROWING_UP            thread = (PRThread*) top;            top = top + sizeof(PRThread);            /*             * Make stack 64-byte aligned             */            if ((PRUptrdiff)top & 0x3f) {                top = (char*)(((PRUptrdiff)top + 0x40) & ~0x3f);            }#else            top = top - sizeof(PRThread);            thread = (PRThread*) top;            /*             * Make stack 64-byte aligned             */            if ((PRUptrdiff)top & 0x3f) {                top = (char*)((PRUptrdiff)top & ~0x3f);            }#endif#if defined(GC_LEAK_DETECTOR)            /*             * sorry, it is not safe to allocate the thread on the stack,             * because we assign to this object before the GC can learn             * about this thread. we'll just leak thread objects instead.             */            thread = PR_NEW(PRThread);#endif            stack->thr = thread;            memset(thread, 0, sizeof(PRThread));            thread->threadAllocatedOnStack = 1;#else            thread = _PR_MD_CREATE_USER_THREAD(stackSize, start, arg);            if (!thread) {                PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);                return NULL;            }            thread->threadAllocatedOnStack = 0;            stack = NULL;            top = NULL;#endif            /* Initialize thread */            thread->tpdLength = 0;            thread->privateData = NULL;            thread->stack = stack;            thread->priority = priority;            thread->startFunc = start;            thread->arg = arg;            PR_INIT_CLIST(&thread->lockList);            if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {                if (thread->threadAllocatedOnStack == 1)                    _PR_FreeStack(thread->stack);                else {                    PR_DELETE(thread);                }                PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);                return NULL;            }            if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {                if (thread->threadAllocatedOnStack == 1)                    _PR_FreeStack(thread->stack);                else {                    PR_DELETE(thread->privateData);                    PR_DELETE(thread);                }                PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);                return NULL;            }            _PR_MD_INIT_CONTEXT(thread, top, _PR_UserRunThread, &status);            if (status == PR_FALSE) {                _PR_MD_FREE_LOCK(&thread->threadLock);                if (thread->threadAllocatedOnStack == 1)                    _PR_FreeStack(thread->stack);                else {                    PR_DELETE(thread->privateData);                    PR_DELETE(thread);                }                return NULL;            }            /*               Set thread flags related to scope and joinable state. If joinable              thread, allocate a "termination" condition variable.            */            if (state == PR_JOINABLE_THREAD) {                thread->term = PR_NewCondVar(_pr_terminationCVLock);                if (thread->term == NULL) {                    _PR_MD_FREE_LOCK(&thread->threadLock);                    if (thread->threadAllocatedOnStack == 1)                        _PR_FreeStack(thread->stack);                    else {                        PR_DELETE(thread->privateData);                        PR_DELETE(thread);                    }                    return NULL;                }            }          }          /* Update thread type counter */        PR_Lock(_pr_activeLock);        thread->flags = flags;        thread->id = ++_pr_utid;        if (type == PR_SYSTEM_THREAD) {            thread->flags |= _PR_SYSTEM;            _pr_systemActive++;        } else {            _pr_userActive++;        }        /* Make thread runnable */        thread->state = _PR_RUNNABLE;    /*     * Add to list of active threads     */        PR_Unlock(_pr_activeLock);        if ((! (thread->flags & _PR_IDLE_THREAD)) && _PR_IS_NATIVE_THREAD(me) )            thread->cpu = _PR_GetPrimordialCPU();        else            thread->cpu = _PR_MD_CURRENT_CPU();        PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));        if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me)) {            _PR_INTSOFF(is);            _PR_RUNQ_LOCK(thread->cpu);            _PR_ADD_RUNQ(thread, thread->cpu, priority);            _PR_RUNQ_UNLOCK(thread->cpu);        }        if (thread->flags & _PR_IDLE_THREAD) {            /*            ** If the creating thread is a kernel thread, we need to            ** awaken the user thread idle thread somehow; potentially            ** it could be sleeping in its idle loop, and we need to poke            ** it.  To do so, wake the idle thread...              */            _PR_MD_WAKEUP_WAITER(NULL);        } else if (_PR_IS_NATIVE_THREAD(me)) {            _PR_MD_WAKEUP_WAITER(thread);        }        if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me) )            _PR_INTSON(is);    }    return thread;}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, 

⌨️ 快捷键说明

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