📄 solaris.c
字号:
ts.tv_nsec = 1000000*n; if (syscall(SYS_nanosleep, &ts, 0, 0) < 0) { PR_ASSERT(0); }} #define VALID_SP(sp, bottom, top) \ (((uint_t)(sp)) > ((uint_t)(bottom)) && ((uint_t)(sp)) < ((uint_t)(top)))void solaris_record_regs(PRThread *t, prstatus_t *lwpstatus){#ifdef sparc long *regs = (long *)&t->md.context.uc_mcontext.gregs[0]; PR_ASSERT(_PR_IS_GCABLE_THREAD(t)); PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[REG_G7]); t->md.sp = lwpstatus->pr_reg[REG_SP]; PR_ASSERT(VALID_SP(t->md.sp, t->stack->stackBottom, t->stack->stackTop)); regs[0] = lwpstatus->pr_reg[R_G1]; regs[1] = lwpstatus->pr_reg[R_G2]; regs[2] = lwpstatus->pr_reg[R_G3]; regs[3] = lwpstatus->pr_reg[R_G4]; regs[4] = lwpstatus->pr_reg[R_O0]; regs[5] = lwpstatus->pr_reg[R_O1]; regs[6] = lwpstatus->pr_reg[R_O2]; regs[7] = lwpstatus->pr_reg[R_O3]; regs[8] = lwpstatus->pr_reg[R_O4]; regs[9] = lwpstatus->pr_reg[R_O5]; regs[10] = lwpstatus->pr_reg[R_O6]; regs[11] = lwpstatus->pr_reg[R_O7];#elif defined(i386) /* * To be implemented and tested */ PR_ASSERT(0); PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[GS]); t->md.sp = lwpstatus->pr_reg[UESP];#endif} void solaris_preempt_off(){ sigset_t set; (void)sigfillset(&set); syscall(SYS_sigprocmask, SIG_SETMASK, &set, &old_mask);}void solaris_preempt_on(){ syscall(SYS_sigprocmask, SIG_SETMASK, &old_mask, NULL); }int solaris_open_main_proc_fd(){ char buf[30]; int fd; /* Not locked, so must be created while threads coming up */ PR_snprintf(buf, sizeof(buf), "/proc/%ld", getpid()); if ( (fd = syscall(SYS_open, buf, O_RDONLY)) < 0) { return -1; } return fd;}/* Return a file descriptor for the /proc entry corresponding to the * given lwp. */int solaris_open_lwp(lwpid_t id, int lwp_main_proc_fd){ int result; if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCOPENLWP, &id)) <0) return -1; /* exited??? */ return result;}void _MD_Begin_SuspendAll(){ solaris_preempt_off(); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin_SuspendAll\n")); /* run at highest prio so I cannot be preempted */ thr_getprio(thr_self(), &gcprio); thr_setprio(thr_self(), 0x7fffffff); suspendAllOn = PR_TRUE; suspendAllThread = _PR_MD_CURRENT_THREAD();}void _MD_End_SuspendAll(){}void _MD_End_ResumeAll(){ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End_ResumeAll\n")); thr_setprio(thr_self(), gcprio); solaris_preempt_on(); suspendAllThread = NULL; suspendAllOn = PR_FALSE;}void _MD_Suspend(PRThread *thr){ int lwp_fd, result; prstatus_t lwpstatus; int lwp_main_proc_fd = 0; if (!_PR_IS_GCABLE_THREAD(thr) || !suspendAllOn){ /*XXX When the suspendAllOn is set, we will be trying to do lwp_suspend * during that time we can't call any thread lib or libc calls. Hence * make sure that no suspension is requested for Non gcable thread * during suspendAllOn */ PR_ASSERT(!suspendAllOn); thr_suspend(thr->md.handle); return; } /* XXX Primordial thread can't be bound to an lwp, hence there is no * way we can assume that we can get the lwp status for primordial * thread reliably. Hence we skip this for primordial thread, hoping * that the SP is saved during lock and cond. wait. * XXX - Again this is concern only for java interpreter, not for the * server, 'cause primordial thread in the server does not do java work */ if (thr->flags & _PR_PRIMORDIAL) return; /* XXX Important Note: If the start function of a thread is not called, * lwpid is -1. Then, skip this thread. This thread will get caught * in PR_NativeRunThread before calling the start function, because * we hold the pr_activeLock during suspend/resume */ /* if the thread is not started yet then don't do anything */ if (!suspendAllOn || thr->md.lwpid == -1) return; if (_lwp_suspend(thr->md.lwpid) < 0) { PR_ASSERT(0); return; } if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) { PR_ASSERT(0); return; /* XXXMB ARGH, we're hosed! */ } if ( (lwp_fd = solaris_open_lwp(thr->md.lwpid, lwp_main_proc_fd)) < 0) { PR_ASSERT(0); close(lwp_main_proc_fd); return; } if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) { /* Hopefully the thread just died... */ close(lwp_fd); close(lwp_main_proc_fd); return; } while ( !(lwpstatus.pr_flags & PR_STOPPED) ) { if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) { PR_ASSERT(0); /* ARGH SOMETHING WRONG! */ break; } solaris_msec_sleep(1); } solaris_record_regs(thr, &lwpstatus); close(lwp_fd); close(lwp_main_proc_fd);}#ifdef OLD_CODEvoid _MD_SuspendAll(){ /* On solaris there are threads, and there are LWPs. * Calling _PR_DoSingleThread would freeze all of the threads bound to LWPs * but not necessarily stop all LWPs (for example if someone did * an attachthread of a thread which was not bound to an LWP). * So now go through all the LWPs for this process and freeze them. * * Note that if any thread which is capable of having the GC run on it must * had better be a LWP with a single bound thread on it. Otherwise, this * might not stop that thread from being run. */ PRThread *current = _PR_MD_CURRENT_THREAD(); prstatus_t status, lwpstatus; int result, index, lwp_fd; lwpid_t me = _lwp_self(); int err; int lwp_main_proc_fd; solaris_preempt_off(); /* run at highest prio so I cannot be preempted */ thr_getprio(thr_self(), &gcprio); thr_setprio(thr_self(), 0x7fffffff); current->md.sp = (uint_t)&me; /* set my own stack pointer */ if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) { PR_ASSERT(0); solaris_preempt_on(); return; /* XXXMB ARGH, we're hosed! */ } if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCSTATUS, &status)) < 0) { err = errno; PR_ASSERT(0); goto failure; /* XXXMB ARGH, we're hosed! */ } num_lwps = status.pr_nlwp; if ( (all_lwps = (lwpid_t *)PR_MALLOC((num_lwps+1) * sizeof(lwpid_t)))==NULL) { PR_ASSERT(0); goto failure; /* XXXMB ARGH, we're hosed! */ } if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCLWPIDS, all_lwps)) < 0) { PR_ASSERT(0); PR_DELETE(all_lwps); goto failure; /* XXXMB ARGH, we're hosed! */ } for (index=0; index< num_lwps; index++) { if (all_lwps[index] != me) { if (_lwp_suspend(all_lwps[index]) < 0) { /* could happen if lwp exited */ all_lwps[index] = me; /* dummy it up */ } } } /* Turns out that lwp_suspend is not a blocking call. * Go through the list and make sure they are all stopped. */ for (index=0; index< num_lwps; index++) { if (all_lwps[index] != me) { if ( (lwp_fd = solaris_open_lwp(all_lwps[index], lwp_main_proc_fd)) < 0) { PR_ASSERT(0); PR_DELETE(all_lwps); all_lwps = NULL; goto failure; /* XXXMB ARGH, we're hosed! */ } if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) { /* Hopefully the thread just died... */ close(lwp_fd); continue; } while ( !(lwpstatus.pr_flags & PR_STOPPED) ) { if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) { PR_ASSERT(0); /* ARGH SOMETHING WRONG! */ break; } solaris_msec_sleep(1); } solaris_record_regs(&lwpstatus); close(lwp_fd); } } close(lwp_main_proc_fd); return;failure: solaris_preempt_on(); thr_setprio(thr_self(), gcprio); close(lwp_main_proc_fd); return;}void _MD_ResumeAll(){ int i; lwpid_t me = _lwp_self(); for (i=0; i < num_lwps; i++) { if (all_lwps[i] == me) continue; if ( _lwp_continue(all_lwps[i]) < 0) { PR_ASSERT(0); /* ARGH, we are hosed! */ } } /* restore priority and sigmask */ thr_setprio(thr_self(), gcprio); solaris_preempt_on(); PR_DELETE(all_lwps); all_lwps = NULL;}#endif /* OLD_CODE */#ifdef USE_SETJMPPRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np){ if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t);}#elsePRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np){ if (isCurrent) { (void) getcontext(CONTEXT(t)); } *np = NGREG; return (PRWord*) &t->md.context.uc_mcontext.gregs[0];}#endif /* USE_SETJMP */#else /* _PR_GLOBAL_THREADS_ONLY */#if defined(_PR_LOCAL_THREADS_ONLY)void _MD_EarlyInit(void){}void _MD_SolarisInit(){ _PR_UnixInit();}void_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri){ return;}PRStatus_MD_InitializeThread(PRThread *thread){ return PR_SUCCESS;}PRStatus_MD_WAIT(PRThread *thread, PRIntervalTime ticks){ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS;}PRStatus_MD_WAKEUP_WAITER(PRThread *thread){ PR_ASSERT((thread == NULL) || (!(thread->flags & _PR_GLOBAL_SCOPE))); return PR_SUCCESS;}/* These functions should not be called for Solaris */void_MD_YIELD(void){ PR_NOT_REACHED("_MD_YIELD should not be called for Solaris");}PRStatus_MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize){ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Solaris"); return(PR_FAILURE);}#ifdef USE_SETJMPPRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np){ if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t);}#elsePRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np){ if (isCurrent) { (void) getcontext(CONTEXT(t)); } *np = NGREG; return (PRWord*) &t->md.context.uc_mcontext.gregs[0];}#endif /* USE_SETJMP */#endif /* _PR_LOCAL_THREADS_ONLY */#endif /* _PR_GLOBAL_THREADS_ONLY */#ifndef _PR_PTHREADS#if defined(i386) && defined(SOLARIS2_4)/* * Because clock_gettime() on Solaris/x86 2.4 always generates a * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(), * which is implemented using gettimeofday(). */int_pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp){ struct timeval tv; if (clock_id != CLOCK_REALTIME) { errno = EINVAL; return -1; } gettimeofday(&tv, NULL); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; return 0;}#endif /* i386 && SOLARIS2_4 */#endif /* _PR_PTHREADS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -