Changeset 15148


Ignore:
Timestamp:
Dec 21, 2011, 6:35:27 PM (8 years ago)
Author:
gb
Message:

Try to fix ticket:862 and some related problems.

If GetThreadContext?() claims that we've suspended a thread at a UUO,
don't interpret that as "about to execute the UUO"; we may have executed
the UUO and not have reentered user mode, and there seems to be reason
to believe that setting the thread's context while it's suspended won't
have the desired effect. Set the tcr's "pending suspend" bit and resume
the thread in this case. Note that there are other situations where
we may be in the process of taking an exception but it's much harder
to tell (e.g., if the instruction causes a memory fault or arithmetic
exception or ...); it'd be nicer if there was a reliable way to detect
that. Win32 doesn't seem to have this problem at all, AFAICT.

If we let a thread continue until it reaches the exception handler and
checks the pending suspend bit, don't set its tcr.suspend_context slot.
When resuming such a thread, just raise its resume semaphore.

Do a little more pc-lusering when suspending Windows threads, e.g.,
if suspended in the first few instructions of restore_windows_context(),
emulate the effect of those instructions.

File:
1 edited

Legend:

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

    r15142 r15148  
    20272027    where = (pc)(xpPC(pcontext));
    20282028
     2029    if ((where >= restore_windows_context_start) &&
     2030        (where < restore_windows_context_end) &&
     2031        (tcr->valence != TCR_STATE_LISP)) {
     2032#ifdef WIN_64
     2033      tcr->valence = xpGPR(pcontext,REG_R8);
     2034#else
     2035      tcr->valence = ((LispObj *)(xpGPR(pcontext,Isp)))[3];
     2036#endif
     2037      pcontext = tcr->pending_exception_context;
     2038      tcr->pending_exception_context = NULL;
     2039      where = (pc)(xpPC(pcontext));
     2040    }
    20292041    if (tcr->valence == TCR_STATE_LISP) {
    20302042      if ((where >= restore_windows_context_start) &&
     
    20612073          ResumeThread(hthread);
    20622074          SEM_WAIT_FOREVER(TCR_AUX(tcr)->suspend);
    2063           SuspendThread(hthread);
    2064           /* The thread is either waiting for its resume semaphore to
    2065              be signaled or is about to wait.  Signal it now, while
    2066              the thread's suspended. */
    2067           SEM_RAISE(TCR_AUX(tcr)->resume);
    2068           pcontext->ContextFlags = CONTEXT_ALL;
    2069           GetThreadContext(hthread, pcontext);
     2075          pcontext = NULL;
    20702076        }
    20712077      }
    2072 #if 0
    2073     } else {
    2074       if (tcr->valence == TCR_STATE_EXCEPTION_RETURN) {
    2075         if (!tcr->pending_exception_context) {
    2076           FBug(pcontext, "we're confused here.");
    2077         }
    2078         *pcontext = *tcr->pending_exception_context;
    2079         tcr->pending_exception_context = NULL;
    2080         tcr->valence = TCR_STATE_LISP;
    2081       }
    2082 #endif
     2078    }
     2079    /* If we're really running lisp code, there's some reason to
     2080       suspect that Windows is lying about that; the thread may have
     2081       already committed to processing an exception and just not have
     2082       reentered user mode.  If there's a way to determine that more
     2083       reliably, I don't know what it is.  We can catch some cases of
     2084       that by looking at whether the PC is at a UUO or other
     2085       "intentional" illegal instruction and letting the thread enter
     2086       exception handling, treating this case just like the case
     2087       above. 
     2088
     2089       When people say that Windows sucks, they aren't always just
     2090       talking about all of the other ways that it sucks.
     2091    */
     2092    if ((*where == INTN_OPCODE) ||
     2093        ((*where == XUUO_OPCODE_0) && (where[1] == XUUO_OPCODE_1))) {
     2094      SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_SUSPEND);
     2095      ResumeThread(hthread);
     2096      SEM_WAIT_FOREVER(TCR_AUX(tcr)->suspend);
     2097      pcontext = NULL;
    20832098    }
    20842099    TCR_AUX(tcr)->suspend_context = pcontext;
     
    21942209    HANDLE hthread = (HANDLE)(TCR_AUX(tcr)->osid);
    21952210
     2211
     2212    TCR_AUX(tcr)->suspend_context = NULL;
    21962213    if (context) {
    2197       context->ContextFlags = CONTEXT_ALL;
    2198       TCR_AUX(tcr)->suspend_context = NULL;
    2199       SetThreadContext(hthread,context);
     2214      if (tcr->valence == TCR_STATE_LISP) {
     2215        rc = SetThreadContext(hthread,context);
     2216        if (! rc) {
     2217          Bug(NULL,"SetThreadContext");
     2218          return false;
     2219        }
     2220      }
    22002221      rc = ResumeThread(hthread);
    22012222      if (rc == -1) {
    2202         wperror("ResumeThread");
     2223        Bug(NULL,"ResumeThread");
    22032224        return false;
    22042225      }
     2226      return true;
     2227    } else {
     2228      SEM_RAISE(TCR_AUX(tcr)->resume);
    22052229      return true;
    22062230    }
     
    23542378{
    23552379  TCR *current = get_tcr(true), *other;
     2380
    23562381  for (other = TCR_AUX(current)->next; other != current; other = TCR_AUX(other)->next) {
    23572382    if ((TCR_AUX(other)->osid != 0)) {
Note: See TracChangeset for help on using the changeset viewer.