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/05/26 02:33:07 UTC

svn commit: r660062 [1/2] - in /harmony/enhanced/drlvm/trunk: make/vm/ vm/include/open/ vm/port/build/ vm/port/include/ vm/port/src/crash_handler/ vm/port/src/memaccess/linux/ vm/port/src/signals/ vm/port/src/signals/include/ vm/port/src/signals/linux/...

Author: iberezhn
Date: Sun May 25 17:33:06 2008
New Revision: 660062

URL: http://svn.apache.org/viewvc?rev=660062&view=rev
Log:
Applied patch from HARMONY-5617
[drlvm] On Linux crash handler may crash itself when handling SOE
condition

The patch moves platform-dependent threading from TM to Portlib, and
platform-dependent signals processing from VMCore to Portlib.


Added:
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_find.c   (with props)
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c   (with props)
Removed:
    harmony/enhanced/drlvm/trunk/vm/thread/src/linux/os_thread.c
    harmony/enhanced/drlvm/trunk/vm/thread/src/win/os_thread.c
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp
Modified:
    harmony/enhanced/drlvm/trunk/make/vm/hythr.xml
    harmony/enhanced/drlvm/trunk/make/vm/port.xml
    harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml
    harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h
    harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp
    harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h
    harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h
    harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c
    harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c
    harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def
    harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp
    harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c
    harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c
    harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp

Modified: harmony/enhanced/drlvm/trunk/make/vm/hythr.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/hythr.xml?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/hythr.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/hythr.xml Sun May 25 17:33:06 2008
@@ -47,8 +47,8 @@
 
             <linkerarg value="/DEF:${vm.home}/thread/src/hythr.def" if="is.windows"/>
 
-            <syslibset libs="stdc++,rt,pthread" if="is.linux"/>
-            <syslibset libs="stdc++,pthread" if="is.freebsd"/>
+            <syslibset type="shared" libs="stdc++,rt,pthread" if="is.linux"/>
+            <syslibset type="shared" libs="stdc++,pthread" if="is.freebsd"/>
             <linkerarg value="-Wl,-init" if="is.unix"/>
             <linkerarg value="-Wl,hythread_library_init" if="is.unix"/>
             <linkerarg value="-Wl,--version-script,${vm.home}/thread/src/hythr.exp" if="is.unix"/>

Modified: harmony/enhanced/drlvm/trunk/make/vm/port.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/port.xml?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/port.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/port.xml Sun May 25 17:33:06 2008
@@ -29,6 +29,7 @@
             <dirset dir="${vm.home}">
                 <include name="include" />
                 <include name="port/include" />
+                <include name="port/src/thread/include" />
             </dirset>
             <pathelement location="${drlvm.include.dir}"/>
             <pathelement location="${hy.hdk}/include" />
@@ -49,10 +50,12 @@
             <include name="vmem/win/*.c" if="is.windows"/>
             <include name="file_io/*.c"/>
 
+            <include name="thread/linux/port_thread_tls_find.c" if="is.unix"/>
             <include name="thread/linux/thread_os.c" if="is.unix"/>
             <include name="thread/linux/*ia32.c" if="is.unix.x86"/>
             <include name="thread/linux/*em64t.c" if="is.unix.x86_64"/>
             <include name="thread/linux/*ipf.c" if="is.unix.ia64"/>
+            <include name="thread/win/port_thread_tls_find.c" if="is.windows"/>
             <include name="thread/win/thread_os.c" if="is.windows"/>
             <include name="thread/win/*ia32.c" if="is.windows.x86"/>
             <include name="thread/win/*em64t.c" if="is.windows.x86_64"/>

Modified: harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml Sun May 25 17:33:06 2008
@@ -30,6 +30,7 @@
                 <include name="include" />
                 <include name="port/include" />
                 <include name="port/src/signals/include" />
+                <include name="port/src/thread/include" />
                 <include name="port/src/crash_handler/include" />
                 <include name="port/src/encoder/ia32_em64t" unless="is.ia64"/>
             </dirset>
@@ -42,14 +43,20 @@
             <include name="modules/linux/*.c" if="is.unix"/>
             <include name="modules/win/*.c" if="is.windows"/>
 
+            <include name="thread/linux/thread_os.c" if="is.unix"/>
+            <include name="thread/linux/port_thread_tls_os.c" if="is.unix"/>
             <include name="thread/linux/*ia32.c" if="is.unix.x86"/>
             <include name="thread/linux/*em64t.c" if="is.unix.x86_64"/>
             <include name="thread/linux/*ipf.c" if="is.unix.ia64"/>
+            <include name="thread/win/thread_os.c" if="is.windows"/>
+            <include name="thread/win/port_thread_tls_os.c" if="is.windows"/>
             <include name="thread/win/*ia32.c" if="is.windows.x86"/>
             <include name="thread/win/*em64t.c" if="is.windows.x86_64"/>
 
             <include name="misc/linux/execname.c" if="is.unix"/>
             <include name="misc/win/execname.c" if="is.windows"/>
+            <!-- port_atomic_casptr is inlined on all platforms except ia64 -->
+            <include name="atomic/linux_ipf/*.c" if="is.unix.ia64"/>
         </patternset>
 
         <patternset id="ch.src.cpp">

Modified: harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h Sun May 25 17:33:06 2008
@@ -346,11 +346,6 @@
     char need_to_free;
 
     /**
-     * Size of thread's stack, set on creation
-     */
-    UDATA stacksize;
-
-    /**
      * Flag of interruption
      */
     U_32 interrupted;
@@ -445,7 +440,6 @@
 UDATA VMCALL hythread_tls_get_offset(hythread_tls_key_t key);
 UDATA VMCALL hythread_tls_get_request_offset();
 UDATA VMCALL hythread_get_thread_times(hythread_t thread, int64* pkernel, int64* puser);
-UDATA hythread_get_thread_stacksize(hythread_t thread);
 UDATA VMCALL hythread_uses_fast_tls(void);
 IDATA VMCALL hythread_get_hythread_offset_in_tls(void);
 IDATA VMCALL hythread_get_struct_size();

Modified: harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp Sun May 25 17:33:06 2008
@@ -16,6 +16,7 @@
     port_init_unwind_context;
     port_clean_unwind_context;
     port_unwind_frame;
+    port_init_shared_data;
 #
   local : *;
 };

Modified: harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h Sun May 25 17:33:06 2008
@@ -58,5 +58,15 @@
 
 #endif /* __cplusplus */
 
