vm/include/open/hythread.h (409 lines of code) (raw):

/* * 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. */ #if !defined(HYTHREAD_H) #define HYTHREAD_H #ifdef _WIN32 # if (_MSC_VER >= 1400) # include <intrin.h> # endif #endif #if defined(__cplusplus) extern "C" { #endif #include <open/types.h> #include <stddef.h> #include "hycomp.h" /* * Idea behind these declarations is to make some functions static inlined for * all files that include hythread_ext.h/hythread.h except one, that * will export this functions in DLL */ #ifndef hy_inline # ifdef PLATFORM_POSIX # define hy_inline inline static # else # define hy_inline static __forceinline # endif //PLATFORM_POSIX #endif // hy_inline typedef UDATA hythread_tls_key_t; #define HYTHREAD_PROC VMCALL typedef IDATA (HYTHREAD_PROC* hythread_entrypoint_t)(void*); typedef void (HYTHREAD_PROC* hythread_tls_finalizer_t)(void*); typedef struct HyThread *hythread_t; typedef struct HyThreadGroup *hythread_group_t; typedef struct HyThreadMonitor *hythread_monitor_t; typedef struct HySemaphore *hysem_t; struct HyPortLibrary; #define HYTHREAD_PRIORITY_MIN 0 #define HYTHREAD_PRIORITY_USER_MIN 1 #define HYTHREAD_PRIORITY_NORMAL 5 #define HYTHREAD_PRIORITY_USER_MAX 10 #define HYTHREAD_PRIORITY_MAX 11 #define HYTHREAD_LOCKING_DEFAULT 0 /* default locking policy for platform */ #define HYTHREAD_LOCKING_NO_DATA (-1) /* if no policy data is provided */ #define HYTHREAD_FLAG_BLOCKED 1 #define HYTHREAD_ALREADY_INITIALIZED 4 #define HYTHREAD_TIMED_OUT 3 #define HYTHREAD_FLAG_STARTED 0x800 #define HYTHREAD_FLAG_JLM_HAS_BEEN_ENABLED 0x20000 #define HYTHREAD_ILLEGAL_MONITOR_STATE 1 #define HYTHREAD_FLAG_PRIORITY_INTERRUPTED 0x100 #define HYTHREAD_FLAG_JLMHST_ENABLED 0x10000 #define HYTHREAD_FLAG_JLM_ENABLED 0x4000 #define HYTHREAD_FLAG_INTERRUPTED 4 #define HYTHREAD_INVALID_ARGUMENT 7 #define HYTHREAD_FLAG_DETACHED 0x80 #define HYTHREAD_PRIORITY_INTERRUPTED 5 #define HYTHREAD_FLAG_CANCELED 0x400 #define HYTHREAD_FLAG_NOTIFIED 16 #define HYTHREAD_FLAG_ATTACHED 0x200 #define HYTHREAD_WOULD_BLOCK 8 #define HYTHREAD_FLAG_DEAD 32 #define HYTHREAD_FLAG_WAITING 2 #define HYTHREAD_FLAG_PARKED 0x40000 #define HYTHREAD_FLAG_UNPARKED 0x80000 #define HYTHREAD_FLAG_INTERRUPTABLE 0x2000 #define HYTHREAD_FLAG_TIMER_SET 0x100000 #define HYTHREAD_FLAG_JLM_ENABLED_ALL 0x1C000 #define HYTHREAD_FLAG_JLMTS_ENABLED 0x8000 #define HYTHREAD_INTERRUPTED 2 #define HYTHREAD_FLAG_BLOCKED_AFTER_WAIT 0x1000 #define HYTHREAD_ALREADY_ATTACHED 6 #define HYTHREAD_FLAG_SUSPENDED 8 #define HYTHREAD_FLAG_SLEEPING 64 #define HYTHREAD_MONITOR_INFLATED 0x10000 #define HYTHREAD_MONITOR_INTERRUPTABLE 0x20000 #define HYTHREAD_MONITOR_PRIORITY_INTERRUPTABLE 0x40000 #define HYTHREAD_MONITOR_SYSTEM 0 #define HYTHREAD_MONITOR_OBJECT 0x60000 #define HYTHREAD_MONITOR_MUTEX_UNINITIALIZED 0x80000 #define HYTHREAD_MONITOR_SUPPRESS_CONTENDED_EXIT 0x100000 #define HYTHREAD_MONITOR_MUTEX_IN_USE 0x200000 #define HYTHREAD_MONITOR_SPINLOCK_UNOWNED 0 #define HYTHREAD_MONITOR_SPINLOCK_OWNED 1 #define HYTHREAD_MONITOR_SPINLOCK_EXCEEDED 2 #define HYTHREAD_LIB_FLAG_JLMHST_ENABLED 0x10000 #define HYTHREAD_LIB_FLAG_JLM_ENABLED 0x4000 #define HYTHREAD_LIB_FLAG_JLM_ENABLED_ALL 0x1C000 #define HYTHREAD_LIB_FLAG_JLM_HAS_BEEN_ENABLED 0x20000 #define HYTHREAD_LIB_FLAG_JLMTS_ENABLED 0x8000 typedef struct HyThreadMonitorTracing { const char* monitor_name; UDATA enter_count; UDATA slow_count; UDATA recursive_count; UDATA spin2_count; UDATA yield_count; } HyThreadMonitorTracing; #ifdef HY_NO_THR /* Thread library version defines */ #define HYTHREAD_MAJOR_VERSION_NUMBER 1 #define HYTHREAD_MINOR_VERSION_NUMBER 0 #define HYTHREAD_CAPABILITY_BASE 0 #define HYTHREAD_CAPABILITY_STANDARD 1 #define HYTHREAD_CAPABILITY_MASK ((U_64)(HYTHREAD_CAPABILITY_STANDARD)) #define HYTHREAD_SET_VERSION(threadLibraryVersion, capabilityMask) \ (threadLibraryVersion)->majorVersionNumber = HYTHREAD_MAJOR_VERSION_NUMBER; \ (threadLibraryVersion)->minorVersionNumber = HYTHREAD_MINOR_VERSION_NUMBER; \ (threadLibraryVersion)->capabilities = (capabilityMask) #define HYTHREAD_SET_VERSION_DEFAULT(threadLibraryVersion) \ (threadLibraryVersion)->majorVersionNumber = HYTHREAD_MAJOR_VERSION_NUMBER; \ (threadLibraryVersion)->minorVersionNumber = HYTHREAD_MINOR_VERSION_NUMBER; \ (threadLibraryVersion)->capabilities = HYTHREAD_CAPABILITY_MASK typedef struct HyThreadLibraryVersion { U_16 majorVersionNumber; U_16 minorVersionNumber; U_32 padding; U_64 capabilities; } HyThreadLibraryVersion; /* Thread library function table */ typedef struct HyThreadLibrary { struct HyThreadLibraryVersion threadVersion; IDATA (PVMCALL sem_destroy) (struct HyThreadLibrary *threadLibraryFuncs, hysem_t s); IDATA (PVMCALL sem_init) (struct HyThreadLibrary *threadLibraryFuncs, hysem_t * sp, I_32 initValue); IDATA (PVMCALL sem_post) (struct HyThreadLibrary *threadLibraryFuncs, hysem_t s); IDATA (PVMCALL sem_wait) (struct HyThreadLibrary *threadLibraryFuncs, hysem_t s); IDATA (PVMCALL thread_attach) (struct HyThreadLibrary *threadLibraryFuncs, hythread_t * handle); IDATA (PVMCALL thread_create) (struct HyThreadLibrary *threadLibraryFuncs, hythread_t * handle, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t entrypoint, void *entryarg); void (PVMCALL thread_detach) (struct HyThreadLibrary *threadLibraryFuncs, hythread_t thread); void (PVMCALL NORETURN thread_exit) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); UDATA *(PVMCALL thread_global) (struct HyThreadLibrary *threadLibraryFuncs, const char *name); IDATA (PVMCALL thread_monitor_destroy) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); IDATA (PVMCALL thread_monitor_enter) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); IDATA (PVMCALL thread_monitor_exit) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); IDATA (PVMCALL thread_monitor_init_with_name) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t * handle, UDATA flags, const char *name); IDATA (PVMCALL thread_monitor_notify) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); IDATA (PVMCALL thread_monitor_notify_all) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); IDATA (PVMCALL thread_monitor_wait) (struct HyThreadLibrary *threadLibraryFuncs, hythread_monitor_t monitor); hythread_t (PVMCALL thread_self) (struct HyThreadLibrary *threadLibraryFuncs); IDATA (PVMCALL thread_sleep) (struct HyThreadLibrary *threadLibraryFuncs, I_64 millis); IDATA (PVMCALL thread_tls_alloc) (struct HyThreadLibrary *threadLibraryFuncs, hythread_tls_key_t * handle); IDATA (PVMCALL thread_tls_free) (struct HyThreadLibrary *threadLibraryFuncs, hythread_tls_key_t key); void *(PVMCALL thread_tls_get) (struct HyThreadLibrary *threadLibraryFuncs, hythread_t thread, hythread_tls_key_t key); IDATA (PVMCALL thread_tls_set) (struct HyThreadLibrary *threadLibraryFuncs, hythread_t thread, hythread_tls_key_t key, void *value); void *self_handle; } HyThreadLibrary; #endif /* HY_NO_THR */ #define HYSIZEOF_HyThreadMonitorTracing 24 extern HY_CFUNC void VMCALL hythread_detach PROTOTYPE((hythread_t thread)); extern HY_CFUNC UDATA VMCALL hythread_lib_set_flags PROTOTYPE((UDATA flags)); extern HY_CFUNC IDATA VMCALL hythread_tls_alloc PROTOTYPE((hythread_tls_key_t* handle)); extern HY_CFUNC IDATA VMCALL hythread_sleep_interruptable PROTOTYPE((I_64 millis, IDATA nanos)); extern HY_CFUNC IDATA VMCALL hythread_monitor_enter_using_threadId PROTOTYPE((hythread_monitor_t monitor, hythread_t threadId)); extern HY_CFUNC void VMCALL hythread_cancel PROTOTYPE((hythread_t thread)); extern HY_CFUNC UDATA VMCALL hythread_clear_interrupted PROTOTYPE((void)); extern HY_CFUNC void VMCALL hythread_lib_unlock PROTOTYPE((hythread_t self)); extern HY_CFUNC IDATA VMCALL hythread_monitor_enter PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_monitor_notify_all PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_attach PROTOTYPE((hythread_t* handle)); extern HY_CFUNC HyThreadMonitorTracing* VMCALL hythread_jlm_get_gc_lock_tracing PROTOTYPE(()); extern HY_CFUNC UDATA VMCALL hythread_priority_interrupted PROTOTYPE((hythread_t thread)); extern HY_CFUNC IDATA VMCALL hythread_monitor_destroy PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hysem_post PROTOTYPE((hysem_t s)); extern HY_CFUNC UDATA VMCALL hythread_monitor_num_waiting PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC UDATA VMCALL hythread_interrupted PROTOTYPE((hythread_t thread)); extern HY_CFUNC void VMCALL hythread_monitor_lock PROTOTYPE((hythread_t self, hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_park PROTOTYPE((I_64 millis, IDATA nanos)); extern HY_CFUNC IDATA VMCALL hythread_monitor_init_with_name PROTOTYPE((hythread_monitor_t* handle, UDATA flags, const char* name)); extern HY_CFUNC IDATA VMCALL hythread_monitor_try_enter PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC hythread_t VMCALL hythread_self_slow PROTOTYPE(()); extern HY_CFUNC void VMCALL hythread_jlm_thread_clear PROTOTYPE((hythread_t thread)); extern HY_CFUNC IDATA VMCALL hythread_tls_free PROTOTYPE((hythread_tls_key_t key)); extern HY_CFUNC UDATA VMCALL hythread_clear_priority_interrupted PROTOTYPE((void)); extern HY_CFUNC void VMCALL hythread_jlm_thread_init PROTOTYPE((hythread_t thread)); extern HY_CFUNC void VMCALL hythread_jlm_gc_lock_init PROTOTYPE(()); extern HY_CFUNC void VMCALL hythread_monitor_unlock PROTOTYPE((hythread_t self, hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hysem_wait PROTOTYPE((hysem_t s)); extern HY_CFUNC void VMCALL hythread_yield PROTOTYPE((void)); extern HY_CFUNC void VMCALL hythread_suspend PROTOTYPE((void)); extern HY_CFUNC void VMCALL hythread_interrupt PROTOTYPE((hythread_t thread)); extern HY_CFUNC IDATA VMCALL hythread_tls_set PROTOTYPE((hythread_t thread, hythread_tls_key_t key, void* value)); extern HY_CFUNC IDATA VMCALL hythread_create PROTOTYPE((hythread_t* handle, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t entrypoint, void* entryarg)); extern HY_CFUNC IDATA VMCALL hysem_init PROTOTYPE((hysem_t* sp, I_32 initValue)); extern HY_CFUNC IDATA VMCALL hythread_monitor_wait PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_monitor_init_policy PROTOTYPE((hythread_monitor_t* handle, UDATA flags, IDATA policy, IDATA policyData)); extern HY_CFUNC void VMCALL hythread_jlm_monitor_init PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hysem_destroy PROTOTYPE((hysem_t s)); extern HY_CFUNC IDATA VMCALL hythread_monitor_wait_interruptable PROTOTYPE((hythread_monitor_t monitor, I_64 millis, IDATA nanos)); extern HY_CFUNC IDATA VMCALL hythread_monitor_try_enter_using_threadId PROTOTYPE((hythread_monitor_t monitor, hythread_t threadId)); extern HY_CFUNC IDATA VMCALL hythread_monitor_exit PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_set_priority PROTOTYPE((hythread_t thread, UDATA priority)); extern HY_CFUNC void VMCALL hythread_unpark PROTOTYPE((hythread_t thread)); extern HY_CFUNC void VMCALL hythread_lib_lock PROTOTYPE((hythread_t self)); extern HY_CFUNC IDATA VMCALL hythread_monitor_init PROTOTYPE((hythread_monitor_t* handle, UDATA flags)); extern HY_CFUNC IDATA VMCALL hythread_sleep PROTOTYPE((I_64 millis)); extern HY_CFUNC UDATA* VMCALL hythread_global PROTOTYPE((const char* name)); extern HY_CFUNC IDATA VMCALL hythread_tls_alloc_with_finalizer PROTOTYPE((hythread_tls_key_t* handle, hythread_tls_finalizer_t finalizer)); extern HY_CFUNC void VMCALL hythread_jlm_monitor_clear PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_monitor_wait_timed PROTOTYPE((hythread_monitor_t monitor, I_64 millis, IDATA nanos)); extern HY_CFUNC void VMCALL hythread_resume PROTOTYPE((hythread_t thread)); extern HY_CFUNC UDATA VMCALL hythread_lib_clear_flags PROTOTYPE((UDATA flags)); extern HY_CFUNC void VMCALL hythread_priority_interrupt PROTOTYPE((hythread_t thread)); extern HY_CFUNC void VMCALL NORETURN hythread_exit PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC IDATA VMCALL hythread_monitor_exit_using_threadId PROTOTYPE((hythread_monitor_t monitor, hythread_t threadId)); extern HY_CFUNC UDATA VMCALL hythread_lib_get_flags PROTOTYPE(()); extern HY_CFUNC IDATA VMCALL hythread_monitor_notify PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC void VMCALL hythread_enable_stack_usage PROTOTYPE((UDATA enable)); extern HY_CFUNC UDATA VMCALL hythread_get_handle PROTOTYPE((hythread_t thread)); extern HY_CFUNC UDATA VMCALL hythread_get_stack_usage PROTOTYPE((hythread_t thread)); extern HY_CFUNC I_64 VMCALL hythread_get_cpu_time PROTOTYPE((hythread_t thread)); extern HY_CFUNC UDATA VMCALL hythread_get_stack_size PROTOTYPE((hythread_t thread)); extern HY_CFUNC I_64 VMCALL hythread_get_user_time PROTOTYPE((hythread_t thread)); extern HY_CFUNC IDATA VMCALL hythread_get_os_priority PROTOTYPE((hythread_t thread, IDATA* policy, IDATA *priority)); extern HY_CFUNC UDATA VMCALL hythread_get_flags PROTOTYPE((hythread_t thread, hythread_monitor_t* blocker)); extern HY_CFUNC HyThreadMonitorTracing* VMCALL hythread_monitor_get_tracing PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC UDATA VMCALL hythread_get_priority PROTOTYPE((hythread_t thread)); extern HY_CFUNC const char* VMCALL hythread_monitor_get_name PROTOTYPE((hythread_monitor_t monitor)); extern HY_CFUNC hythread_monitor_t VMCALL hythread_monitor_walk PROTOTYPE((hythread_monitor_t monitor)); struct RWMutex; typedef struct RWMutex* hythread_rwmutex_t; extern HY_CFUNC IDATA VMCALL hythread_rwmutex_enter_read PROTOTYPE((hythread_rwmutex_t mutex)); extern HY_CFUNC IDATA VMCALL hythread_rwmutex_destroy PROTOTYPE((hythread_rwmutex_t mutex)); extern HY_CFUNC IDATA VMCALL hythread_rwmutex_exit_read PROTOTYPE((hythread_rwmutex_t mutex)); extern HY_CFUNC IDATA VMCALL hythread_rwmutex_exit_write PROTOTYPE((hythread_rwmutex_t mutex)); extern HY_CFUNC IDATA VMCALL hythread_rwmutex_init PROTOTYPE((hythread_rwmutex_t* handle, UDATA flags, const char* name)); extern HY_CFUNC IDATA VMCALL hythread_rwmutex_enter_write PROTOTYPE((hythread_rwmutex_t mutex)); /* HyVMThreadHelpers*/ #if !defined(_HYVMTHREADHELPERS_) #define _HYVMTHREADHELPERS_ extern HY_CFUNC UDATA VMCALL current_stack_depth (); extern HY_CFUNC void VMCALL hythread_monitor_unpin ( hythread_monitor_t monitor, hythread_t osThread); extern HY_CFUNC void VMCALL hythread_monitor_pin ( hythread_monitor_t monitor, hythread_t osThread); #endif /* _HYVMTHREADHELPERS_ */ /* HyVMThreadSpinlocks*/ #if !defined(_HYVMTHREADSPINLOCKS_) #define _HYVMTHREADSPINLOCKS_ extern HY_CFUNC IDATA VMCALL hythread_spinlock_acquire (hythread_t self, hythread_monitor_t monitor); extern HY_CFUNC UDATA VMCALL hythread_spinlock_swapState (hythread_monitor_t monitor, UDATA newState); #endif /* _HYVMTHREADSPINLOCKS_ */ #define hythread_global_monitor() (*(hythread_monitor_t*)hythread_global("global_monitor")) #define hythread_monitor_init(pMon,flags) hythread_monitor_init_with_name(pMon,flags, #pMon) #define hythread_monitor_set_name(pMon,pName) /** * Native thread control structure's public fields. */ typedef struct HyThread_public { #ifndef POSIX // This is dummy pointer for Microsoft Visual Studio debugging // If this is removed, Visual Studio, when attached to VM, will show // no symbolic information void* reserved; #endif // Public fields exported by HyThread_public. If you change these fields, // please, check fields in thread_private.h/HyThread /** * Number of requests made for this thread, it includes both * suspend requests and safe point callback requests. * The field is modified by atomic operations. * * Increment in functions: * 1. send_suspend_request() * - sets suspend request for a given thread * 2. hythread_set_safepoint_callback() * - sets safe point callback request for a given thread * * Decrement in functions: * 1. hythread_resume() * - removes suspend request for a given thread * 2. hythread_exception_safe_point() * - removes safe point callback request for current thread */ I_32 request; /** * Field indicating that thread can safely be suspended. * Safe suspension is enabled on value 0. * * The disable_count is increased/decreaded in * hythread_suspend_disable()/hythread_suspend_enable() function * for current thread only. * * Also disable_count could be reset to value 0 and restored in * hythread_reset_suspend_disable()/hythread_set_suspend_disable() function * for current thread only. * * Function hythread_exception_safe_point() sets disable_count to * value 1 before safe point callback function calling and restores * it after the call. * * Function thread_safe_point_impl() sets disable_count to * value 0 before entering to the safe point and restores it * after exitting. */ int16 disable_count; /** * Group for this thread. Different groups are needed in order * to be able to quickly iterate over the specific group. * Examples are: Java threads, GC private threads. * Equal to the address of the head of the list of threads for this group. */ hythread_group_t group; /** * Array representing thread local storage */ void *thread_local_storage[10]; } HyThread_public; /** * HYTHREAD_FAST_TLS * Enables platform-specific TLS access optimization, such as: * - On Win32, free TIB slot is used via direct reference FS:[0x14] * (see http://www.microsoft.com/msj/archive/S2CE.aspx); * - On Linuxes, initial-exec TLS model allows to address static TLS directly, * via GS:[0] on IA32 and FS:[0] on x86_64 * (see http://people.redhat.com/drepper/tls.pdf) * * * APR_TLS_USE * * When APR_TLS_USE is declared DRLVM uses APR functions for getting current * thread. (currently it's used only on Windows 64-bit) * * If none of these defined, current thread id is kept in the tm_self_tls * variable which is declared as __thread, thread local variable for gcc * (*note Thread-Local:: in gcc.info), in thread_native_basic.c. This * way it works on Linux. */ #ifdef _IPF_ //don't use optimized asm monitor enter and exit helpers #else //use optimized asm monitor enter and exit helpers # define ASM_MONITOR_HELPER #endif #if defined (_WIN32) # define HYTHREAD_FAST_TLS_ATTRIBUTE # if defined(_IA32_) # define HYTHREAD_FAST_TLS (1) // FIXME suggested to drop FS14_TLS_USE in favor of common HYTHREAD_FAST_TLS # define FS14_TLS_USE # else # define APR_TLS_USE # endif #elif defined(__linux__) // some kind of nix - the threads internals are known for IA32/Intel64 // kernels, will use slow way on other HWs (TODO: add IPF support) # if defined(_IA32_) || defined(_EM64T_) # define HYTHREAD_FAST_TLS (1) # define HYTHREAD_FAST_TLS_ATTRIBUTE __attribute__((tls_model("initial-exec"))) # endif #elif defined(FREEBSD) # define APR_TLS_USE # define HYTHREAD_FAST_TLS_ATTRIBUTE # undef HYTHREAD_FAST_TLS #else # undef HYTHREAD_FAST_TLS #endif #if !defined(HYTHREAD_FAST_TLS) # define HYTHREAD_FAST_TLS_ATTRIBUTE #endif #ifdef APR_TLS_USE #ifdef __cplusplus extern "C" { #endif hy_inline hythread_t VMCALL hythread_self() { extern hythread_t hythread_self_slow(); return hythread_self_slow(); } #define tm_self_tls (hythread_self_slow()) #ifdef __cplusplus } #endif #elif defined FS14_TLS_USE #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ hy_inline hythread_t VMCALL hythread_self() { #ifndef _WIN64 # if (_MSC_VER >= 1400) // file winnt.h can't be included here // 0x14 = offsetof(NT_TIB, ArbitraryUserPointer) return (hythread_t) __readfsdword(0x14); # else register hythread_t t; _asm { mov eax, fs:[0x14] mov t, eax; } return t; # endif #else // file winnt.h can't be included here // 0x28 = offsetof(NT_TIB, ArbitraryUserPointer) return (hythread_t) __readgsqword(0x28); #endif } #define tm_self_tls (hythread_self()) #ifdef __cplusplus } #endif #else #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifdef PLATFORM_POSIX extern __thread hythread_t tm_self_tls; #else extern __declspec(thread) hythread_t tm_self_tls; #endif //PLATFORM_POSIX hy_inline hythread_t VMCALL hythread_self() { return tm_self_tls; } #ifdef __cplusplus } #endif /* __cplusplus */ #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Returns a thread's TLS value. */ hy_inline void* VMCALL hythread_tls_get(hythread_t thread, hythread_tls_key_t key) { return ((struct HyThread_public *)thread)->thread_local_storage[key]; } #ifdef __cplusplus } #endif /* __cplusplus */ #if defined(__cplusplus) } #endif #endif /* HYTHREAD_H */