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

📄 pth_mctx.c

📁 Linux下的中文输入法
💻 C
📖 第 1 页 / 共 2 页
字号:
    ss.ss_sp    = pth_skaddr(sigaltstack, sk_addr_lo, sk_addr_hi-sk_addr_lo);    ss.ss_size  = pth_sksize(sigaltstack, sk_addr_lo, sk_addr_hi-sk_addr_lo);    ss.ss_flags = 0;    if (sigaltstack(&ss, &oss) < 0)        return FALSE;#elif PTH_MCTX_STK(ss)    ss.ss_sp = pth_skaddr(sigstack, sk_addr_lo, sk_addr_hi-sk_addr_lo);    ss.ss_onstack = 0;    if (sigstack(&ss, &oss) < 0)        return FALSE;#else#error "unknown mctx stack setup"#endif    /*     * Now transfer control onto the signal stack and set it up.     * It will return immediately via "return" after the setjmp()     * was performed. Be careful here with race conditions.  The     * signal can be delivered the first time sigsuspend() is     * called.     */    mctx_called = FALSE;    kill(getpid(), SIGUSR1);    sigfillset(&sigs);    sigdelset(&sigs, SIGUSR1);    while (!mctx_called)        sigsuspend(&sigs);    /*     * Inform the system that we are back off the signal stack by     * removing the alternative signal stack. Be careful here: It     * first has to be disabled, before it can be removed.     */#if PTH_MCTX_STK(sas)    sigaltstack(NULL, &ss);    ss.ss_flags = SS_DISABLE;    if (sigaltstack(&ss, NULL) < 0)        return FALSE;    sigaltstack(NULL, &ss);    if (!(ss.ss_flags & SS_DISABLE))        return pth_error(FALSE, EIO);    if (!(oss.ss_flags & SS_DISABLE))        sigaltstack(&oss, NULL);#elif PTH_MCTX_STK(ss)    if (sigstack(&oss, NULL))        return FALSE;#endif    /*     * Restore the old SIGUSR1 signal handler and mask     */    sigaction(SIGUSR1, &osa, NULL);    pth_sc(sigprocmask)(SIG_SETMASK, &osigs, NULL);    /*     * Initialize additional ingredients of the machine     * context structure.     */#if PTH_MCTX_DSP(sjlje)    sigemptyset(&mctx->block);#endif    sigemptyset(&mctx->sigs);    mctx->error = 0;    /*     * Tell the trampoline and bootstrap function where to dump     * the new machine context, and what to do afterwards...     */    mctx_creating      = mctx;    mctx_creating_func = func;    memcpy((void *)&mctx_creating_sigs, &osigs, sizeof(sigset_t));    /*     * Now enter the trampoline again, but this time not as a signal     * handler. Instead we jump into it directly. The functionally     * redundant ping-pong pointer arithmentic is neccessary to avoid     * type-conversion warnings related to the `volatile' qualifier and     * the fact that `jmp_buf' usually is an array type.     */    if (pth_mctx_save((pth_mctx_t *)&mctx_caller) == 0)        longjmp(*((jmp_buf *)&mctx_trampoline), 1);    /*     * Ok, we returned again, so now we're finished     */    pth_debug1("pth_mctx_set: leave");    return TRUE;}/* trampoline signal handler */static void pth_mctx_set_trampoline(int sig){    /*     * Save current machine state and _immediately_ go back with     * a standard "return" (to stop the signal handler situation)     * to let him remove the stack again. Notice that we really     * have do a normal "return" here, or the OS would consider     * the thread to be running on a signal stack which isn't     * good (for instance it wouldn't allow us to spawn a thread     * from within a thread, etc.)     *     * The functionally redundant ping-pong pointer arithmentic is again     * neccessary to avoid type-conversion warnings related to the     * `volatile' qualifier and the fact that `jmp_buf' usually is an     * array type.     *     * Additionally notice that we INTENTIONALLY DO NOT USE pth_mctx_save()     * here. Instead we use a plain setjmp(3) call because we have to make     * sure the alternate signal stack environment is _NOT_ saved into the     * machine context (which can be the case for sigsetjmp(3) on some     * platforms).     */    if (setjmp(*((jmp_buf *)&mctx_trampoline)) == 0) {        pth_debug1("pth_mctx_set_trampoline: return to caller");        mctx_called = TRUE;        return;    }    pth_debug1("pth_mctx_set_trampoline: reentered from caller");    /*     * Ok, the caller has longjmp'ed back to us, so now prepare     * us for the real machine state switching. We have to jump     * into another function here to get a new stack context for     * the auto variables (which have to be auto-variables     * because the start of the thread happens later). Else with     * PIC (i.e. Position Independent Code which is used when PTH     * is built as a shared library) most platforms would     * horrible core dump as experience showed.     */    pth_mctx_set_bootstrap();}/* boot function */static void pth_mctx_set_bootstrap(void){    pth_mctx_t * volatile mctx_starting;    void (* volatile mctx_starting_func)(void);    /*     * Switch to the final signal mask (inherited from parent)     */    pth_sc(sigprocmask)(SIG_SETMASK, (sigset_t *)&mctx_creating_sigs, NULL);    /*     * Move startup details from static storage to local auto     * variables which is necessary because it has to survive in     * a local context until the thread is scheduled for real.     */    mctx_starting      = mctx_creating;    mctx_starting_func = mctx_creating_func;    /*     * Save current machine state (on new stack) and     * go back to caller until we're scheduled for real...     */    pth_debug1("pth_mctx_set_trampoline_jumpin: switch back to caller");    pth_mctx_switch((pth_mctx_t *)mctx_starting, (pth_mctx_t *)&mctx_caller);    /*     * The new thread is now running: GREAT!     * Now we just invoke its init function....     */    pth_debug1("pth_mctx_set_trampoline_jumpin: reentered from scheduler");    mctx_starting_func();    abort();}#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljlx)/* * VARIANT 3: LINUX SPECIFIC JMP_BUF FIDDLING * * Oh hell, I really love it when Linux guys talk about their "POSIX * compliant system". It's far away from POSIX compliant, IMHO. Autoconf * finds sigstack/sigaltstack() on Linux, yes. But it doesn't work. Why? * Because on Linux below version 2.2 and glibc versions below 2.1 these * two functions are nothing more than silly stub functions which always * return just -1. Very useful, yeah... */#include <features.h>intern int pth_mctx_set(    pth_mctx_t *mctx, void (*func)(void), char *sk_addr_lo, char *sk_addr_hi){    pth_mctx_save(mctx);#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \    && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(JB_PC) && defined(JB_SP)    mctx->jb[0].__jmpbuf[JB_PC] = (int)func;    mctx->jb[0].__jmpbuf[JB_SP] = (int)sk_addr_hi;#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \    && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(__mc68000__)    mctx->jb[0].__jmpbuf[0].__aregs[0] = (long int)func;    mctx->jb[0].__jmpbuf[0].__sp = (int *)sk_addr_hi;#elif defined(__GNU_LIBRARY__) && defined(__i386__)    mctx->jb[0].__jmpbuf[0].__pc = (char *)func;    mctx->jb[0].__jmpbuf[0].__sp = sk_addr_hi;#else#error "Unsupported Linux (g)libc version and/or platform"#endif    sigemptyset(&mctx->sigs);    mctx->error = 0;    return TRUE;}/* * VARIANT 4: INTERACTIVE SPECIFIC JMP_BUF FIDDLING * * No wonder, Interactive Unix (ISC) 4.x contains Microsoft code, so * it's clear that this beast lacks both sigstack and sigaltstack (about * makecontext we not even have to talk). So our only chance is to * fiddle with it's jmp_buf ingredients, of course. We support only i386 * boxes. */#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljisc)intern intpth_mctx_set(pth_mctx_t *mctx, void (*func)(void),                     char *sk_addr_lo, char *sk_addr_hi){    pth_mctx_save(mctx);#if i386    mctx->jb[4] = (int)sk_addr_hi - sizeof(mctx->jb);    mctx->jb[5] = (int)func;#else#error "Unsupported ISC architecture"#endif    sigemptyset(&mctx->sigs);    mctx->error = 0;    return TRUE;}/* * VARIANT 5: WIN32 SPECIFIC JMP_BUF FIDDLING * * Oh hell, Win32 has setjmp(3), but no sigstack(2) or sigaltstack(2). * So we have to fiddle around with the jmp_buf here too... */#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljw32)intern intpth_mctx_set(pth_mctx_t *mctx, void (*func)(void),                     char *sk_addr_lo, char *sk_addr_hi){    pth_mctx_save(mctx);#if i386    mctx->jb[7] = (int)sk_addr_hi;    mctx->jb[8] = (int)func;#else#error "Unsupported Win32 architecture"#endif    sigemptyset(&mctx->sigs);    mctx->error = 0;    return TRUE;}/* * VARIANT X: JMP_BUF FIDDLING FOR ONE MORE ESOTERIC OS * Add the jmp_buf fiddling for your esoteric OS here... *#elif PTH_MCTX_MTH(sjlj) && PTH_MCTX_DSP(sjljeso)intern intpth_mctx_set(pth_mctx_t *mctx, void (*func)(void),             char *sk_addr_lo, char *sk_addr_hi){    pth_mctx_save(mctx);    sigemptyset(&mctx->sigs);    mctx->error = 0;    ...start hacking here...    mctx->.... = func;    mctx->.... = sk_addr_hi;    mctx->.... = sk_addr_lo;    return TRUE;}*/#else#error "unknown mctx method"#endif

⌨️ 快捷键说明

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