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

📄 solaris.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "primpl.h"extern PRBool suspendAllOn;extern PRThread *suspendAllThread;extern void _MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);PRIntervalTime _MD_Solaris_TicksPerSecond(void){    /*     * Ticks have a 10-microsecond resolution.  So there are     * 100000 ticks per second.     */    return 100000UL;}/* Interval timers, implemented using gethrtime() */PRIntervalTime _MD_Solaris_GetInterval(void){    union {	hrtime_t hrt;  /* hrtime_t is a 64-bit (long long) integer */	PRInt64 pr64;    } time;    PRInt64 resolution;    PRIntervalTime ticks;    time.hrt = gethrtime();  /* in nanoseconds */    /*     * Convert from nanoseconds to ticks.  A tick's resolution is     * 10 microseconds, or 10000 nanoseconds.     */    LL_I2L(resolution, 10000);    LL_DIV(time.pr64, time.pr64, resolution);    LL_L2UI(ticks, time.pr64);    return ticks;}#ifdef _PR_PTHREADSvoid _MD_EarlyInit(void){}PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np){	*np = 0;	return NULL;}#endif /* _PR_PTHREADS */#if !defined(i386) && !defined(IS_64)#if defined(_PR_HAVE_ATOMIC_OPS)/* NOTE: * SPARC v9 (Ultras) do have an atomic test-and-set operation.  But * SPARC v8 doesn't.  We should detect in the init if we are running on * v8 or v9, and then use assembly where we can. * * This code uses the Solaris threads API.  It can be used in both the * pthreads and Solaris threads versions of nspr20 because "POSIX threads * and Solaris threads are fully compatible even within the same process", * to quote from pthread_create(3T). */#include <thread.h>#include <synch.h>static mutex_t _solaris_atomic = DEFAULTMUTEX;PRInt32_MD_AtomicIncrement(PRInt32 *val){    PRInt32 rv;    if (mutex_lock(&_solaris_atomic) != 0)        PR_ASSERT(0);    rv = ++(*val);    if (mutex_unlock(&_solaris_atomic) != 0)\        PR_ASSERT(0);	return rv;}PRInt32_MD_AtomicAdd(PRInt32 *ptr, PRInt32 val){    PRInt32 rv;    if (mutex_lock(&_solaris_atomic) != 0)        PR_ASSERT(0);    rv = ((*ptr) += val);    if (mutex_unlock(&_solaris_atomic) != 0)\        PR_ASSERT(0);	return rv;}PRInt32_MD_AtomicDecrement(PRInt32 *val){    PRInt32 rv;    if (mutex_lock(&_solaris_atomic) != 0)        PR_ASSERT(0);    rv = --(*val);    if (mutex_unlock(&_solaris_atomic) != 0)\        PR_ASSERT(0);	return rv;}PRInt32_MD_AtomicSet(PRInt32 *val, PRInt32 newval){    PRInt32 rv;    if (mutex_lock(&_solaris_atomic) != 0)        PR_ASSERT(0);    rv = *val;    *val = newval;    if (mutex_unlock(&_solaris_atomic) != 0)\        PR_ASSERT(0);	return rv;}#endif  /* _PR_HAVE_ATOMIC_OPS */#endif  /* !defined(i386) */#if defined(_PR_GLOBAL_THREADS_ONLY)#include <signal.h>#include <errno.h>#include <fcntl.h>#include <thread.h>#include <sys/lwp.h>#include <sys/procfs.h>#include <sys/syscall.h>extern int syscall();  /* not declared in sys/syscall.h */static sigset_t old_mask;	/* store away original gc thread sigmask */static PRIntn gcprio;		/* store away original gc thread priority */THREAD_KEY_T threadid_key;THREAD_KEY_T cpuid_key;THREAD_KEY_T last_thread_key;static sigset_t set, oldset;void _MD_EarlyInit(void){    THR_KEYCREATE(&threadid_key, NULL);    THR_KEYCREATE(&cpuid_key, NULL);    THR_KEYCREATE(&last_thread_key, NULL);    sigemptyset(&set);    sigaddset(&set, SIGALRM);}PRStatus _MD_CreateThread(PRThread *thread, 					void (*start)(void *), 					PRThreadPriority priority,					PRThreadScope scope, 					PRThreadState state, 					PRUint32 stackSize) {	PRInt32 flags;	    /* mask out SIGALRM for native thread creation */    thr_sigsetmask(SIG_BLOCK, &set, &oldset);     /*     * Note that we create joinable threads with the THR_DETACHED     * flag.  The reasons why we don't use thr_join to implement     * PR_JoinThread are:     * - We use a termination condition variable in the PRThread     *   structure to implement PR_JoinThread across all classic     *   nspr implementation strategies.     * - The native threads may be recycled by NSPR to run other     *   new NSPR threads, so the native threads may not terminate     *   when the corresponding NSPR threads terminate.       */    flags = THR_SUSPENDED|THR_DETACHED;    if (_PR_IS_GCABLE_THREAD(thread) || (thread->flags & _PR_BOUND_THREAD) ||    							(scope == PR_GLOBAL_BOUND_THREAD))		flags |= THR_BOUND;    if (thr_create(NULL, thread->stack->stackSize,                  (void *(*)(void *)) start, (void *) thread, 				  flags,                  &thread->md.handle)) {        thr_sigsetmask(SIG_SETMASK, &oldset, NULL);         return PR_FAILURE;    }    /* When the thread starts running, then the lwpid is set to the right     * value. Until then we want to mark this as 'uninit' so that     * its register state is initialized properly for GC */    thread->md.lwpid = -1;    thr_sigsetmask(SIG_SETMASK, &oldset, NULL);     _MD_NEW_SEM(&thread->md.waiter_sem, 0);    if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {		thread->flags |= _PR_GLOBAL_SCOPE;    }    _MD_SET_PRIORITY(&(thread->md), priority);    /* Activate the thread */    if (thr_continue( thread->md.handle ) ) {	return PR_FAILURE;    }    return PR_SUCCESS;}void _MD_cleanup_thread(PRThread *thread){    thread_t hdl;    hdl = thread->md.handle;    /*     ** First, suspend the thread (unless it's the active one)    ** Because we suspend it first, we don't have to use LOCK_SCHEDULER to    ** prevent both of us modifying the thread structure at the same time.    */    if ( thread != _PR_MD_CURRENT_THREAD() ) {        thr_suspend(hdl);    }    PR_LOG(_pr_thread_lm, PR_LOG_MIN,            ("(0X%x)[DestroyThread]\n", thread));    _MD_DESTROY_SEM(&thread->md.waiter_sem);}void _MD_exit_thread(PRThread *thread){    _MD_CLEAN_THREAD(thread);    _MD_SET_CURRENT_THREAD(NULL);}void _MD_SET_PRIORITY(_MDThread *md_thread,        PRThreadPriority newPri){	PRIntn nativePri;	if (newPri < PR_PRIORITY_FIRST) {		newPri = PR_PRIORITY_FIRST;	} else if (newPri > PR_PRIORITY_LAST) {		newPri = PR_PRIORITY_LAST;	}	/* Solaris priorities are from 0 to 127 */	nativePri = newPri * 127 / PR_PRIORITY_LAST;	if(thr_setprio((thread_t)md_thread->handle, nativePri)) {		PR_LOG(_pr_thread_lm, PR_LOG_MIN,		   ("_PR_SetThreadPriority: can't set thread priority\n"));	}}void _MD_WAIT_CV(    struct _MDCVar *md_cv, struct _MDLock *md_lock, PRIntervalTime timeout){    struct timespec tt;    PRUint32 msec;    PRThread *me = _PR_MD_CURRENT_THREAD();	PR_ASSERT((!suspendAllOn) || (suspendAllThread != me));    if (PR_INTERVAL_NO_TIMEOUT == timeout) {        COND_WAIT(&md_cv->cv, &md_lock->lock);    } else {        msec = PR_IntervalToMilliseconds(timeout);        GETTIME(&tt);        tt.tv_sec += msec / PR_MSEC_PER_SEC;        tt.tv_nsec += (msec % PR_MSEC_PER_SEC) * PR_NSEC_PER_MSEC;        /* Check for nsec overflow - otherwise we'll get an EINVAL */        if (tt.tv_nsec >= PR_NSEC_PER_SEC) {            tt.tv_sec++;            tt.tv_nsec -= PR_NSEC_PER_SEC;        }        COND_TIMEDWAIT(&md_cv->cv, &md_lock->lock, &tt);    }}void _MD_lock(struct _MDLock *md_lock){#ifdef DEBUG    /* This code was used for GC testing to make sure that we didn't attempt     * to grab any locks while threads are suspended.     */    PRLock *lock;        if ((suspendAllOn) && (suspendAllThread == _PR_MD_CURRENT_THREAD())) {        lock = ((PRLock *) ((char*) (md_lock) - offsetof(PRLock,ilock)));	PR_ASSERT(lock->owner == NULL);        return;    }#endif /* DEBUG */    mutex_lock(&md_lock->lock);}PRThread *_pr_current_thread_tls(){    PRThread *ret;    thr_getspecific(threadid_key, (void **)&ret);    return ret;}PRStatus_MD_wait(PRThread *thread, PRIntervalTime ticks){        _MD_WAIT_SEM(&thread->md.waiter_sem);        return PR_SUCCESS;}PRStatus_MD_WakeupWaiter(PRThread *thread){	if (thread == NULL) {		return PR_SUCCESS;	}	_MD_POST_SEM(&thread->md.waiter_sem);	return PR_SUCCESS;}_PRCPU *_pr_current_cpu_tls(){    _PRCPU *ret;    thr_getspecific(cpuid_key, (void **)&ret);    return ret;}PRThread *_pr_last_thread_tls(){    PRThread *ret;    thr_getspecific(last_thread_key, (void **)&ret);    return ret;}_MDLock _pr_ioq_lock;void_MD_InitIO(void){    _MD_NEW_LOCK(&_pr_ioq_lock);}PRStatus _MD_InitializeThread(PRThread *thread){    if (!_PR_IS_NATIVE_THREAD(thread))        return PR_SUCCESS;    /* sol_curthread is an asm routine which grabs GR7; GR7 stores an internal     * thread structure ptr used by solaris.  We'll use this ptr later     * with suspend/resume to find which threads are running on LWPs.     */    thread->md.threadID = sol_curthread();		/* prime the sp; substract 4 so we don't hit the assert that		 * curr sp > base_stack		 */    thread->md.sp = (uint_t) thread->stack->allocBase - sizeof(long);    thread->md.lwpid = _lwp_self();    thread->md.handle = THR_SELF();	/* all threads on Solaris are global threads from NSPR's perspective	 * since all of them are mapped to Solaris threads.	 */    thread->flags |= _PR_GLOBAL_SCOPE;  	/* For primordial/attached thread, we don't create an underlying native thread. 	 * So, _MD_CREATE_THREAD() does not get called.  We need to do initialization 	 * like allocating thread's synchronization variables and set the underlying 	 * native thread's priority. 	 */	if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {	    _MD_NEW_SEM(&thread->md.waiter_sem, 0);	    _MD_SET_PRIORITY(&(thread->md), thread->priority);	}	return PR_SUCCESS;}/* Sleep for n milliseconds, n < 1000   */void solaris_msec_sleep(int n){    struct timespec ts;    ts.tv_sec = 0;

⌨️ 快捷键说明

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