📄 disp.c
字号:
struct context_t *scp; int restore_context; struct context_t *oscp; pthread_cond_t *cond;{ register pthread_t p = mac_pthread_self(); sigset_t omask; register int saved_errno = errno; register struct frame *framep; register int old_pc = scp->sc_pc; register int old_sp = scp->sc_sp;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) register int old_bp = scp->sc_fp;#endif register int new_sp = p->osp; register int new_pc = p->opc;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) register int new_bp = p->obp;#endif void pthread_handle_pending_signals_wrapper(); PTRACEIN; PDEBUG(PDBG_SIGNAL,"scp->sp: 0x%x scp->pc: 0x%x (%x)",scp->sc_sp,scp->sc_pc,scp); pthread_sigcpyset2set(&omask, &scp->sc_mask); if (cond) pthread_cond_wait_terminate(cond); CLEAR_KERNEL_FLAG; infop->si_signo = sig; (*user_handler)(sig, infop, scp); SET_KERNEL_FLAG; errno = saved_errno; if (restore_context) { if (old_pc != scp->sc_pc) { PDEBUG(PDBG_SIGNAL,"restore_context sp: 0x%x pc: pthread_clear_kernel_flag_wrapper",old_sp); p->context[THREAD_JB_SP] = old_sp; p->context[THREAD_JB_PC] = (int) pthread_clear_kernel_flag_wrapper; new_sp = scp->sc_sp; new_pc = scp->sc_pc; new_pc -= RETURN_OFFSET; } else { PDEBUG(PDBG_SIGNAL,"restore_context sp: 0x%x pc: 0x%x",scp->sc_sp,scp->sc_pc); p->context[THREAD_JB_SP] = scp->sc_sp; p->context[THREAD_JB_PC] = scp->sc_pc; } p->context[THREAD_JB_PC] -= RETURN_OFFSET; pthread_sigcpyset2set(smask, &scp->sc_mask); } else { pthread_sigcpyset2set(smask, &scp->sc_mask); pthread_sigcpyset2set(&scp->sc_mask, &omask); } pthread_sigcpyset2set(&p->mask, smask); pthread_sigcpyset2set(smask, &p->pending); pthread_sigaddset2set(smask, &pending_signals); pthread_sigdelset2set(smask, &p->mask); //p->terrno = errno; if (restore_context) { old_sp = p->context[THREAD_JB_SP];#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) old_bp = p->context[THREAD_JB_BP];#endif old_pc = p->context[THREAD_JB_PC]; } if (pthread_signonemptyset(smask)) if (!SAVE_CONTEXT(p)) pthread_handle_pending_signals_wrapper(); /* never returns from call */ else if (restore_context) { p->context[THREAD_JB_SP] = old_sp;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) p->context[THREAD_JB_BP] = old_bp;#endif p->context[THREAD_JB_PC] = old_pc; } p->nscp = oscp; if (restore_context) { p->osp = new_sp;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) p->obp = new_bp;#endif p->opc = new_pc; } else { p->context[THREAD_JB_SP] = new_sp;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__) p->context[THREAD_JB_BP] = new_bp;#endif p->context[THREAD_JB_PC] = new_pc;#ifdef ASM_SETJMP p->context[THREAD_JB_PC] -= RETURN_OFFSET;#endif /* ASM_SETJMP */ } pthread_sched(); /* never returns from call */}/*------------------------------------------------------------*//* * pthread_handle_pending_signals_wrapper - * change to temp stack and call pthread_handle_pending_signals() * then jumps into regular scheduler * assumes SET_KERNEL_FLAG */void pthread_handle_pending_signals_wrapper(){ static pthread_t old; old = mac_pthread_self(); /* * always flush windows before the stack is changed to preserve the proper * linking of frame pointers */ SWITCH_TO_STACK(SA((int) pthread_tempstack_top) - SA(WINDOWSIZE), old); pthread_handle_pending_signals(); SWITCH_TO_STACK(old_stack_ptr, old); pthread_sched(); /* never returns from call */}/*------------------------------------------------------------*//* * pthread_signal_sched - * change to temp stack and call pthread_handle_one_process_signal(sig) * then jumps into regular scheduler * This is called by the universal signal handler to minimize calls * to set the process mask which is an expensive UNIX system call. * assumes SET_KERNEL_FLAG */void pthread_signal_sched(sig, code) int sig, code;{ static pthread_t old; PTRACEIN; old = mac_pthread_self(); old->sig = sig; old->code = code; /* * always flush windows before the stack is changed to preserve the proper * linking of frame pointers */ SWITCH_TO_STACK(SA((int) pthread_tempstack_top) - SA(WINDOWSIZE), old); pthread_handle_one_process_signal(old->sig, old->code); SWITCH_TO_STACK(old_stack_ptr, old); pthread_sched(); /* never returns from call */} #ifdef _ASM/*------------------------------------------------------------*//* * setjmp - */int setjmp(env) jmp_buf env;{ return(sigsetjmp(env, TRUE));}/*------------------------------------------------------------*//* * longjmp - */void longjmp(env, val) jmp_buf env; int val;{ siglongjmp(env, val);}/*------------------------------------------------------------*//* * sigsetjmp - */int sigsetjmp(env, savemask) sigjmp_buf env; int savemask;{ env[THREAD_JB_SP] = sp; env[THREAD_JB_PC] = pc; env[THREAD_JB_SVMASK] = savemask; if (env[THREAD_JB_SVMASK]) pthread_sigcpyset2set(&env[THREAD_JB_MASK], &mac_pthread_self()->mask); return(0);}/*------------------------------------------------------------*//* * siglongjmp - */void siglongjmp(env, val) sigjmp_buf env; int val;{ int new_sp; if (env[THREAD_JB_SVMASK]) sigprocmask(SIG_SETMASK, &env[SV_MASK], (struct sigaction *) NULL); ST_FLUSH_WINDOWS(); fp = env[THREAD_JB_SP]; pc = env[THREAD_JB_PC]; if (val == 0) val = 1; ret;}#ifdef NOERR_CHECK/*------------------------------------------------------------*//* * pthread_mutex_lock - */int pthread_mutex_lock(mutex) pthread_mutex_t *mutex;{#ifdef _POSIX_THREADS_PRIO_PROTECT if (mutex->protocol == PTHREAD_PRIO_PROTECT) goto slow_lock;#endif if (test_and_set(&mutex->lock)) { mutex->owner = mac_pthread_self(); return(0); } /* * if the queue is not empty or if someone holds the mutex, * we need to enter the kernel to queue up. */#ifdef _POSIX_THREADS_PRIO_PROTECTslow_lock:#endif return(slow_mutex_lock(mutex));}/*------------------------------------------------------------*//* * pthread_mutex_trylock - */int pthread_mutex_trylock(mutex) pthread_mutex_t *mutex;{#ifdef _POSIX_THREADS_PRIO_PROTECT if (mutex->protocol == PTHREAD_PRIO_PROTECT) return slow_mutex_trylock(mutex);#endif if (test_and_set(&mutex->lock)) { mutex->owner = mac_pthread_self(); return(EBUSY); } return(0);}/*------------------------------------------------------------*//* * pthread_mutex_unlock - */int pthread_mutex_unlock(mutex) pthread_mutex_t *mutex;{#ifdef _POSIX_THREADS_PRIO_PROTECT if (mutex->protocol == PTHREAD_PRIO_PROTECT) goto slow_unlock;#endif mutex->owner = NO_PTHREAD; if (mutex->queue.head == NULL) { mutex->lock = FALSE; /* * We have to test the queue again since there is a window * between the previous test and the unlocking of the mutex * where someone could have queued up. */ if (mutex->queue.head == NULL) return(0); if (test_and_set(&mutex->lock)) /* * if the test & set is not successful, someone else must * have acquired the mutex and will handle proper queueing, * so we're done. */ return(0); } /* * if the queue is not empty, we need to enter the kernel to unqueue. */#ifdef _POSIX_THREADS_PRIO_PROTECTslow_unlock:#endif return(slow_mutex_unlock(mutex));}#endif /* NOERR_CHECK */#ifndef CLEANUP_HEAP/*------------------------------------------------------------*//* * pthread_cleanup_push - */int pthread_cleanup_push(func, arg) pthread_func_t func; any_t arg;{ cleanup_t *new;#ifndef C_INTERFACE sp -= SA(sizeof(*new)+SA(MINFRAME)-WINDOWSIZE);#else sp -= SA(sizeof(*new));#endif new = sp + SA(MINFRAME); pthread_cleanup_push_body(func, arg, new);}/*------------------------------------------------------------*//* * pthread_cleanup_pop - */int pthread_cleanup_pop(execute) int execute;{ pthread_cleanup_pop_body(execute);#ifndef C_INTERFACE sp += SA(sizeof(*new)+SA(MINFRAME)-WINDOWSIZE);#else sp += SA(sizeof(*new));#endif}#endif /* !CLEANUP_HEAP */#ifndef SOLARIS/*------------------------------------------------------------*//* * start_float - */void start_float(){ pthread_init();}#endif /* !SOLARIS */#endif /* _ASM */#endif /* C_CONTEXT_SWITCH *//*------------------------------------------------------------*//* * process_exit - switches stacks to process stack and * calls UNIX exit with parameter status */static void process_exit(){ CLEAR_KERNEL_FLAG; exit((int) status);}/*------------------------------------------------------------*//* * pthread_process_exit - switches stacks to process stack and * calls UNIX exit with parameter status */void pthread_process_exit(p_status) int p_status;{ status = p_status; /* * always flush windows before the stack is changed to preserve the proper * linking of frame pointers */ thread_setjmp(stack_env, FALSE); stack_env[THREAD_JB_SP] = (int) process_stack_base; stack_env[THREAD_JB_PC] = (int) process_exit;#if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH) stack_env[THREAD_JB_PC] -= RETURN_OFFSET;#endif /* defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH) */ thread_longjmp(stack_env, p_status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -