📄 irix.c
字号:
* 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 + -