Changeset 14671


Ignore:
Timestamp:
Mar 8, 2011, 4:02:07 AM (9 years ago)
Author:
gb
Message:

On x86 Darwin, use catch_exception_raise_state(); this keeps Mach from
pointlessly incrementing a port right usage count and keeps us from
having to worry about decrementing that, and also saves us a few
Mach messaging operations to get/set thread state.

Change a few related functions, remove some obsolete functions and
comments.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/lisp-kernel/x86-exceptions.c

    r14619 r14671  
    29252925#ifdef DARWIN
    29262926
     2927#ifdef X8664
     2928#define ts_pc(t) t->__rip
     2929typedef 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
     2932typedef 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
     2935typedef 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
     2940typedef 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
     2943typedef 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
     2946typedef 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
    29272951#define TCR_FROM_EXCEPTION_PORT(p) ((TCR *)((natural)p))
    29282952#define TCR_TO_EXCEPTION_PORT(tcr) ((mach_port_t)((natural)(tcr)))
     
    30283052
    30293053void
    3030 restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext)
     3054restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext, native_thread_state_t *ts)
    30313055{
    30323056  kern_return_t kret;
     
    30383062
    30393063  /* Set the thread's FP state from the pseudosigcontext */
    3040 #if WORD_SIZE == 64
    30413064  kret = thread_set_state(thread,
    3042                           x86_FLOAT_STATE64,
     3065                          NATIVE_FLOAT_STATE_FLAVOR,
    30433066                          (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);
    30513068  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;
    30663070
    30673071
    3068 /* This code runs in the exception handling thread, in response
    3069    to an attempt to execute the UU0 at "pseudo_sigreturn" (e.g.,
    3070    in response to a call to pseudo_sigreturn() from the specified
    3071    user thread.
    3072    Find that context (the user thread's R3 points to it), then
    3073    use that context to set the user thread's state.  When this
    3074    function's caller returns, the Mach kernel will resume the
    3075    user thread.
    3076 */
    3077 
    30783072kern_return_t
    3079 do_pseudo_sigreturn(mach_port_t thread, TCR *tcr)
     3073do_pseudo_sigreturn(mach_port_t thread, TCR *tcr, native_thread_state_t *out)
    30803074{
    30813075  ExceptionInformation *xp;
     
    30883082    tcr->pending_exception_context = NULL;
    30893083    tcr->valence = TCR_STATE_LISP;
    3090     restore_mach_thread_state(thread, xp);
     3084    restore_mach_thread_state(thread, xp, out);
    30913085    raise_pending_interrupt(tcr);
    30923086  } else {
     
    31043098                            siginfo_t **info_ptr,
    31053099                            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
    31113101                            )
    31123102{
     
    31383128  memmove(&(mc->__ss),ts,sizeof(*ts));
    31393129
    3140 #ifdef X8664
    3141   thread_state_count = x86_FLOAT_STATE64_COUNT;
     3130  thread_state_count = NATIVE_FLOAT_STATE_COUNT;
    31423131  thread_get_state(thread,
    3143                    x86_FLOAT_STATE64,
     3132                   NATIVE_FLOAT_STATE_FLAVOR,
    31443133                   (thread_state_t)&(mc->__fs),
    31453134                   &thread_state_count);
    31463135
    3147   thread_state_count = x86_EXCEPTION_STATE64_COUNT;
     3136  thread_state_count = NATIVE_EXCEPTION_STATE_COUNT;
    31483137  thread_get_state(thread,
    3149                    x86_EXCEPTION_STATE64,
     3138                   NATIVE_EXCEPTION_STATE_FLAVOR,
    31503139                   (thread_state_t)&(mc->__es),
    31513140                   &thread_state_count);
    3152 #else
    3153   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 #endif
    31653141
    31663142
     
    31953171                   int code,
    31963172                   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
    32023175                   )
    32033176{
    3204 #ifdef X8664
    3205   x86_thread_state64_t new_ts;
    3206 #else
    3207   x86_thread_state32_t new_ts;
    3208 #endif
    32093177  ExceptionInformation *pseudosigcontext;
    32103178  int  old_valence = tcr->valence;
     
    32383206
    32393207#ifdef X8664
    3240   new_ts.__rip = (natural) handler_address;
     3208  new_ts->__rip = (natural) handler_address;
    32413209  stackpp = (natural *)stackp;
    32423210  *--stackpp = (natural)pseudo_sigreturn;
    32433211  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;
    32633229  stackpp = (natural *)stackp;
    32643230  *--stackpp = 0;               /* alignment */
     
    32723238  *--stackpp = (natural)pseudo_sigreturn;
    32733239  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;
    32883242#endif
    32893243#ifdef DEBUG_MACH_EXCEPTIONS
     
    33163270*/
    33173271
    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
    33303273
    33313274
     
    33343277
    33353278kern_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)
     3279catch_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)
    33423288{
    33433289  int signum = 0, code = *code_vector;
    33443290  TCR *tcr = TCR_FROM_EXCEPTION_PORT(exception_port);
     3291  mach_port_t thread = (mach_port_t)((natural)tcr->native_thread_id);
    33453292  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;
    33513297  mach_msg_type_number_t thread_state_count;
    33523298
    33533299
    33543300
    3355 
    3356 #ifdef DEBUG_MACH_EXCEPTIONS
    3357   fprintf(dbgout, "obtaining Mach exception lock in exception thread\n");
    3358 #endif
    3359 
    3360 
    33613301  if (1) {
    3362 #ifdef X8664
    3363     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 #else
    3372     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 #endif
    33793302    if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_EXCEPTION)) {
    33803303      CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION);
     
    33823305    if ((code == EXC_I386_GPFLT) &&
    33833306        ((natural)(ts_pc(ts)) == (natural)pseudo_sigreturn)) {
    3384       kret = do_pseudo_sigreturn(thread, tcr);
     3307      kret = do_pseudo_sigreturn(thread, tcr, out_ts);
    33853308#if 0
    33863309      fprintf(dbgout, "Exception return in 0x%x\n",tcr);
     
    34513374                                  code,
    34523375                                  tcr,
    3453                                   &ts);
    3454 #if 0
    3455         fprintf(dbgout, "Setup pseudosignal handling in 0x%x\n",tcr);
    3456 #endif
     3376                                  ts,
     3377                                  out_ts);
    34573378       
    34583379      } else {
     
    34603381      }
    34613382    }
     3383  }
     3384  if (kret) {
     3385    *out_state_count = 0;
     3386    *flavor = 0;
     3387  } else {
     3388    *out_state_count = NATIVE_THREAD_STATE_COUNT;
    34623389  }
    34633390  return kret;
     
    35553482                                     LISP_EXCEPTIONS_HANDLED_MASK,
    35563483                                     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
    35593490                                     fxs->masks,
    35603491                                     &n,
     
    36813612
    36823613
    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
    37663615
    37673616void
Note: See TracChangeset for help on using the changeset viewer.