| Index: mozilla/nsprpub/pr/src/threads/prcthr.c
|
| ===================================================================
|
| --- mozilla/nsprpub/pr/src/threads/prcthr.c (revision 191424)
|
| +++ mozilla/nsprpub/pr/src/threads/prcthr.c (working copy)
|
| @@ -1,395 +0,0 @@
|
| -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -
|
| -#include "primpl.h"
|
| -
|
| -#if defined(WIN95)
|
| -/*
|
| -** Some local variables report warnings on Win95 because the code paths
|
| -** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
|
| -** The pragma suppresses the warning.
|
| -**
|
| -*/
|
| -#pragma warning(disable : 4101)
|
| -#endif
|
| -
|
| -
|
| -extern PRLock *_pr_sleeplock; /* allocated and initialized in prinit */
|
| -/*
|
| -** Routines common to both native and user threads.
|
| -**
|
| -**
|
| -** Clean up a thread object, releasing all of the attached data. Do not
|
| -** free the object itself (it may not have been malloc'd)
|
| -*/
|
| -void _PR_CleanupThread(PRThread *thread)
|
| -{
|
| - /* Free up per-thread-data */
|
| - _PR_DestroyThreadPrivate(thread);
|
| -
|
| - /* Free any thread dump procs */
|
| - if (thread->dumpArg) {
|
| - PR_DELETE(thread->dumpArg);
|
| - }
|
| - thread->dump = 0;
|
| -
|
| - PR_DELETE(thread->name);
|
| - PR_DELETE(thread->errorString);
|
| - thread->errorStringSize = 0;
|
| - thread->errorStringLength = 0;
|
| - thread->environment = NULL;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRStatus) PR_Yield()
|
| -{
|
| - 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));
|
| -}
|
| -
|
| -/*
|
| -** Make the current thread sleep until "timeout" ticks amount of time
|
| -** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is
|
| -** equivalent to a yield. Waiting for an infinite amount of time is
|
| -** allowed in the expectation that another thread will interrupt().
|
| -**
|
| -** A single lock is used for all threads calling sleep. Each caller
|
| -** does get its own condition variable since each is expected to have
|
| -** a unique 'timeout'.
|
| -*/
|
| -PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
|
| -{
|
| - PRStatus rv = PR_SUCCESS;
|
| -
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| -
|
| - if (PR_INTERVAL_NO_WAIT == timeout)
|
| - {
|
| - /*
|
| - ** This is a simple yield, nothing more, nothing less.
|
| - */
|
| - PRIntn is;
|
| - PRThread *me = PR_GetCurrentThread();
|
| - PRUintn pri = me->priority;
|
| - _PRCPU *cpu = _PR_MD_CURRENT_CPU();
|
| -
|
| - if ( _PR_IS_NATIVE_THREAD(me) ) _PR_MD_YIELD();
|
| - else
|
| - {
|
| - _PR_INTSOFF(is);
|
| - _PR_RUNQ_LOCK(cpu);
|
| - if (_PR_RUNQREADYMASK(cpu) >> pri) {
|
| - me->cpu = cpu;
|
| - me->state = _PR_RUNNABLE;
|
| - _PR_ADD_RUNQ(me, cpu, pri);
|
| - _PR_RUNQ_UNLOCK(cpu);
|
| -
|
| - PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding"));
|
| - _PR_MD_SWITCH_CONTEXT(me);
|
| - PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done"));
|
| -
|
| - _PR_FAST_INTSON(is);
|
| - }
|
| - else
|
| - {
|
| - _PR_RUNQ_UNLOCK(cpu);
|
| - _PR_INTSON(is);
|
| - }
|
| - }
|
| - }
|
| - else
|
| - {
|
| - /*
|
| - ** This is waiting for some finite period of time.
|
| - ** A thread in this state is interruptible (PR_Interrupt()),
|
| - ** but the lock and cvar used are local to the implementation
|
| - ** and not visible to the caller, therefore not notifiable.
|
| - */
|
| - PRCondVar *cv;
|
| - PRIntervalTime timein;
|
| -
|
| - timein = PR_IntervalNow();
|
| - cv = PR_NewCondVar(_pr_sleeplock);
|
| - PR_ASSERT(cv != NULL);
|
| - PR_Lock(_pr_sleeplock);
|
| - do
|
| - {
|
| - PRIntervalTime delta = PR_IntervalNow() - timein;
|
| - if (delta > timeout) break;
|
| - rv = PR_WaitCondVar(cv, timeout - delta);
|
| - } while (rv == PR_SUCCESS);
|
| - PR_Unlock(_pr_sleeplock);
|
| - PR_DestroyCondVar(cv);
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread)
|
| -{
|
| - return thread->id;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread)
|
| -{
|
| - return (PRThreadPriority) thread->priority;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRThread *) PR_GetCurrentThread()
|
| -{
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| - return _PR_MD_CURRENT_THREAD();
|
| -}
|
| -
|
| -/*
|
| -** Set the interrupt flag for a thread. The thread will be unable to
|
| -** block in i/o functions when this happens. Also, any PR_Wait's in
|
| -** progress will be undone. The interrupt remains in force until
|
| -** PR_ClearInterrupt is called.
|
| -*/
|
| -PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thread)
|
| -{
|
| -#ifdef _PR_GLOBAL_THREADS_ONLY
|
| - PRCondVar *victim;
|
| -
|
| - _PR_THREAD_LOCK(thread);
|
| - thread->flags |= _PR_INTERRUPT;
|
| - victim = thread->wait.cvar;
|
| - _PR_THREAD_UNLOCK(thread);
|
| - if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) {
|
| - int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());
|
| -
|
| - if (!haveLock) PR_Lock(victim->lock);
|
| - PR_NotifyAllCondVar(victim);
|
| - if (!haveLock) PR_Unlock(victim->lock);
|
| - }
|
| - return PR_SUCCESS;
|
| -#else /* ! _PR_GLOBAL_THREADS_ONLY */
|
| - PRIntn is;
|
| - PRThread *me = _PR_MD_CURRENT_THREAD();
|
| -
|
| - if (!_PR_IS_NATIVE_THREAD(me))
|
| - _PR_INTSOFF(is);
|
| -
|
| - _PR_THREAD_LOCK(thread);
|
| - thread->flags |= _PR_INTERRUPT;
|
| - switch (thread->state) {
|
| - case _PR_COND_WAIT:
|
| - /*
|
| - * call is made with thread locked;
|
| - * on return lock is released
|
| - */
|
| - if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
|
| - _PR_NotifyLockedThread(thread);
|
| - break;
|
| - case _PR_IO_WAIT:
|
| - /*
|
| - * Need to hold the thread lock when calling
|
| - * _PR_Unblock_IO_Wait(). On return lock is
|
| - * released.
|
| - */
|
| -#if defined(XP_UNIX) || defined(WINNT) || defined(WIN16)
|
| - if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
|
| - _PR_Unblock_IO_Wait(thread);
|
| -#else
|
| - _PR_THREAD_UNLOCK(thread);
|
| -#endif
|
| - break;
|
| - case _PR_RUNNING:
|
| - case _PR_RUNNABLE:
|
| - case _PR_LOCK_WAIT:
|
| - default:
|
| - _PR_THREAD_UNLOCK(thread);
|
| - break;
|
| - }
|
| - if (!_PR_IS_NATIVE_THREAD(me))
|
| - _PR_INTSON(is);
|
| - return PR_SUCCESS;
|
| -#endif /* _PR_GLOBAL_THREADS_ONLY */
|
| -}
|
| -
|
| -/*
|
| -** Clear the interrupt flag for self.
|
| -*/
|
| -PR_IMPLEMENT(void) PR_ClearInterrupt()
|
| -{
|
| - PRIntn is;
|
| - PRThread *me = _PR_MD_CURRENT_THREAD();
|
| -
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
|
| - _PR_THREAD_LOCK(me);
|
| - me->flags &= ~_PR_INTERRUPT;
|
| - _PR_THREAD_UNLOCK(me);
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
| -}
|
| -
|
| -PR_IMPLEMENT(void) PR_BlockInterrupt()
|
| -{
|
| - PRIntn is;
|
| - PRThread *me = _PR_MD_CURRENT_THREAD();
|
| -
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
|
| - _PR_THREAD_LOCK(me);
|
| - _PR_THREAD_BLOCK_INTERRUPT(me);
|
| - _PR_THREAD_UNLOCK(me);
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
| -} /* PR_BlockInterrupt */
|
| -
|
| -PR_IMPLEMENT(void) PR_UnblockInterrupt()
|
| -{
|
| - PRIntn is;
|
| - PRThread *me = _PR_MD_CURRENT_THREAD();
|
| -
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
|
| - _PR_THREAD_LOCK(me);
|
| - _PR_THREAD_UNBLOCK_INTERRUPT(me);
|
| - _PR_THREAD_UNLOCK(me);
|
| - if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
|
| -} /* PR_UnblockInterrupt */
|
| -
|
| -/*
|
| -** Return the thread stack pointer of the given thread.
|
| -*/
|
| -PR_IMPLEMENT(void *) PR_GetSP(PRThread *thread)
|
| -{
|
| - return (void *)_PR_MD_GET_SP(thread);
|
| -}
|
| -
|
| -PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thread)
|
| -{
|
| - return thread->environment;
|
| -}
|
| -
|
| -PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thread, void *env)
|
| -{
|
| - thread->environment = env;
|
| -}
|
| -
|
| -
|
| -PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
|
| -{
|
| -#ifdef HAVE_THREAD_AFFINITY
|
| - return _PR_MD_GETTHREADAFFINITYMASK(thread, mask);
|
| -#else
|
| - return 0;
|
| -#endif
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
|
| -{
|
| -#ifdef HAVE_THREAD_AFFINITY
|
| -#ifndef IRIX
|
| - return _PR_MD_SETTHREADAFFINITYMASK(thread, mask);
|
| -#else
|
| - return 0;
|
| -#endif
|
| -#else
|
| - return 0;
|
| -#endif
|
| -}
|
| -
|
| -/* This call is thread unsafe if another thread is calling SetConcurrency()
|
| - */
|
| -PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask)
|
| -{
|
| -#ifdef HAVE_THREAD_AFFINITY
|
| - PRCList *qp;
|
| - extern PRUint32 _pr_cpu_affinity_mask;
|
| -
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| -
|
| - _pr_cpu_affinity_mask = mask;
|
| -
|
| - qp = _PR_CPUQ().next;
|
| - while(qp != &_PR_CPUQ()) {
|
| - _PRCPU *cpu;
|
| -
|
| - cpu = _PR_CPU_PTR(qp);
|
| - PR_SetThreadAffinityMask(cpu->thread, mask);
|
| -
|
| - qp = qp->next;
|
| - }
|
| -#endif
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -PRUint32 _pr_recycleThreads = 0;
|
| -PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count)
|
| -{
|
| - _pr_recycleThreads = count;
|
| -}
|
| -
|
| -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_GCABLE_THREAD);
|
| -}
|
| -
|
| -#ifdef SOLARIS
|
| -PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type,
|
| - void (*start)(void *arg),
|
| - void *arg,
|
| - PRUintn priority,
|
| - PRThreadScope scope,
|
| - PRThreadState state,
|
| - PRUint32 stackSize)
|
| -{
|
| - return _PR_CreateThread(type, start, arg, priority, scope, state,
|
| - stackSize, _PR_BOUND_THREAD);
|
| -}
|
| -#endif
|
| -
|
| -
|
| -PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble(
|
| - PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
|
| -{
|
| - /* $$$$ not sure how to finese this one */
|
| - PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
|
| - return NULL;
|
| -}
|
| -
|
| -PR_IMPLEMENT(void) PR_SetThreadGCAble()
|
| -{
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| - PR_Lock(_pr_activeLock);
|
| - _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD;
|
| - PR_Unlock(_pr_activeLock);
|
| -}
|
| -
|
| -PR_IMPLEMENT(void) PR_ClearThreadGCAble()
|
| -{
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| - PR_Lock(_pr_activeLock);
|
| - _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD);
|
| - PR_Unlock(_pr_activeLock);
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread)
|
| -{
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| -
|
| - if (_PR_IS_NATIVE_THREAD(thread)) {
|
| - return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD :
|
| - PR_GLOBAL_THREAD;
|
| - } else
|
| - return PR_LOCAL_THREAD;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread)
|
| -{
|
| - return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;
|
| -}
|
| -
|
| -PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thread)
|
| -{
|
| - return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
|
| -} /* PR_GetThreadState */
|
|
|