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

📄 pthreads_user.c

📁 Netscape NSPR库源码
💻 C
字号:
/* -*- 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"#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <pthread.h>sigset_t ints_off;pthread_mutex_t	_pr_heapLock;pthread_key_t current_thread_key;pthread_key_t current_cpu_key;pthread_key_t last_thread_key;pthread_key_t intsoff_key;PRInt32 _pr_md_pthreads_created, _pr_md_pthreads_failed;PRInt32 _pr_md_pthreads = 1;void _MD_EarlyInit(void){extern PRInt32 _nspr_noclock;	if (pthread_key_create(&current_thread_key, NULL) != 0) {		perror("pthread_key_create failed");		exit(1);	}	if (pthread_key_create(&current_cpu_key, NULL) != 0) {		perror("pthread_key_create failed");		exit(1);	}	if (pthread_key_create(&last_thread_key, NULL) != 0) {		perror("pthread_key_create failed");		exit(1);	}	if (pthread_key_create(&intsoff_key, NULL) != 0) {		perror("pthread_key_create failed");		exit(1);	}	sigemptyset(&ints_off);	sigaddset(&ints_off, SIGALRM);	sigaddset(&ints_off, SIGIO);	sigaddset(&ints_off, SIGCLD);	/*	 * disable clock interrupts	 */	_nspr_noclock = 1;}void _MD_InitLocks(){	if (pthread_mutex_init(&_pr_heapLock, NULL) != 0) {		perror("pthread_mutex_init failed");		exit(1);	}}PR_IMPLEMENT(void) _MD_FREE_LOCK(struct _MDLock *lockp){	PRIntn _is;	PRThread *me = _PR_MD_CURRENT_THREAD();	if (me && !_PR_IS_NATIVE_THREAD(me))		_PR_INTSOFF(_is); 	pthread_mutex_destroy(&lockp->mutex);	if (me && !_PR_IS_NATIVE_THREAD(me))		_PR_FAST_INTSON(_is);}PR_IMPLEMENT(PRStatus) _MD_NEW_LOCK(struct _MDLock *lockp){    PRStatus rv;    PRIntn is;    PRThread *me = _PR_MD_CURRENT_THREAD();		if (me && !_PR_IS_NATIVE_THREAD(me))		_PR_INTSOFF(is);	rv = pthread_mutex_init(&lockp->mutex, NULL);	if (me && !_PR_IS_NATIVE_THREAD(me))		_PR_FAST_INTSON(is);	return (rv == 0) ? PR_SUCCESS : PR_FAILURE;}PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np){    if (isCurrent) {	(void) setjmp(CONTEXT(t));    }    *np = sizeof(CONTEXT(t)) / sizeof(PRWord);    return (PRWord *) CONTEXT(t);}PR_IMPLEMENT(void)_MD_SetPriority(_MDThread *thread, PRThreadPriority newPri){	/*	 * XXX - to be implemented	 */    return;}PR_IMPLEMENT(PRStatus) _MD_InitThread(struct PRThread *thread){    struct sigaction sigact;    if (thread->flags & _PR_GLOBAL_SCOPE) {        thread->md.pthread = pthread_self();#if 0		/*		 * set up SIGUSR1 handler; this is used to save state		 * during PR_SuspendAll		 */		sigact.sa_handler = save_context_and_block;		sigact.sa_flags = SA_RESTART;		/*		 * Must mask clock interrupts		 */		sigact.sa_mask = timer_set;		sigaction(SIGUSR1, &sigact, 0);#endif    }    return PR_SUCCESS;}PR_IMPLEMENT(void) _MD_ExitThread(struct PRThread *thread){    if (thread->flags & _PR_GLOBAL_SCOPE) {        _MD_CLEAN_THREAD(thread);        _MD_SET_CURRENT_THREAD(NULL);    }}PR_IMPLEMENT(void) _MD_CleanThread(struct PRThread *thread){    if (thread->flags & _PR_GLOBAL_SCOPE) {		pthread_mutex_destroy(&thread->md.pthread_mutex);		pthread_cond_destroy(&thread->md.pthread_cond);    }}PR_IMPLEMENT(void) _MD_SuspendThread(struct PRThread *thread){    PRInt32 rv;    PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&        _PR_IS_GCABLE_THREAD(thread));#if 0	thread->md.suspending_id = getpid();	rv = kill(thread->md.id, SIGUSR1);	PR_ASSERT(rv == 0);	/*	 * now, block the current thread/cpu until woken up by the suspended	 * thread from it's SIGUSR1 signal handler	 */	blockproc(getpid());#endif}PR_IMPLEMENT(void) _MD_ResumeThread(struct PRThread *thread){    PRInt32 rv;    PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&        _PR_IS_GCABLE_THREAD(thread));#if 0    rv = unblockproc(thread->md.id);#endif}PR_IMPLEMENT(void) _MD_SuspendCPU(struct _PRCPU *thread){    PRInt32 rv;#if 0	cpu->md.suspending_id = getpid();	rv = kill(cpu->md.id, SIGUSR1);	PR_ASSERT(rv == 0);	/*	 * now, block the current thread/cpu until woken up by the suspended	 * thread from it's SIGUSR1 signal handler	 */	blockproc(getpid());#endif}PR_IMPLEMENT(void) _MD_ResumeCPU(struct _PRCPU *thread){#if 0	unblockproc(cpu->md.id);#endif}#define PT_NANOPERMICRO 1000UL#define PT_BILLION 1000000000ULPR_IMPLEMENT(PRStatus)_pt_wait(PRThread *thread, PRIntervalTime timeout){int rv;struct timeval now;struct timespec tmo;PRUint32 ticks = PR_TicksPerSecond();	if (timeout != PR_INTERVAL_NO_TIMEOUT) {		tmo.tv_sec = timeout / ticks;		tmo.tv_nsec = timeout - (tmo.tv_sec * ticks);		tmo.tv_nsec = PR_IntervalToMicroseconds(PT_NANOPERMICRO *											tmo.tv_nsec);		/* pthreads wants this in absolute time, off we go ... */		(void)GETTIMEOFDAY(&now);		/* that one's usecs, this one's nsecs - grrrr! */		tmo.tv_sec += now.tv_sec;		tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);		tmo.tv_sec += tmo.tv_nsec / PT_BILLION;		tmo.tv_nsec %= PT_BILLION;	}	pthread_mutex_lock(&thread->md.pthread_mutex);	thread->md.wait--;	if (thread->md.wait < 0) {		if (timeout != PR_INTERVAL_NO_TIMEOUT) {			rv = pthread_cond_timedwait(&thread->md.pthread_cond,					&thread->md.pthread_mutex, &tmo);        }		else			rv = pthread_cond_wait(&thread->md.pthread_cond,					&thread->md.pthread_mutex);		if (rv != 0) {			thread->md.wait++;		}	} else		rv = 0;	pthread_mutex_unlock(&thread->md.pthread_mutex);	return (rv == 0) ? PR_SUCCESS : PR_FAILURE;}PR_IMPLEMENT(PRStatus)_MD_wait(PRThread *thread, PRIntervalTime ticks){    if ( thread->flags & _PR_GLOBAL_SCOPE ) {		_MD_CHECK_FOR_EXIT();        if (_pt_wait(thread, ticks) == PR_FAILURE) {	    	_MD_CHECK_FOR_EXIT();            /*             * wait timed out             */            _PR_THREAD_LOCK(thread);            if (thread->wait.cvar) {                /*                 * The thread will remove itself from the waitQ                 * of the cvar in _PR_WaitCondVar                 */                thread->wait.cvar = NULL;                thread->state =  _PR_RUNNING;                _PR_THREAD_UNLOCK(thread);            }  else {        		_pt_wait(thread, PR_INTERVAL_NO_TIMEOUT);                _PR_THREAD_UNLOCK(thread);            }        }    } else {		_PR_MD_SWITCH_CONTEXT(thread);    }    return PR_SUCCESS;}PR_IMPLEMENT(PRStatus)_MD_WakeupWaiter(PRThread *thread){    PRThread *me = _PR_MD_CURRENT_THREAD();    PRInt32 pid, rv;    PRIntn is;	PR_ASSERT(_pr_md_idle_cpus >= 0);    if (thread == NULL) {		if (_pr_md_idle_cpus)        	_MD_Wakeup_CPUs();    } else if (!_PR_IS_NATIVE_THREAD(thread)) {		/*		 * If the thread is on my cpu's runq there is no need to		 * wakeup any cpus		 */		if (!_PR_IS_NATIVE_THREAD(me)) {			if (me->cpu != thread->cpu) {				if (_pr_md_idle_cpus)        			_MD_Wakeup_CPUs();			}		} else {			if (_pr_md_idle_cpus)        		_MD_Wakeup_CPUs();		}    } else {		PR_ASSERT(_PR_IS_NATIVE_THREAD(thread));		if (!_PR_IS_NATIVE_THREAD(me))			_PR_INTSOFF(is);		pthread_mutex_lock(&thread->md.pthread_mutex);		thread->md.wait++;		rv = pthread_cond_signal(&thread->md.pthread_cond);		PR_ASSERT(rv == 0);		pthread_mutex_unlock(&thread->md.pthread_mutex);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);    }     return PR_SUCCESS;}/* These functions should not be called for AIX */PR_IMPLEMENT(void)_MD_YIELD(void){    PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");}PR_IMPLEMENT(PRStatus)_MD_CreateThread(    PRThread *thread,    void (*start) (void *),    PRThreadPriority priority,    PRThreadScope scope,    PRThreadState state,    PRUint32 stackSize){    PRIntn is;    int rv;	PRThread *me = _PR_MD_CURRENT_THREAD();		pthread_attr_t attr;	if (!_PR_IS_NATIVE_THREAD(me))		_PR_INTSOFF(is);	if (pthread_mutex_init(&thread->md.pthread_mutex, NULL) != 0) {		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return PR_FAILURE;	}	if (pthread_cond_init(&thread->md.pthread_cond, NULL) != 0) {		pthread_mutex_destroy(&thread->md.pthread_mutex);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return PR_FAILURE;	}    thread->flags |= _PR_GLOBAL_SCOPE;	pthread_attr_init(&attr); /* initialize attr with default attributes */	if (pthread_attr_setstacksize(&attr, (size_t) stackSize) != 0) {		pthread_mutex_destroy(&thread->md.pthread_mutex);		pthread_cond_destroy(&thread->md.pthread_cond);		pthread_attr_destroy(&attr);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return PR_FAILURE;	}	thread->md.wait = 0;    rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread);    if (0 == rv) {        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created);        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return PR_SUCCESS;    } else {		pthread_mutex_destroy(&thread->md.pthread_mutex);		pthread_cond_destroy(&thread->md.pthread_cond);		pthread_attr_destroy(&attr);        _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv);        return PR_FAILURE;    }}PR_IMPLEMENT(void)_MD_InitRunningCPU(struct _PRCPU *cpu){    extern int _pr_md_pipefd[2];    _MD_unix_init_running_cpu(cpu);    cpu->md.pthread = pthread_self();	if (_pr_md_pipefd[0] >= 0) {    	_PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];#ifndef _PR_USE_POLL    	FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));#endif	}}void_MD_CleanupBeforeExit(void){#if 0    extern PRInt32    _pr_cpus_exit;	_pr_irix_exit_now = 1;    if (_pr_numCPU > 1) {        /*         * Set a global flag, and wakeup all cpus which will notice the flag         * and exit.         */        _pr_cpus_exit = getpid();        _MD_Wakeup_CPUs();        while(_pr_numCPU > 1) {            _PR_WAIT_SEM(_pr_irix_exit_sem);            _pr_numCPU--;        }    }    /*     * cause global threads on the recycle list to exit     */     _PR_DEADQ_LOCK;     if (_PR_NUM_DEADNATIVE != 0) {	PRThread *thread;    	PRCList *ptr;        ptr = _PR_DEADNATIVEQ.next;        while( ptr != &_PR_DEADNATIVEQ ) {        	thread = _PR_THREAD_PTR(ptr);		_MD_CVAR_POST_SEM(thread);                ptr = ptr->next;        }      }     _PR_DEADQ_UNLOCK;     while(_PR_NUM_DEADNATIVE > 1) {	_PR_WAIT_SEM(_pr_irix_exit_sem);	_PR_DEC_DEADNATIVE;     }#endif}

⌨️ 快捷键说明

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