Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 75524 invoked from network); 26 May 2008 00:33:32 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 26 May 2008 00:33:32 -0000 Received: (qmail 10872 invoked by uid 500); 26 May 2008 00:33:33 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 10847 invoked by uid 500); 26 May 2008 00:33:33 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 10838 invoked by uid 99); 26 May 2008 00:33:33 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 May 2008 17:33:33 -0700 X-ASF-Spam-Status: No, hits=-1996.2 required=10.0 tests=ALL_TRUSTED,FRT_GUARANTEE1,FUZZY_GUARANTEE X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 May 2008 00:32:53 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id B1D2E2388A49; Sun, 25 May 2008 17:33:09 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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/... Date: Mon, 26 May 2008 00:33:07 -0000 To: commits@harmony.apache.org From: iberezhn@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080526003309.B1D2E2388A49@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 -#include // sched_param +#include // sched_param #include +#include #include -#include -#include +#include #include -#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 +#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());