Changeset 14671
- Timestamp:
- Mar 7, 2011, 8:02:07 PM (14 years ago)
- File:
-
- 1 edited
-
trunk/source/lisp-kernel/x86-exceptions.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/source/lisp-kernel/x86-exceptions.c
r14619 r14671 2925 2925 #ifdef DARWIN 2926 2926 2927 #ifdef X8664 2928 #define ts_pc(t) t->__rip 2929 typedef x86_thread_state64_t native_thread_state_t; 2930 #define NATIVE_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT 2931 #define NATIVE_THREAD_STATE_FLAVOR x86_THREAD_STATE64 2932 typedef x86_float_state64_t native_float_state_t; 2933 #define NATIVE_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT 2934 #define NATIVE_FLOAT_STATE_FLAVOR x86_FLOAT_STATE64 2935 typedef x86_exception_state64_t native_exception_state_t; 2936 #define NATIVE_EXCEPTION_STATE_COUNT x86_EXCEPTION_STATE64_COUNT 2937 #define NATIVE_EXCEPTION_STATE_FLAVOR x86_EXCEPTION_STATE64 2938 #else 2939 #define ts_pc(t) t->__eip 2940 typedef x86_thread_state32_t native_thread_state_t; 2941 #define NATIVE_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT 2942 #define NATIVE_THREAD_STATE_FLAVOR x86_THREAD_STATE32 2943 typedef x86_float_state32_t native_float_state_t; 2944 #define NATIVE_FLOAT_STATE_COUNT x86_FLOAT_STATE32_COUNT 2945 #define NATIVE_FLOAT_STATE_FLAVOR x86_FLOAT_STATE32 2946 typedef x86_exception_state32_t native_exception_state_t; 2947 #define NATIVE_EXCEPTION_STATE_COUNT x86_EXCEPTION_STATE32_COUNT 2948 #define NATIVE_EXCEPTION_STATE_FLAVOR x86_EXCEPTION_STATE32 2949 #endif 2950 2927 2951 #define TCR_FROM_EXCEPTION_PORT(p) ((TCR *)((natural)p)) 2928 2952 #define TCR_TO_EXCEPTION_PORT(tcr) ((mach_port_t)((natural)(tcr))) … … 3028 3052 3029 3053 void 3030 restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext )3054 restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext, native_thread_state_t *ts) 3031 3055 { 3032 3056 kern_return_t kret; … … 3038 3062 3039 3063 /* Set the thread's FP state from the pseudosigcontext */ 3040 #if WORD_SIZE == 643041 3064 kret = thread_set_state(thread, 3042 x86_FLOAT_STATE64,3065 NATIVE_FLOAT_STATE_FLAVOR, 3043 3066 (thread_state_t)&(mc->__fs), 3044 x86_FLOAT_STATE64_COUNT); 3045 #else 3046 kret = thread_set_state(thread, 3047 x86_FLOAT_STATE32, 3048 (thread_state_t)&(mc->__fs), 3049 x86_FLOAT_STATE32_COUNT); 3050 #endif 3067 NATIVE_FLOAT_STATE_COUNT); 3051 3068 MACH_CHECK_ERROR("setting thread FP state", kret); 3052 3053 /* The thread'll be as good as new ... */ 3054 #if WORD_SIZE == 64 3055 kret = thread_set_state(thread, 3056 x86_THREAD_STATE64, 3057 (thread_state_t)&(mc->__ss), 3058 x86_THREAD_STATE64_COUNT); 3059 #else 3060 kret = thread_set_state(thread, 3061 x86_THREAD_STATE32, 3062 (thread_state_t)&(mc->__ss), 3063 x86_THREAD_STATE32_COUNT); 3064 #endif 3065 MACH_CHECK_ERROR("setting thread state", kret); 3069 *ts = mc->__ss; 3066 3070 } 3067 3071 3068 /* This code runs in the exception handling thread, in response3069 to an attempt to execute the UU0 at "pseudo_sigreturn" (e.g.,3070 in response to a call to pseudo_sigreturn() from the specified3071 user thread.3072 Find that context (the user thread's R3 points to it), then3073 use that context to set the user thread's state. When this3074 function's caller returns, the Mach kernel will resume the3075 user thread.3076 */3077 3078 3072 kern_return_t 3079 do_pseudo_sigreturn(mach_port_t thread, TCR *tcr )3073 do_pseudo_sigreturn(mach_port_t thread, TCR *tcr, native_thread_state_t *out) 3080 3074 { 3081 3075 ExceptionInformation *xp; … … 3088 3082 tcr->pending_exception_context = NULL; 3089 3083 tcr->valence = TCR_STATE_LISP; 3090 restore_mach_thread_state(thread, xp );3084 restore_mach_thread_state(thread, xp, out); 3091 3085 raise_pending_interrupt(tcr); 3092 3086 } else { … … 3104 3098 siginfo_t **info_ptr, 3105 3099 TCR *tcr, 3106 #ifdef X8664 3107 x86_thread_state64_t *ts 3108 #else 3109 x86_thread_state32_t *ts 3110 #endif 3100 native_thread_state_t *ts 3111 3101 ) 3112 3102 { … … 3138 3128 memmove(&(mc->__ss),ts,sizeof(*ts)); 3139 3129 3140 #ifdef X8664 3141 thread_state_count = x86_FLOAT_STATE64_COUNT; 3130 thread_state_count = NATIVE_FLOAT_STATE_COUNT; 3142 3131 thread_get_state(thread, 3143 x86_FLOAT_STATE64,3132 NATIVE_FLOAT_STATE_FLAVOR, 3144 3133 (thread_state_t)&(mc->__fs), 3145 3134 &thread_state_count); 3146 3135 3147 thread_state_count = x86_EXCEPTION_STATE64_COUNT;3136 thread_state_count = NATIVE_EXCEPTION_STATE_COUNT; 3148 3137 thread_get_state(thread, 3149 x86_EXCEPTION_STATE64,3138 NATIVE_EXCEPTION_STATE_FLAVOR, 3150 3139 (thread_state_t)&(mc->__es), 3151 3140 &thread_state_count); 3152 #else3153 thread_state_count = x86_FLOAT_STATE32_COUNT;3154 thread_get_state(thread,3155 x86_FLOAT_STATE32,3156 (thread_state_t)&(mc->__fs),3157 &thread_state_count);3158 3159 thread_state_count = x86_EXCEPTION_STATE32_COUNT;3160 thread_get_state(thread,3161 x86_EXCEPTION_STATE32,3162 (thread_state_t)&(mc->__es),3163 &thread_state_count);3164 #endif3165 3141 3166 3142 … … 3195 3171 int code, 3196 3172 TCR *tcr, 3197 #ifdef X8664 3198 x86_thread_state64_t *ts 3199 #else 3200 x86_thread_state32_t *ts 3201 #endif 3173 native_thread_state_t *ts, 3174 native_thread_state_t *new_ts 3202 3175 ) 3203 3176 { 3204 #ifdef X86643205 x86_thread_state64_t new_ts;3206 #else3207 x86_thread_state32_t new_ts;3208 #endif3209 3177 ExceptionInformation *pseudosigcontext; 3210 3178 int old_valence = tcr->valence; … … 3238 3206 3239 3207 #ifdef X8664 3240 new_ts .__rip = (natural) handler_address;3208 new_ts->__rip = (natural) handler_address; 3241 3209 stackpp = (natural *)stackp; 3242 3210 *--stackpp = (natural)pseudo_sigreturn; 3243 3211 stackp = (natural)stackpp; 3244 new_ts.__rdi = signum; 3245 new_ts.__rsi = (natural)info; 3246 new_ts.__rdx = (natural)pseudosigcontext; 3247 new_ts.__rcx = (natural)tcr; 3248 new_ts.__r8 = (natural)old_valence; 3249 new_ts.__rsp = stackp; 3250 new_ts.__rflags = ts->__rflags; 3251 #else 3252 #define USER_CS 0x17 3253 #define USER_DS 0x1f 3254 bzero(&new_ts, sizeof(new_ts)); 3255 new_ts.__cs = ts->__cs; 3256 new_ts.__ss = ts->__ss; 3257 new_ts.__ds = ts->__ds; 3258 new_ts.__es = ts->__es; 3259 new_ts.__fs = ts->__fs; 3260 new_ts.__gs = ts->__gs; 3261 3262 new_ts.__eip = (natural)handler_address; 3212 new_ts->__rdi = signum; 3213 new_ts->__rsi = (natural)info; 3214 new_ts->__rdx = (natural)pseudosigcontext; 3215 new_ts->__rcx = (natural)tcr; 3216 new_ts->__r8 = (natural)old_valence; 3217 new_ts->__rsp = stackp; 3218 new_ts->__rflags = ts->__rflags; 3219 #else 3220 bzero(new_ts, sizeof(*new_ts)); 3221 new_ts->__cs = ts->__cs; 3222 new_ts->__ss = ts->__ss; 3223 new_ts->__ds = ts->__ds; 3224 new_ts->__es = ts->__es; 3225 new_ts->__fs = ts->__fs; 3226 new_ts->__gs = ts->__gs; 3227 3228 new_ts->__eip = (natural)handler_address; 3263 3229 stackpp = (natural *)stackp; 3264 3230 *--stackpp = 0; /* alignment */ … … 3272 3238 *--stackpp = (natural)pseudo_sigreturn; 3273 3239 stackp = (natural)stackpp; 3274 new_ts.__esp = stackp; 3275 new_ts.__eflags = ts->__eflags; 3276 #endif 3277 3278 #ifdef X8664 3279 thread_set_state(thread, 3280 x86_THREAD_STATE64, 3281 (thread_state_t)&new_ts, 3282 x86_THREAD_STATE64_COUNT); 3283 #else 3284 thread_set_state(thread, 3285 x86_THREAD_STATE32, 3286 (thread_state_t)&new_ts, 3287 x86_THREAD_STATE32_COUNT); 3240 new_ts->__esp = stackp; 3241 new_ts->__eflags = ts->__eflags; 3288 3242 #endif 3289 3243 #ifdef DEBUG_MACH_EXCEPTIONS … … 3316 3270 */ 3317 3271 3318 /* We need the thread's state earlier on x86_64 than we did on PPC; 3319 the PC won't fit in code_vector[1]. We shouldn't try to get it 3320 lazily (via catch_exception_raise_state()); until we own the 3321 exception lock, we shouldn't have it in userspace (since a GCing 3322 thread wouldn't know that we had our hands on it.) 3323 */ 3324 3325 #ifdef X8664 3326 #define ts_pc(t) t.__rip 3327 #else 3328 #define ts_pc(t) t.__eip 3329 #endif 3272 3330 3273 3331 3274 … … 3334 3277 3335 3278 kern_return_t 3336 catch_exception_raise(mach_port_t exception_port, 3337 mach_port_t thread, 3338 mach_port_t task, 3339 exception_type_t exception, 3340 exception_data_t code_vector, 3341 mach_msg_type_number_t code_count) 3279 catch_exception_raise_state(mach_port_t exception_port, 3280 exception_type_t exception, 3281 exception_data_t code_vector, 3282 mach_msg_type_number_t code_count, 3283 int * flavor, 3284 thread_state_t in_state, 3285 mach_msg_type_number_t in_state_count, 3286 thread_state_t out_state, 3287 mach_msg_type_number_t * out_state_count) 3342 3288 { 3343 3289 int signum = 0, code = *code_vector; 3344 3290 TCR *tcr = TCR_FROM_EXCEPTION_PORT(exception_port); 3291 mach_port_t thread = (mach_port_t)((natural)tcr->native_thread_id); 3345 3292 kern_return_t kret, call_kret; 3346 #ifdef X8664 3347 x86_thread_state64_t ts; 3348 #else 3349 x86_thread_state32_t ts; 3350 #endif 3293 3294 native_thread_state_t 3295 *ts = (native_thread_state_t *)in_state, 3296 *out_ts = (native_thread_state_t*)out_state; 3351 3297 mach_msg_type_number_t thread_state_count; 3352 3298 3353 3299 3354 3300 3355 3356 #ifdef DEBUG_MACH_EXCEPTIONS3357 fprintf(dbgout, "obtaining Mach exception lock in exception thread\n");3358 #endif3359 3360 3361 3301 if (1) { 3362 #ifdef X86643363 do {3364 thread_state_count = x86_THREAD_STATE64_COUNT;3365 call_kret = thread_get_state(thread,3366 x86_THREAD_STATE64,3367 (thread_state_t)&ts,3368 &thread_state_count);3369 } while (call_kret == KERN_ABORTED);3370 MACH_CHECK_ERROR("getting thread state",call_kret);3371 #else3372 thread_state_count = x86_THREAD_STATE32_COUNT;3373 call_kret = thread_get_state(thread,3374 x86_THREAD_STATE32,3375 (thread_state_t)&ts,3376 &thread_state_count);3377 MACH_CHECK_ERROR("getting thread state",call_kret);3378 #endif3379 3302 if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_EXCEPTION)) { 3380 3303 CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION); … … 3382 3305 if ((code == EXC_I386_GPFLT) && 3383 3306 ((natural)(ts_pc(ts)) == (natural)pseudo_sigreturn)) { 3384 kret = do_pseudo_sigreturn(thread, tcr );3307 kret = do_pseudo_sigreturn(thread, tcr, out_ts); 3385 3308 #if 0 3386 3309 fprintf(dbgout, "Exception return in 0x%x\n",tcr); … … 3451 3374 code, 3452 3375 tcr, 3453 &ts); 3454 #if 0 3455 fprintf(dbgout, "Setup pseudosignal handling in 0x%x\n",tcr); 3456 #endif 3376 ts, 3377 out_ts); 3457 3378 3458 3379 } else { … … 3460 3381 } 3461 3382 } 3383 } 3384 if (kret) { 3385 *out_state_count = 0; 3386 *flavor = 0; 3387 } else { 3388 *out_state_count = NATIVE_THREAD_STATE_COUNT; 3462 3389 } 3463 3390 return kret; … … 3555 3482 LISP_EXCEPTIONS_HANDLED_MASK, 3556 3483 lisp_port, 3557 EXCEPTION_DEFAULT, 3558 THREAD_STATE_NONE, 3484 EXCEPTION_STATE, 3485 #if WORD_SIZE==64 3486 x86_THREAD_STATE64, 3487 #else 3488 x86_THREAD_STATE32, 3489 #endif 3559 3490 fxs->masks, 3560 3491 &n, … … 3681 3612 3682 3613 3683 Boolean 3684 suspend_mach_thread(mach_port_t mach_thread) 3685 { 3686 kern_return_t status; 3687 Boolean aborted = false; 3688 3689 do { 3690 aborted = false; 3691 status = thread_suspend(mach_thread); 3692 if (status == KERN_SUCCESS) { 3693 status = thread_abort_safely(mach_thread); 3694 if (status == KERN_SUCCESS) { 3695 aborted = true; 3696 } else { 3697 fprintf(dbgout, "abort failed on thread = 0x%x\n",mach_thread); 3698 thread_resume(mach_thread); 3699 } 3700 } else { 3701 return false; 3702 } 3703 } while (! aborted); 3704 return true; 3705 } 3706 3707 /* 3708 Only do this if pthread_kill indicated that the pthread isn't 3709 listening to signals anymore, as can happen as soon as pthread_exit() 3710 is called on Darwin. The thread could still call out to lisp as it 3711 is exiting, so we need another way to suspend it in this case. 3712 */ 3713 Boolean 3714 mach_suspend_tcr(TCR *tcr) 3715 { 3716 mach_port_t mach_thread = (mach_port_t)((natural)( tcr->native_thread_id)); 3717 ExceptionInformation *pseudosigcontext; 3718 Boolean result = false; 3719 3720 result = suspend_mach_thread(mach_thread); 3721 if (result) { 3722 mach_msg_type_number_t thread_state_count; 3723 #ifdef X8664 3724 x86_thread_state64_t ts; 3725 thread_state_count = x86_THREAD_STATE64_COUNT; 3726 thread_get_state(mach_thread, 3727 x86_THREAD_STATE64, 3728 (thread_state_t)&ts, 3729 &thread_state_count); 3730 #else 3731 x86_thread_state32_t ts; 3732 thread_state_count = x86_THREAD_STATE_COUNT; 3733 thread_get_state(mach_thread, 3734 x86_THREAD_STATE, 3735 (thread_state_t)&ts, 3736 &thread_state_count); 3737 #endif 3738 3739 pseudosigcontext = create_thread_context_frame(mach_thread, NULL, NULL,tcr, &ts); 3740 pseudosigcontext->uc_onstack = 0; 3741 pseudosigcontext->uc_sigmask = (sigset_t) 0; 3742 tcr->suspend_context = pseudosigcontext; 3743 } 3744 return result; 3745 } 3746 3747 void 3748 mach_resume_tcr(TCR *tcr) 3749 { 3750 ExceptionInformation *xp; 3751 mach_port_t mach_thread = (mach_port_t)((natural)(tcr->native_thread_id)); 3752 3753 xp = tcr->suspend_context; 3754 #ifdef DEBUG_MACH_EXCEPTIONS 3755 fprintf(dbgout, "resuming TCR 0x%x, pending_exception_context = 0x%x\n", 3756 tcr, tcr->pending_exception_context); 3757 #endif 3758 tcr->suspend_context = NULL; 3759 restore_mach_thread_state(mach_thread, xp); 3760 #ifdef DEBUG_MACH_EXCEPTIONS 3761 fprintf(dbgout, "restored state in TCR 0x%x, pending_exception_context = 0x%x\n", 3762 tcr, tcr->pending_exception_context); 3763 #endif 3764 thread_resume(mach_thread); 3765 } 3614 3766 3615 3767 3616 void
Note:
See TracChangeset
for help on using the changeset viewer.