+#ifdef _IA32_
+#ifdef WIN32
+#define PORT_CDECL __cdecl
+#else /* !WIN32 */
+#define PORT_CDECL __attribute__ ((cdecl))
+#endif /* WIN32 */
+#else /* _IA32_ */
+#define PORT_CDECL
+#endif /* _IA32_ */
+
 
 #endif /* _PORT_GENERAL_H_ */

Modified: harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h Sun May 25 17:33:06 2008
@@ -50,6 +50,7 @@
 
 #endif /* LINUX || FREEBSD */
 
+
 /* To skip platform_types.h inclusion */
 typedef struct Registers Registers;
 
@@ -71,18 +72,251 @@
 #endif
 }
 
-void port_thread_yield_other(osthread_t thread);
+/**
+ * The type of pointer to thread start function
+ * Function receives single argument - user-defined pointer
+ */
+typedef int (PORT_CDECL *port_threadfunc_t)(void*);
+
+/**
+ * Creates new thread.
+ *
+ * @param[out] handle on success, thread handle is stored in memory pointed by handle
+ * @param stacksize size of stack to be allocated for a new thread
+ * @param priority priority of a new thread
+ * @param func function to be started on a new thread
+ * @param data value to be passed to a function started on a new thread
+ *
+ * @return 0 on success, system error otherwise.
+ */
+int port_thread_create(osthread_t* phandle, size_t stacksize, int priority,
+        port_threadfunc_t func, void *data);
+
+/**
+ * Attaches current thread to the porting library.
+ *
+ * This includes setting guard page in thread's stack memory and setting
+ * alternative stack for stack overflow processing.
+ * This function should be called for any thread which can produce expected
+ * hardware signals/exceptions, to guarantee proper signals processing.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_detach()
+ */
+int port_thread_attach();
+
+/**
+ * Detaches current thread from the porting library.
+ * This includes restoring thread's stack settings.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_attach()
+ */
+int port_thread_detach();
+
+/**
+ * Restores guard page after stack overflow processing, when
+ * <code>port_thread_postpone_guard_page()</code> function was used
+ * to postpone authomatic gurd page restoring.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_postpone_guard_page()
+ * @sa port_thread_clear_guard_page()
+ */
+int port_thread_restore_guard_page();
+
+/**
+ * Clears guard page in thread's stack on demand.
+ * Guard page is cleared automatically for stack overflow processing; this
+ * function allows clearing it when needed for other purposes.
+ * Guard page can be restored with
+ * <code>port_thread_postpone_guard_page()</code> function.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_restore_guard_page()
+ */
+int port_thread_clear_guard_page();
+
+/**
+ * Postpones automatic guard page restoring after stack overflow processing.
+ *
+ * This function can be used inside of STACK_OVERFLOW signal callback to
+ * disable automatic guard poge restoring. This is useful when the program
+ * expects to consume some more stack before unwinding to SO handler.
+ *
+ * @sa port_thread_restore_guard_page()
+ */
+void port_thread_postpone_guard_page();
+
+
+/**
+ * Returns stack bottom address for the current thread.
+ *
+ * @return              NULL on error
+ */
+void* port_thread_get_stack_address();
+
+
+/**
+ * Returns total thread's stack size for the current thread.
+ *
+ * @return              0 on error
+ */
+size_t port_thread_get_stack_size();
+
+
+/**
+ * Returns effective stack size for the current thread.
+ * Effective stack size is an area from stack bottom to guard page.
+ *
+ * Return value depends thread's state. When the thread is not in signal,
+ * return value is a total stack size excluding system page, i.e.
+ * (port_thread_get_stack_size() - <guard page size>). When processing a signal,
+ * return value is the same when guard page is cleared, and is a size of area
+ * from stack bottom to Port's guard page otherwise.
+ *
+ * @return              0 on error
+ */
+size_t port_thread_get_effective_stack_size();
+
+
+/**
+ * Adjusts priority of the running thread.
+ *
+ * @param thread        handle of thread
+ * @param priority      new priority value
+ *
+ * @return              0 on success, system error otherwise
+ */
+int port_thread_set_priority(osthread_t thread, int priority);
+
+/**
+ * Returns os handle of the current thread.
+ *
+ * @return current thread handle on success, NULL on error
+ *
+ * @note The handle returned need to be freed by port_thread_free_handle()
+ * @sa port_thread_free_handle()
+ */
+osthread_t port_thread_current();
+
+/**
+ * Frees thread handle returned by port_thread_current()
+ *
+ * @param os_thread     thread handle
+ *
+ * @sa port_thread_current()
+ */
+int port_thread_free_handle(osthread_t os_thread);
+
+/**
+ * Joins the os thread.
+ *
+ * @param os_thread     thread handle
+ *
+ * @return              0 on success, systerm error otherwise
+ */
+int port_thread_join(osthread_t os_thread);
+
+/**
+ * Terminates the os thread.
+ *
+ * @param os_thread     thread to terminate
+ */
 int port_thread_cancel(osthread_t os_thread);
 
+/**
+ * Causes the current thread to stop execution.
+ *
+ * @param status        return status of a thread
+ */
+void port_thread_exit(int status);
+
+/**
+ * Queries amount of user and kernel times consumed by the thread,
+ * in nanoseconds.
+ *
+ * @param os_thread     thread handle
+ * @param[out] pkernel  a pointer to a variable to store kernel time to
+ * @param[out] puser    a pointer to a variable to store user time to
+ *
+ * @return      0 on success, system error otherwise
+ */
+int port_get_thread_times(osthread_t os_thread, int64* pkernel, int64* puser);
+
+/**
+ * Causes the other thread to have a memory barrier by suspending
+ * and resuming it.
+ *
+ * @param thread     thread handle
+ */
+void port_thread_yield_other(osthread_t thread);
 
+/**
+ * Suspend given thread
+ *
+ * @param thread The thread to suspend
+ */
 int port_thread_suspend(osthread_t thread);
+
+/**
+ * Resume given thread
+ *
+ * @param thread The thread to resume
+ */
 int port_thread_resume(osthread_t thread);
+
+/**
+ * Returnd suspend count for the given thread
+ *
+ * @param thread The thread to check
+ *
+ * @return suspend count of the thread, -1 if error
+ */
 int port_thread_get_suspend_count(osthread_t thread);
 
+/**
+ * Get context for given thread
+ *
+ * @param thread The thread to process
+ * @param context Pointer to platform-dependent context structure
+ *
+ * @return 0 if successful, -1 otherwise
+ *
+ * @note The thread must be suspended
+ */
 int port_thread_get_context(osthread_t thread, thread_context_t* pcontext);
