From nobody Mon Sep 17 00:00:00 2001 From: Ilya Berezhniuk Date: Thu, 21 Feb 2008 20:48:29 +0300 Subject: [PATCH] PORT thread basic implementation apr_memory_rw_barrier is replaced with port_rw_barrier removed unused port/src/thread/**/apr_thread_ext.c Implemented transfer_to_regs(Registers* regs) function for Win/Linux x86/x86_64 JVMTI control transfers are switched from si_transfer_control to transfer_to_regs Transfer control stubs in VM are slightly modified --- make/vm/port.xml | 5 + vm/doc/doc.properties | 1 vm/include/open/hythread_ext.h | 4 vm/port/include/port_general.h | 4 vm/port/include/port_thread.h | 40 ++-- vm/port/src/thread/linux/apr_thread_ext.c | 219 ---------------------- vm/port/src/thread/linux/thread_asm_em64t.s | 82 ++++++++ vm/port/src/thread/linux/thread_asm_ia32.s | 58 ++++++ vm/port/src/thread/linux/thread_ipf.cpp | 30 +++ vm/port/src/thread/win/apr_thread_ext.c | 195 -------------------- vm/port/src/thread/win/thread_asm_em64t.asm | 89 +++++++++ vm/port/src/thread/win/thread_asm_ia32.asm | 68 +++++++ vm/tests/unit/thread/test_stress_suspend_1.c | 4 vm/tests/unit/thread/test_stress_suspend_2.c | 4 vm/tests/unit/thread/test_stress_suspend_3.c | 4 vm/tests/unit/thread/test_stress_suspend_4.c | 4 vm/tests/unit/thread/test_stress_suspend_5.c | 4 vm/tests/unit/thread/test_stress_suspend_6.c | 4 vm/thread/doc/ThreadManager.htm | 2 vm/thread/src/thread_native_suspend.c | 5 - vm/thread/src/thread_native_thin_monitor.c | 3 vm/thread/src/thread_private.h | 1 vm/vmcore/src/jvmti/jvmti_break_intf.cpp | 15 +- vm/vmcore/src/lil/em64t/stack_iterator_em64t.cpp | 11 - vm/vmcore/src/lil/ia32/stack_iterator_ia32.cpp | 7 - vm/vmcore/src/thread/thread_ti_timing.cpp | 1 26 files changed, 391 insertions(+), 473 deletions(-) mode change 100644 => 100755 vm/port/include/port_thread.h delete mode 100644 vm/port/src/thread/linux/apr_thread_ext.c create mode 100755 vm/port/src/thread/linux/thread_asm_em64t.s create mode 100755 vm/port/src/thread/linux/thread_asm_ia32.s create mode 100755 vm/port/src/thread/linux/thread_ipf.cpp delete mode 100644 vm/port/src/thread/win/apr_thread_ext.c create mode 100755 vm/port/src/thread/win/thread_asm_em64t.asm create mode 100755 vm/port/src/thread/win/thread_asm_ia32.asm 145e54382dbb8cd834413dd5a710211bef6b9eba diff --git a/make/vm/port.xml b/make/vm/port.xml index ae7fdcb..7ed5d58 100644 --- a/make/vm/port.xml +++ b/make/vm/port.xml @@ -54,6 +54,7 @@ + @@ -65,6 +66,10 @@ + + + + diff --git a/vm/doc/doc.properties b/vm/doc/doc.properties index 8c822d4..46d7c27 100644 --- a/vm/doc/doc.properties +++ b/vm/doc/doc.properties @@ -132,7 +132,6 @@ vmi.intf= \ ${classlib.dir}/modules/luni/src/main/native/include/shared/vmi.h \ apr_extension.intf= \ -port/include/apr_thread_ext.h \ port/include/clog.h \ port/include/cxxlog.h \ port/include/lil.h \ diff --git a/vm/include/open/hythread_ext.h b/vm/include/open/hythread_ext.h index 3e5bd55..47a46e3 100644 --- a/vm/include/open/hythread_ext.h +++ b/vm/include/open/hythread_ext.h @@ -133,7 +133,7 @@ #include #include #include -#include "apr_thread_ext.h" +#include "port_barriers.h" //@{ /** @@ -641,7 +641,7 @@ hy_inline void VMCALL hythread_suspend_d thread = tm_self_tls; ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (((HyThread_public *)thread)->request && ((HyThread_public *)thread)->disable_count == 1) { diff --git a/vm/port/include/port_general.h b/vm/port/include/port_general.h index 12afd99..20ec145 100644 --- a/vm/port/include/port_general.h +++ b/vm/port/include/port_general.h @@ -38,11 +38,11 @@ #define PORT_INLINE inline #else // !__cplusplus #ifdef WIN32 -#define PORT_INLINE __inline +#define PORT_INLINE __forceinline #else // !WIN32 #ifdef __linux__ -#define PORT_INLINE inline __attribute__((always_inline)) +#define PORT_INLINE static __attribute__((always_inline)) #else // !__linux__ #define PORT_INLINE static #endif // __linux__ diff --git a/vm/port/include/port_thread.h b/vm/port/include/port_thread.h old mode 100644 new mode 100755 index c431eec..b1551b8 --- a/vm/port/include/port_thread.h +++ b/vm/port/include/port_thread.h @@ -14,31 +14,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#ifndef _PORT_THREAD_H_ +#define _PORT_THREAD_H_ + /** - * @author Andrey Chernyshev - * @version $Revision$ + * @file port_thread.h + * @brief PORT thread support */ -#ifndef APR_EXT_H -#define APR_EXT_H -#include -#include -#include -#include +/* To skip platform_types.h inclusion */ +typedef struct Registers Registers; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** @name Threads manipulation and information + */ +//@{ -APR_DECLARE(apr_status_t) apr_thread_set_priority(apr_thread_t *thread, apr_int32_t priority); -APR_DECLARE(void) apr_memory_rw_barrier(); +/* Transfer control to specified register context */ +void transfer_to_regs(Registers* regs); -APR_DECLARE(apr_status_t) apr_thread_yield_other(apr_thread_t *thread); -APR_DECLARE(apr_status_t) apr_thread_times(apr_thread_t *thread, - apr_time_t * kernel_time, apr_time_t * user_time); -APR_DECLARE(apr_status_t) apr_thread_cancel(apr_thread_t *thread); +//@} -APR_DECLARE(apr_status_t) apr_get_thread_time(apr_thread_t *thread, apr_int64_t* nanos_ptr); +#ifdef __cplusplus +} +#endif -#endif /* APR_EXT_H */ +#endif /* _PORT_THREAD_H_ */ diff --git a/vm/port/src/thread/linux/apr_thread_ext.c b/vm/port/src/thread/linux/apr_thread_ext.c deleted file mode 100644 index bf24c37..0000000 --- a/vm/port/src/thread/linux/apr_thread_ext.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * 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. - */ -/** - * @author Artem Aliev - * @version $Revision$ - */ - -#define _GNU_SOURCE 1 -#include "apr_thread_ext.h" -//#include "apr_arch_threadproc.h" -#include -#include - -int convert_priority(apr_int32_t priority); - -APR_DECLARE(apr_status_t) apr_thread_set_priority(apr_thread_t *thread, - apr_int32_t priority) -{ - /* HANDLE *os_thread; - apr_status_t status; - - if (status = apr_os_thread_get(&((apr_os_thread_t *)os_thread), thread)) { - return status; - } - - if (SetThreadPriority(os_thread, (int)convert_priority(priority))) { - return APR_SUCCESS; - } else { - return apr_get_os_error(); - } - */ - return APR_SUCCESS; -} - -int convert_priority(apr_int32_t priority) { - return (int)priority; -} - - - -pthread_mutex_t yield_other_mutex = PTHREAD_MUTEX_INITIALIZER; -sem_t yield_other_sem; -int yield_other_init_flag = 0; - -void yield_other_handler(int signum, siginfo_t* info, void* context) { - if (yield_other_init_flag) { - sem_post(&yield_other_sem); - } - -} - -static void init_thread_yield_other () { - struct sigaction sa; - //init notification semaphore - sem_init(&yield_other_sem,0,0); - //set signal handler - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO | SA_RESTART; - sa.sa_sigaction = yield_other_handler; - sigaction(SIGUSR2, &sa, NULL); - yield_other_init_flag = 1; - -} -// touch thread to flash memory -APR_DECLARE(apr_status_t) apr_thread_yield_other(apr_thread_t* thread) { - apr_status_t status; - pthread_t *os_thread; - struct timespec timeout; - timeout.tv_sec = 1; - timeout.tv_nsec = 0; - - pthread_mutex_lock(&yield_other_mutex); - if (!yield_other_init_flag) { - init_thread_yield_other (); - } - if (!thread - || (status = apr_os_thread_get((apr_os_thread_t**)&os_thread, thread)) !=APR_SUCCESS - || !*os_thread) { - pthread_mutex_unlock(&yield_other_mutex); - return status; - } - if((pthread_kill(*os_thread, SIGUSR2))) { - } else - { - // let's do timed wait to workaroud missed signals - // sem_wait(&yield_other_sem); - sem_timedwait(&yield_other_sem,&timeout); - } - pthread_mutex_unlock(&yield_other_mutex); - return APR_SUCCESS; -} - -APR_DECLARE(void) apr_memory_rw_barrier() { -#if defined(_EM64T_) - asm volatile ("mfence" : : : "memory"); -#elif defined(_IPF_) - asm volatile ("mf" : : : "memory"); -#else // General x86 case - /* - * This code must use a lock-prefixed assembly instruction, so that - * we can support P3 processors (SSE2 only). With P4 and SSE3, we - * could use 'mfence'. - * References: - * Java Memory Model cookbook - * - http://gee.cs.oswego.edu/dl/jmm/cookbook.html - * Linux Kernel, mb() function - * - http://lxr.linux.no/source/include/asm-i386/system.h - * This is a GCC inline assembly command. The final bit, "memory", will - * clobber all of the memory registers. - */ - asm volatile ("lock; addl $0,0(%%esp)" : : : "memory"); -#endif -} - -APR_DECLARE(apr_status_t) apr_thread_times(apr_thread_t *thread, - apr_time_t * kernel_time, apr_time_t * user_time){ -/* FILETIME creationTime; - FILETIME exitTime; - FILETIME kernelTime; - FILETIME userTime; - HANDLE hThread; - SYSTEMTIME sysTime; - int res; - __int64 xx; - __int32 * pp; - - res = GetThreadTimes( - thread->td, - &creationTime, - &exitTime, - &kernelTime, - &userTime - ); - - printf( "Creation time = %08x %08x\n", creationTime.dwHighDateTime, creationTime.dwLowDateTime); - printf( "Exit time = %08x %08x\n", exitTime.dwHighDateTime, exitTime.dwLowDateTime); - printf( "Kernrl time = %08x %08x %08d\n", kernelTime.dwHighDateTime - , kernelTime.dwLowDateTime, kernelTime.dwLowDateTime); - printf( "User time = %08x %08x %08d\n", userTime.dwHighDateTime - , userTime.dwLowDateTime, userTime.dwLowDateTime); - printf("%d\n", - ((unsigned)exitTime.dwLowDateTime - (unsigned)creationTime.dwLowDateTime)/10000000); - - FileTimeToSystemTime(&creationTime, &sysTime); - printf("%d %d %d %d %d %d \n", sysTime.wYear, sysTime.wMonth, - sysTime.wHour + 3, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); - - pp = (int*)&xx; - *pp = kernelTime.dwLowDateTime; - *(pp + 1) = kernelTime.dwHighDateTime; - *kernel_time = xx; - pp = (int*)&xx; - *pp = userTime.dwLowDateTime; - *(pp + 1) = userTime.dwHighDateTime; - *user_time = xx;*/ - - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_get_thread_time(apr_thread_t *thread, apr_int64_t* nanos_ptr) -{ -#ifdef FREEBSD - return APR_ENOTIME; /* TOFIX: Implement */ -#else - clockid_t clock_id; - pthread_t *os_thread; - struct timespec tp; - apr_status_t status; - int res; - if (!thread) - return APR_DETACH; - status = apr_os_thread_get((apr_os_thread_t**)&os_thread, thread); - if(status!=APR_SUCCESS) - { - return status; - } - - res = pthread_getcpuclockid(*os_thread, &clock_id); - if (0 != res) - { - return APR_ENOTIME; - } - res = clock_gettime(clock_id, &tp); - - if (0 != res) - { - return APR_ENOTIME; - } - - *nanos_ptr = tp.tv_sec * 1000000000ULL + tp.tv_nsec; - return APR_SUCCESS; -#endif -} - - -APR_DECLARE(apr_status_t) apr_thread_cancel(apr_thread_t *thread) { - apr_os_thread_t *os_thread; - apr_status_t status = apr_os_thread_get(&os_thread, thread); - - if (status ) { - return status; - } - status = pthread_cancel(*(pthread_t *)os_thread); - return status; -} diff --git a/vm/port/src/thread/linux/thread_asm_em64t.s b/vm/port/src/thread/linux/thread_asm_em64t.s new file mode 100755 index 0000000..1d88ab6 --- /dev/null +++ b/vm/port/src/thread/linux/thread_asm_em64t.s @@ -0,0 +1,82 @@ +// +// 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. + + .text + .align 16 + +// struct Registers { +// uint64 rsp; ; 00h +// uint64 rbp; ; 08h +// uint64 rip; ; 10h +// // callee-saved +// uint64 rbx; ; 18h +// uint64 r12; ; 20h +// uint64 r13; ; 28h +// uint64 r14; ; 30h +// uint64 r15; ; 38h +// // scratched +// uint64 rax; ; 40h +// uint64 rcx; ; 48h +// uint64 rdx; ; 50h +// uint64 rsi; ; 58h +// uint64 rdi; ; 60h +// uint64 r8; ; 68h +// uint64 r9; ; 70h +// uint64 r10; ; 78h +// uint64 r11; ; 80h +// +// uint32 eflags;; 88h +// }; +// +// void transfer_to_regs(Registers* regs) + +.globl transfer_to_regs + .type transfer_to_regs, @function +transfer_to_regs: + movq %rdi, %rdx // regs pointer (1st param - RDI) -> RDX + + movq 0x08(%rdx), %rbp // RBP field + movq 0x18(%rdx), %rbx // RBX field + movq 0x20(%rdx), %r12 // R12 field + movq 0x28(%rdx), %r13 // R13 field + movq 0x30(%rdx), %r14 // R14 field + movq 0x38(%rdx), %r15 // R15 field + movq 0x58(%rdx), %rsi // RSI field + movq 0x60(%rdx), %rdi // RDI field + movq 0x68(%rdx), %r8 // R8 field + movq 0x70(%rdx), %r9 // R9 field + movq 0x78(%rdx), %r10 // R10 field + movq 0x80(%rdx), %r11 // R11 field + + movq 0x00(%rdx), %rax // (new RSP) -> RAX + movq %rax, (%rsp) // (new RSP) -> [RSP] for future use + movq 0x10(%rdx), %rcx // (new RIP) -> RCX + movq %rcx, -0x88(%rax)// (new RIP) -> [(new RSP) - 128 - 8] + movq 0x40(%rdx), %rax // RAX field + + movzbq 0x88(%rdx), %rcx // (EFLAGS & 0xff) -> RCX + test %rcx, %rcx + je __skipefl__ + push %rcx + popfq +__skipefl__: + + movq 0x48(%rdx), %rcx // RCX field + movq 0x50(%rdx), %rdx // RDX field + + movq (%rsp), %rsp // load new RSP + jmpq * -0x88(%rsp) // JMP to new RIP + diff --git a/vm/port/src/thread/linux/thread_asm_ia32.s b/vm/port/src/thread/linux/thread_asm_ia32.s new file mode 100755 index 0000000..0530184 --- /dev/null +++ b/vm/port/src/thread/linux/thread_asm_ia32.s @@ -0,0 +1,58 @@ +// +// 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. + + .text + .align 4 + +// struct Registers { +// uint32 eax; +00 +// uint32 ebx; +04 +// uint32 ecx; +08 +// uint32 edx; +0C +// uint32 edi; +10 +// uint32 esi; +14 +// uint32 ebp; +18 +// uint32 esp; +1C +// uint32 eip; +20 +// uint32 eflags; +24 +// }; +// +// void transfer_to_regs(Registers* regs) + +.globl transfer_to_regs + .type transfer_to_regs, @function +transfer_to_regs: + movl 0x04(%esp), %edx // store regs pointer to EDX + movl 0x20(%edx), %ebx // EIP field -> EBX + movl 0x1C(%edx), %ecx // ESP field + subl $4, %ecx + movl %ecx, 0x04(%esp) // (new ESP - 4) -> [ESP + 4] (safe storage) + movl 0x14(%edx), %esi // ESI field + movl 0x10(%edx), %edi // EDI field + movl 0x18(%edx), %ebp // EBP field + movl %ebx, (%ecx) // new EIP -> (new ESP - 4) (as return address) + movl 0x00(%edx), %eax // EAX field + movl 0x04(%edx), %ebx // EBX field + movzbl 0x24(%edx), %ecx // (EFLAGS & 0xff) -> ECX + test %ecx, %ecx + je _label_ + push %ecx // restore EFLAGS + popfl +_label_: + movl 0x08(%edx), %ecx // ECX field + movl 0x0C(%edx), %edx // EDX field + movl 0x04(%esp), %esp // ((new ESP - 4) -> ESP + ret // JMP by RET diff --git a/vm/port/src/thread/linux/thread_ipf.cpp b/vm/port/src/thread/linux/thread_ipf.cpp new file mode 100755 index 0000000..7b4b70a --- /dev/null +++ b/vm/port/src/thread/linux/thread_ipf.cpp @@ -0,0 +1,30 @@ +/* + * 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 +#include +#include +#include "open/platform_types.h" + + +void transfer_to_regs(Registers* regs) +{ + // FIXME: not implemented + fprintf(stderr, "FIXME: transfer_to_regs: not implemented\n"); + assert(0); + abort(); +} diff --git a/vm/port/src/thread/win/apr_thread_ext.c b/vm/port/src/thread/win/apr_thread_ext.c deleted file mode 100644 index 8612a15..0000000 --- a/vm/port/src/thread/win/apr_thread_ext.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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. - */ -/** - * @author Artem Aliev - * @version $Revision:$ - */ - -#include -#include -#include "apr_thread_ext.h" -#include - -// MSVC barrier intrinsics setup -#if _MSC_VER < 1400 - // VC++ 2003 - extern void _ReadWriteBarrier(); - extern void _mm_mfence(void); -#else - // VC++ 2005 - #include - #include -#endif - -#if !defined(__INTEL_COMPILER) -# pragma intrinsic (_ReadWriteBarrier) -#else -# define _ReadWriteBarrier __memory_barrier -#endif - - -APR_DECLARE(apr_status_t) apr_thread_set_priority(apr_thread_t *thread, - apr_int32_t priority) -{ - HANDLE *os_thread; - apr_status_t status; - - if (status = apr_os_thread_get(&((apr_os_thread_t *)os_thread), thread)) { - return status; - } - - if (SetThreadPriority(*os_thread, (int)priority)) { - return APR_SUCCESS; - } else { - return apr_get_os_error(); - } -} - -// touch thread to flash memory -APR_DECLARE(apr_status_t) apr_thread_yield_other(apr_thread_t* thread) { - HANDLE *os_thread = NULL; - apr_status_t status; - - static CRITICAL_SECTION *yield_other_mutex = NULL; - if (yield_other_mutex == NULL) { - CRITICAL_SECTION *cs = malloc(sizeof(CRITICAL_SECTION)); - InitializeCriticalSectionAndSpinCount(cs, 400); - // there should be the only one CS - // do nothing if some one else already init it. - if(apr_atomic_casptr ((volatile void**)&yield_other_mutex, (void*)cs, NULL)) { - DeleteCriticalSection(cs); - free(cs); - } - } - - if (status = apr_os_thread_get(&((apr_os_thread_t *)os_thread), thread)) { - return status; - } - if(!os_thread) { - return status; - } - - /* - * Synchronization is needed to avoid cyclic (mutual) suspension problem. - * Accordingly to MSDN, it is possible on multiprocessor box that - * 2 threads suspend each other and become deadlocked. - */ - EnterCriticalSection(yield_other_mutex); - if(-1 != SuspendThread(*os_thread)) { - /* suspended successfully, so resume it back. */ - ResumeThread(*os_thread); - } - LeaveCriticalSection(yield_other_mutex); - return APR_SUCCESS; -} - -APR_DECLARE(void) apr_memory_rw_barrier() { -#ifdef _EM64T_ - // if x86_64/x64/EM64T, then use an mfence to flush memory caches - _mm_mfence(); -#else - /* otherwise, we assume this is an x86, so insert an inline assembly - * macro to insert a lock instruction - * - * the lock is what's needed, so the 'add' is setup, essentially, as a no-op - */ - __asm {lock add [esp], 0 } -#endif - - _ReadWriteBarrier(); -} - -APR_DECLARE(apr_status_t) apr_thread_times(apr_thread_t *thread, - apr_time_t * kernel_time, apr_time_t * user_time){ - FILETIME creationTime; - FILETIME exitTime; - FILETIME kernelTime; - FILETIME userTime; - HANDLE *hThread; - SYSTEMTIME sysTime; - int res; - __int64 xx; - __int32 * pp; - apr_status_t status; - - if (status = apr_os_thread_get(&((apr_os_thread_t *)hThread), thread)) { - return status; - } - - res = GetThreadTimes( - *hThread, - &creationTime, - &exitTime, - &kernelTime, - &userTime - ); - - printf( "Creation time = %08x %08x\n", creationTime.dwHighDateTime, creationTime.dwLowDateTime); - printf( "Exit time = %08x %08x\n", exitTime.dwHighDateTime, exitTime.dwLowDateTime); - printf( "Kernrl time = %08x %08x %08d\n", kernelTime.dwHighDateTime - , kernelTime.dwLowDateTime, kernelTime.dwLowDateTime); - printf( "User time = %08x %08x %08d\n", userTime.dwHighDateTime - , userTime.dwLowDateTime, userTime.dwLowDateTime); - printf("%d\n", - ((unsigned)exitTime.dwLowDateTime - (unsigned)creationTime.dwLowDateTime)/10000000); - - FileTimeToSystemTime(&creationTime, &sysTime); - printf("%d %d %d %d %d %d \n", sysTime.wYear, sysTime.wMonth, - sysTime.wHour + 3, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); - - pp = (int*)&xx; - *pp = kernelTime.dwLowDateTime; - *(pp + 1) = kernelTime.dwHighDateTime; - *kernel_time = xx; - pp = (int*)&xx; - *pp = userTime.dwLowDateTime; - *(pp + 1) = userTime.dwHighDateTime; - *user_time = xx; - - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_get_thread_time(apr_thread_t *thread, apr_int64_t* nanos_ptr) -{ - HANDLE *os_thread; - apr_status_t status; - FILETIME creation_time, exit_time, kernel_time, user_time; - if (status = apr_os_thread_get(&((apr_os_thread_t *)os_thread), thread)!=APR_SUCCESS) { - return status; - } - GetThreadTimes(*os_thread, &creation_time, - &exit_time, &kernel_time, - &user_time); - - *nanos_ptr=(Int64ShllMod32((&user_time)->dwHighDateTime, 32)|(&user_time)->dwLowDateTime);//*100; - // *nanos_ptr = user_time * 100; // convert to nanos - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_thread_cancel(apr_thread_t *thread) { - HANDLE *os_thread; - apr_status_t status; - if (status = apr_os_thread_get(&((apr_os_thread_t *)os_thread), thread)) { - return status; - } - - if (TerminateThread(*os_thread, 0)) { - return APR_SUCCESS; - } else { - return apr_get_os_error(); - } -} diff --git a/vm/port/src/thread/win/thread_asm_em64t.asm b/vm/port/src/thread/win/thread_asm_em64t.asm new file mode 100755 index 0000000..1580d68 --- /dev/null +++ b/vm/port/src/thread/win/thread_asm_em64t.asm @@ -0,0 +1,89 @@ +; +; 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. + + +_TEXT SEGMENT + +; struct Registers { +; uint64 rsp; ; 00h +; uint64 rbp; ; 08h +; uint64 rip; ; 10h +; // callee-saved +; uint64 rbx; ; 18h +; uint64 r12; ; 20h +; uint64 r13; ; 28h +; uint64 r14; ; 30h +; uint64 r15; ; 38h +; // scratched +; uint64 rax; ; 40h +; uint64 rcx; ; 48h +; uint64 rdx; ; 50h +; uint64 rsi; ; 58h +; uint64 rdi; ; 60h +; uint64 r8; ; 68h +; uint64 r9; ; 70h +; uint64 r10; ; 78h +; uint64 r11; ; 80h +; +; uint32 eflags;; 88h +; }; +; +; void transfer_to_regs(Registers* regs) + +PUBLIC transfer_to_regs + +transfer_to_regs PROC + + mov rdx, rcx ; regs pointer (1st param - RCX) -> RDX + + mov rbp, qword ptr [rdx+08h] ; RBP field + mov rbx, qword ptr [rdx+18h] ; RBX field + mov r12, qword ptr [rdx+20h] ; R12 field + mov r13, qword ptr [rdx+28h] ; R13 field + mov r14, qword ptr [rdx+30h] ; R14 field + mov r15, qword ptr [rdx+38h] ; R15 field + mov rsi, qword ptr [rdx+58h] ; RSI field + mov rdi, qword ptr [rdx+60h] ; RDI field + mov r8, qword ptr [rdx+68h] ; R8 field + mov r9, qword ptr [rdx+70h] ; R9 field + mov r10, qword ptr [rdx+78h] ; R10 field + mov r11, qword ptr [rdx+80h] ; R11 field + + mov rax, qword ptr [rdx+00h] ; (new RSP) -> RAX + mov qword ptr [rsp], rax ; (new RSP) -> [RSP] for future use + mov rcx, qword ptr [rdx+10h] ; (new RIP) -> RCX + mov qword ptr [rax-88h],rcx ; (new RIP) -> [(new RSP) - 128 - 8] + mov rax, qword ptr [rdx+40h] ; RAX field + + movzx rcx, byte ptr [rdx+88h] ; (EFLAGS & 0xff) -> RCX + test rcx, rcx + je __skipefl__ + push rcx + popfq +__skipefl__: + + mov rcx, qword ptr [rdx+48h] ; RCX field + mov rdx, qword ptr [rdx+50h] ; RDX field + + mov rsp, qword ptr [rsp] ; load new RSP + jmp qword ptr [rsp-88h] ; JMP to new RIP + +transfer_to_regs ENDP + + +_TEXT ENDS + +END diff --git a/vm/port/src/thread/win/thread_asm_ia32.asm b/vm/port/src/thread/win/thread_asm_ia32.asm new file mode 100755 index 0000000..1b8241a --- /dev/null +++ b/vm/port/src/thread/win/thread_asm_ia32.asm @@ -0,0 +1,68 @@ +; +; 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. + + .386P + +_TEXT SEGMENT PARA USE32 PUBLIC 'CODE' + +; struct Registers { +; uint32 eax; +00 +; uint32 ebx; +04 +; uint32 ecx; +08 +; uint32 edx; +0C +; uint32 edi; +10 +; uint32 esi; +14 +; uint32 ebp; +18 +; uint32 esp; +1C +; uint32 eip; +20 +; uint32 eflags; +24 +; }; +; +; void transfer_to_regs(Registers* regs) + +PUBLIC transfer_to_regs + +transfer_to_regs PROC + + mov edx, dword ptr [esp+04h] ; store regs pointer to EDX + mov ebx, dword ptr [edx+20h] ; EIP field -> EBX + mov ecx, dword ptr [edx+1Ch] ; ESP field + sub ecx,4 + mov dword ptr [esp+04h], ecx ; (new ESP - 4) -> [ESP + 4] (safe storage) + mov esi, dword ptr [edx+14h] ; ESI field + mov edi, dword ptr [edx+10h] ; EDI field + mov ebp, dword ptr [edx+18h] ; EBP field + mov dword ptr [ecx], ebx ; new EIP -> (new ESP - 4) (as return address) + mov eax, dword ptr [edx+00h] ; EAX field + mov ebx, dword ptr [edx+04h] ; EBX field + movzx ecx, byte ptr [edx+24h] ; (EFLAGS & 0xff) -> ECX + test ecx, ecx + je _label_ + push ecx ; restore EFLAGS + popfd +_label_: + mov ecx, dword ptr [edx+08h] ; ECX field + mov edx, dword ptr [edx+0Ch] ; EDX field + mov esp, dword ptr [esp+04h] ; ((new ESP - 4) -> ESP + ret ; JMP by RET + +transfer_to_regs ENDP + + +_TEXT ENDS + +END + diff --git a/vm/tests/unit/thread/test_stress_suspend_1.c b/vm/tests/unit/thread/test_stress_suspend_1.c index 502bdb5..c3865c4 100644 --- a/vm/tests/unit/thread/test_stress_suspend_1.c +++ b/vm/tests/unit/thread/test_stress_suspend_1.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/tests/unit/thread/test_stress_suspend_2.c b/vm/tests/unit/thread/test_stress_suspend_2.c index f06f59a..73d3ec8 100644 --- a/vm/tests/unit/thread/test_stress_suspend_2.c +++ b/vm/tests/unit/thread/test_stress_suspend_2.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/tests/unit/thread/test_stress_suspend_3.c b/vm/tests/unit/thread/test_stress_suspend_3.c index 7efb4f7..58060f2 100644 --- a/vm/tests/unit/thread/test_stress_suspend_3.c +++ b/vm/tests/unit/thread/test_stress_suspend_3.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/tests/unit/thread/test_stress_suspend_4.c b/vm/tests/unit/thread/test_stress_suspend_4.c index ee0c346..2891be8 100644 --- a/vm/tests/unit/thread/test_stress_suspend_4.c +++ b/vm/tests/unit/thread/test_stress_suspend_4.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/tests/unit/thread/test_stress_suspend_5.c b/vm/tests/unit/thread/test_stress_suspend_5.c index 8ef12ac..63e59d1 100644 --- a/vm/tests/unit/thread/test_stress_suspend_5.c +++ b/vm/tests/unit/thread/test_stress_suspend_5.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/tests/unit/thread/test_stress_suspend_6.c b/vm/tests/unit/thread/test_stress_suspend_6.c index 79ae33f..bb9220c 100644 --- a/vm/tests/unit/thread/test_stress_suspend_6.c +++ b/vm/tests/unit/thread/test_stress_suspend_6.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -46,7 +46,7 @@ hy_inline void test_hythread_suspend_dis assert(((HyThread_public *)thread)->group == get_java_thread_group()); ((HyThread_public *)thread)->disable_count++; - //apr_memory_rw_barrier(); + //port_rw_barrier(); if (thread->request && thread->disable_count == 1) { // enter to safe point if suspend request was set diff --git a/vm/thread/doc/ThreadManager.htm b/vm/thread/doc/ThreadManager.htm index 1441310..de54354 100644 --- a/vm/thread/doc/ThreadManager.htm +++ b/vm/thread/doc/ThreadManager.htm @@ -375,7 +375,7 @@ The porting layer to interact with the underlying system and enable portability for threading. The TM native layer queries functions of - the APR interfaces and the apr_thread_ext interface. + the APR interfaces and the portlib interfaces.
  • The just-in-time compiler to provide optimized diff --git a/vm/thread/src/thread_native_suspend.c b/vm/thread/src/thread_native_suspend.c index d3d59f3..0f43d36 100644 --- a/vm/thread/src/thread_native_suspend.c +++ b/vm/thread/src/thread_native_suspend.c @@ -26,6 +26,7 @@ #define LOG_DOMAIN "tm.suspend" #include #include "thread_private.h" #include +#include "port_barriers.h" static void thread_safe_point_impl(hythread_t thread); @@ -126,7 +127,7 @@ static void thread_safe_point_impl(hythr // set disable count to 0 (safe region value) gc_disable_count = thread->disable_count; thread->disable_count = 0; - apr_memory_rw_barrier(); + port_rw_barrier(); do { TRACE(("safe point enter: thread: %p, suspend_count: %d, request: %d", @@ -464,7 +465,7 @@ void VMCALL hythread_set_suspend_disable assert(count >= 0); self->disable_count = count; - apr_memory_rw_barrier(); + port_rw_barrier(); if (count && self->suspend_count) { thread_safe_point_impl(self); diff --git a/vm/thread/src/thread_native_thin_monitor.c b/vm/thread/src/thread_native_thin_monitor.c index cb05a71..e222043 100644 --- a/vm/thread/src/thread_native_thin_monitor.c +++ b/vm/thread/src/thread_native_thin_monitor.c @@ -27,6 +27,7 @@ #include #include "thread_private.h" #include #include +#include "port_barriers.h" /** @name Thin monitors support. Implement thin-fat scheme. */ @@ -94,7 +95,7 @@ #endif lockword&=0x7FF; lockword|=(monitor_id << 11) | 0x80000000; *lockword_ptr=lockword; - apr_memory_rw_barrier(); + port_rw_barrier(); } IDATA get_fat_lock_id(hythread_thin_monitor_t *lockword_ptr) { diff --git a/vm/thread/src/thread_private.h b/vm/thread/src/thread_private.h index 34c144f..8cc2bd3 100644 --- a/vm/thread/src/thread_private.h +++ b/vm/thread/src/thread_private.h @@ -30,7 +30,6 @@ #include #include #include -#include "apr_thread_ext.h" #ifdef __linux__ #include diff --git a/vm/vmcore/src/jvmti/jvmti_break_intf.cpp b/vm/vmcore/src/jvmti/jvmti_break_intf.cpp index 75643dd..3f096c3 100644 --- a/vm/vmcore/src/jvmti/jvmti_break_intf.cpp +++ b/vm/vmcore/src/jvmti/jvmti_break_intf.cpp @@ -38,6 +38,7 @@ #include "cci.h" #include "ncai_internal.h" #include "jvmti_break_intf.h" #include "cci.h" +#include "port_thread.h" #if (defined _IA32_) || (defined _EM64T_) @@ -616,10 +617,8 @@ #if (defined _IA32_) || (defined _EM64T_ // context. In case the target location happens to be // instrumented, it means that another breakpoint has been set // there right after unlock was done. - StackIterator* si = (StackIterator*) STD_ALLOCA(si_size()); - si_fill_from_registers(si, ®s, false, m2n_get_previous_frame(m2nf)); - - si_transfer_control(si); + m2n_set_last_frame(m2n_get_previous_frame(m2nf)); + transfer_to_regs(®s); } assert(bp->addr == addr); TRACE2("jvmti.break", "Process native breakpoint: " @@ -836,11 +835,9 @@ #if (defined _IA32_) || (defined _EM64T_ // transfers execution control to the instruction buffer to // execute the original instruction with the registers which it // had before breakpoint happened - StackIterator* si = (StackIterator*) STD_ALLOCA(si_size()); - si_fill_from_registers(si, ®s, false, m2n_get_previous_frame(m2nf)); - - si_set_ip(si, instruction_buffer, false); - si_transfer_control(si); + m2n_set_last_frame(m2n_get_previous_frame(m2nf)); + regs.set_ip(instruction_buffer); + transfer_to_regs(®s); #else // PLATFORM dependent code abort(); diff --git a/vm/vmcore/src/lil/em64t/stack_iterator_em64t.cpp b/vm/vmcore/src/lil/em64t/stack_iterator_em64t.cpp index a57c909..bd80833 100644 --- a/vm/vmcore/src/lil/em64t/stack_iterator_em64t.cpp +++ b/vm/vmcore/src/lil/em64t/stack_iterator_em64t.cpp @@ -177,7 +177,7 @@ static transfer_control_stub_type gen_tr return addr; } - const int STUB_SIZE = 247; + const int STUB_SIZE = 239; char * stub = (char *)malloc_fixed_code_for_jit(STUB_SIZE, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_COLD, CAA_Allocate); char * ss = stub; @@ -225,14 +225,12 @@ #endif ss = get_reg(ss, rax_opnd, rdx_reg, CONTEXT_OFFSET(p_rax), true); // Restore processor flags - ss = alu(ss, xor_opc, rcx_opnd, rcx_opnd); - ss = mov(ss, rcx_opnd, M_Base_Opnd(rdx_reg, CONTEXT_OFFSET(eflags)), size_8); + ss = movzx(ss, rcx_opnd, M_Base_Opnd(rdx_reg, CONTEXT_OFFSET(eflags)), size_8); ss = test(ss, rcx_opnd, rcx_opnd); ss = branch8(ss, Condition_Z, Imm_Opnd(size_8, 0)); char* patch_offset = ((char*)ss) - 1; // Store location for jump patch - ss = alu(ss, and_opc, rcx_opnd, Imm_Opnd(size_32, 0xff)); ss = push(ss, rcx_opnd); - *ss++ = (char)0x9D; // POPFD + *ss++ = (char)0x9D; // POPFQ // Patch conditional jump POINTER_SIZE_SINT offset = (POINTER_SIZE_SINT)ss - (POINTER_SIZE_SINT)patch_offset - 1; @@ -277,8 +275,7 @@ __label11__ je __label12__ mov rax,qword ptr [rax] __label12__ - xor rcx,rcx - mov ecx,dword ptr [rdx+90h] + movzx rcx,byte ptr [rdx+90h] test rcx,rcx je __label13__ push rcx diff --git a/vm/vmcore/src/lil/ia32/stack_iterator_ia32.cpp b/vm/vmcore/src/lil/ia32/stack_iterator_ia32.cpp index 9236205..768530e 100644 --- a/vm/vmcore/src/lil/ia32/stack_iterator_ia32.cpp +++ b/vm/vmcore/src/lil/ia32/stack_iterator_ia32.cpp @@ -134,7 +134,7 @@ static transfer_control_stub_type gen_tr return addr; } - const int stub_size = 0x4d; + const int stub_size = 0x48; char *stub = (char *)malloc_fixed_code_for_jit(stub_size, DEFAULT_CODE_ALIGNMENT, CODE_BLOCK_HEAT_COLD, CAA_Allocate); #ifdef _DEBUG memset(stub, 0xcc /*int 3*/, stub_size); @@ -168,11 +168,10 @@ #endif ss = get_reg(ss, &eax_opnd, eax_reg, edx_reg, (unsigned)&((StackIterator*)0)->c.p_eax); ss = get_reg(ss, &ebx_opnd, ebx_reg, edx_reg, (unsigned)&((StackIterator*)0)->c.p_ebx); - ss = mov(ss, ecx_opnd, M_Base_Opnd(edx_reg, (unsigned)&((StackIterator*)0)->c.eflags)); + ss = movzx(ss, ecx_opnd, M_Base_Opnd(edx_reg, (unsigned)&((StackIterator*)0)->c.eflags), size_8); ss = test(ss, ecx_opnd, ecx_opnd); ss = branch8(ss, Condition_Z, Imm_Opnd(size_8, 0)); char* patch_offset = ((char *)ss) - 1; // Store location for jump patch - ss = alu(ss, and_opc, ecx_opnd, Imm_Opnd(size_32, 0xff)); ss = push(ss, ecx_opnd); *ss++ = (char)0x9D; // POPFD // Patch conditional jump @@ -208,7 +207,7 @@ #endif mov eax,dword ptr [eax] mov ebx,dword ptr [edx+18h] mov ebx,dword ptr [ebx] - mov ecx,dword ptr [edx+28h] + movzx ecx,byte ptr [edx+28h] test ecx,ecx je _label_ push ecx diff --git a/vm/vmcore/src/thread/thread_ti_timing.cpp b/vm/vmcore/src/thread/thread_ti_timing.cpp index 66245ec..f44163c 100644 --- a/vm/vmcore/src/thread/thread_ti_timing.cpp +++ b/vm/vmcore/src/thread/thread_ti_timing.cpp @@ -24,7 +24,6 @@ #include #include #include #include "vm_threads.h" -#include "apr_thread_ext.h" #define THREAD_CPU_TIME_SUPPORTED 1 -- 1.3.3