blob: 9f25b6d989062d614c8f191c77e3a085451d902b [file] [log] [blame]
/*
* 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 */