+
+/**
+ * Set context for given thread
+ *
+ * @param thread The thread to process
+ * @param context Pointer to platform-dependent context structure
+ *
+ * @return 0 if successful, -1 otherwise
+ *
+ * @note The thread must be suspended
+ */
 int port_thread_set_context(osthread_t thread, thread_context_t* pcontext);
 
+/**
+ * Translates platform-dependent thread context to Registers structure
+ *
+ * @param regs Pointer to Registers structure
+ * @param context Pointer to platform-dependent context structure
+ */
 void port_thread_context_to_regs(Registers* regs, thread_context_t* context);
+
+/**
+ * Translates Registers structure to platform-dependent thread context
+ *
+ * @param context Pointer to platform-dependent context structure
+ * @param regs Pointer to Registers structure
+ */
 void port_thread_regs_to_context(thread_context_t* context, Registers* regs);
 
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp Sun May 25 17:33:06 2008
@@ -58,9 +58,6 @@
     if (port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED) != APR_SUCCESS)
         return FALSE;
 
-	if (init_private_tls_data() != 0)
-	    return FALSE;
-
     for (unsigned iii = 0; iii < count; iii++)
     {
         assert(registrations[iii].signum >= PORT_SIGNAL_MIN);
@@ -136,9 +133,6 @@
     if (shutdown_signals() != 0)
         return FALSE;
 
-	if (free_private_tls_data() != 0)
-	    return FALSE;
-
     for (crash_additional_actions *a = crash_actions; NULL != a;)
     {
         crash_additional_actions *next = a->next;

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp Sun May 25 17:33:06 2008
@@ -58,8 +58,12 @@
     "%s\n", // No signature no sourcefile
 };
 
-static void sd_print_vm_line(FILE* file, int count, port_stack_frame_info* fi)
+static void sd_print_vm_line(FILE* file, int count, Registers* regs, port_stack_frame_info* fi)
 {
+    static char pi_blanks[2*sizeof(void*) + 3];
+    static void* pi_blanks_set_res = memset(pi_blanks, ' ', sizeof(pi_blanks));
+    static char pi_blanks_zero_res = (pi_blanks[sizeof(pi_blanks) - 1] = 0);
+
     if (!fi->method_name)
         return;
 
@@ -68,6 +72,11 @@
     else
         fprintf(file, "     "); // additional VM info - indent
 
+    if (regs)
+        fprintf(file, "0x%"W_PI_FMT"  ", regs->get_ip());
+    else
+        fprintf(file, "%s  ", pi_blanks); // additional VM info - indent
+
     const void* args[5] = {fi->method_class_name, fi->method_name,
                      fi->method_signature, fi->source_file_name,
                      (const void*)(size_t)fi->source_line_number};
@@ -93,13 +102,13 @@
 }
 
 
-static void sd_print_c_line(FILE* file, int count, CFunInfo* cfi)
+static void sd_print_c_line(FILE* file, int count, Registers* regs, CFunInfo* cfi)
 {
     if (!cfi->name)
         return;
 
-    fprintf(file, "%3d: %s (%s:%d)\n",
-        count, cfi->name,
+    fprintf(file, "%3d: 0x%"W_PI_FMT"  %s (%s:%d)\n",
+        count, regs->get_ip(), cfi->name,
         cfi->filename ? cfi->filename : "??",
         cfi->line);
 }
@@ -124,6 +133,7 @@
     fprintf(stderr, "\nStack trace:\n");
 
     Registers locregs = *regs;
+    Registers tmpregs = locregs;
     UnwindContext uwcontext;
     bool hasnative = false;
 
@@ -155,10 +165,11 @@
         // Unwinding with VM callback
         if (unwind && uwresult == 0)
         {
-            sd_print_vm_line(stderr, framenum++, &uwinfo);
+            sd_print_vm_line(stderr, framenum++, &tmpregs, &uwinfo);
             // Cleanup frame info except 'iteration_state'
             memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
             // Try unwinding by the callback for next iteration
+            tmpregs = locregs;
             uwresult = unwind(&locregs, &uwinfo);
             continue;
         }
@@ -167,11 +178,11 @@
         CFunInfo cfi = {0};
         native_module_t* module = port_find_module(uwcontext.modules, locregs.get_ip());
         sd_get_c_method_info(&cfi, module, locregs.get_ip());
-        sd_print_c_line(stderr, framenum++, &cfi);
+        sd_print_c_line(stderr, framenum++, &locregs, &cfi);
 
         if (unwind && uwresult < 0 && uwinfo.method_name)
         { // VM has not unwound but has provided additional frame info
-            sd_print_vm_line(stderr, -1, &uwinfo); // Print as additional info
+            sd_print_vm_line(stderr, -1, NULL, &uwinfo); // Print as additional info
         }
 
         if (!hasnative) // Native unwinding is not initialized
@@ -186,6 +197,7 @@
         // Cleanup frame info except 'iteration_state'
         memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
         // Try unwinding by the callback for next iteration
+        tmpregs = locregs;
         uwresult = unwind(&locregs, &uwinfo);
     }
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp Sun May 25 17:33:06 2008
@@ -24,9 +24,11 @@
 
 #include "port_general.h"
 #include "port_barriers.h"
+#include "port_malloc.h"
 
 #include "signals_internal.h"
 #include "port_memaccess.h"
+#include "port_thread_internal.h"
 
 
 extern "C" void port_memcpy_asm(void* dst, const void* src, size_t size,
@@ -35,22 +37,28 @@
 
 static int memcpy_internal(void* dst, const void* src, size_t size, int from)
 {
-    port_tls_data tlsdata;
+    int res;
+    port_tls_data_t* tlsdata = get_private_tls_data();
 
-    if (!get_private_tls_data())
+    if (!tlsdata)
     {
-        if (set_private_tls_data(&tlsdata) != 0)
-            return -1;
+        tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
+
+        res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+        if (res != 0)
+            return res;
     }
 
-    tlsdata.violation_flag = 1;
+    tlsdata->violation_flag = 1;
 
     void* memcpyaddr = (void*)&memcpy;
-    port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
+    port_memcpy_asm(dst, src, size, &tlsdata->restart_address, memcpyaddr);
 
-    if (tlsdata.violation_flag == 1)
+    if (tlsdata->violation_flag == 1)
     {
-        pthread_setspecific(port_tls_key, NULL);
+        tlsdata->violation_flag = 0;
+        port_thread_detach_temporary();
         return 0;
     }
 
@@ -76,14 +84,20 @@
     }
 
     if (result != 0)
+    {
+        tlsdata->violation_flag = 0;
+        port_thread_detach_temporary();
         return -1;
+    }
 
-    tlsdata.violation_flag = 1;
+    tlsdata->violation_flag = 1;
 
-    port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
+    port_memcpy_asm(dst, src, size, &tlsdata->restart_address, memcpyaddr);
 
-    pthread_setspecific(port_tls_key, NULL);
-    return (tlsdata.violation_flag == 1) ? 0 : -1;
+    res = (tlsdata->violation_flag == 1) ? 0 : -1;
+    tlsdata->violation_flag = 0;
+    port_thread_detach_temporary();
+    return res;
 }
 
 

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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -19,67 +19,14 @@
 #define _SIGNALS_INTERNAL_H_
 
 #include "port_general.h"
-#include "port_thread.h"
 #include "open/platform_types.h"
 #include "open/hythread_ext.h" /* For windows.h */
 
-
-/* Thread-specific structure */
-typedef struct
-{
-    /* Previous crash handling stage to restart crash processing */
-    int     crash_stage;
-
-#ifndef WIN32 /* UNIX */
-    /* Flag and restart address for memory access violation detection */
-    int     violation_flag;
-    void*   restart_address;
-#endif /* UNIX */
-
-    /* Flag to indicate that debugger should be attached right in OS handler */
-    Boolean debugger;
-    /* Flag to produce minidump/core on the second exception catch */
-    Boolean   produce_core;
-
-} port_tls_data;
-
-
-#ifdef WIN32
-typedef DWORD port_tls_key_t;
-#else
-typedef pthread_key_t port_tls_key_t;
-#endif
-
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 
-extern port_tls_key_t port_tls_key;
-
-int init_private_tls_data();
-int free_private_tls_data();
-
-PORT_INLINE port_tls_data* get_private_tls_data()
-{
-#ifdef WIN32
-        return (port_tls_data*)TlsGetValue(port_tls_key);
-#else
-        return (port_tls_data*)pthread_getspecific(port_tls_key);
-#endif
-}
-
-PORT_INLINE int set_private_tls_data(port_tls_data* data)
-{
-#ifdef WIN32
-        return TlsSetValue(port_tls_key, data) ? 0 : -1;
-#else
-        return pthread_setspecific(port_tls_key, data);
-#endif
-}
-
-
 /* Transfer control to specified register context */
 void port_transfer_to_regs(Registers* regs);
 
@@ -153,7 +100,7 @@
 /* Internal exception handler */
 LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception);
 
