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

📄 pruthr.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
             */            _PR_MD_EXIT_THREAD(thread);            /*             * Free memory allocated for the thread             */            _PR_NativeDestroyThread(thread);            /*             * thread gone, cannot de-reference thread now             */            return;        }        /* Now wait for someone to activate us again... */        _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);    }}static void _PR_UserRunThread(void){    PRThread *thread = _PR_MD_CURRENT_THREAD();    PRIntn is;    if (_MD_LAST_THREAD())    _MD_LAST_THREAD()->no_sched = 0;#ifdef HAVE_CUSTOM_USER_THREADS    if (thread->stack == NULL) {        thread->stack = PR_NEWZAP(PRThreadStack);        _PR_InitializeNativeStack(thread->stack);    }#endif /* HAVE_CUSTOM_USER_THREADS */    while(1) {        /* Run thread main */        if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0);    /*     * Add to list of active threads     */    if (!(thread->flags & _PR_IDLE_THREAD)) {        PR_Lock(_pr_activeLock);        PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());        _pr_local_threads++;        PR_Unlock(_pr_activeLock);    }        (*thread->startFunc)(thread->arg);        /*         * The following two assertions are meant for NT asynch io.         *         * The thread should have no asynch io in progress when it         * exits, otherwise the overlapped buffer, which is part of         * the thread structure, would become invalid.         */        PR_ASSERT(thread->io_pending == PR_FALSE);        /*         * This assertion enforces the programming guideline that         * if an io function times out or is interrupted, the thread         * should close the fd to force the asynch io to abort         * before it exits.  Right now, closing the fd is the only         * way to clear the io_suspended flag.         */        PR_ASSERT(thread->io_suspended == PR_FALSE);        PR_Lock(_pr_activeLock);    /*     * remove thread from list of active threads     */    if (!(thread->flags & _PR_IDLE_THREAD)) {           PR_REMOVE_LINK(&thread->active);        _pr_local_threads--;    }    PR_Unlock(_pr_activeLock);        PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));        /* All done, time to go away */        _PR_CleanupThread(thread);        _PR_INTSOFF(is);            _PR_NotifyJoinWaiters(thread);    _PR_DecrActiveThreadCount(thread);        thread->state = _PR_DEAD_STATE;        if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==                        PR_FAILURE)) {            /*            ** Destroy the thread resources            */        _PR_UserDestroyThread(thread);        }        /*        ** Find another user thread to run. This cpu has finished the        ** previous threads main and is now ready to run another thread.        */        {            PRInt32 is;            _PR_INTSOFF(is);            _PR_MD_SWITCH_CONTEXT(thread);        }        /* Will land here when we get scheduled again if we are recycling... */    }}void _PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri){    PRThread *me = _PR_MD_CURRENT_THREAD();    PRIntn is;    if ( _PR_IS_NATIVE_THREAD(thread) ) {        _PR_MD_SET_PRIORITY(&(thread->md), newPri);        return;    }    if (!_PR_IS_NATIVE_THREAD(me))    _PR_INTSOFF(is);    _PR_THREAD_LOCK(thread);    if (newPri != thread->priority) {    _PRCPU *cpu = thread->cpu;    switch (thread->state) {      case _PR_RUNNING:        /* Change my priority */            _PR_RUNQ_LOCK(cpu);        thread->priority = newPri;        if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) {            if (!_PR_IS_NATIVE_THREAD(me))                    _PR_SET_RESCHED_FLAG();        }            _PR_RUNQ_UNLOCK(cpu);        break;      case _PR_RUNNABLE:        _PR_RUNQ_LOCK(cpu);            /* Move to different runQ */            _PR_DEL_RUNQ(thread);            thread->priority = newPri;            PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));            _PR_ADD_RUNQ(thread, cpu, newPri);        _PR_RUNQ_UNLOCK(cpu);            if (newPri > me->priority) {            if (!_PR_IS_NATIVE_THREAD(me))                    _PR_SET_RESCHED_FLAG();            }        break;      case _PR_LOCK_WAIT:      case _PR_COND_WAIT:      case _PR_IO_WAIT:      case _PR_SUSPENDED:        thread->priority = newPri;        break;    }    }    _PR_THREAD_UNLOCK(thread);    if (!_PR_IS_NATIVE_THREAD(me))    _PR_INTSON(is);}/*** Suspend the named thread and copy its gc registers into regBuf*/static void _PR_Suspend(PRThread *thread){    PRIntn is;    PRThread *me = _PR_MD_CURRENT_THREAD();    PR_ASSERT(thread != me);    PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread) || (!thread->cpu));    if (!_PR_IS_NATIVE_THREAD(me))        _PR_INTSOFF(is);    _PR_THREAD_LOCK(thread);    switch (thread->state) {      case _PR_RUNNABLE:        if (!_PR_IS_NATIVE_THREAD(thread)) {            _PR_RUNQ_LOCK(thread->cpu);            _PR_DEL_RUNQ(thread);            _PR_RUNQ_UNLOCK(thread->cpu);            _PR_MISCQ_LOCK(thread->cpu);            _PR_ADD_SUSPENDQ(thread, thread->cpu);            _PR_MISCQ_UNLOCK(thread->cpu);        } else {            /*             * Only LOCAL threads are suspended by _PR_Suspend             */             PR_ASSERT(0);        }        thread->state = _PR_SUSPENDED;        break;      case _PR_RUNNING:        /*         * The thread being suspended should be a LOCAL thread with         * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state         */        PR_ASSERT(0);        break;      case _PR_LOCK_WAIT:      case _PR_IO_WAIT:      case _PR_COND_WAIT:        if (_PR_IS_NATIVE_THREAD(thread)) {            _PR_MD_SUSPEND_THREAD(thread);    }        thread->flags |= _PR_SUSPENDING;        break;      default:        PR_Abort();    }    _PR_THREAD_UNLOCK(thread);    if (!_PR_IS_NATIVE_THREAD(me))    _PR_INTSON(is);}static void _PR_Resume(PRThread *thread){    PRThreadPriority pri;    PRIntn is;    PRThread *me = _PR_MD_CURRENT_THREAD();    if (!_PR_IS_NATIVE_THREAD(me))    _PR_INTSOFF(is);    _PR_THREAD_LOCK(thread);    switch (thread->state) {      case _PR_SUSPENDED:        thread->state = _PR_RUNNABLE;        thread->flags &= ~_PR_SUSPENDING;        if (!_PR_IS_NATIVE_THREAD(thread)) {            _PR_MISCQ_LOCK(thread->cpu);            _PR_DEL_SUSPENDQ(thread);            _PR_MISCQ_UNLOCK(thread->cpu);            pri = thread->priority;            _PR_RUNQ_LOCK(thread->cpu);            _PR_ADD_RUNQ(thread, thread->cpu, pri);            _PR_RUNQ_UNLOCK(thread->cpu);            if (pri > _PR_MD_CURRENT_THREAD()->priority) {                if (!_PR_IS_NATIVE_THREAD(me))                    _PR_SET_RESCHED_FLAG();            }        } else {            PR_ASSERT(0);        }        break;      case _PR_IO_WAIT:      case _PR_COND_WAIT:        thread->flags &= ~_PR_SUSPENDING;/*      PR_ASSERT(thread->wait.monitor->stickyCount == 0); */        break;      case _PR_LOCK_WAIT:       {        PRLock *wLock = thread->wait.lock;        thread->flags &= ~_PR_SUSPENDING;         _PR_LOCK_LOCK(wLock);        if (thread->wait.lock->owner == 0) {            _PR_UnblockLockWaiter(thread->wait.lock);        }        _PR_LOCK_UNLOCK(wLock);        break;      }      case _PR_RUNNABLE:        break;      case _PR_RUNNING:        /*         * The thread being suspended should be a LOCAL thread with         * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state         */        PR_ASSERT(0);        break;      default:    /*     * thread should have been in one of the above-listed blocked states     * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE)     */        PR_Abort();    }    _PR_THREAD_UNLOCK(thread);    if (!_PR_IS_NATIVE_THREAD(me))        _PR_INTSON(is);}#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus){    PRThread *thread;    PRIntn pri;    PRUint32 r;    PRCList *qp;    PRIntn priMin, priMax;    _PR_RUNQ_LOCK(cpu);    r = _PR_RUNQREADYMASK(cpu);    if (r==0) {        priMin = priMax = PR_PRIORITY_FIRST;    } else if (r == (1<<PR_PRIORITY_NORMAL) ) {        priMin = priMax = PR_PRIORITY_NORMAL;    } else {        priMin = PR_PRIORITY_FIRST;        priMax = PR_PRIORITY_LAST;    }    thread = NULL;    for (pri = priMax; pri >= priMin ; pri-- ) {    if (r & (1 << pri)) {            for (qp = _PR_RUNQ(cpu)[pri].next;                  qp != &_PR_RUNQ(cpu)[pri];                 qp = qp->next) {                thread = _PR_THREAD_PTR(qp);                /*                * skip non-schedulable threads                */                PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));                if (thread->no_sched) {                    thread = NULL;                    /*                     * Need to wakeup cpus to avoid missing a                     * runnable thread                     * Waking up all CPU's need happen only once.                     */                    *wakeup_cpus = PR_TRUE;                    continue;                } else if (thread->flags & _PR_BOUND_THREAD) {                    /*                     * Thread bound to cpu 0                     */                    thread = NULL;#ifdef IRIX					_PR_MD_WAKEUP_PRIMORDIAL_CPU();#endif                    continue;                } else if (thread->io_pending == PR_TRUE) {                    /*                     * A thread that is blocked for I/O needs to run                     * on the same cpu on which it was blocked. This is because                     * the cpu's ioq is accessed without lock protection and scheduling                     * the thread on a different cpu would preclude this optimization.                     */                    thread = NULL;                    continue;                } else {                    /* Pull thread off of its run queue */                    _PR_DEL_RUNQ(thread);                    _PR_RUNQ_UNLOCK(cpu);                    return(thread);                }            }        }        thread = NULL;    }    _PR_RUNQ_UNLOCK(cpu);    return(thread);}#endif /* !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) *//*** Schedule this native thread by finding the highest priority nspr** thread that is ready to run.**** Note- everyone really needs to call _PR_MD_SWITCH_CONTEXT (which calls**       PR_Schedule() rather than calling PR_Schedule.  Otherwise if there**       is initialization required for switching from SWITCH_CONTEXT,**       it will not get done!*/void _PR_Schedule(void){    PRThread *thread, *me = _PR_MD_CURRENT_THREAD();    _PRCPU *cpu = _PR_MD_CURRENT_CPU();    PRIntn pri;    PRUint32 r;    PRCList *qp;    PRIntn priMin, priMax;#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)    PRBool wakeup_cpus;#endif    /* Interrupts must be disabled */    PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);    /* Since we are rescheduling, we no longer want to */    _PR_CLEAR_RESCHED_FLAG();    /*    ** Find highest priority thread to run. Bigger priority numbers are    ** higher priority threads    */    _PR_RUNQ_LOCK(cpu);    /*     *  if we are in SuspendAll mode, can schedule only the thread     *    that called PR_SuspendAll     *     *  The thread may be ready to run now, after completing an I/O     *  operation, for example     */    if ((thread = suspendAllThread) != 0) {    if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) {            /* Pull thread off of its run queue */            _PR_DEL_RUNQ(thread);            _PR_RUNQ_UNLOCK(cpu);            goto found_thread;    } else {            thread = NULL;            _PR_RUNQ_UNLOCK(cpu);            goto idle_thread;    }    }    r = _PR_RUNQREADYMASK(cpu);    if (r==0) {        priMin = priMax = PR_PRIORITY_FIRST;    } else if (r == (1<<PR_PRIORITY_NORMAL) ) {        priMin = priMax = PR_PRIORITY_NORMAL;    } else {        priMin = PR_PRIORITY_FIRST;        priMax = PR_PRIORITY_LAST;    }    thread = NULL;    for (pri = priMax; pri >= priMin ; pri-- ) {    if (r & (1 << pri)) {            for (qp = _PR_RUNQ(cpu)[pri].next;                  qp != &_PR_RUNQ(cpu)[pri];                 qp = qp->next) {                thread = _PR_THREAD_PTR(qp);                /*                * skip non-schedulable threads                */#if !defined(XP_MAC)                PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));#endif                if ((thread->no_sched) && (me != thread)){                    thread = NULL;                    continue;                } else {                    /* Pull thread off of its run queue */                    _PR_DEL_RUNQ(thread);                    _PR_RUNQ_UNLOCK(cpu);                    goto found_thread;                }            }        }        thread = NULL;    }    _PR_RUNQ_UNLOCK(cpu);#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)    wakeup_cpus = PR_FALSE;    _PR_CPU_LIST_LOCK();    for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {        if (cpu != _PR_CPU_PTR(qp)) {            if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))                                        != NULL) {                thread->cpu = cpu;                _PR_CPU_LIST_UNLOCK();                if (wakeup_cpus == PR_TRUE)                    _PR_MD_WAKEUP_CPUS();

⌨️ 快捷键说明

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