📄 irix.c
字号:
_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_ExitThread(PRThread *thread){ if (thread->flags & _PR_GLOBAL_SCOPE) { _MD_ATOMIC_DECREMENT(&_pr_md_irix_sprocs); _MD_CLEAN_THREAD(thread); _MD_SET_CURRENT_THREAD(NULL); }}void_MD_SuspendCPU(_PRCPU *cpu){ PRInt32 rv; 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());}void_MD_ResumeCPU(_PRCPU *cpu){ unblockproc(cpu->md.id);}#if 0/* * save the register context of a suspended sproc */void get_context(PRThread *thr){ int len, fd; char pidstr[24]; char path[24]; /* * open the file corresponding to this process in procfs */ sprintf(path,"/proc/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",thr->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { (void) ioctl(fd, PIOCGREG, thr->md.gregs); close(fd); } return;}#endif /* 0 */void_MD_SuspendThread(PRThread *thread){ PRInt32 rv; PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); 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());}void_MD_ResumeThread(PRThread *thread){ PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); (void)unblockproc(thread->md.id);}/* * return the set of processors available for scheduling procs in the * "mask" argument */PRInt32 _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask){ PRInt32 nprocs, rv; struct pda_stat *pstat;#define MAX_PROCESSORS 32 nprocs = sysmp(MP_NPROCS); if (nprocs < 0) return(-1); pstat = (struct pda_stat*)PR_MALLOC(sizeof(struct pda_stat) * nprocs); if (pstat == NULL) return(-1); rv = sysmp(MP_STAT, pstat); if (rv < 0) { PR_DELETE(pstat); return(-1); } /* * look at the first 32 cpus */ nprocs = (nprocs > MAX_PROCESSORS) ? MAX_PROCESSORS : nprocs; *mask = 0; while (nprocs) { if ((pstat->p_flags & PDAF_ENABLED) && !(pstat->p_flags & PDAF_ISOLATED)) { *mask |= (1 << pstat->p_cpuid); } nprocs--; pstat++; } return 0;}static char *_thr_state[] = { "UNBORN", "RUNNABLE", "RUNNING", "LOCK_WAIT", "COND_WAIT", "JOIN_WAIT", "IO_WAIT", "SUSPENDED", "DEAD"};void _PR_List_Threads(){ PRThread *thr; void *handle; struct _PRCPU *cpu; PRCList *qp; int len, fd; char pidstr[24]; char path[24]; prpsinfo_t pinfo; printf("\n%s %-s\n"," ","LOCAL Threads"); printf("%s %-s\n"," ","----- -------"); printf("%s %-14s %-10s %-12s %-3s %-10s %-10s %-12s\n\n"," ", "Thread", "State", "Wait-Handle", "Cpu","Stk-Base","Stk-Sz","SP"); for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) { thr = _PR_ACTIVE_THREAD_PTR(qp); printf("%s 0x%-12x %-10s "," ",thr,_thr_state[thr->state]); if (thr->state == _PR_LOCK_WAIT) handle = thr->wait.lock; else if (thr->state == _PR_COND_WAIT) handle = thr->wait.cvar; else handle = NULL; if (handle) printf("0x%-10x ",handle); else printf("%-12s "," "); printf("%-3d ",thr->cpu->id); printf("0x%-8x ",thr->stack->stackBottom); printf("0x%-8x ",thr->stack->stackSize); printf("0x%-10x\n",thr->md.jb[JB_SP]); } printf("\n%s %-s\n"," ","GLOBAL Threads"); printf("%s %-s\n"," ","------ -------"); printf("%s %-14s %-6s %-12s %-12s %-12s %-12s\n\n"," ","Thread", "Pid","State","Wait-Handle", "Stk-Base","Stk-Sz"); for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) { thr = _PR_ACTIVE_THREAD_PTR(qp); if (thr->cpu != NULL) continue; /* it is a cpu thread */ printf("%s 0x%-12x %-6d "," ",thr,thr->md.id); /* * check if the sproc is still running * first call prctl(PR_GETSHMASK,pid) to check if * the process is part of the share group (the pid * could have been recycled by the OS) */ if (prctl(PR_GETSHMASK,thr->md.id) < 0) { printf("%-12s\n","TERMINATED"); continue; } /* * Now, check if the sproc terminated and is in zombie * state */ sprintf(path,"/proc/pinfo/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",thr->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) printf("%-12s ","TERMINATED"); else if (pinfo.pr_zomb) printf("%-12s ","TERMINATED"); else printf("%-12s ",_thr_state[thr->state]); close(fd); } else { printf("%-12s ","TERMINATED"); } if (thr->state == _PR_LOCK_WAIT) handle = thr->wait.lock; else if (thr->state == _PR_COND_WAIT) handle = thr->wait.cvar; else handle = NULL; if (handle) printf("%-12x ",handle); else printf("%-12s "," "); printf("0x%-10x ",thr->stack->stackBottom); printf("0x%-10x\n",thr->stack->stackSize); } printf("\n%s %-s\n"," ","CPUs"); printf("%s %-s\n"," ","----"); printf("%s %-14s %-6s %-12s \n\n"," ","Id","Pid","State"); for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { cpu = _PR_CPU_PTR(qp); printf("%s %-14d %-6d "," ",cpu->id,cpu->md.id); /* * check if the sproc is still running * first call prctl(PR_GETSHMASK,pid) to check if * the process is part of the share group (the pid * could have been recycled by the OS) */ if (prctl(PR_GETSHMASK,cpu->md.id) < 0) { printf("%-12s\n","TERMINATED"); continue; } /* * Now, check if the sproc terminated and is in zombie * state */ sprintf(path,"/proc/pinfo/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",cpu->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) printf("%-12s\n","TERMINATED"); else if (pinfo.pr_zomb) printf("%-12s\n","TERMINATED"); else printf("%-12s\n","RUNNING"); close(fd); } else { printf("%-12s\n","TERMINATED"); } } fflush(stdout);}#endif /* defined(_PR_PTHREADS) */ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np){#if !defined(_PR_PTHREADS) if (isCurrent) { (void) setjmp(t->md.jb); } *np = sizeof(t->md.jb) / sizeof(PRWord); return (PRWord *) (t->md.jb);#else *np = 0; return NULL;#endif}void _MD_EarlyInit(void){#if !defined(_PR_PTHREADS) char *eval; int fd; extern int __ateachexit(void (*func)(void)); sigemptyset(&ints_off); sigaddset(&ints_off, SIGALRM); sigaddset(&ints_off, SIGIO); sigaddset(&ints_off, SIGCLD); if (eval = getenv("_NSPR_TERMINATE_ON_ERROR")) _nspr_terminate_on_error = (0 == atoi(eval) == 0) ? PR_FALSE : PR_TRUE; fd = open("/dev/zero",O_RDWR , 0); if (fd < 0) { perror("open /dev/zero failed"); exit(1); } /* * Set up the sproc private data area. * This region exists at the same address, _nspr_sproc_private, for * every sproc, but each sproc gets a private copy of the region. */ _nspr_sproc_private = (char*)mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE| MAP_LOCAL, fd, 0); if (_nspr_sproc_private == (void*)-1) { perror("mmap /dev/zero failed"); exit(1); } _MD_SET_SPROC_PID(getpid()); close(fd); __ateachexit(irix_detach_sproc);#endif _MD_IrixIntervalInit();} /* _MD_EarlyInit */void _MD_IrixInit(void){#if !defined(_PR_PTHREADS) struct sigaction sigact; PRThread *me = _PR_MD_CURRENT_THREAD(); int rv;#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 * during PR_SuspendAll */ sigact.sa_handler = save_context_and_block; sigact.sa_flags = SA_RESTART; sigact.sa_mask = ints_off; sigaction(SIGUSR1, &sigact, 0); /* * Change the name of the core file from core to core.pid, * This is inherited by the sprocs created by this process */#ifdef PR_COREPID prctl(PR_COREPID, 0, 1);#endif /* * Irix-specific terminate on error processing */ /* * 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. * */ } /* * PR_SETEXITSIG - send the SIGCLD signal to the parent * sproc when any sproc terminates * * This is used to cause the entire application to * terminate when any sproc terminates abnormally by * receipt of a SIGSEGV, SIGBUS or SIGABRT signal. * If this is not done, the application may seem * "hung" to the user because the other sprocs may be * waiting for resources held by the * abnormally-terminating sproc. */ prctl(PR_SETEXITSIG, 0); sigact.sa_handler = sigchld_handler; sigact.sa_flags = SA_RESTART; sigact.sa_mask = ints_off; sigaction(SIGCLD, &sigact, NULL); /* * setup stack fields for the primordial thread */ me->stack->stackSize = prctl(PR_GETSTACKSIZE); me->stack->stackBottom = me->stack->stackTop - me->stack->stackSize; rv = pipe(_pr_irix_primoridal_cpu_fd); PR_ASSERT(rv == 0);#ifndef _PR_USE_POLL _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0]; FD_SET(_pr_irix_primoridal_cpu_fd[0], &_PR_FD_READ_SET(me->cpu));#endif libc_handle = dlopen("libc.so",RTLD_NOW); PR_ASSERT(libc_handle != NULL); libc_exit = (void (*)(int)) dlsym(libc_handle, "exit"); PR_ASSERT(libc_exit != NULL); /* dlclose(libc_handle); */#endif /* _PR_PTHREADS */ _PR_UnixInit();}/**************************************************************************//************** code and such for NSPR 2.0's interval times ***************//**************************************************************************/#define PR_PSEC_PER_SEC 1000000000000ULL /* 10^12 */#ifndef SGI_CYCLECNTR_SIZE#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */#endifstatic PRIntn mmem_fd = -1;static PRIntn clock_width = 0;static void *iotimer_addr = NULL;static PRUint32 pr_clock_mask = 0;static PRUint32 pr_clock_shift = 0;static PRIntervalTime pr_ticks = 0;static PRUint32 pr_clock_granularity = 1;static PRUint32 pr_previous = 0, pr_residual = 0;static PRUint32 pr_ticks_per_second = 0;extern PRIntervalTime _PR_UNIX_GetInterval(void);extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);static void _MD_IrixIntervalInit(void){ /* * As much as I would like, the service available through this * interface on R3000's (aka, IP12) just isn't going to make it. * The register is only 24 bits wide, and rolls over at a verocious * rate. */ PRUint32 one_tick = 0; struct utsname utsinfo; uname(&utsinfo); if ((strncmp("IP12", utsinfo.machine, 4) != 0) && ((mmem_fd = open("/dev/mmem", O_RDONLY)) != -1)) { int poffmask = getpagesize() - 1; __psunsigned_t phys_addr, raddr, cycleval; phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval); raddr = phys_addr & ~poffmask; iotimer_addr = mmap( 0, poffmask, PROT_READ, MAP_PRIVATE, mmem_fd, (__psint_t)raddr); clock_width = syssgi(SGI_CYCLECNTR_SIZE); if (clock_width < 0) { /* * We must be executing on a 6.0 or earlier system, since the * SGI_CYCLECNTR_SIZE call is not supported. * * The only pre-6.1 platforms with 64-bit counters are * IP19 and IP21 (Challenge, PowerChallenge, Onyx). */ if (!strncmp(utsinfo.machine, "IP19", 4) || !strncmp(utsinfo.machine, "IP21", 4)) clock_width = 64; else clock_width = 32; } /* * 'cycleval' is picoseconds / increment of the counter. * I'm pushing for a tick to be 100 microseconds, 10^(-4). * That leaves 10^(-8) left over, or 10^8 / cycleval. * Did I do that right? */ one_tick = 100000000UL / cycleval ; /* 100 microseconds */ while (0 != one_tick) { pr_clock_shift += 1; one_tick = one_tick >> 1; pr_clock_granularity = pr_clock_granularity << 1; } pr_clock_mask = pr_clock_granularity - 1; /* to make a mask out of it */ pr_ticks_per_second = PR_PSEC_PER_SEC / ((PRUint64)pr_clock_granularity * (PRUint64)cycleval); iotimer_addr = (void*) ((__psunsigned_t)iotimer_addr + (phys_addr & poffmask)); } else { pr_ticks_per_second = _PR_UNIX_TicksPerSecond(); }} /* _MD_IrixIntervalInit */PRIntervalTime _MD_IrixIntervalPerSec(void){ return pr_ticks_per_second;}PRIntervalTime _MD_IrixGetInterval(void){ if (mmem_fd != -1) { if (64 == clock_width) { PRUint64 temp = *(PRUint64*)iotimer_addr; pr_ticks = (PRIntervalTime)(temp >> pr_clock_shift); } else { PRIntervalTime ticks = pr_ticks; PRUint32 now = *(PRUint32*)iotimer_addr, temp; PRUint32 residual = pr_residual, previous = pr_previous; temp = now - previous + residual; residual = temp & pr_clock_mask; ticks += temp >> pr_clock_shift; pr_previous = now; pr_residual = residual; pr_ticks = ticks; } } else { /* * No fast access. Use the time of day clock. This isn't the * right answer since this clock can get set back, tick at odd * rates, and it's expensive to acqurie. */ pr_ticks = _PR_UNIX_GetInterval(); } return pr_ticks;} /* _MD_IrixGetInterval */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -