Changeset 11710


Ignore:
Timestamp:
Feb 10, 2009, 3:01:57 AM (10 years ago)
Author:
gb
Message:

Try to handle the case of suspending a Windows thread that's in the
middle of restore_windows_context() more sanely/completely, especially
on win32.

Move the code that's concerned with this into a separate function
(pc_luser_restore_windows_context), which always overwrites some or
all of the context as of thread suspend with the context that the
suspended thread is trying to restore (e.g., whatever pc-lusering
we do always has the effect of causing the thread to resume at the
point where restore_windows_context() would have completed.

Since restore_windows_context() is only used to return from an
exception, clear tcr->pending_exception_context when we've got
things to a known point.

Define ia32_iret_frame in x86-constants32.h.

Use iret to restore flags/cs:eip on ia32.

Ensure that the last thing that win32_restore_context() does before
the iret is to reload %rcx/%ecx from the context (kept in %rcx/%ecx),
so suspending in the middle of restore_lisp_context() - before the iret -
just has to find the context being restored in %rcx/%ecx (it doesn't
matter where we are in the process of restoring it.)

If we're at the iret, just emulate the (machine-specific) effects of
the iret.

Need to make sure that this isn't grossly broken on win64, and need
to look at interrupt (vice suspend) code.

Location:
trunk/source/lisp-kernel
Files:
4 edited

Legend:

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

    r11623 r11710  
    5050extern pc spentry_start, spentry_end,subprims_start,subprims_end;
    5151extern pc restore_windows_context_start, restore_windows_context_end,
    52   restore_windows_context_load_rcx, restore_windows_context_iret;
     52  restore_windows_context_iret;
     53
    5354
    5455extern void interrupt_handler(int, siginfo_t *, ExceptionInformation *);
     
    18731874
    18741875#ifdef WINDOWS
     1876void *
     1877pc_luser_restore_windows_context(CONTEXT *pcontext, TCR *tcr, pc where)
     1878{
     1879  /* Thread has started to return from an exception. */
     1880  if (where < restore_windows_context_iret) {
     1881    /* In the process of restoring registers; context still in
     1882       %rcx.  Just make our suspend_context be the context
     1883       we're trying to restore, so that we'll resume from
     1884       the suspend in the same context that we're trying to
     1885       restore */
     1886#ifdef WIN_64
     1887    *pcontext = * (CONTEXT *)(pcontext->Rcx);
     1888#else
     1889    *pcontext = * (CONTEXT *)(pcontext->Ecx);
     1890#endif
     1891  } else {
     1892    /* Most of the context has already been restored; fix %rcx
     1893       if need be, then restore ss:rsp, cs:rip, and flags. */
     1894#ifdef WIN_64
     1895    x64_iret_frame *iret_frame = (x64_iret_frame *) (pcontext->Rsp);
     1896
     1897    pcontext->Rip = iret_frame->Rip;
     1898    pcontext->SegCs = (WORD) iret_frame->Cs;
     1899    pcontext->EFlags = (DWORD) iret_frame->Rflags;
     1900    pcontext->Rsp = iret_frame->Rsp;
     1901    pcontext->SegSs = (WORD) iret_frame->Ss;
     1902#else
     1903    ia32_iret_frame *iret_frame = (ia32_iret_frame *) (pcontext->Esp);
     1904
     1905    pcontext->Eip = iret_frame->Eip;
     1906    pcontext->SegCs = (WORD) iret_frame->Cs;
     1907    pcontext->EFlags = (DWORD) iret_frame->EFlags;
     1908    pcontext->Esp += sizeof(ia32_iret_frame);
     1909#endif
     1910  }
     1911  tcr->pending_exception_context = NULL;
     1912}
    18751913
    18761914Boolean
     
    19041942      if ((where >= restore_windows_context_start) &&
    19051943          (where < restore_windows_context_end)) {
    1906         /* Thread has started to return from an exception. */
    1907         if (where < restore_windows_context_load_rcx) {
    1908           /* In the process of restoring registers; context still in
    1909              %rcx.  Just make our suspend_context be the context
    1910              we're trying to restore, so that we'll resume from
    1911              the suspend in the same context that we're trying to
    1912              restore */
    1913 #ifdef WIN_64
    1914           *pcontext = * (CONTEXT *)(pcontext->Rcx);
    1915 #else
    1916           fprintf(dbgout, "missing win32 suspend code, case (1)\n");
    1917 #endif
    1918         } else {
    1919           /* Most of the context has already been restored; fix %rcx
    1920              if need be, then restore ss:rsp, cs:rip, and flags. */
    1921 #ifdef WIN64
    1922           x64_iret_frame *iret_frame = (x64_iret_frame *) (pcontext->Rsp);
    1923           if (where == restore_windows_context_load_rcx) {
    1924             pcontext->Rcx = ((CONTEXT*)(pcontext->Rcx))->Rcx;
    1925           }
    1926           pcontext->Rip = iret_frame->Rip;
    1927           pcontext->SegCs = (WORD) iret_frame->Cs;
    1928           pcontext->EFlags = (DWORD) iret_frame->Rflags;
    1929           pcontext->Rsp = iret_frame->Rsp;
    1930           pcontext->SegSs = (WORD) iret_frame->Ss;
    1931 #else
    1932 #warning need context setup for win32
    1933           fprintf(dbgout, "missing win32 suspend code, case (2)\n");
    1934 #endif
    1935         }
    1936         tcr->suspend_context = NULL;
     1944        pc_luser_restore_windows_context(pcontext, tcr, where);
    19371945      } else {
    19381946        area *ts = tcr->ts_area;
  • trunk/source/lisp-kernel/x86-asmutils32.s

    r11609 r11710  
    198198_exportfn(C(restore_windows_context))
    199199Xrestore_windows_context_start:
     200        __(movl 4(%esp),%ecx)   /* context */
    200201        __(movl 12(%esp),%edx)  /* old valence */
    201202        __(movl 8(%esp),%eax)   /* tcr */
    202203        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
    203         __(movl 4(%esp),%ecx)   /* context */
    204204        __(movl %edx,rcontext(tcr.valence))
    205205        __(movl $0,rcontext(tcr.pending_exception_context))
     
    223223        __(movl win32_context.Eax(%ecx),%eax)
    224224        __(movl win32_context.Esp(%ecx),%esp)
    225         __(pushl win32_context.Eip(%ecx))
    226 Xrestore_windows_context_load_rcx:               
     225        __(pushl win32_context.EFlags(%ecx))
     226        __(pushl %cs)
     227        __(pushl win32_context.Eip(%ecx))       
     228        /* This must be the last thing before the iret, e.g., if we're
     229        interrupted before the iret, the context we're returning to here
     230        is still in %ecx.  If we're interrupted -at- the iret, then
     231        everything but that which the iret will restore has been restored. */
    227232        __(movl win32_context.Ecx(%ecx),%ecx)
    228233Xrestore_windows_context_iret:           
    229         __(ret)
     234        __(iret)
    230235Xrestore_windows_context_end:             
    231236        __(nop)
     
    247252        .globl C(restore_windows_context_start)
    248253        .globl C(restore_windows_context_end)
    249         .globl C(restore_windows_context_load_rcx)
    250254        .globl C(restore_windows_context_iret)
    251255C(restore_windows_context_start):  .long Xrestore_windows_context_start
    252256C(restore_windows_context_end): .long Xrestore_windows_context_end
    253 C(restore_windows_context_load_rcx):  .long Xrestore_windows_context_load_rcx
    254257C(restore_windows_context_iret): .long Xrestore_windows_context_iret
    255258        .text
  • trunk/source/lisp-kernel/x86-asmutils64.s

    r11695 r11710  
    265265        __(movq win64_context.R14(%rcx),%r14)
    266266        __(movq win64_context.R15(%rcx),%r15)
    267 Xrestore_windows_context_load_rcx:               
     267        /* This must be the last thing before the iret, e.g., if we're
     268        interrupted before the iret, the context we're returning to here
     269        is still in %rcx.  If we're interrupted -at- the iret, then
     270        everything but that which the iret will restore has been restored. */
    268271        __(movq win64_context.Rcx(%rcx),%rcx)
    269272Xrestore_windows_context_iret:           
     
    284287        .globl C(restore_windows_context_start)
    285288        .globl C(restore_windows_context_end)
    286         .globl C(restore_windows_context_load_rcx)
    287289        .globl C(restore_windows_context_iret)
    288290C(restore_windows_context_start):  .quad Xrestore_windows_context_start
    289291C(restore_windows_context_end): .quad Xrestore_windows_context_end
    290 C(restore_windows_context_load_rcx):  .quad Xrestore_windows_context_load_rcx
    291292C(restore_windows_context_iret): .quad Xrestore_windows_context_iret
    292293        .text
  • trunk/source/lisp-kernel/x86-constants32.h

    r11675 r11710  
    484484#define misc_data_offset misc_header_offset + node_size
    485485
     486typedef struct {
     487  natural Eip;
     488  natural Cs;                   /* in low 16 bits */
     489  natural EFlags;
     490} ia32_iret_frame;
     491
    486492#define heap_segment_size 0x00010000
    487493#define log2_heap_segment_size 16
Note: See TracChangeset for help on using the changeset viewer.