-void __cdecl port_win_dbg_break(void);
+void PORT_CDECL port_win_dbg_break(void);
 
 #else /* UNIX */
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp Sun May 25 17:33:06 2008
@@ -27,64 +27,45 @@
 #include "stack_dump.h"
 #include "../linux/include/gdb_crash_handler.h"
 #include "signals_internal.h"
+#include "port_thread_internal.h"
 
 
-port_tls_key_t port_tls_key;
+#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)
 
-int init_private_tls_data()
-{
-    return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
-}
-
-int free_private_tls_data()
-{
-    return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
-}
 
-
-// Because application can set up some protected area in stack region,
-// we need to re-enable access to this area because we need to operate
-// with the original stack of the thread
-// Application should take care of restoring this protected area after
-// signal processing
-// FIXME This is workaround only; it also can break crash processing for SIGSEGV
-// Ideally all the functionality on guard pages should be in Port.
-// Unfortunately, it can involve thread creation in Port, additional
-// thread wrapper, and moving general TLS operations to Port, so
-// it's postponed
-static void clear_stack_protection(Registers* regs, void* fault_addr)
+bool is_stack_overflow(port_tls_data_t* tlsdata, void* fault_addr)
 {
-    if (!fault_addr) // is not SO
-        return;
-
-    size_t fault = (size_t)fault_addr;
-    size_t sp = (size_t)regs->get_sp();
-    size_t diff = (fault > sp) ? (fault - sp) : (sp - fault);
-    size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE);
-
-    if (diff > page_size)
-        return; // Most probably is not SO
-
-    size_t start = sp & ~(page_size - 1);
-    size_t size = page_size;
+    if (!tlsdata || !fault_addr)
+        return false;
 
-    if (sp - start < 0x400)
+    if (tlsdata->guard_page_addr)
     {
-        start -= page_size;
-        size += page_size;
+        return (fault_addr >= tlsdata->guard_page_addr &&
+                (size_t)fault_addr < (size_t)tlsdata->guard_page_addr
+                                                + tlsdata->guard_page_size);
     }
 
-    int res = mprotect((void*)start, size, PROT_READ | PROT_WRITE);
+    size_t stack_top =
+        (size_t)tlsdata->stack_addr - tlsdata->stack_size + tlsdata->guard_page_size;
+
+    // Determine that fault is beyond stack top
+    return ((size_t)fault_addr < stack_top &&
+            (size_t)fault_addr > stack_top - tlsdata->stack_size);
 }
 
 static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
 { // this exception handler is executed *after* OS signal handler returned
     int result;
+    port_tls_data_t* tlsdata = get_private_tls_data();
 
     switch ((int)signum)
     {
     case SIGSEGV:
-        result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
+        if (tlsdata->restore_guard_page)
+            result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, FALSE);
+        else
+            result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
         break;
     case SIGFPE:
         result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, FALSE);
@@ -108,25 +89,35 @@
     }
 
     if (result == 0)
+    {
+        // Restore guard page if needed
+        if (tlsdata->restore_guard_page)
+        {
+            port_thread_restore_guard_page();
+            tlsdata->restore_guard_page = FALSE;
+
+            if (port_thread_detach_temporary() == 0)
+                STD_FREE(tlsdata);
+        }
         return;
+    }
 
     // We've got a crash
+    if (signum == SIGSEGV)
+    {
+        port_thread_restore_guard_page(); // To catch SO again
+        tlsdata->restore_guard_page = FALSE;
+    }
+
     if (result > 0) // invoke debugger
     { // Prepare second catch of signal to attach GDB from signal handler
-        port_tls_data* tlsdata = get_private_tls_data();
-        if (!tlsdata)
-        {   // STD_MALLOC can be harmful here
-            tlsdata = (port_tls_data*)STD_MALLOC(sizeof(port_tls_data));
-            memset(tlsdata, 0, sizeof(port_tls_data));
-            set_private_tls_data(tlsdata);
-        }
-
+        //assert(tlsdata); // Should be attached - provided by general_signal_handler
         tlsdata->debugger = TRUE;
         return; // To produce signal again
     }
 
     // result < 0 - exit process
