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 [2/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/...
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c Sun May 25 17:33:06 2008
@@ -17,56 +17,45 @@
#define _GNU_SOURCE
#include <assert.h>
-#include <sched.h> // sched_param
+#include <sched.h> // sched_param
#include <semaphore.h>
+#include <signal.h>
#include <unistd.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
+#include <sys/mman.h>
#include <stdlib.h>
-#include "port_thread.h"
-
+#include "port_malloc.h"
+#include "port_thread.h"
+#include "port_thread_internal.h"
-typedef enum
-{
- THREADREQ_NONE = 0,
- THREADREQ_SUS = 1,
- THREADREQ_RES = 2,
- THREADREQ_YIELD = 3
-} os_suspend_req_t;
-
-typedef struct os_thread_info_t os_thread_info_t;
-
-struct os_thread_info_t
-{
- osthread_t thread;
- int suspend_count;
- sem_t wake_sem; /* to sem_post from signal handler */
- thread_context_t context;
-
- os_thread_info_t* next;
-};
-
-
-/* Global mutex to syncronize access to os_thread_info_t list */
-static pthread_mutex_t g_suspend_mutex;
-/* Global list with suspended threads info */
-static os_thread_info_t* g_suspended_list;
-/* request type for signal handler */
-os_suspend_req_t g_req_type;
-/* The thread which is processed */
-static osthread_t g_suspendee;
-/* Semaphore used to inform signal sender about signal delivery */
-static sem_t g_yield_sem;
+// Linux/FreeBSD defines
+#if defined(FREEBSD)
+#define STACK_MMAP_ATTRS \
+ (MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_STACK)
+#else
+#ifdef _IPF_
+#define STACK_MMAP_ATTRS \
+ (MAP_PRIVATE | MAP_ANONYMOUS)
+#else /* !_IPF_ */
+#define STACK_MMAP_ATTRS \
+ (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN)
+#endif /* _IPF_ */
+#endif
+
+#ifdef _IPF_
+#define STACK_MAPPING_ACCESS (PROT_READ | PROT_WRITE)
+#else /* !_IPF_ */
+#define STACK_MAPPING_ACCESS (PROT_READ | PROT_WRITE | PROT_EXEC)
+#endif /* _IPF_ */
/* Forward declarations */
static int suspend_init();
static int suspend_init_lock();
-static os_thread_info_t* init_susres_list_item();
-static os_thread_info_t* suspend_add_thread(osthread_t thread);
+static port_thread_info_t* init_susres_list_item();
+static port_thread_info_t* suspend_add_thread(osthread_t thread);
static void suspend_remove_thread(osthread_t thread);
-static os_thread_info_t* suspend_find_thread(osthread_t thread);
+static port_thread_info_t* suspend_find_thread(osthread_t thread);
static void sigusr2_handler(int signum, siginfo_t* info, void* context);
@@ -88,34 +77,506 @@
}
}
-/**
- * Terminates the os thread.
- */
+typedef void* (PORT_CDECL *pthread_func_t)(void*);
+
+typedef struct
+{
+ port_threadfunc_t fun;
+ void* arg;
+ size_t stack_size;
+} thread_start_struct_t;
+
+static PORT_CDECL int thread_start_func(void* arg)
+{
+ int err, result;
+ port_tls_data_t* tlsdata = NULL;
+ thread_start_struct_t* ptr = (thread_start_struct_t*)arg;
+ port_threadfunc_t fun = ptr->fun;
+ size_t stack_size = ptr->stack_size;
+ arg = ptr->arg;
+ STD_FREE(ptr);
+
+ if (port_shared_data)
+ {
+ tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
+ err = port_thread_attach_local(tlsdata, FALSE, FALSE, stack_size);
+ assert(err == 0);
+ }
+
+ result = fun(arg);
+
+ if (tlsdata)
+ port_thread_detach();
+
+ return result;
+}
+
+int port_thread_create(/* out */osthread_t* phandle, size_t stacksize, int priority,
+ port_threadfunc_t func, void *data)
+{
+ pthread_t thread;
+ pthread_attr_t attr;
+ struct sched_param param;
+ thread_start_struct_t* startstr;
+ int res;
+
+ if (!port_shared_data)
+ {
+ res = init_port_shared_data();
+ /* assert(res); */
+ /* It's OK to have an error here when Port shared library
+ is not available yet; only signals/crash handling will
+ not be available for the thread */
+ /* return res; */
+ }
+
+ if (!func)
+ return EINVAL;
+
+ startstr =
+ (thread_start_struct_t*)STD_MALLOC(sizeof(thread_start_struct_t));
+
+ if (!startstr)
+ return ENOMEM;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (stacksize != 0)
+ {
+ if (stacksize < MINSIGSTKSZ)
+ stacksize = MINSIGSTKSZ;
+
+ if (port_shared_data)
+ {
+ size_t min_stacksize =
+ /* Let's get alt stack size for normal stack and add guard page size */
+ ((2*port_shared_data->guard_stack_size + port_shared_data->guard_page_size)
+ /* Roung up to alt stack size */
+ + port_shared_data->guard_stack_size - 1) & ~(port_shared_data->guard_stack_size - 1);
+
+ if (stacksize < min_stacksize)
+ stacksize = min_stacksize;
+ }
+
+ res = pthread_attr_setstacksize(&attr, stacksize);
+ if (res)
+ {
+ pthread_attr_destroy(&attr);
+ STD_FREE(startstr);
+ return res;
+ }
+ }
+
+ if (priority)
+ {
+ res = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ if (res == 0)
+ {
+ param.sched_priority = priority;
+ res = pthread_attr_setschedparam(&attr, ¶m);
+ }
+ /* This does not work anyway on some Linuses
+ if (res != 0)
+ {
+ pthread_attr_destroy(&attr);
+ STD_FREE(startstr);
+ return res;
+ }*/
+ }
+
+ startstr->fun = func;
+ startstr->arg = data;
+ startstr->stack_size = stacksize;
+
+ res = pthread_create(&thread, &attr, (pthread_func_t)thread_start_func, startstr);
+
+ pthread_attr_destroy(&attr);
+
+ if (res == 0)
+ {
+ *phandle = thread;
+ return 0;
+ }
+
+ STD_FREE(startstr);
+ return res;
+}
+
+static int set_guard_page(port_tls_data_t* tlsdata, Boolean set)
+{
+ int res;
+ stack_t sigalt;
+
+ if (!tlsdata)
+ tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return -1;
+
+ if (!tlsdata->guard_page_addr)
+ return 0;
+
+ if ((set && tlsdata->guard_page_set) ||
+ !set && !tlsdata->guard_page_set)
+ return 0; // Already in needed state
+
+ res = mprotect(tlsdata->guard_page_addr, tlsdata->guard_page_size,
+ set ? PROT_NONE : (PROT_READ | PROT_WRITE | PROT_EXEC));
+
+ if (res != 0)
+ return errno;
+
+ // sets alternative stack
+ sigalt.ss_sp = tlsdata->guard_stack_addr;
+ sigalt.ss_size = tlsdata->guard_stack_size;
+//#if defined(FREEBSD)
+ sigalt.ss_flags = set ? 0 : SS_DISABLE;
+//#else
+// sigalt.ss_flags = set ? SS_ONSTACK : SS_DISABLE;
+//#endif
+ res = sigaltstack(&sigalt, NULL);
+
+ if (res != 0)
+ return errno;
+
+ tlsdata->guard_page_set = set;
+ return 0;
+}
+
+int port_thread_restore_guard_page()
+{
+ return set_guard_page(NULL, TRUE);
+}
+
+int port_thread_clear_guard_page()
+{
+ return set_guard_page(NULL, FALSE);
+}
+
+void port_thread_postpone_guard_page()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata || !tlsdata->guard_page_addr)
+ return;
+
+ tlsdata->restore_guard_page = FALSE;
+}
+
+void* port_thread_get_stack_address()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+ return tlsdata ? tlsdata->stack_addr : NULL;
+}
+
+size_t port_thread_get_stack_size()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+ return tlsdata ? tlsdata->stack_size : 0;
+}
+
+size_t port_thread_get_effective_stack_size()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return 0;
+
+ if (!tlsdata->guard_page_addr || !tlsdata->guard_page_set)
+ return tlsdata->stack_size
+ - PSD->guard_page_size
+ - PSD->mem_protect_size;
+
+ return tlsdata->stack_size - 2*PSD->guard_page_size
+ - PSD->guard_stack_size - PSD->mem_protect_size;
+}
+
+static int setup_stack(port_tls_data_t* tlsdata)
+{
+ int res;
+ void* ptr;
+ stack_t sigalt;
+ size_t current_page_addr, mapping_addr, mapping_size;
+
+ if (!port_shared_data)
+ return -1;
+
+ current_page_addr = ((size_t)&res) & ~(PSD->guard_page_size - 1);
+ // leave place for mmap work
+ mapping_addr = current_page_addr - PSD->guard_page_size;
+ // found size of the stack area which should be maped
+ mapping_size = tlsdata->stack_size
+ - ((size_t)tlsdata->stack_addr - mapping_addr);
+
+ if ((size_t)(&res) - PSD->mem_protect_size
+ < (size_t)tlsdata->guard_page_addr + tlsdata->guard_page_size)
+ return EINVAL;
+
+ // maps unmapped part of the stack
+ ptr = (char*)mmap(tlsdata->stack_addr - tlsdata->stack_size, mapping_size,
+ STACK_MAPPING_ACCESS, STACK_MMAP_ATTRS, -1, 0);
+
+ if (ptr == MAP_FAILED)
+ return errno;
+
+ res = set_guard_page(tlsdata, TRUE);
+
+ if (res != 0)
+ return errno;
+
+ return 0;
+}
+
+inline int find_stack_addr_size(void** paddr, size_t* psize)
+{
+ int err;
+ pthread_attr_t pthread_attr;
+ void* stack_addr;
+ size_t stack_size;
+ pthread_t thread = pthread_self();
+
+ if (!paddr) return EINVAL;
+
+ err = pthread_attr_init(&pthread_attr);
+ if (err != 0) return err;
+
+#if defined(FREEBSD)
+ err = pthread_attr_get_np(thread, &pthread_attr);
+#else
+ err = pthread_getattr_np(thread, &pthread_attr);
+#endif
+ if (err != 0) return err;
+
+ err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size);
+ if (err != 0) return err;
+
+ pthread_attr_destroy(&pthread_attr);
+ *paddr = (void*)((size_t)stack_addr + stack_size);
+ *psize = stack_size;
+ return 0;
+}
+
+static int init_stack(port_tls_data_t* tlsdata, size_t stack_size, Boolean temp)
+{
+ int err;
+ size_t stack_begin;
+
+ if (!port_shared_data)
+ return -1;
+
+ err = find_stack_addr_size(&tlsdata->stack_addr, &tlsdata->stack_size);
+ if (err != 0) return err;
+
+ if (tlsdata->foreign || temp || stack_size == 0)
+ tlsdata->stack_size = PSD->foreign_stack_size;
+ else
+ tlsdata->stack_size = stack_size;
+
+ tlsdata->guard_page_size = PSD->guard_page_size;
+ tlsdata->guard_stack_size = PSD->guard_stack_size;
+ tlsdata->mem_protect_size = PSD->mem_protect_size;
+
+ if (temp)
+ return 0;
+
+ stack_begin = (size_t)tlsdata->stack_addr - tlsdata->stack_size;
+ tlsdata->guard_stack_addr = (void*)(stack_begin + tlsdata->guard_page_size);
+ tlsdata->guard_page_addr =
+ (void*)((size_t)tlsdata->guard_stack_addr + tlsdata->guard_stack_size);
+
+ return setup_stack(tlsdata);
+}
+
+int port_thread_attach_local(port_tls_data_t* tlsdata, Boolean temp,
+ Boolean foreign, size_t stack_size)
+{
+ int res;
+
+ memset(tlsdata, 0, sizeof(port_tls_data_t));
+
+ tlsdata->foreign = foreign;
+ res = init_stack(tlsdata, stack_size, temp);
+ if (res != 0) return res;
+/* They are already zeroed
+ tlsdata->violation_flag = 0;
+ tlsdata->debugger = FALSE;
+ tlsdata->produce_core = FALSE;*/
+
+ res = set_private_tls_data(tlsdata);
+
+ if (res != 0)
+ set_guard_page(tlsdata, FALSE);
+
+ return res;
+}
+
+int port_thread_attach()
+{
+ int res;
+ port_tls_data_t* tlsdata;
+
+ if (!port_shared_data && (res = init_port_shared_data()) != 0)
+ return res;
+
+ if (get_private_tls_data())
+ return 0;
+
+ tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+ if (!tlsdata)
+ return ENOMEM;
+
+ res = port_thread_attach_local(tlsdata, FALSE, TRUE, 0);
+
+ if (res != 0)
+ STD_FREE(tlsdata);
+
+ return res;
+}
+
+int port_thread_detach_temporary()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata || tlsdata->guard_page_addr)
+ return -1;
+
+ return set_private_tls_data(NULL);
+}
+
+int port_thread_detach()
+{
+ port_tls_data_t* tlsdata;
+ int res;
+
+ if (!port_shared_data && (res = init_port_shared_data()) != 0)
+ return res;
+
+ tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return 0;
+
+ if (port_thread_detach_temporary() == 0)
+ return 0;
+
+ res = set_guard_page(tlsdata, FALSE);
+
+ if (res != 0)
+ return res;
+
+ if (tlsdata->foreign)
+ STD_FREE(tlsdata);
+
+ return set_private_tls_data(NULL);
+}
+
+int port_thread_set_priority(osthread_t os_thread, int priority)
+{
+#if defined(FREEBSD)
+ /* Not sure why we don't just use this on linux? - MRH */
+ struct sched_param param;
+ int policy;
+ int r = pthread_getschedparam(os_thread, &policy, ¶m);
+ if (r == 0) {
+ param.sched_priority = priority;
+ r = pthread_setschedparam(os_thread, policy, ¶m);
+ }
+ return r;
+#else
+ // setting thread priority on linux is only supported for current thread
+ if (os_thread == pthread_self()) {
+ int r;
+ struct sched_param param;
+ pid_t self = gettid();
+ param.sched_priority = priority;
+ r = sched_setparam(self, ¶m);
+ return r ? errno : 0;
+ } else {
+ // setting other thread priority not supported on linux
+ return 0;
+ }
+#endif
+}
+
+osthread_t port_thread_current()
+{
+ return pthread_self();
+}
+
+int port_thread_free_handle(osthread_t os_thread)
+{
+ return 0;
+}
+
+int port_thread_join(osthread_t os_thread)
+{
+ int error;
+
+ do {
+ // FIXME - somehow pthread_join returns before thread is terminated
+ error = pthread_join(os_thread, NULL);
+ } while (error != ESRCH && error != EINVAL && error != EDEADLK);
+ return 0;
+}
+
int port_thread_cancel(osthread_t os_thread)
{
int status;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!suspend_init_lock())
return -1;
pinfo = suspend_find_thread(os_thread);
+
+ if (os_thread == pthread_self())
+ {
+ if (pinfo && status == 0)
+ suspend_remove_thread(os_thread);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
+ return pthread_cancel(os_thread);
+ }
+
status = pthread_cancel(os_thread);
if (pinfo && status == 0)
suspend_remove_thread(os_thread);
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
-/**
-* Sends a signal to a thread to make sure thread's write
- * buffers are flushed.
- */
+void port_thread_exit(int status)
+{
+ pthread_exit((void*)(size_t)status);
+}
+
+int port_get_thread_times(osthread_t os_thread, int64* pkernel, int64* puser)
+{
+ clockid_t clock_id;
+ struct timespec tp;
+ int r;
+#ifdef FREEBSD
+ return EINVAL; /* TOFIX: Implement */
+#else
+
+ r = pthread_getcpuclockid(os_thread, &clock_id);
+ if (r) return r;
+
+ r = clock_gettime(clock_id, &tp);
+ if (r) return r;
+
+ *puser = tp.tv_sec * 1000000000ULL + tp.tv_nsec;
+ return 0;
+#endif
+}
+
void port_thread_yield_other(osthread_t os_thread) {
struct timespec timeout;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
+ int err = -1;
if (!suspend_init_lock())
return;
@@ -123,37 +584,35 @@
pinfo = suspend_find_thread(os_thread);
if (pinfo && pinfo->suspend_count > 0) {
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return;
}
- g_suspendee = os_thread;
- g_req_type = THREADREQ_YIELD;
+ PSD->req_type = THREADREQ_YIELD;
assert(os_thread);
if (pthread_kill(os_thread, SIGUSR2) == 0) {
// signal sent, let's do timed wait to make sure the signal
// was actually delivered
- get_exceed_time(&timeout, 1000000L);
- sem_timedwait(&g_yield_sem, &timeout);
+ get_exceed_time(&timeout, 10000000L);
+ err = sem_timedwait(&PSD->yield_sem, &timeout);
+// sem_wait(&PSD->yield_sem);
} else {
if (pinfo)
suspend_remove_thread(os_thread);
}
- g_req_type = THREADREQ_NONE;
- pthread_mutex_unlock(&g_suspend_mutex);
+ if (err != 0)
+ PSD->req_type = THREADREQ_NONE;
+
+ pthread_mutex_unlock(&PSD->suspend_mutex);
}
-/**
- * Suspend given thread
- * @param thread The thread to suspend
- */
int port_thread_suspend(osthread_t thread)
{
int status;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!thread)
return -1;
@@ -168,24 +627,24 @@
if (!pinfo)
{
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return -1;
}
if (pinfo->suspend_count > 0)
{
++pinfo->suspend_count;
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return 0;
}
- g_suspendee = thread;
- g_req_type = THREADREQ_SUS;
+ PSD->suspendee = thread;
+ PSD->req_type = THREADREQ_SUS;
if (pthread_kill(thread, SIGUSR2) != 0)
{
suspend_remove_thread(thread);
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return -1;
}
@@ -194,18 +653,14 @@
/* Check result */
status = (pinfo->suspend_count > 0) ? 0 : -1;
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
-/**
- * Resume given thread
- * @param thread The thread to resume
- */
int port_thread_resume(osthread_t thread)
{
int status;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!thread)
return -1;
@@ -217,24 +672,24 @@
if (!pinfo)
{
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return -1;
}
if (pinfo->suspend_count > 1)
{
--pinfo->suspend_count;
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return 0;
}
- g_suspendee = thread;
- g_req_type = THREADREQ_RES;
+ PSD->suspendee = thread;
+ PSD->req_type = THREADREQ_RES;
if ((status = pthread_kill(thread, SIGUSR2)) != 0)
{
suspend_remove_thread(thread);
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
@@ -243,18 +698,13 @@
suspend_remove_thread(thread);
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return 0;
}
-/**
- * Determine suspend count for the given thread
- * @param thread The thread to check
- * @return -1 if error have occured
- */
int port_thread_get_suspend_count(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
int suspend_count;
if (!thread)
@@ -267,20 +717,14 @@
suspend_count = pinfo ? pinfo->suspend_count : 0;
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return suspend_count;
}
-/**
- * Get context for given thread
- * @param thread The thread to process
- * @param context Pointer to platform-dependant context structure
- * @note The thread must be suspended
- */
int port_thread_get_context(osthread_t thread, thread_context_t *context)
{
int status = -1;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!thread || !context)
return -1;
@@ -292,7 +736,7 @@
if (!pinfo)
{
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
@@ -302,20 +746,14 @@
status = -1;
}
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
-/**
- * Set context for given thread
- * @param thread The thread to process
- * @param context Pointer to platform-dependant context structure
- * @note The thread must be suspended
- */
int port_thread_set_context(osthread_t thread, thread_context_t *context)
{
int status = -1;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!thread || !context)
return -1;
@@ -327,7 +765,7 @@
if (!pinfo)
{
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
@@ -337,53 +775,39 @@
status = 0;
}
- pthread_mutex_unlock(&g_suspend_mutex);
+ pthread_mutex_unlock(&PSD->suspend_mutex);
return status;
}
static int suspend_init()
{
- static int initialized = 0;
struct sigaction sa;
- static pthread_mutex_t suspend_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+ int result = 1;
- if (initialized)
+ if (port_shared_data && PSD->signal_set)
return 1;
- pthread_mutex_lock(&suspend_init_mutex);
-
- if (!initialized)
- {
- /* Initialize all nesessary objects */
- int status;
- pthread_mutex_t mut_init = PTHREAD_MUTEX_INITIALIZER;
-
- status = sem_init(&g_yield_sem, 0, 0);
-
- if (status != 0)
- {
- pthread_mutex_unlock(&suspend_init_mutex);
- return 0;
- }
-
- g_suspend_mutex = mut_init;
- pthread_mutex_init(&g_suspend_mutex, NULL);
+ if (!port_shared_data && init_port_shared_data() != 0)
+ return 0;
- g_suspended_list = NULL;
- g_req_type = THREADREQ_NONE;
+ pthread_mutex_lock(&PSD->suspend_init_mutex);
+ if (!PSD->signal_set)
+ {
/* set signal handler */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_RESTART;
sa.sa_sigaction = sigusr2_handler;
- sigaction(SIGUSR2, &sa, NULL);
- initialized = 1;
+ if (sigaction(SIGUSR2, &sa, NULL) != 0)
+ result = 0;
+ else
+ PSD->signal_set = TRUE;
}
- pthread_mutex_unlock(&suspend_init_mutex);
- return 1;
+ pthread_mutex_unlock(&PSD->suspend_init_mutex);
+ return result;
}
static int suspend_init_lock()
@@ -391,16 +815,16 @@
if (!suspend_init())
return 0;
- if (pthread_mutex_lock(&g_suspend_mutex) != 0)
+ if (pthread_mutex_lock(&PSD->suspend_mutex) != 0)
return 0;
return 1;
}
-static os_thread_info_t* init_susres_list_item()
+static port_thread_info_t* init_susres_list_item()
{
- os_thread_info_t* pinfo =
- (os_thread_info_t*)malloc(sizeof(os_thread_info_t));
+ port_thread_info_t* pinfo =
+ (port_thread_info_t*)malloc(sizeof(port_thread_info_t));
if (pinfo == NULL)
return NULL;
@@ -418,25 +842,25 @@
return pinfo;
}
-static os_thread_info_t* suspend_add_thread(osthread_t thread)
+static port_thread_info_t* suspend_add_thread(osthread_t thread)
{
- os_thread_info_t* pinfo = init_susres_list_item();
+ port_thread_info_t* pinfo = init_susres_list_item();
if (pinfo == NULL)
return NULL;
pinfo->thread = thread;
- pinfo->next = g_suspended_list;
- g_suspended_list = pinfo;
+ pinfo->next = PSD->suspended_list;
+ PSD->suspended_list = pinfo;
return pinfo;
}
static void suspend_remove_thread(osthread_t thread)
{
- os_thread_info_t** pprev = &g_suspended_list;
- os_thread_info_t* pinfo;
+ port_thread_info_t** pprev = &PSD->suspended_list;
+ port_thread_info_t* pinfo;
- for (pinfo = g_suspended_list; pinfo; pinfo = pinfo->next)
+ for (pinfo = PSD->suspended_list; pinfo; pinfo = pinfo->next)
{
if (pinfo->thread == thread)
break;
@@ -452,12 +876,12 @@
}
}
-static os_thread_info_t* suspend_find_thread(osthread_t thread)
+static port_thread_info_t* suspend_find_thread(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
int status;
- for (pinfo = g_suspended_list; pinfo; pinfo = pinfo->next)
+ for (pinfo = PSD->suspended_list; pinfo; pinfo = pinfo->next)
{
if (pinfo->thread == thread)
break;
@@ -470,31 +894,34 @@
static void sigusr2_handler(int signum, siginfo_t* info, void* context)
{
int status;
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
- if (!suspend_init())
+ if (!PSD)
return;
- if (signum != SIGUSR2)
- return;
-
- /* We have g_suspend_mutex locked already */
+ /* We have suspend_mutex locked already */
- if (g_req_type == THREADREQ_YIELD)
+ if (PSD->req_type == THREADREQ_YIELD)
{
- g_req_type = THREADREQ_NONE;
+ PSD->req_type = THREADREQ_NONE;
/* Inform requester */
- sem_post(&g_yield_sem);
+ sem_post(&PSD->yield_sem);
return;
}
- if ((pinfo = suspend_find_thread(g_suspendee)) == NULL)
+ if (PSD->req_type == THREADREQ_NONE)
return;
- if (g_req_type == THREADREQ_SUS)
+ if (!suspend_init() ||
+ (pinfo = suspend_find_thread(PSD->suspendee)) == NULL)
+ {
+ return; /* Return to interrupted THREADREQ_SUS handler */
+ }
+
+ if (PSD->req_type == THREADREQ_SUS)
{
pinfo->suspend_count++;
- g_req_type = THREADREQ_NONE;
+ PSD->req_type = THREADREQ_NONE;
memcpy(&pinfo->context, context, sizeof(ucontext_t));
/* Inform suspender */
sem_post(&pinfo->wake_sem);
@@ -513,10 +940,10 @@
sem_post(&pinfo->wake_sem);
return;
}
- else if (g_req_type == THREADREQ_RES)
+ else if (PSD->req_type == THREADREQ_RES)
{
pinfo->suspend_count--;
- g_req_type = THREADREQ_NONE;
+ PSD->req_type = THREADREQ_NONE;
return; /* Return to interrupted THREADREQ_SUS handler */
}
}
Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_find.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_find.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_find.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/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 "open/hythread_ext.h" // To properly include 'windows.h'
+#include "port_thread_internal.h"
+
+
+#define SHPORT_DLL_NAME (CH_SHLIB_NAME ".dll")
+
+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()
+{
+ HMODULE native_handle;
+ fn_port_init_shared_data_t fn_ptr;
+
+ if (port_shared_data)
+ return 0;
+
+ native_handle = LoadLibrary(SHPORT_DLL_NAME);
+
+ if (native_handle == NULL)
+ return -1;
+
+ fn_ptr =
+ (fn_port_init_shared_data_t)GetProcAddress(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/win/port_thread_tls_find.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c Sun May 25 17:33:06 2008
@@ -0,0 +1,110 @@
+/*
+ * 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 "open/platform_types.h"
+#include "open/hythread_ext.h"
+#include "port_mutex.h"
+#include "port_thread_internal.h"
+
+
+volatile port_shared_data_t* port_shared_data = NULL;
+
+static port_shared_data_t* g_port_shared_data = NULL;
+static port_shared_data_t g_port_shared_data_struct;
+
+
+#define MEM_PROTECT_SIZE 0x100
+
+#ifdef _EM64T_
+#define GUARD_STACK_SIZE (64*1024)
+#else /* IA-32 */
+#define GUARD_STACK_SIZE (find_guard_page_size())
+#endif
+
+
+static size_t find_guard_page_size()
+{
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ return system_info.dwPageSize;
+}
+
+static int init_psd_structure(port_shared_data_t* data)
+{
+ DWORD key;
+
+ if ((key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return -1;
+
+ data->tls_key = key;
+ InitializeCriticalSection(&data->crit_section);
+ data->foreign_stack_size = 0;
+ data->guard_page_size = find_guard_page_size();
+ data->guard_stack_size = GUARD_STACK_SIZE;
+ data->mem_protect_size = MEM_PROTECT_SIZE;
+ return 0;
+}
+
+__declspec(dllexport) int port_init_shared_data(volatile port_shared_data_t** p_psd)
+{
+ int err = 0;
+static CRITICAL_SECTION struct_lock;
+static int lock_initialized = 0;
+
+ if (*p_psd)
+ return 0;
+
+ if (lock_initialized == 0)
+ { /* Probable race condition because of using static flag */
+ InitializeCriticalSection(&struct_lock);
+ lock_initialized = 1;
+ }
+
+ EnterCriticalSection(&struct_lock);
+
+ /* If another thread had filled the pointer */
+ if (*p_psd)
+ {
+ LeaveCriticalSection(&struct_lock);
+ 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;
+
+ LeaveCriticalSection(&struct_lock);
+ 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/win/port_thread_tls_os.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c Sun May 25 17:33:06 2008
@@ -16,39 +16,393 @@
*/
-#include <port_atomic.h>
+#include "port_atomic.h"
+#include "port_malloc.h"
#include "port_thread.h"
+#include "port_thread_internal.h"
-typedef struct os_thread_info_t os_thread_info_t;
+/* Forward declarations */
+static int suspend_init_lock();
+static port_thread_info_t* init_susres_list_item();
+static port_thread_info_t* suspend_add_thread(osthread_t thread);
+static void suspend_remove_thread(osthread_t thread);
+static port_thread_info_t* suspend_find_thread(osthread_t thread);
-struct os_thread_info_t
+
+typedef unsigned (__stdcall *beginthread_func_t)(void*);
+
+typedef struct
{
- osthread_t thread;
- int suspend_count;
- thread_context_t context;
+ port_threadfunc_t fun;
+ void* arg;
+ size_t stack_size;
+} thread_start_struct_t;
- os_thread_info_t* next;
-};
+static unsigned __stdcall thread_start_func(void* arg)
+{
+ int err, result;
+ port_tls_data_t* tlsdata;
+ thread_start_struct_t* ptr = (thread_start_struct_t*)arg;
+ port_threadfunc_t fun = ptr->fun;
+ size_t stack_size = ptr->stack_size;
+ arg = ptr->arg;
+ STD_FREE(ptr);
+ if (port_shared_data)
+ {
+ tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
+ err = port_thread_attach_local(tlsdata, FALSE, FALSE, stack_size);
+ assert(err == 0);
+ }
-static CRITICAL_SECTION g_crit_section;
-static os_thread_info_t* g_suspended_list = NULL;
+ result = (int)fun(arg);
-/* Forward declarations */
-static int suspend_init_lock();
-static os_thread_info_t* init_susres_list_item();
-static os_thread_info_t* suspend_add_thread(osthread_t thread);
-static void suspend_remove_thread(osthread_t thread);
-static os_thread_info_t* suspend_find_thread(osthread_t thread);
+ port_thread_detach();
+ return result;
+}
+
+
+int port_thread_create(/* out */osthread_t* phandle, size_t stacksize, int priority,
+ port_threadfunc_t func, void *data)
+{
+ uintptr_t handle;
+ thread_start_struct_t* startstr;
+ int res;
+
+ if (!port_shared_data)
+ {
+ res = init_port_shared_data();
+ /* assert(res); */
+ /* It's OK to have an error here when Port shared library
+ is not available yet; only signals/crash handling will
+ not be available for the thread */
+ /* return res; */
+ }
+
+ if (!func)
+ return -1;
+
+ startstr =
+ (thread_start_struct_t*)STD_MALLOC(sizeof(thread_start_struct_t));
+
+ if (!startstr)
+ return -1;
+
+ if (stacksize != 0)
+ {
+ if (port_shared_data)
+ {
+ size_t min_stacksize =
+ /* Let's get alt stack size for normal stack and add guard page size */
+ ((2*port_shared_data->guard_stack_size + port_shared_data->guard_page_size)
+ /* Roung up to alt stack size */
+ + port_shared_data->guard_stack_size - 1) & ~(port_shared_data->guard_stack_size - 1);
+
+ if (stacksize < min_stacksize)
+ stacksize = min_stacksize;
+ }
+ }
+
+ startstr->fun = func;
+ startstr->arg = data;
+ startstr->stack_size = stacksize;
+
+ handle = _beginthreadex(NULL, stacksize, thread_start_func, startstr, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
+
+ if (handle != (uintptr_t)-1L)
+ {
+ *phandle = (HANDLE)handle;
+
+ if (priority)
+ SetThreadPriority(*phandle, priority);
+
+ return 0;
+ }
+
+ STD_FREE(startstr);
+ return res;
+}
+
+static int set_guard_page(port_tls_data_t* tlsdata, Boolean set)
+{
+ if (!tlsdata)
+ tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return -1;
+
+ if (!tlsdata->guard_page_addr)
+ return 0;
+
+ if ((set && tlsdata->guard_page_set) ||
+ !set && !tlsdata->guard_page_set)
+ return 0; // Already in needed state
+
+ if (set)
+ {
+ if ((size_t)&set - PSD->mem_protect_size
+ < (size_t)tlsdata->guard_page_addr + tlsdata->guard_page_size)
+ return -1;
+
+ if (!VirtualAlloc(tlsdata->guard_page_addr, tlsdata->guard_page_size,
+ MEM_COMMIT, PAGE_GUARD | PAGE_READWRITE))
+ // should be successful always
+ return -1;
+ }
+ else
+ {
+ DWORD oldProtect;
+
+ if ((size_t)&set < (size_t)tlsdata->guard_page_addr + tlsdata->guard_page_size)
+ return -1;
+
+ if (!VirtualProtect(tlsdata->guard_page_addr, tlsdata->guard_page_size,
+ PAGE_READWRITE, &oldProtect))
+ // should be successful always
+ return -1;
+ }
+
+ tlsdata->guard_page_set = set;
+ return 0;
+}
+
+int port_thread_restore_guard_page()
+{
+ return set_guard_page(NULL, TRUE);
+}
+
+int port_thread_clear_guard_page()
+{
+ return set_guard_page(NULL, FALSE);
+}
+
+void port_thread_postpone_guard_page()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata || !tlsdata->guard_page_addr)
+ return;
+
+ tlsdata->restore_guard_page = FALSE;
+}
+
+void* port_thread_get_stack_address()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+ return tlsdata ? tlsdata->stack_addr : NULL;
+}
+
+size_t port_thread_get_stack_size()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+ return tlsdata ? tlsdata->stack_size : 0;
+}
+
+size_t port_thread_get_effective_stack_size()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return 0;
+
+ if (!tlsdata->guard_page_addr || !tlsdata->guard_page_set)
+ return tlsdata->stack_size
+ - PSD->guard_page_size - PSD->mem_protect_size;
+
+ return tlsdata->stack_size - 2*PSD->guard_page_size
+ - PSD->guard_stack_size - PSD->mem_protect_size;
+}
+
+static int setup_stack(port_tls_data_t* tlsdata)
+{
+#ifdef _EM64T_
+ ULONG guard_stack_size_param;
+#endif
+
+ if (!port_shared_data)
+ return -1;
+
+#ifdef _EM64T_
+ /* this code in future should be used on both platforms x86-32 and x86-64 */
+ guard_stack_size_param = (ULONG)PSD->guard_stack_size;
+
+ if (!SetThreadStackGuarantee(&guard_stack_size_param))
+ /* should be successful always */
+ return -1;
+#endif
+
+ if ((size_t)&tlsdata - PSD->mem_protect_size
+ < (size_t)tlsdata->guard_page_addr + tlsdata->guard_page_size)
+ return -1;
+
+ if (!VirtualFree(tlsdata->guard_stack_addr,
+ tlsdata->guard_stack_size, MEM_DECOMMIT))
+ // should be successful always
+ return -1;
+
+ return 0;
+}
+
+static int find_stack_addr_size(void** paddr, size_t* psize)
+{
+ size_t reg_size;
+ MEMORY_BASIC_INFORMATION memory_information;
+
+ VirtualQuery(&memory_information, &memory_information, sizeof(memory_information));
+ reg_size = memory_information.RegionSize;
+ *paddr = (void*)((size_t)memory_information.BaseAddress + reg_size);
+ *psize = (size_t)*paddr - (size_t)memory_information.AllocationBase;
+ return 0;
+}
+
+static int init_stack(port_tls_data_t* tlsdata, size_t stack_size, Boolean temp)
+{
+ int err;
+ size_t stack_begin;
+
+ if (!port_shared_data)
+ return -1;
+
+ err = find_stack_addr_size(&tlsdata->stack_addr, &tlsdata->stack_size);
+ if (err != 0) return err;
+
+ if (stack_size)
+ tlsdata->stack_size = stack_size;
+
+ tlsdata->guard_page_size = PSD->guard_page_size;
+ tlsdata->guard_stack_size = PSD->guard_stack_size;
+ tlsdata->mem_protect_size = PSD->mem_protect_size;
+
+ if (temp)
+ return 0;
+
+ stack_begin = (size_t)tlsdata->stack_addr - tlsdata->stack_size;
+ tlsdata->guard_stack_addr = (void*)(stack_begin + tlsdata->guard_page_size);
+ tlsdata->guard_page_addr =
+ (void*)((size_t)tlsdata->guard_stack_addr + tlsdata->guard_stack_size);
+
+ return setup_stack(tlsdata);
+}
+
+int port_thread_attach_local(port_tls_data_t* tlsdata, Boolean temp,
+ Boolean foreign, size_t stack_size)
+{
+ int res;
+
+ memset(tlsdata, 0, sizeof(port_tls_data_t));
+
+ tlsdata->foreign = foreign;
+ res = init_stack(tlsdata, stack_size, temp);
+ if (res != 0) return res;
+
+ res = set_private_tls_data(tlsdata);
+
+ if (res != 0)
+ set_guard_page(tlsdata, FALSE);
+
+ return res;
+}
+
+int port_thread_attach()
+{
+ int res;
+ port_tls_data_t* tlsdata;
+
+ if (!port_shared_data && (res = init_port_shared_data()) != 0)
+ return res;
+
+ if (get_private_tls_data())
+ return 0;
+
+ tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+ if (!tlsdata) return ENOMEM;
+
+ res = port_thread_attach_local(tlsdata, FALSE, TRUE, 0);
+
+ if (res != 0)
+ STD_FREE(tlsdata);
+
+ return res;
+}
+
+int port_thread_detach_temporary()
+{
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!tlsdata || tlsdata->guard_page_addr)
+ return -1;
+
+ return set_private_tls_data(NULL);
+}
+
+int port_thread_detach()
+{
+ port_tls_data_t* tlsdata;
+ int res;
+
+ if (!port_shared_data && (res = init_port_shared_data()) != 0)
+ return res;
+
+ tlsdata = get_private_tls_data();
+
+ if (!tlsdata)
+ return 0;
+
+ if (port_thread_detach_temporary() == 0)
+ return 0;
+
+ if (tlsdata->foreign)
+ STD_FREE(tlsdata);
+
+ return set_private_tls_data(NULL);
+}
+
+int port_thread_set_priority(osthread_t os_thread, int priority)
+{
+ if (SetThreadPriority(os_thread, (int)priority)) {
+ return 0;
+ } else {
+ return GetLastError();
+ }
+}
+
+osthread_t port_thread_current()
+{
+ HANDLE hproc = GetCurrentProcess();
+ HANDLE hthread = GetCurrentThread();
+ if (!DuplicateHandle(hproc, hthread,
+ hproc, &hthread, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ return NULL;
+ }
+ return hthread;
+}
+
+int port_thread_free_handle(osthread_t os_thread)
+{
+ BOOL r = CloseHandle(os_thread);
+ return !r;
+}
+
+int port_thread_join(osthread_t os_thread)
+{
+ int error = 0;
+ DWORD r;
+ r = WaitForSingleObject(os_thread, INFINITE);
+ if (r == WAIT_OBJECT_0 || r == WAIT_ABANDONED)
+ r = 0;
+ else
+ r = GetLastError();
+ CloseHandle(os_thread);
+ return r;
+}
-/**
- * Terminates the os thread.
- */
int port_thread_cancel(osthread_t os_thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
int status = TM_ERROR_NONE;
if (!suspend_init_lock())
@@ -62,17 +416,42 @@
if (!TerminateThread(os_thread, 0))
status = (int)GetLastError();
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return status;
}
-/**
- * Causes the other thread to have a memory barrier by suspending
- * and resuming it.
- */
+void port_thread_exit(int status)
+{
+ ExitThread(status);
+}
+
+int port_get_thread_times(osthread_t os_thread, int64* pkernel, int64* puser)
+{
+ FILETIME creation_time;
+ FILETIME exit_time;
+ FILETIME kernel_time;
+ FILETIME user_time;
+ int r;
+
+ r = GetThreadTimes(os_thread,
+ &creation_time, &exit_time, &kernel_time, &user_time);
+
+ if (r) {
+ // according to MSDN, time is counted in 100 ns units, so we need to multiply by 100
+ *pkernel = 100 *
+ (((int64)kernel_time.dwHighDateTime << 32)
+ | kernel_time.dwLowDateTime);
+ *puser = 100 *
+ (((int64)user_time.dwHighDateTime << 32)
+ | user_time.dwLowDateTime);
+ return 0;
+ } else
+ return GetLastError();
+}
+
void port_thread_yield_other(osthread_t os_thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
/*
* Synchronization is needed to avoid cyclic (mutual) suspension problem.
@@ -85,7 +464,7 @@
pinfo = suspend_find_thread(os_thread);
if (pinfo && pinfo->suspend_count > 0) {
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return;
}
@@ -94,17 +473,13 @@
ResumeThread(os_thread);
}
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
}
-/**
- * Suspend given thread
- * @param thread The thread to suspend
- */
int port_thread_suspend(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
DWORD old_count;
if (!thread)
@@ -120,14 +495,14 @@
if (!pinfo)
{
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_OUT_OF_MEMORY;
}
if (pinfo->suspend_count > 0)
{
++pinfo->suspend_count;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
@@ -136,22 +511,18 @@
if (old_count == (DWORD)-1)
{
int status = (int)GetLastError();
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return status;
}
++pinfo->suspend_count;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
-/**
- * Resume given thread
- * @param thread The thread to resume
- */
int port_thread_resume(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
DWORD old_count;
if (!thread)
@@ -164,14 +535,14 @@
if (!pinfo)
{
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_UNATTACHED_THREAD;
}
if (pinfo->suspend_count > 1)
{
--pinfo->suspend_count;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
@@ -180,25 +551,20 @@
if (old_count == (DWORD)-1)
{
int status = (int)GetLastError();
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return status;
}
if (--pinfo->suspend_count == 0)
suspend_remove_thread(thread);
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
-/**
- * Determine suspend count for the given thread
- * @param thread The thread to check
- * @return -1 if error have occured
- */
int port_thread_get_suspend_count(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
int suspend_count;
if (!thread)
@@ -210,19 +576,13 @@
pinfo = suspend_find_thread(thread);
suspend_count = pinfo ? pinfo->suspend_count : 0;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return suspend_count;
}
-/**
- * Get context for given thread
- * @param thread The thread to process
- * @param context Pointer to platform-dependant context structure
- * @note The thread must be suspended
- */
int port_thread_get_context(osthread_t thread, thread_context_t *context)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
CONTEXT local_context;
if (!thread || !context)
@@ -235,7 +595,7 @@
if (!pinfo)
{
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_UNATTACHED_THREAD;
}
@@ -248,25 +608,19 @@
if (!GetThreadContext(thread, &local_context))
{
int status = (int)GetLastError();
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return status;
}
pinfo->context = local_context;
*context = local_context;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
-/**
- * Set context for given thread
- * @param thread The thread to process
- * @param context Pointer to platform-dependant context structure
- * @note The thread must be suspended
- */
int port_thread_set_context(osthread_t thread, thread_context_t *context)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
if (!thread || !context)
return -1;
@@ -278,19 +632,19 @@
if (!pinfo)
{
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_UNATTACHED_THREAD;
}
if (!SetThreadContext(thread, context))
{
int status = (int)GetLastError();
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return status;
}
pinfo->context = *context;
- LeaveCriticalSection(&g_crit_section);
+ LeaveCriticalSection(&PSD->crit_section);
return TM_ERROR_NONE;
}
@@ -304,17 +658,17 @@
// Critical section should be initialized only once,
// do nothing in case someone else already initialized it.
if (port_atomic_cas16((volatile uint16*)&initialized, 1, 0) == 0)
- InitializeCriticalSectionAndSpinCount(&g_crit_section, 400);
+ InitializeCriticalSectionAndSpinCount(&PSD->crit_section, 400);
}
- EnterCriticalSection(&g_crit_section);
+ EnterCriticalSection(&PSD->crit_section);
return 1;
}
-static os_thread_info_t* init_susres_list_item()
+static port_thread_info_t* init_susres_list_item()
{
- os_thread_info_t* pinfo =
- (os_thread_info_t*)malloc(sizeof(os_thread_info_t));
+ port_thread_info_t* pinfo =
+ (port_thread_info_t*)malloc(sizeof(port_thread_info_t));
if (pinfo)
pinfo->suspend_count = 0;
@@ -322,26 +676,26 @@
return pinfo;
}
-static os_thread_info_t* suspend_add_thread(osthread_t thread)
+static port_thread_info_t* suspend_add_thread(osthread_t thread)
{
- os_thread_info_t* pinfo = init_susres_list_item();
+ port_thread_info_t* pinfo = init_susres_list_item();
if (!pinfo)
return NULL;
pinfo->thread = thread;
- pinfo->next = g_suspended_list;
- g_suspended_list = pinfo;
+ pinfo->next = PSD->suspended_list;
+ PSD->suspended_list = pinfo;
return pinfo;
}
static void suspend_remove_thread(osthread_t thread)
{
- os_thread_info_t** pprev = &g_suspended_list;
- os_thread_info_t* pinfo;
+ port_thread_info_t** pprev = &PSD->suspended_list;
+ port_thread_info_t* pinfo;
- for (pinfo = g_suspended_list; pinfo; pinfo = pinfo->next)
+ for (pinfo = PSD->suspended_list; pinfo; pinfo = pinfo->next)
{
if (pinfo->thread == thread)
break;
@@ -356,11 +710,11 @@
}
}
-static os_thread_info_t* suspend_find_thread(osthread_t thread)
+static port_thread_info_t* suspend_find_thread(osthread_t thread)
{
- os_thread_info_t* pinfo;
+ port_thread_info_t* pinfo;
- for (pinfo = g_suspended_list; pinfo; pinfo = pinfo->next)
+ for (pinfo = PSD->suspended_list; pinfo; pinfo = pinfo->next)
{
if (pinfo->thread == thread)
break;
Modified: harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def (original)
+++ harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def Sun May 25 17:33:06 2008
@@ -53,7 +53,6 @@
hythread_get_id
hythread_get_thread
hythread_get_thread_times
-hythread_get_thread_stacksize
hythread_struct_init
hythread_cancel_all
hythread_group_create
Modified: harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp (original)
+++ harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp Sun May 25 17:33:06 2008
@@ -39,7 +39,6 @@
hythread_resume;
hythread_monitor_notify;
hythread_get_priority;
-hythread_get_thread_stacksize;
hythread_tls_get;
hythread_tls_get_request_offset;
hythread_get_hythread_offset_in_tls;
Modified: harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c Sun May 25 17:33:06 2008
@@ -38,7 +38,7 @@
* @returns 0 on success or negative value on failure (priority wasn't changed)
*/
IDATA VMCALL hythread_set_priority(hythread_t thread, UDATA priority) {
- int r = os_thread_set_priority(thread->os_handle, priority);
+ int r = port_thread_set_priority(thread->os_handle, priority);
if (r) return r;
thread->priority = priority;
return 0;
Modified: harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c (original)
+++ harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c Sun May 25 17:33:06 2008
@@ -87,7 +87,6 @@
self = hythread_self();
new_thread->library = self ? self->library : TM_LIBRARY;
new_thread->priority = priority ? priority : HYTHREAD_PRIORITY_NORMAL;
- new_thread->stacksize = stacksize ? stacksize : TM_DEFAULT_STACKSIZE;
if (!wrapper) {
hythread_start_proc_data_t start_proc_data;
@@ -112,9 +111,10 @@
}
// Need to make sure thread will not register itself with a thread group
- // until os_thread_create returned and initialized thread->os_handle properly.
+ // until port_thread_create returned and initialized thread->os_handle properly.
hythread_global_lock();
- result = os_thread_create(&new_thread->os_handle, new_thread->stacksize,
+ result = port_thread_create(&new_thread->os_handle,
+ stacksize ? stacksize : TM_DEFAULT_STACKSIZE,
priority, wrapper, data);
assert(/* error */ result || new_thread->os_handle /* or thread created ok */);
hythread_global_unlock();
@@ -166,6 +166,7 @@
hythread_library_t lib,
hythread_group_t group)
{
+ int res;
IDATA status;
hythread_t self = hythread_self();
@@ -176,13 +177,19 @@
new_thread->library = TM_LIBRARY;
if (self) {
- // to avoid creating multiple OS handle
+ // to avoid creating multiple OS handles
new_thread->os_handle = self->os_handle;
} else {
- new_thread->os_handle = os_thread_current();
+ new_thread->os_handle = port_thread_current();
}
assert(new_thread->os_handle);
+ res = port_thread_attach();
+ // It's OK to have an error here when Port shared library
+ // is not available yet; only signals/crash handling will
+ // not be available for the thread
+ //assert(res == 0);
+
CTRACE(("TM: native attached: native: %p ", new_thread));
status = hythread_set_to_group(new_thread,
@@ -277,6 +284,9 @@
// Detach if thread is attached to group.
hythread_remove_from_group(thread);
+ if (thread == hythread_self()) // Detach current thread only
+ port_thread_detach();
+
// FIXME - uncomment after TM state transition complete
// release thread data
//hythread_struct_release(thread);
@@ -525,7 +535,7 @@
osthread_t os_handle = thread->os_handle;
hythread_detach(thread);
port_thread_cancel(os_handle);
- os_thread_join(os_handle);
+ port_thread_join(os_handle);
}
/**
@@ -679,7 +689,7 @@
hythread_monitor_t monitor;
// release thread OS handle
- result = os_thread_free(new_thread->os_handle);
+ result = port_thread_free_handle(new_thread->os_handle);
assert(0 == result);
resume = new_thread->resume_event;
@@ -697,7 +707,6 @@
new_thread->java_status = jstatus;
new_thread->priority = HYTHREAD_PRIORITY_NORMAL;
- new_thread->stacksize = os_get_foreign_thread_stack_size();
port_mutex_lock(&new_thread->mutex);
new_thread->state = TM_THREAD_STATE_NEW;
@@ -754,7 +763,7 @@
start_proc = start_proc_data.proc;
CTRACE(("TM: native thread started: native: %p tm: %p",
- apr_os_thread_current(), thread));
+ port_thread_current(), thread));
// check hythread library state
if (hythread_lib_state() != TM_LIBRARY_STATUS_INITIALIZED) {
@@ -774,7 +783,7 @@
hythread_set_self(NULL);
CTRACE(("TM: native thread terminated due to shutdown: native: %p tm: %p",
- apr_os_thread_current(), thread));
+ port_thread_current(), thread));
// release hythread global lock
status = hythread_global_unlock();
@@ -832,7 +841,7 @@
hythread_monitor_exit(monitor);
}
hythread_detach_ex(NULL);
- os_thread_exit(0);
+ port_thread_exit(0);
// unreachable statement
abort();
}
@@ -847,14 +856,10 @@
* @returns 0 on success, system error code otherwise
*/
UDATA hythread_get_thread_times(hythread_t thread, int64* pkernel, int64* puser) {
- return os_get_thread_times(thread->os_handle, pkernel, puser);
+ return port_get_thread_times(thread->os_handle, pkernel, puser);
}
-UDATA hythread_get_thread_stacksize(hythread_t thread) {
- return thread->stacksize;
-}
-
IDATA VMCALL hythread_thread_lock(hythread_t thread) {
assert(thread);
return port_mutex_lock(&thread->mutex);
Modified: harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h Sun May 25 17:33:06 2008
@@ -304,17 +304,7 @@
/*
* portability functions, private for thread module
*/
-int os_thread_create(osthread_t* phandle, UDATA stacksize, UDATA priority,
- hythread_wrapper_t func, void *data);
-int os_thread_set_priority(osthread_t thread, int priority);
-osthread_t os_thread_current();
-int os_thread_free(osthread_t os_thread);
-void os_thread_exit(IDATA status);
-int os_thread_join(osthread_t os_thread);
-int os_get_thread_times(osthread_t os_thread, int64* pkernel, int64* puser);
-
int os_cond_timedwait(hycond_t *cond, osmutex_t *mutex, I_64 ms, IDATA nano);
-UDATA os_get_foreign_thread_stack_size();
#ifdef __cplusplus
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h Sun May 25 17:33:06 2008
@@ -269,10 +269,7 @@
void exn_rethrow();
void exn_rethrow_if_pending();
-bool set_guard_stack();
typedef struct VM_thread * vm_thread_t;
-void remove_guard_stack(vm_thread_t vm_thread);
-void init_stack_info();
void* get_exception_catch_stack_addr(void* curr_ip);
VMEXPORT size_t get_available_stack_size();
VMEXPORT bool check_available_stack_size(size_t required_size);
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp Sun May 25 17:33:06 2008
@@ -35,6 +35,7 @@
#include "object_handles.h"
#include "vm_arrays.h"
#include "vm_strings.h"
+#include "port_thread.h"
#include "cci.h"
#include "ExpandableMemBlock.h"
@@ -120,15 +121,17 @@
clear_exception_internal();
tmn_suspend_enable_recursive();
- // if quard stack should be restored - restores it
+ // This will restore quard stack if needed
if (p_TLS_vmthread->restore_guard_page) {
- bool result = set_guard_stack();
+ int res = port_thread_restore_guard_page();
// if guard stack can't be restored raise SOE
- if (result == false) {
+ if (res != 0) {
Global_Env *env = VM_Global_State::loader_env;
exn_raise_by_class(env->java_lang_StackOverflowError_Class);
}
+
+ p_TLS_vmthread->restore_guard_page = false;
}
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp Sun May 25 17:33:06 2008
@@ -652,16 +652,16 @@
// si_create_from_registers uses large stack space,
// so guard page restored after its invoke.
if (p_TLS_vmthread->restore_guard_page) {
- bool result = set_guard_stack();
+ int res = port_thread_restore_guard_page();
- if (result == false) {
+ if (res != 0) {
Global_Env *env = VM_Global_State::loader_env;
if (si_is_native(si)) {
m2n_set_last_frame(prev_m2n);
- if ((interpreter_enabled() || (!prev_m2n)
- || (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
+ if ((interpreter_enabled() || (!prev_m2n) ||
+ (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
exn_raise_by_class(env->java_lang_StackOverflowError_Class);
} else {
//si_free(si);
@@ -672,6 +672,8 @@
exn_throw_by_class(env->java_lang_StackOverflowError_Class);
}
}
+
+ p_TLS_vmthread->restore_guard_page = false;
}
si_transfer_control(si);
@@ -699,16 +701,16 @@
// but befor ti agent callback invokation,
// because it should work on protected page.
if (p_TLS_vmthread->restore_guard_page) {
- bool result = set_guard_stack();
+ int res = port_thread_restore_guard_page();
- if (result == false) {
+ if (res != 0) {
Global_Env *env = VM_Global_State::loader_env;
if (si_is_native(si)) {
m2n_set_last_frame(prev_m2n);
- if ((interpreter_enabled() || (!prev_m2n)
- || (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
+ if ((interpreter_enabled() || (!prev_m2n) ||
+ (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
exn_raise_by_class(env->java_lang_StackOverflowError_Class);
} else {
//si_free(si);
@@ -719,6 +721,8 @@
exn_throw_by_class(env->java_lang_StackOverflowError_Class);
}
}
+
+ p_TLS_vmthread->restore_guard_page = false;
}
if (!si_is_native(si))
@@ -732,6 +736,7 @@
*exn_obj = jvmti_jit_exception_catch_event_callback_call( *exn_obj,
catch_method_jit, catch_method, catch_method_location);
}
+
si_transfer_control(si);
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp Sun May 25 17:33:06 2008
@@ -189,8 +189,6 @@
jni_env->reserved0 = (void *) 0x1234abcd;
*p_jni_env = jni_env;
- init_stack_info();
-
m2n_null_init(p_m2n);
m2n_set_last_frame(p_m2n);
@@ -248,11 +246,6 @@
gc_thread_kill(&p_vm_thread->_gc_private_information);
}
-#ifdef PLATFORM_POSIX
- // Remove guard page on the stack on linux
- remove_guard_stack(p_vm_thread);
-#endif // PLATFORM_POSIX
-
if (ti_is_enabled())
{
apr_status_t UNREF status;
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp Sun May 25 17:33:06 2008
@@ -26,6 +26,7 @@
#include "open/vm_properties.h"
#include "jthread.h"
#include "vm_threads.h"
+#include "port_thread.h"
#include "jni.h"
static jmethodID jthread_get_run_method(JNIEnv * env, jthread java_thread);
@@ -86,7 +87,7 @@
hythread_set_self(NULL);
CTRACE(("TM: native thread terminated due to shutdown: native: %p tm: %p",
- apr_os_thread_current(), native_thread));
+ port_thread_current(), native_thread));
// FIXME - uncomment after TM state transition complete
//STD_FREE(native_thread);
@@ -127,7 +128,7 @@
vm_thread->daemon = start_proc_data.daemon;
CTRACE(("TM: Java thread started: id=%d OS_handle=%p",
- hythread_get_id(native_thread), apr_os_thread_current()));
+ hythread_get_id(native_thread), port_thread_current()));
if (!vm_thread->daemon) {
status = hythread_increase_nondaemon_threads_count(native_thread);
@@ -179,7 +180,7 @@
assert(status == TM_ERROR_NONE);
CTRACE(("TM: Java thread finished: id=%d OS_handle=%p",
- hythread_get_id(native_thread), apr_os_thread_current()));
+ hythread_get_id(native_thread), port_thread_current()));
hythread_detach_ex(native_thread);
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp Sun May 25 17:33:06 2008
@@ -23,9 +23,164 @@
#include "init.h"
#include "vm_threads.h"
#include "environment.h"
+#include "exceptions.h"
#include "signals.h"
+#ifdef PLATFORM_POSIX
+
+#if defined(_EM64T_)
+#define RESTORE_STACK_SIZE 0x0400
+#elif defined (_IA32_)
+#define RESTORE_STACK_SIZE 0x0100
+#else // IPF
+#define RESTORE_STACK_SIZE 0x0200
+#endif
+
+#else // WINDOWS
+#define RESTORE_STACK_SIZE 0x0100
+#endif
+
+
+size_t get_available_stack_size()
+{
+ size_t stack_addr = (size_t)port_thread_get_stack_address();
+ size_t stack_size = port_thread_get_effective_stack_size();
+ size_t used_stack_size = stack_addr - (size_t)&stack_size;
+ size_t available_stack_size = stack_size - used_stack_size;
+
+ return (available_stack_size > 0) ? available_stack_size : 0;
+}
+
+bool check_available_stack_size(size_t required_size)
+{
+ size_t available_stack_size = get_available_stack_size();
+
+ if (available_stack_size < required_size)
+ {
+ port_thread_clear_guard_page();
+ p_TLS_vmthread->restore_guard_page = true;
+ Global_Env *env = VM_Global_State::loader_env;
+ exn_raise_by_class(env->java_lang_StackOverflowError_Class);
+ return false;
+ }
+
+ return true;
+}
+
+static inline size_t get_available_stack_size(void* sp) {
+ size_t stack_addr = (size_t)port_thread_get_stack_address();
+ size_t stack_size = port_thread_get_effective_stack_size();
+ size_t used_stack_size = stack_addr - (size_t)sp;
+ size_t available_stack_size = stack_size - used_stack_size;
+
+ return (available_stack_size > 0) ? available_stack_size : 0;
+}
+
+bool check_stack_size_enough_for_exception_catch(void* sp)
+{
+ size_t stack_addr = (size_t)port_thread_get_stack_address();
+ size_t stack_size = port_thread_get_effective_stack_size();
+ size_t used_stack_size = stack_addr - (size_t)sp;
+ size_t available_stack_size = stack_size - used_stack_size;
+
+ return RESTORE_STACK_SIZE < available_stack_size;
+}
+
+Boolean stack_overflow_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
+{
+ TRACE2("signals", ("SOE detected at ip=%p, sp=%p",
+ regs->get_ip(), regs->get_sp()));
+
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
+
+ if (is_in_ti_handler(vmthread, saved_ip))
+ {
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
+ }
+
+ if (!vmthread || env == NULL)
+ return FALSE; // Crash
+
+ port_thread_postpone_guard_page();
+ vmthread->restore_guard_page = true;
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
+ {
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
+ }
+
+ Class* exn_class = env->java_lang_StackOverflowError_Class;
+
+ if (is_in_java(regs))
+ {
+ signal_throw_java_exception(regs, exn_class);
+ }
+ else if (is_unwindable())
+ {
+ if (hythread_is_suspend_enabled())
+ hythread_suspend_disable();
+ signal_throw_exception(regs, exn_class);
+ } else {
+ exn_raise_by_class(exn_class);
+ }
+
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
+
+ return TRUE;
+}
+
+Boolean null_reference_handler(port_sigtype UNREF signum, Registers* regs, void* fault_addr)
+{
+ TRACE2("signals", "NPE detected at " << regs->get_ip());
+
+ vm_thread_t vmthread = get_thread_ptr();
+ Global_Env* env = VM_Global_State::loader_env;
+ void* saved_ip = regs->get_ip();
+ void* new_ip = NULL;
+
+ if (is_in_ti_handler(vmthread, saved_ip))
+ {
+ new_ip = vm_get_ip_from_regs(vmthread);
+ regs->set_ip(new_ip);
+ }
+
+ if (!vmthread || env == NULL)
+ return FALSE; // Crash
+
+ if (!is_in_java(regs) || interpreter_enabled())
+ return FALSE; // Crash
+
+ // Pass exception to NCAI exception handler
+ bool is_handled = 0;
+ ncai_process_signal_event((NativeCodePtr)regs->get_ip(),
+ (jint)signum, false, &is_handled);
+ if (is_handled)
+ {
+ if (new_ip)
+ regs->set_ip(saved_ip);
+ return TRUE;
+ }
+
+ signal_throw_java_exception(regs, env->java_lang_NullPointerException_Class);
+
+ if (new_ip && regs->get_ip() == new_ip)
+ regs->set_ip(saved_ip);
+
+ return TRUE;
+}
+
Boolean abort_handler(port_sigtype UNREF signum, Registers* UNREF regs, void* fault_addr)
{
TRACE2("signals", "Abort detected at " << regs->get_ip());