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, ®s, 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, ®s, fault_addr, FALSE);
+ else
+ result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, ®s, 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(®s);
}
+
+
+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(®s);
+}
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(®s);
}
+
+
+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(®s);
+}