-    if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+    if (FLAG_CORE)
     { // Return to the same place to produce the same crash and generate core
         signal(signum, SIG_DFL); // setup default handler
         return;
@@ -145,9 +136,10 @@
 
     // Convert OS context to Registers
     port_thread_context_to_regs(&regs, (ucontext_t*)context);
+    void* fault_addr = info ? info->si_addr : NULL;
 
     // Check if SIGSEGV is produced by port_read/write_memory
-    port_tls_data* tlsdata = get_private_tls_data();
+    port_tls_data_t* tlsdata = get_private_tls_data();
     if (tlsdata && tlsdata->violation_flag)
     {
         tlsdata->violation_flag = 0;
@@ -155,25 +147,87 @@
         return;
     }
 
-    if (tlsdata && tlsdata->debugger)
+    if (!tlsdata) // Tread is not attached - attach thread temporarily
+    {
+        int res;
+        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+        if (tlsdata) // Try to attach the thread
+            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+        if (!tlsdata || res != 0)
+        { // Can't process correctly; perform default actions
+            if (FLAG_DBG)
+            {
+                bool result = gdb_crash_handler(&regs);
+                _exit(-1); // Exit process if not sucessful...
+            }
+
+            if (FLAG_CORE &&
+                signum != SIGABRT) // SIGABRT can't be rethrown
+            {
+                signal(signum, SIG_DFL); // setup default handler
+                return;
+            }
+
+            _exit(-1);
+        }
+
+        // SIGSEGV can represent SO which can't be processed out of signal handler
+        if (signum == SIGSEGV && // This can occur only when a user set an alternative stack
+            is_stack_overflow(tlsdata, fault_addr))
+        {
+            int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
+
+            if (result == 0)
+            {
+                if (port_thread_detach_temporary() == 0)
+                    STD_FREE(tlsdata);
+                return;
+            }
+
+            if (result > 0)
+                tlsdata->debugger = TRUE;
+            else
+            {
+                if (FLAG_CORE)
+                { // Rethrow crash to generate core
+                    signal(signum, SIG_DFL); // setup default handler
+                    return;
+                }
+                _exit(-1);
+            }
+        }
+    }
+
+    if (tlsdata->debugger)
     {
         bool result = gdb_crash_handler(&regs);
         _exit(-1); // Exit process if not sucessful...
     }
 
     if (signum == SIGABRT && // SIGABRT can't be trown again from c_handler
-        (port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
+        FLAG_DBG)
     { // So attaching GDB right here
         bool result = gdb_crash_handler(&regs);
         _exit(-1); // Exit process if not sucessful...
     }
 
-    if (signum == SIGSEGV)
-        clear_stack_protection(&regs, info->si_addr);
+    if (signum == SIGSEGV &&
+        is_stack_overflow(tlsdata, fault_addr))
+    {
+        // Second SO while previous SO is not processed yet - is GPF
+        if (tlsdata->restore_guard_page)
+            tlsdata->restore_guard_page = FALSE;
+        else
+        { // To process signal on protected stack area
+            port_thread_clear_guard_page();
+            tlsdata->restore_guard_page = TRUE;
+        }
+    }
 
     // Prepare registers for transfering control out of signal handler
     void* callback = (void*)&c_handler;
-    void* fault_addr = info ? info->si_addr : NULL;
 
     port_set_longjump_regs(callback, &regs, 3,
                             &regs, (void*)(size_t)signum, fault_addr);
@@ -223,7 +277,8 @@
 
     for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
     {
-        if (!sd_is_handler_registered(signals_used[i].port_sig))
+        if (!sd_is_handler_registered(signals_used[i].port_sig) &&
+            signals_used[i].signal != SIGSEGV) // Sigsegv is needed for port_memaccess
             continue;
 
         sigemptyset(&sa.sa_mask);

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp Sun May 25 17:33:06 2008
@@ -21,37 +21,53 @@
 
 #include "open/platform_types.h"
 #include "port_crash_handler.h"
+#include "port_malloc.h"
 #include "stack_dump.h"
 #include "../linux/include/gdb_crash_handler.h"
 #include "signals_internal.h"
+#include "port_thread_internal.h"
 
 
-port_tls_key_t port_tls_key;
+#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)
 
-int init_private_tls_data()
-{
-    return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
+/* Out-of-signal-handler signal processing is not implemented for IPF
+
+static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
+{ // this exception handler is executed *after* VEH handler returned
 }
+*/
 
-int free_private_tls_data()
+bool is_stack_overflow(port_tls_data_t* tlsdata, void* fault_addr)
 {
-    return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
-}
+    if (!tlsdata || !fault_addr)
+        return false;
 
+    if (tlsdata->guard_page_addr)
+    {
+        return (fault_addr >= tlsdata->guard_page_addr &&
+                (size_t)fault_addr < (size_t)tlsdata->guard_page_addr
+                                                + tlsdata->guard_page_size);
+    }
 
-/* Out-of-signal-handler signal processing is not implemented for IPF
+    size_t stack_top =
+        (size_t)tlsdata->stack_addr - tlsdata->stack_size + tlsdata->guard_page_size;
 
-static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
-{ // this exception handler is executed *after* VEH handler returned
+    // Determine that fault is beyond stack top
+    return ((size_t)fault_addr < stack_top &&
+            (size_t)fault_addr > stack_top - tlsdata->stack_size);
 }
-*/
 
 static void general_signal_handler(int signum, siginfo_t* info, void* context)
 {
     Registers regs;
+    port_tls_data_t* tlsdata = get_private_tls_data();
+
+    if (!context)
+        return;
+
 /* Not implemented
     // Check if SIGSEGV is produced by port_read/write_memory
-    port_tls_data* tlsdata = get_private_tls_data();
     if (tlsdata && tlsdata->violation_flag)
     {
         tlsdata->violation_flag = 0;
@@ -63,6 +79,60 @@
     port_thread_context_to_regs(&regs, (ucontext_t*)context);
 
     void* fault_addr = info ? info->si_addr : NULL;
+
+    if (!tlsdata) // Tread is not attached - attach thread temporarily
+    {
+        int res;
+        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+        if (tlsdata) // Try to attach the thread
+            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+        if (!tlsdata || res != 0)
+        { // Can't process correctly; perform default actions
+            if (FLAG_DBG)
+            {
+                bool result = gdb_crash_handler(&regs);
+                _exit(-1); // Exit process if not sucessful...
+            }
+
+            if (FLAG_CORE &&
+                signum != SIGABRT) // SIGABRT can't be rethrown
+            {
+                signal(signum, SIG_DFL); // setup default handler
+                return;
+            }
+
+            _exit(-1);
+        }
+
+        // SIGSEGV can represent SO which can't be processed out of signal handler
+        if (signum == SIGSEGV && // This can occur only when a user set an alternative stack
+            is_stack_overflow(tlsdata, fault_addr))
+        {
+            int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
+
+            if (result == 0)
+            {
+                if (port_thread_detach_temporary() == 0)
+                    STD_FREE(tlsdata);
+                return;
+            }
+
+            if (result > 0)
+                tlsdata->debugger = TRUE;
+            else
+            {
+                if (FLAG_CORE)
+                { // Rethrow crash to generate core
+                    signal(signum, SIG_DFL); // setup default handler
+                    return;
+                }
+                _exit(-1);
+            }
+        }
+    }
+
     int result;
 
     switch ((int)signum)
@@ -91,21 +161,26 @@
         result = port_process_signal(PORT_SIGNAL_UNKNOWN, &regs, fault_addr, TRUE);
     }
 
-    if (result == 0)
+    // Convert Registers back to OS context
+    port_thread_regs_to_context((ucontext_t*)context, &regs);
+
+    if (result == 0) // Signal was processed - continue execution
+    {
+        if (port_thread_detach_temporary() == 0)
+            STD_FREE(tlsdata);
         return;
+    }
 
     // We've got a crash
     if (result > 0)
     { // result > 0 - invoke debugger
         bool result = gdb_crash_handler(&regs);
-        // Continue with exiting process if not sucessful...
+        // Continue with making core or exiting process if not successful...
     }
 
-    // Convert Registers back to OS context
-    port_thread_regs_to_context((ucontext_t*)context, &regs);
-
     // result < 0 - exit process
-    if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+    if (FLAG_CORE &&
+        signum != SIGABRT) // SIGABRT can't be rethrown
     { // Return to the same place to produce the same crash and generate core
         signal(signum, SIG_DFL); // setup default handler
         return;

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp Sun May 25 17:33:06 2008
@@ -26,12 +26,20 @@
     if (!addr || !prev)
         return -1;
 
+    unsigned char buf;
     unsigned char instr = INSTRUMENTATION_BYTE;
 
-    if (port_read_memory(addr, 1, prev) != 0)
+    int err = port_read_memory(addr, 1, &buf);
+    if (err != 0) return err;
+
+    if (buf == instr)
         return -1;
 
-    return port_write_memory(addr, 1, &instr);
+    err = port_write_memory(addr, 1, &instr);
+    if (err != 0) return err;
+
+    *prev = buf;
+    return 0;
 }
 
 int port_clear_breakpoint(void* addr, unsigned char prev)
@@ -39,6 +47,15 @@
     if (!addr)
         return -1;
 
+    unsigned char buf;
+    unsigned char instr = INSTRUMENTATION_BYTE;
+
+    int err = port_read_memory(addr, 1, &buf);
+    if (err != 0) return err;
+
+    if (buf != instr)
+        return -1;
+
     return port_write_memory(addr, 1, &prev);
 }
 

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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -27,6 +27,7 @@
 #include "port_crash_handler.h"
 #include "stack_dump.h"
 #include "signals_internal.h"
+#include "port_thread_internal.h"
 
 
 #if INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3
@@ -37,10 +38,11 @@
 #error Unknown value of INSTRUMENTATION_BYTE
 #endif
 
+#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)
 
-port_tls_key_t port_tls_key = TLS_OUT_OF_INDEXES;
 
-typedef void (__cdecl *sigh_t)(int); // Signal handler type
+typedef void (PORT_CDECL *sigh_t)(int); // Signal handler type
 
 static PVOID veh = NULL;
 static sigh_t prev_sig = (sigh_t)SIG_ERR;
@@ -53,20 +55,22 @@
 static bool asserts_disabled = false;
 
 
-int init_private_tls_data()
+static void show_debugger_dialog()
 {
-    DWORD key = TlsAlloc();
-
-    if (key == TLS_OUT_OF_INDEXES)
-        return -1;
+    int result = MessageBox(NULL,
+                    "Crash handler has been requested to call the debugger\n\n"
+                    "Press Retry to attach to the debugger\n"
+                    "Press Cancel to terminate the application",
+                    "Crash Handler",
+                    MB_RETRYCANCEL | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL);
 
-    port_tls_key = key;
-    return 0;
-}
+    if (result == IDCANCEL)
+    {
+        _exit(3);
+        return;
+    }
 
-int free_private_tls_data()
-{
-    return TlsFree(port_tls_key) ? 0 : -1;
+    port_win_dbg_break(); // Call the debugger
 }
 
 
@@ -74,7 +78,6 @@
                         void* fault_addr, size_t code, size_t flags)
 { // this exception handler is executed *after* VEH handler returned
     int result;
-    Registers regs = *pregs;
     Boolean iscrash = (DWORD)flags == EXCEPTION_NONCONTINUABLE;
 
     switch ((DWORD)code)
@@ -99,69 +102,127 @@
         result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
     }
 
+    port_tls_data_t* tlsdata = get_private_tls_data();
+
     if (result == 0)
+    {
+        // Restore guard page if needed
+        if (tlsdata->restore_guard_page)
+        {
+            port_thread_restore_guard_page();
+            tlsdata->restore_guard_page = FALSE;
+
+            if (port_thread_detach_temporary() == 0)
+                STD_FREE(tlsdata);
+        }
         return;
+    }
 
-    if (result > 0 || // Assert dialog
-        (port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+    if (result > 0 /*Assert dialog*/|| FLAG_CORE)
     {
         // Prepare second catch of this exception to produce minidump (because
         // we've lost LPEXCEPTION_POINTERS structure) and/or show assert dialog
-        // FIXME: This will not work for stack overflow, because guard page
-        // is disabled automatically - need to restore it somehow
-        port_tls_data* tlsdata = get_private_tls_data();
-        if (!tlsdata)
-        {   // STD_MALLOC can be harmful here
-            tlsdata = (port_tls_data*)STD_MALLOC(sizeof(port_tls_data));
-            memset(tlsdata, 0, sizeof(port_tls_data));
-            set_private_tls_data(tlsdata);
-        }
-
-        if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+        if (FLAG_CORE)
             tlsdata->produce_core = TRUE;
         if (result > 0)
             tlsdata->debugger = TRUE;
+        // To catch STACK_OVERFLOW
+        port_thread_restore_guard_page();
 
         return; // To produce exception again
     }
 
-    _exit(-1);
+    _exit(-1); // We need neither dump nor assert dialog
 }
 
 void prepare_assert_dialog(Registers* regs)
 {
+    // To catch STACK_OVERFLOW
+    port_thread_restore_guard_page();
     shutdown_signals();
 }
 
 LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
 {
+    DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
+    void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress;
+
     Registers regs;
     // Convert NT context to Registers
     port_thread_context_to_regs(&regs, nt_exception->ContextRecord);
 
     // Check if TLS structure is set - probably we should produce minidump
-    port_tls_data* tlsdata = get_private_tls_data();
+    port_tls_data_t* tlsdata = get_private_tls_data();
 
-    if (tlsdata)
+    if (!tlsdata) // Tread is not attached - attach thread temporarily
     {
-        if (tlsdata->produce_core)
-        {
-            tlsdata->produce_core = FALSE;
-            create_minidump(nt_exception);
-            if (!tlsdata->debugger)
+        int res;
+        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+        if (tlsdata) // Try to attach the thread
+            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+        if (!tlsdata || res != 0)
+        { // Can't process correctly; perform default actions
+            if (FLAG_CORE)
+                create_minidump(nt_exception);
+
+            if (FLAG_DBG)
+            {
+                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                 _exit(-1);
+                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
+            }
+
+            _exit(-1);
         }
 
-        if (tlsdata->debugger)
+        // SO for alien thread can't be processed out of VEH
+        if (code == STATUS_STACK_OVERFLOW &&
+            sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
         {
-            // Go to handler to restore CRT/VEH settings and crash once again
-            port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
-            port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
-            return EXCEPTION_CONTINUE_EXECUTION;
+            int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
+
+            if (result == 0)
+            {
+                if (port_thread_detach_temporary() == 0)
+                    STD_FREE(tlsdata);
+                return EXCEPTION_CONTINUE_EXECUTION;
+            }
+
+            if (FLAG_CORE)
+                create_minidump(nt_exception);
+
+            if (result > 0)
+            {
+                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
+                _exit(-1);
+                shutdown_signals();
+                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
+            }
+
+            _exit(-1);
         }
     }
 
-    switch (nt_exception->ExceptionRecord->ExceptionCode)
+    if (tlsdata->produce_core)
+    {
+        create_minidump(nt_exception);
+        if (!tlsdata->debugger)
+            _exit(-1);
+    }
+
+    if (tlsdata->debugger)
+    {
+        show_debugger_dialog(); // Workaround
+        _exit(-1);
+        // Go to handler to restore CRT/VEH settings and crash once again
+//        port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
+//        port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
+//        return EXCEPTION_CONTINUE_EXECUTION;
+    }
+
+    switch (code)
     {
     case STATUS_STACK_OVERFLOW:
         if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
@@ -187,6 +248,12 @@
         return EXCEPTION_CONTINUE_SEARCH;
     }
 
+    if (code == STATUS_STACK_OVERFLOW)
+    {
+        if (!tlsdata->restore_guard_page)
+            tlsdata->restore_guard_page = TRUE;
+    }
+
     // Prepare to transfering control out of VEH handler
     port_set_longjump_regs(&c_handler, &regs, 4, &regs,
         nt_exception->ExceptionRecord->ExceptionAddress,
@@ -258,25 +325,7 @@
 #endif // _DEBUG
 }
 
-static void show_debugger_dialog()
-{
-    int result = MessageBox(NULL,
-                    "ABORT handler has requested to call the debugger\n\n"
-                    "Press Retry to attach to the debugger\n"
-                    "Press Cancel to terminate the application",
-                    "Crash Handler",
-                    MB_RETRYCANCEL | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL);
-
-    if (result == IDCANCEL)
-    {
-        _exit(3);
-        return;
-    }
-
-    port_win_dbg_break(); // Call the debugger
-}
-
-static void __cdecl sigabrt_handler(int signum)
+static void PORT_CDECL sigabrt_handler(int signum)
 {
     int result = port_process_signal(PORT_SIGNAL_ABORT, NULL, NULL, FALSE);
     // There no reason for checking for 0 - abort() will do _exit(3) anyway
@@ -291,7 +340,7 @@
     _exit(3);
 }
 
-static void __cdecl final_sigabrt_handler(int signum)
+static void PORT_CDECL final_sigabrt_handler(int signum)
 {
     _exit(3);
 }

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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -36,7 +36,7 @@
     }
 }
 
-void __declspec(naked) __cdecl port_win_dbg_break()
+void __declspec(naked) PORT_CDECL port_win_dbg_break()
 {
 __asm { int 3 }
 }

Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h Sun May 25 17:33:06 2008
@@ -0,0 +1,167 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef _PORT_THREAD_INTERNAL_H_
+#define _PORT_THREAD_INTERNAL_H_
+
+#include "port_general.h"
+#include "port_thread.h"
+#include "open/platform_types.h"
+#include "open/hythread_ext.h" /* For windows.h */
+/* UNIX-specific includes */
+#ifndef WIN32
+#include <semaphore.h>
+#endif
+
+/* The name of Port shared library - now crash handler module */
+#define CH_SHLIB_NAME "ch"
+
+#ifdef WIN32
+typedef DWORD port_tls_key_t;
+#else
+typedef pthread_key_t port_tls_key_t;
+#endif
+
+typedef enum
+{
+    THREADREQ_NONE = 0,
+    THREADREQ_SUS = 1,
+    THREADREQ_RES = 2,
+    THREADREQ_YIELD = 3
+} port_suspend_req_t;
+
+
+typedef struct port_thread_info_t port_thread_info_t;
+struct port_thread_info_t
+{
+    osthread_t              thread;
+    thread_context_t        context;
+    int                     suspend_count;
+#ifndef WIN32
+    sem_t                   wake_sem;       /* to sem_post from signal handler */
+#endif /* !WIN32 */
+    port_thread_info_t*       next;
+};
+
+
+typedef struct
+{
+    port_tls_key_t tls_key;
+
+    size_t guard_page_size;
+    size_t guard_stack_size;
+    size_t mem_protect_size;
+    size_t foreign_stack_size;
+
+    /* Stuff for suspend/resume handling */
+    port_thread_info_t* suspended_list;
+#ifdef WIN32
+    CRITICAL_SECTION crit_section;
+#else /* !WIN32 */
+    pthread_mutex_t suspend_init_mutex;
+    pthread_mutex_t suspend_mutex;
+    port_suspend_req_t req_type; /* request type for signal handler */
+    osthread_t suspendee; /* The thread which is processed */
+    sem_t yield_sem; /* Semaphore to inform signal sender */
+    Boolean signal_set; /* Is SIGUSR2 handler set up */
+#endif /* !WIN32 */
+
+} port_shared_data_t;
+
+
+/* Thread-specific structure */
+typedef struct
+{
+    /* vv Threading stuff vv */
+    void*  stack_addr;
+    size_t stack_size;
+    void*  guard_page_addr;
+    size_t guard_page_size;
+    void*  guard_stack_addr;
+    size_t guard_stack_size;
+    size_t mem_protect_size;
+
+    Boolean guard_page_set;
+    Boolean restore_guard_page;
+
+    Boolean foreign; /* The thread was attached */
+    //Boolean temp; /* Is indicated by 0ed guard_page_addr instead */
+
+    /* vv Signal handling stuff vv */
+#ifndef WIN32 /* UNIX */
+    /* Flag and restart address for memory access violation detection */
+    int     violation_flag;
+    void*   restart_address;
+#endif /* UNIX */
+
+    /* vv Crash handling stuff vv */
+    /* Previous crash handling stage to restart crash processing */
+    int     crash_stage;
+
+    /* Flag to indicate that debugger should be attached right in OS handler */
+    Boolean debugger;
+    /* Flag to produce minidump/core on the second exception catch */
+    Boolean   produce_core;
+
+} port_tls_data_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile port_shared_data_t* port_shared_data;
+#define PSD ((port_shared_data_t*)port_shared_data)
+
+int init_port_shared_data();
+
+
+PORT_INLINE port_tls_data_t* get_private_tls_data()
+{
+    if (!port_shared_data && init_port_shared_data() != 0)
+            return NULL;
+#ifdef WIN32
+    return (port_tls_data_t*)TlsGetValue(port_shared_data->tls_key);
+#else
+    return (port_tls_data_t*)pthread_getspecific(port_shared_data->tls_key);
+#endif
+}
+
+PORT_INLINE int set_private_tls_data(port_tls_data_t* data)
+{
+    if (!port_shared_data && init_port_shared_data() != 0)
+            return -1;
+#ifdef WIN32
+    return TlsSetValue(port_shared_data->tls_key, data) ? 0 : -1;
+#else
+    return pthread_setspecific(port_shared_data->tls_key, data);
+#endif
+}
+
+
+/* Is used in both threading and signals */
+int port_thread_attach_local(port_tls_data_t* tlsdata, Boolean temp,
+                                Boolean foreign, size_t stack_size);
+/* Detaches temporarily attached thread */
+int port_thread_detach_temporary();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PORT_THREAD_INTERNAL_H_ */

Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c Sun May 25 17:33:06 2008
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include "port_thread_internal.h"
+
+
+#define SHPORT_SH_NAME ("lib" CH_SHLIB_NAME ".so")
+
+volatile port_shared_data_t* port_shared_data = NULL;
+
+typedef int (*fn_port_init_shared_data_t)(volatile port_shared_data_t** pdata);
+
+
+int init_port_shared_data()
+{
+    void* native_handle;
+    fn_port_init_shared_data_t fn_ptr;
+
+    if (port_shared_data)
+        return 0;
+
+    native_handle = dlopen(SHPORT_SH_NAME, RTLD_NOW | RTLD_GLOBAL);
+
+    if (native_handle == NULL)
+        return -1;
+
+    fn_ptr =
+        (fn_port_init_shared_data_t)dlsym(native_handle, "port_init_shared_data");
+
+    if (!fn_ptr)
+        return -1;
+
+    return fn_ptr(&port_shared_data);
+}

Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c Sun May 25 17:33:06 2008
@@ -0,0 +1,137 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#undef __USE_XOPEN
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "port_mutex.h"
+#include "port_atomic.h"
+#include "port_thread_internal.h"
+
+volatile port_shared_data_t* port_shared_data = NULL;
+
+static pthread_mutex_t g_shared_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+static port_shared_data_t* g_port_shared_data = NULL;
+static port_shared_data_t g_port_shared_data_struct;
+
+#ifdef _EM64T_
+#define MEM_PROTECT_SIZE 0x400
+#elif defined (_IPF_)
+#define MEM_PROTECT_SIZE 0
+#else /* _IA32_ */
+#define MEM_PROTECT_SIZE 0x100
+#endif
+
+static int init_psd_structure(port_shared_data_t* data)
+{
+    int err;
+    pthread_attr_t pthread_attr;
+    size_t stack_size, guard_size;
+
+    memset(data, 0, sizeof(port_shared_data_t));
+
+    if ((err = pthread_key_create(&data->tls_key, NULL)) != 0)
+        return err;
+
+    if ((err = pthread_mutex_init(&data->suspend_mutex, NULL)) != 0)
+        return err;
+
+    if ((err = pthread_mutex_init(&data->suspend_init_mutex, NULL)) != 0)
+        return err;
+
+    pthread_attr_init(&pthread_attr);
+    err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
+    pthread_attr_destroy(&pthread_attr);
+
+    if (err != 0)
+        return err;
+
+    pthread_attr_init(&pthread_attr);
+    err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
+    pthread_attr_destroy(&pthread_attr);
+
+    if (err != 0)
+        return err;
+
+    if (sem_init(&data->yield_sem, 0, 0) != 0)
+        return err;
+
+    data->foreign_stack_size = stack_size;
+    data->guard_page_size = guard_size;
+    data->mem_protect_size = MEM_PROTECT_SIZE;
+    data->req_type = THREADREQ_NONE;
+    data->signal_set = FALSE;
+
+    data->guard_stack_size = 64*1024;
+
+    if (data->guard_stack_size < MINSIGSTKSZ)
+        data->guard_stack_size =
+            (MINSIGSTKSZ + guard_size - 1) & ~(guard_size - 1);
+
+    return 0;
+}
+
+int port_init_shared_data(volatile port_shared_data_t** p_psd)
+{
+    int err = 0;
+
+    if (*p_psd)
+        return 0;
+
+    /* Serialize access to avoid multiple initialization */
+    err = pthread_mutex_lock(&g_shared_data_mutex);
+
+    if (err != 0)
+        return err;
+
+    /* If another thread had filled the pointer */
+    if (*p_psd)
+    {
+        pthread_mutex_unlock(&g_shared_data_mutex);
+        return 0;
+    }
+
+    /* If structure is already initialized */
+    if (!g_port_shared_data)
+    {
+        err = init_psd_structure(&g_port_shared_data_struct);
+
+        if (err == 0)
+            g_port_shared_data = &g_port_shared_data_struct;
+    }
+
+    if (g_port_shared_data)
+        *p_psd = g_port_shared_data;
+
+    pthread_mutex_unlock(&g_shared_data_mutex);
+    return err;
+}
+
+
+int init_port_shared_data()
+{
+    if (port_shared_data)
+        return 0;
+
+    return port_init_shared_data(&port_shared_data);
+}

Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c
------------------------------------------------------------------------------
    svn:eol-style = native