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

📄 irix.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
     * did not timeout     */    if (!thread->md.cvar_pollsem_select) {        rv = _PR_WAIT_SEM(thread->md.cvar_pollsem);		PR_ASSERT(rv >= 0);	} else        rv = 0;again:    if(!rv) {#ifdef _PR_USE_POLL		pfd.events = POLLIN;		pfd.fd = thread->md.cvar_pollsemfd;		rv = _MD_POLL(&pfd, 1, msecs);#else		rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd, NULL,NULL,tvp);#endif        if ((rv == -1) && (errno == EINTR)) {			rv = 0;			goto again;		}		PR_ASSERT(rv >= 0);	}    if (rv > 0) {        /*         * acquired the semaphore, call uspsema next time         */        thread->md.cvar_pollsem_select = 0;        return PR_SUCCESS;    } else {        /*         * select timed out; must call select, not uspsema, when trying         * to acquire the semaphore the next time         */        thread->md.cvar_pollsem_select = 1;        return PR_FAILURE;    }}PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks){    if ( thread->flags & _PR_GLOBAL_SCOPE ) {	_MD_CHECK_FOR_EXIT();        if (pr_cvar_wait_sem(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 {                _PR_THREAD_UNLOCK(thread);                /*             * This thread was woken up by a notifying thread             * at the same time as a timeout; so, consume the             * extra post operation on the semaphore             */	        _MD_CHECK_FOR_EXIT();            pr_cvar_wait_sem(thread, PR_INTERVAL_NO_TIMEOUT);            }	    _MD_CHECK_FOR_EXIT();        }    } else {        _PR_MD_SWITCH_CONTEXT(thread);    }    return PR_SUCCESS;}PRStatus _MD_WakeupWaiter(PRThread *thread){    PRThread *me = _PR_MD_CURRENT_THREAD();    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 (_pr_md_idle_cpus)       		_MD_Wakeup_CPUs();    } else {		PR_ASSERT(_PR_IS_NATIVE_THREAD(thread));		if (!_PR_IS_NATIVE_THREAD(me))			_PR_INTSOFF(is);		_MD_CVAR_POST_SEM(thread);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);    }     return PR_SUCCESS;}void create_sproc (void (*entry) (void *, size_t), unsigned inh,					void *arg, caddr_t sp, size_t len, int *pid){sproc_params sparams;char data;int rv;PRThread *me = _PR_MD_CURRENT_THREAD();	if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {		*pid = sprocsp(entry,		/* startup func		*/						inh,        /* attribute flags	*/						arg,     	/* thread param		*/						sp,         /* stack address	*/						len);       /* stack size		*/	} else {		sparams.sd.entry = entry;		sparams.sd.inh = inh;		sparams.sd.arg = arg;		sparams.sd.sp = sp;		sparams.sd.len = len;		sparams.sd.pid = pid;		sparams.sd.creator_pid = getpid();		_PR_LOCK(sproc_list_lock);		PR_APPEND_LINK(&sparams.links, &sproc_list);		rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);		PR_ASSERT(rv == 1);		_PR_UNLOCK(sproc_list_lock);		blockproc(getpid());	}}/* * _PR_MD_WAKEUP_PRIMORDIAL_CPU * *		wakeup cpu 0 */void _PR_MD_WAKEUP_PRIMORDIAL_CPU(){char data = '0';int rv;	rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);	PR_ASSERT(rv == 1);}/* * _PR_MD_primordial_cpu * *		process events that need to executed by the primordial cpu on each *		iteration through the idle loop */void _PR_MD_primordial_cpu(){PRCList *qp;sproc_params *sp;int pid;	_PR_LOCK(sproc_list_lock);	while ((qp = sproc_list.next) != &sproc_list) {		sp = SPROC_PARAMS_PTR(qp);		PR_REMOVE_LINK(&sp->links);		pid = sp->sd.creator_pid;		(*(sp->sd.pid)) = sprocsp(sp->sd.entry,		/* startup func    */							sp->sd.inh,            	/* attribute flags     */							sp->sd.arg,     		/* thread param     */							sp->sd.sp,             	/* stack address    */							sp->sd.len);         	/* stack size     */		unblockproc(pid);	}	_PR_UNLOCK(sproc_list_lock);}PRStatus _MD_CreateThread(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize){    typedef void (*SprocEntry) (void *, size_t);    SprocEntry spentry = (SprocEntry)start;    PRIntn is;	PRThread *me = _PR_MD_CURRENT_THREAD();		PRInt32 pid;	PRStatus rv;	if (!_PR_IS_NATIVE_THREAD(me))		_PR_INTSOFF(is);    thread->md.cvar_pollsem_select = 0;    thread->flags |= _PR_GLOBAL_SCOPE;	thread->md.cvar_pollsemfd = -1;	if (new_poll_sem(&thread->md,0) == PR_FAILURE) {		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);		return PR_FAILURE;	}	thread->md.cvar_pollsemfd =		_PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);	if ((thread->md.cvar_pollsemfd < 0)) {		free_poll_sem(&thread->md);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);		return PR_FAILURE;	}    create_sproc(spentry,            /* startup func    */    			PR_SALL,            /* attribute flags     */    			(void *)thread,     /* thread param     */    			NULL,               /* stack address    */    			stackSize, &pid);         /* stack size     */    if (pid > 0) {        _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created);        _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs);		rv = PR_SUCCESS;		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return rv;    } else {        close(thread->md.cvar_pollsemfd);        thread->md.cvar_pollsemfd = -1;		free_poll_sem(&thread->md);        thread->md.cvar_pollsem = NULL;        _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed);		if (!_PR_IS_NATIVE_THREAD(me))			_PR_FAST_INTSON(is);        return PR_FAILURE;    }}void _MD_CleanThread(PRThread *thread){    if (thread->flags & _PR_GLOBAL_SCOPE) {        close(thread->md.cvar_pollsemfd);        thread->md.cvar_pollsemfd = -1;		free_poll_sem(&thread->md);        thread->md.cvar_pollsem = NULL;    }}void _MD_SetPriority(_MDThread *thread, PRThreadPriority newPri){    return;}extern void _MD_unix_terminate_waitpid_daemon(void);void_MD_CleanupBeforeExit(void){    extern PRInt32    _pr_cpus_exit;    _MD_unix_terminate_waitpid_daemon();	_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;     }}#ifdef _PR_HAVE_SGI_PRDA_PROCMASKextern void __sgi_prda_procmask(int);#endifPRStatus_MD_InitAttachedThread(PRThread *thread, PRBool wakeup_parent){	PRStatus rv = PR_SUCCESS;    if (thread->flags & _PR_GLOBAL_SCOPE) {		if (new_poll_sem(&thread->md,0) == PR_FAILURE) {			return PR_FAILURE;		}		thread->md.cvar_pollsemfd =			_PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);		if ((thread->md.cvar_pollsemfd < 0)) {			free_poll_sem(&thread->md);			return PR_FAILURE;		}		if (_MD_InitThread(thread, PR_FALSE) == PR_FAILURE) {			close(thread->md.cvar_pollsemfd);			thread->md.cvar_pollsemfd = -1;			free_poll_sem(&thread->md);			thread->md.cvar_pollsem = NULL;			return PR_FAILURE;		}    }	return rv;}PRStatus_MD_InitThread(PRThread *thread, PRBool wakeup_parent){    struct sigaction sigact;	PRStatus rv = PR_SUCCESS;    if (thread->flags & _PR_GLOBAL_SCOPE) {		thread->md.id = getpid();        setblockproccnt(thread->md.id, 0);		_MD_SET_SPROC_PID(getpid());	#ifdef _PR_HAVE_SGI_PRDA_PROCMASK		/*		 * enable user-level processing of sigprocmask(); this is an		 * undocumented feature available in Irix 6.2, 6.3, 6.4 and 6.5		 */		__sgi_prda_procmask(USER_LEVEL);#endif		/*		 * set up SIGUSR1 handler; this is used to save state		 */		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);		/*		 * PR_SETABORTSIG is a new command implemented in a patch to		 * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all		 * sprocs in the process when one of them terminates abnormally		 *		 */		if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {			/*			 *  if (errno == EINVAL)			 *			 *	PR_SETABORTSIG not supported under this OS.			 *	You may want to get a recent kernel rollup patch that			 *	supports this feature.			 */		}		/*		 * SIGCLD handler for detecting abormally-terminating		 * sprocs and for reaping sprocs		 */		sigact.sa_handler = sigchld_handler;		sigact.sa_flags = SA_RESTART;		sigact.sa_mask = ints_off;		sigaction(SIGCLD, &sigact, NULL);    }	return rv;}/* * PR_Cleanup should be executed on the primordial sproc; migrate the thread * to the primordial cpu */void _PR_MD_PRE_CLEANUP(PRThread *me){PRIntn is;_PRCPU *cpu = _pr_primordialCPU;	PR_ASSERT(cpu);	me->flags |= _PR_BOUND_THREAD;		if (me->cpu->id != 0) {		_PR_INTSOFF(is);		_PR_RUNQ_LOCK(cpu);		me->cpu = cpu;		me->state = _PR_RUNNABLE;		_PR_ADD_RUNQ(me, cpu, me->priority);		_PR_RUNQ_UNLOCK(cpu);		_MD_Wakeup_CPUs();		_PR_MD_SWITCH_CONTEXT(me);		_PR_FAST_INTSON(is);		PR_ASSERT(me->cpu->id == 0);	}}/* * process exiting */PR_EXTERN(void ) _MD_exit(PRIntn status){PRThread *me = _PR_MD_CURRENT_THREAD();	/*	 * the exit code of the process is the exit code of the primordial	 * sproc	 */	if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {		/*		 * primordial sproc case: call _exit directly		 * Cause SIGKILL to be sent to other sprocs		 */		prctl(PR_SETEXITSIG, SIGKILL);		_exit(status);	} else {		int rv;		char data;		sigset_t set;		/*		 * non-primordial sproc case: cause the primordial sproc, cpu 0,		 * to wakeup and call _exit		 */		_pr_irix_process_exit = 1;		_pr_irix_process_exit_code = status;		rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);		PR_ASSERT(rv == 1);		/*		 * block all signals and wait for SIGKILL to terminate this sproc		 */		sigfillset(&set);		sigsuspend(&set);		/*		 * this code doesn't (shouldn't) execute		 */		prctl(PR_SETEXITSIG, SIGKILL);		_exit(status);	}}/* * Override the exit() function in libc to cause the process to exit * when the primodial/main nspr thread calls exit. Calls to exit by any * other thread simply result in a call to the exit function in libc. * The exit code of the process is the exit code of the primordial * sproc. */void exit(int status){PRThread *me, *thr;PRCList *qp;	if (!_pr_initialized)  {		if (!libc_exit) {			if (!libc_handle)				libc_handle = dlopen("libc.so",RTLD_NOW);			if (libc_handle)				libc_exit = (void (*)(int)) dlsym(libc_handle, "exit");		}		if (libc_exit)			(*libc_exit)(status);		else			_exit(status);	}	me = _PR_MD_CURRENT_THREAD();	if (me == NULL) 		/* detached thread */		(*libc_exit)(status);	PR_ASSERT(_PR_IS_NATIVE_THREAD(me) ||						(_PR_MD_CURRENT_CPU())->id == me->cpu->id);	if (me->flags & _PR_PRIMORDIAL) {		me->flags |= _PR_BOUND_THREAD;			PR_ASSERT((_PR_MD_CURRENT_CPU())->id == me->cpu->id);		if (me->cpu->id != 0) {			_PRCPU *cpu = _pr_primordialCPU;			PRIntn is;			_PR_INTSOFF(is);			_PR_RUNQ_LOCK(cpu);			me->cpu = cpu;			me->state = _PR_RUNNABLE;			_PR_ADD_RUNQ(me, cpu, me->priority);			_PR_RUNQ_UNLOCK(cpu);			_MD_Wakeup_CPUs();			_PR_MD_SWITCH_CONTEXT(me);			_PR_FAST_INTSON(is);		}		PR_ASSERT((_PR_MD_CURRENT_CPU())->id == 0);		if (prctl(PR_GETNSHARE) > 1) {#define SPROC_EXIT_WAIT_TIME 5			int sleep_cnt = SPROC_EXIT_WAIT_TIME;			/*			 * sprocs still running; caue cpus and recycled global threads			 * to exit			 */			_pr_irix_exit_now = 1;			if (_pr_numCPU > 1) {				_MD_Wakeup_CPUs();			}			 _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;				} 			 }			while (sleep_cnt-- > 0) {				if (waitpid(0, NULL, WNOHANG) >= 0) 					sleep(1);				else					break;			}			prctl(PR_SETEXITSIG, SIGKILL);		}		(*libc_exit)(status);	} else {		/*		 * non-primordial thread; simply call exit in libc.		 */		(*libc_exit)(status);	}}void_MD_InitRunningCPU(_PRCPU *cpu){    extern int _pr_md_pipefd[2];    _MD_unix_init_running_cpu(cpu);    cpu->md.id = getpid();	_MD_SET_SPROC_PID(getpid());		if (_pr_md_pipefd[0] >= 0) {

⌨️ 快捷键说明

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