Changeset 9305


Ignore:
Timestamp:
Apr 27, 2008, 11:01:31 AM (11 years ago)
Author:
gb
Message:

Try to get Windows versions of suspend_tcr/restore_tcr closer to usability.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/win64/lisp-kernel/thread_manager.c

    r9297 r9305  
    12201220
    12211221  thread_handle = (HANDLE)_beginthreadex(NULL,
    1222                                         stack_size,
    1223                                         start_routine,
    1224                                         param,
    1225                                         0,
    1226                                         NULL);
     1222                                         stack_size,
     1223                                         start_routine,
     1224                                         param,
     1225                                         0,
     1226                                         NULL);
    12271227
    12281228  if (thread_handle == NULL) {
     
    13191319
    13201320#ifdef WINDOWS
     1321extern pc spentry_start, spentry_end,subprims_start,subprims_end;
     1322extern pc restore_win64_context_start, restore_win64_context_end,
     1323  restore_win64_context_load_rcx, restore_win64_context_iret;
     1324
    13211325Boolean
    13221326suspend_tcr(TCR *tcr)
     
    13251329  DWORD rc;
    13261330  if (suspend_count == 1) {
     1331    /* Can't seem to get gcc to align a CONTEXT structure correctly */
     1332    char _contextbuf[sizeof(CONTEXT)+__alignof(CONTEXT)];
     1333
     1334    CONTEXT *suspend_context, *pcontext;
     1335    HANDLE hthread = (HANDLE)(tcr->osid);
     1336    pc where;
     1337    area *cs = tcr->cs_area;
     1338    LispObj foreign_rsp;
     1339
     1340    pcontext = (CONTEXT *)((((natural)&_contextbuf)+15)&~15);
     1341
    13271342#if SUSPEND_RESUME_VERBOSE
    13281343    fprintf(stderr,"Suspending 0x%x\n", tcr);
    13291344#endif
    1330     rc = SuspendThread(tcr->osid);
     1345    rc = SuspendThread(hthread);
    13311346    if (rc == -1) {
     1347      /* If the thread's simply dead, we should handle that here */
    13321348      wperror("SuspendThread");
    13331349      return false;
    13341350    }
     1351    pcontext->ContextFlags = CONTEXT_ALL;
     1352    rc = GetThreadContext(hthread, pcontext);
     1353    if (rc == 0) {
     1354      wperror("GetThreadContext");
     1355    }
     1356    where = (pc)(xpPC(pcontext));
     1357
     1358    if (tcr->valence == TCR_STATE_LISP) {
     1359      if ((where >= restore_win64_context_start) &&
     1360          (where < restore_win64_context_end)) {
     1361        /* Thread has started to return from an exception. */
     1362        if (where < restore_win64_context_load_rcx) {
     1363          /* In the process of restoring registers; context still in
     1364             %rcx.  Just make our suspend_context be the context
     1365             we're trying to restore, so that we'll resume from
     1366             the suspend in the same context that we're trying to
     1367             restore */
     1368          *pcontext = * (CONTEXT *)(pcontext->Rcx);
     1369        } else {
     1370          /* Most of the context has already been restored; fix %rcx
     1371             if need be, then restore ss:rsp, cs:rip, and flags. */
     1372          x64_iret_frame *iret_frame = (x64_iret_frame *) (pcontext->Rsp);
     1373          if (where == restore_win64_context_load_rcx) {
     1374            pcontext->Rcx = ((CONTEXT*)(pcontext->Rcx))->Rcx;
     1375          }
     1376          pcontext->Rip = iret_frame->Rip;
     1377          pcontext->SegCs = (WORD) iret_frame->Cs;
     1378          pcontext->EFlags = (DWORD) iret_frame->Rflags;
     1379          pcontext->Rsp = iret_frame->Rsp;
     1380          pcontext->SegSs = (WORD) iret_frame->Ss;
     1381        }
     1382        tcr->suspend_context = NULL;
     1383      } else {
     1384        area *ts = tcr->ts_area;
     1385        /* If we're in the lisp heap, or in x86-spentry64.o, or in
     1386           x86-subprims64.o, or in the subprims jump table at #x15000,
     1387           or on the tstack ... we're just executing lisp code.  Otherwise,
     1388           we got an exception while executing lisp code, but haven't
     1389           yet entered the handler yet (still in Windows exception glue
     1390           or switching stacks or something.)  In the latter case, we
     1391           basically want to get to he handler and have it notice
     1392           the pending exception request, and suspend the thread at that
     1393           point. */
     1394        if (!((where < (pc)lisp_global(HEAP_END)) &&
     1395              (where >= (pc)lisp_global(HEAP_START))) &&
     1396            !((where < spentry_end) && (where >= spentry_start)) &&
     1397            !((where < subprims_end) && (where >= subprims_start)) &&
     1398            !((where < (pc) 0x16000) &&
     1399              (where >= (pc) 0x15000)) &&
     1400            !((where < (pc) (ts->high)) &&
     1401              (where >= (pc) (ts->low)))) {
     1402          /* The thread has lisp valence, but is not executing code
     1403             where we expect lisp code to be and is not exiting from
     1404             an exception handler.  That pretty much means that it's
     1405             on its way into an exception handler; we have to handshake
     1406             until it enters an exception-wait state. */
     1407          /* There are likely race conditions here */
     1408          SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_SUSPEND);
     1409          ResumeThread(hthread);
     1410          SEM_WAIT_FOREVER(tcr->suspend);
     1411          SuspendThread(hthread);
     1412          /* The thread is either waiting for its resume semaphore to
     1413             be signaled or is about to wait.  Signal it now, while
     1414             the thread's suspended. */
     1415          SEM_RAISE(tcr->resume);
     1416          pcontext->ContextFlags = CONTEXT_ALL;
     1417          GetThreadContext(hthread, pcontext);
     1418        }
     1419      }
     1420    } else {
     1421      if (tcr->valence == TCR_STATE_EXCEPTION_RETURN) {
     1422        *pcontext = *tcr->pending_exception_context;
     1423        tcr->pending_exception_context = NULL;
     1424        tcr->valence = TCR_STATE_LISP;
     1425      }
     1426    }
     1427
     1428    /* If the context's stack pointer is pointing into the cs_area,
     1429       copy the context below the stack pointer. else copy it
     1430       below tcr->foreign_rsp. */
     1431    foreign_rsp = xpGPR(pcontext,Isp);
     1432
     1433    if ((foreign_rsp < (LispObj)(cs->high)) ||
     1434        (foreign_rsp >= (LispObj)(cs->low))) {
     1435      foreign_rsp = (LispObj)(tcr->foreign_sp);
     1436    }
     1437    foreign_rsp -= 0x200;
     1438    foreign_rsp &= ~15;
     1439    suspend_context = (CONTEXT *)(foreign_rsp)-1;
     1440    *suspend_context = *pcontext;
     1441    tcr->suspend_context = suspend_context;
    13351442    return true;
    13361443  }
     
    14301537  DWORD rc;
    14311538  if (suspend_count == 0) {
    1432     rc = ResumeThread(tcr->osid);
     1539    CONTEXT *context = tcr->suspend_context;
     1540    HANDLE hthread = (HANDLE)(tcr->osid);
     1541
     1542    if (context == NULL) {
     1543      Bug(NULL, "no suspend_context for TCR = 0x%Ix", (natural)tcr);
     1544    }
     1545    tcr->suspend_context = NULL;
     1546    SetThreadContext(hthread,context);
     1547    rc = ResumeThread(hthread);
    14331548    if (rc == -1) {
    14341549      wperror("ResumeThread");
     
    17841899    LOCK_SPINLOCK(rw->spin,tcr);
    17851900    rw->blocked_writers--;
    1786     if (err = EINTR) {
     1901    if (err == EINTR) {
    17871902      err = 0;
    17881903    }
Note: See TracChangeset for help on using the changeset viewer.