You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ib...@apache.org on 2008/06/05 13:30:15 UTC

svn commit: r663534 - in /harmony/enhanced/drlvm/trunk/vm/port/src/signals: include/signals_internal.h win/signals_asm_em64t.asm win/signals_asm_ia32.asm win/signals_common.cpp win/signals_em64t.cpp win/signals_ia32.cpp

Author: iberezhn
Date: Thu Jun  5 04:30:15 2008
New Revision: 663534

URL: http://svn.apache.org/viewvc?rev=663534&view=rev
Log:
Applied patch from HARMONY-5819
[drlvm][signals] Not enough stack for SO processing in pure native threads


Modified:
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_ia32.asm
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_em64t.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h Thu Jun  5 04:30:15 2008
@@ -102,6 +102,21 @@
 
 void PORT_CDECL port_win_dbg_break(void);
 
+
+/**
+* The function to call another function on alternative stack.
+*
+* @param [in] fn    - the address of the function to be called
+* @param [in] stack - the address of memory area to be used as a stack
+* @param [in] num   - the number of parameters passed to the 'fn' function
+*                     in the variable args list (6 args at maximum)
+* @param [in] ...   - the parameters for 'fn'; should all be void* or of
+*                     the same size (pointer-sized)
+* @return           - can return any pointer-size value
+*/
+void* port_call_alt_stack(void* fn, void* stack_addr, int num, ...);
+
+
 #else /* UNIX */
 
 //

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm Thu Jun  5 04:30:15 2008
@@ -145,6 +145,54 @@
 port_longjump_stub ENDP
 
 
+; void* __cdecl port_setstack_stub(Registers* regs);
+;
+; The function calls some function on alternative stack.
+; Function address is already in RIP register of 'regs' structure.
+; We only need to store return address and stack address.
+;
+; | saved stack |
+; |  address    | <- to store RSP of current stack
+; |-------------|
+; |    arg 5    | <- present even if not used
+; |-------------|
+; |    arg 4    | <- present even if not used
+; |-------------|
+; |  32 bytes   | <- 'red zone' for argument registers flushing
+; |-------------|
+; | return addr | <- points to port_setstack_stub_end
+; |-------------| <- regs->rsp points to this cell
+
+PUBLIC  port_setstack_stub
+
+port_setstack_stub PROC
+
+    push    rbp
+    
+    mov     r9, qword ptr [rcx] ; get new rsp
+
+    call    port_setstack_stub_mid
+port_setstack_stub_mid:
+    pop     rax ; get address of port_setstack_stub_mid
+    ; calculate address of port_setstack_stub_end
+    add     rax, (port_setstack_stub_end - port_setstack_stub_mid)
+    ; store return address
+    mov     qword ptr [r9], rax
+    ; store current RSP
+    mov     qword ptr [r9 + 56], rsp
+
+    ; RCX is unchanged
+    call    port_transfer_to_regs
+
+port_setstack_stub_end:
+    ; restore RSP
+    mov     rsp, qword ptr [rsp + 48]
+    pop     rbp
+    ret
+
+port_setstack_stub ENDP
+
+
 _TEXT   ENDS
 
 END

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_ia32.asm
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_ia32.asm?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_ia32.asm (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_ia32.asm Thu Jun  5 04:30:15 2008
@@ -102,6 +102,54 @@
 port_longjump_stub ENDP
 
 
+; void* __cdecl port_setstack_stub(Registers* regs);
+;
+; The function calls some function on alternative stack.
+; Function address is already in EIP register of 'regs' structure.
+; We only need to store return address and stack address.
+;
+; | saved stack |
+; |  address    | <- to store ESP of current stack
+; |-------------|
+; |    arg 5    | <- present even if not used
+; |-------------|
+; |     ...     |
+; |-------------|
+; |    arg 0    | <- present even if not used
+; |-------------|
+; | return addr | <- points to port_setstack_stub_end
+; |-------------| <- regs->esp points to this cell
+
+PUBLIC  port_setstack_stub
+
+port_setstack_stub PROC
+
+    push    ebp
+    mov     edx, dword ptr [esp + 4 + 4]   ; get regs pointer
+    mov     ebp, dword ptr [edx + 1Ch] ; get new esp
+
+    call    port_setstack_stub_mid
+port_setstack_stub_mid:
+    pop     eax ; get address of port_setstack_stub_mid
+    ; calculate address of port_setstack_stub_end
+    add     eax, (port_setstack_stub_end - port_setstack_stub_mid)
+    ; store return address
+    mov     dword ptr [ebp], eax
+    ; store current ESP
+    mov     dword ptr [ebp + 28], esp
+
+    push    edx
+    call    port_transfer_to_regs
+
+port_setstack_stub_end:
+    ; restore ESP
+    mov     esp, dword ptr [esp + 24]
+    pop     ebp
+    ret
+
+port_setstack_stub ENDP
+
+
 _TEXT   ENDS
 
 END

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp Thu Jun  5 04:30:15 2008
@@ -41,6 +41,8 @@
 #define FLAG_CORE ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
 #define FLAG_DBG  ((port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
 
+#define ALT_PAGES_COUNT 16
+
 
 typedef void (PORT_CDECL *sigh_t)(int); // Signal handler type
 
@@ -142,6 +144,20 @@
     shutdown_signals();
 }
 
+static void* map_alt_stack(size_t size)
+{
+    LPVOID res = VirtualAlloc(0, (SIZE_T)size, MEM_RESERVE, PAGE_READWRITE);
+    if (!res)
+        return NULL;
+
+    return VirtualAlloc(res, (SIZE_T)size, MEM_COMMIT, PAGE_READWRITE);
+}
+
+static void unmap_alt_stack(void* addr, size_t size)
+{
+    VirtualFree(addr, (SIZE_T)size, MEM_RELEASE);
+}
+
 LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
 {
     DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
@@ -181,17 +197,37 @@
         if (code == STATUS_STACK_OVERFLOW &&
             sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
         {
-            int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
+            int result;
+            size_t alt_stack_size = ALT_PAGES_COUNT*tlsdata->guard_page_size;
+            void* alt_stack = map_alt_stack(alt_stack_size);
+            void* stack_bottom = (void*)((POINTER_SIZE_INT)alt_stack + alt_stack_size);
+
+            if (alt_stack)
+                result = (int)(POINTER_SIZE_INT)port_call_alt_stack(
+                                            port_process_signal, stack_bottom, 4,
+                                            PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
+            else
+                result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
 
             if (result == 0)
             {
                 if (port_thread_detach_temporary() == 0)
                     STD_FREE(tlsdata);
+                if (alt_stack)
+                    unmap_alt_stack(alt_stack, alt_stack_size);
                 return EXCEPTION_CONTINUE_EXECUTION;
             }
 
             if (FLAG_CORE)
-                create_minidump(nt_exception);
+            {
+                if (alt_stack)
+                    port_call_alt_stack(create_minidump, stack_bottom, 1, nt_exception);
+                else
+                    create_minidump(nt_exception);
+            }
+
+            if (alt_stack)
+                unmap_alt_stack(alt_stack, alt_stack_size);
 
             if (result > 0)
             {

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_em64t.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_em64t.cpp?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_em64t.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_em64t.cpp Thu Jun  5 04:30:15 2008
@@ -135,3 +135,53 @@
 
     port_transfer_to_regs(&regs);
 }
+
+
+extern "C" void* __cdecl port_setstack_stub(Registers* regs);
+
+// New stack's organization:
+//
+// |  alignment  |
+// |-------------|
+// | saved stack |
+// |  address    | <- to store RSP of current stack
+// |-------------|
+// |    arg 5    | <- present even if not used
+// |-------------|
+// |    arg 4    | <- present even if not used
+// |-------------|
+// |  32 bytes   | <- 'red zone' for argument registers flushing
+// |-------------|
+// | return addr | <- points to port_setstack_stub_end
+// |-------------| <- regs->rsp points to this cell
+
+void* port_call_alt_stack(void* fn, void* stack_addr, int num, ...)
+{
+    void** sp;
+    va_list ap;
+    Registers regs = {};
+
+    regs.rsp = (uint64)stack_addr;
+    regs.rsp -= 8*(1 + 1 + 6 + 1);
+    sp = (void**)regs.rsp;
+
+    va_start(ap, num);
+
+    if (num > 0)
+        regs.rcx = (uint64)va_arg(ap, void*);
+    if (num > 1)
+        regs.rdx = (uint64)va_arg(ap, void*);
+    if (num > 2)
+        regs.r8 = (uint64)va_arg(ap, void*);
+    if (num > 3)
+        regs.r9 = (uint64)va_arg(ap, void*);
+
+    for (int i = 5; i <= num; i++)
+    {
+        sp[i] = va_arg(ap, void*);
+    }
+
+    regs.rip = (uint64)fn;
+
+    return port_setstack_stub(&regs);
+}

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp?rev=663534&r1=663533&r2=663534&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp Thu Jun  5 04:30:15 2008
@@ -125,3 +125,42 @@
 
     port_transfer_to_regs(&regs);
 }
+
+
+extern "C" void* __cdecl port_setstack_stub(Registers* regs);
+
+// New stack's organization:
+//
+// | saved stack |
+// |  address    | <- to store ESP of current stack
+// |-------------|
+// |    arg 5    | <- present even if not used
+// |-------------|
+// |     ...     |
+// |-------------|
+// |    arg 0    | <- present even if not used
+// |-------------|
+// | return addr | <- points to port_setstack_stub_end
+// |-------------| <- regs->esp points to this cell
+
+void* port_call_alt_stack(void* fn, void* stack_addr, int num, ...)
+{
+    void** sp;
+    va_list ap;
+    Registers regs = {};
+
+    regs.esp = (U_32)stack_addr;
+    regs.esp -= 4*(1 + 6 + 1);
+    sp = (void**)regs.esp;
+
+    va_start(ap, num);
+
+    for (int i = 1; i <= num; i++)
+    {
+        sp[i] = va_arg(ap, void*);
+    }
+
+    regs.eip = (U_32)fn;
+
+    return port_setstack_stub(&regs);
+}