Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions TSRM/TSRM.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ typedef struct {
ts_allocate_ctor ctor;
ts_allocate_dtor dtor;
size_t fast_offset;
/* When set, storage comes from __thread memory instead of being allocated by TSRM. */
void *(*tls_addr)(void);
int done;
} tsrm_resource_type;

Expand Down Expand Up @@ -163,14 +165,19 @@ TSRM_API bool tsrm_startup(int expected_threads, int expected_resources, int deb

static void ts_free_resources(tsrm_tls_entry *thread_resources)
{
bool own_thread = thread_resources->thread_id == tsrm_thread_id();
Comment thread
henderkes marked this conversation as resolved.

/* Need to destroy in reverse order to respect dependencies. */
for (int i = thread_resources->count - 1; i >= 0; i--) {
if (!resource_types_table[i].done) {
if (resource_types_table[i].tls_addr && !own_thread) {
continue;
}
if (resource_types_table[i].dtor) {
resource_types_table[i].dtor(thread_resources->storage[i]);
}

if (!resource_types_table[i].fast_offset) {
if (!resource_types_table[i].fast_offset && !resource_types_table[i].tls_addr) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't manually free __thread storage

free(thread_resources->storage[i]);
}
}
Expand Down Expand Up @@ -256,7 +263,10 @@ static void tsrm_update_active_threads(void)

p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
for (j=p->count; j<id_count; j++) {
if (resource_types_table[j].fast_offset) {
if (resource_types_table[j].tls_addr) {
TSRM_ASSERT(p->thread_id == tsrm_thread_id());
p->storage[j] = resource_types_table[j].tls_addr();
} else if (resource_types_table[j].fast_offset) {
p->storage[j] = (void *) (((char*)p) + resource_types_table[j].fast_offset);
} else {
p->storage[j] = (void *) malloc(resource_types_table[j].size);
Expand Down Expand Up @@ -301,6 +311,7 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = 0;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].tls_addr = NULL;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;

tsrm_update_active_threads();
Expand Down Expand Up @@ -359,6 +370,7 @@ TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, siz
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = *offset;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].tls_addr = NULL;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;

tsrm_update_active_threads();
Expand All @@ -368,6 +380,41 @@ TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, siz
return *rsrc_id;
}/*}}}*/

/* allocates a resource id whose per-thread storage is a native __thread block */
TSRM_API ts_rsrc_id ts_allocate_tls_id(ts_rsrc_id *rsrc_id, void *(*tls_addr)(void), size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
{/*{{{*/
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new TLS resource id, %d bytes", size));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function largely copied from above, looking at it now I see that size_t should be printed as %zu.


tsrm_mutex_lock(tsmm_mutex);

*rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);

if (resource_types_table_size < id_count) {
tsrm_resource_type *_tmp;
_tmp = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
if (!_tmp) {
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
*rsrc_id = 0;
tsrm_mutex_unlock(tsmm_mutex);
return 0;
}
resource_types_table = _tmp;
resource_types_table_size = id_count;
}
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = 0;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].tls_addr = tls_addr;
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;

tsrm_update_active_threads();
tsrm_mutex_unlock(tsmm_mutex);

TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new TLS resource id %d", *rsrc_id));
return *rsrc_id;
}/*}}}*/

static void set_thread_local_storage_resource_to(tsrm_tls_entry *thread_resource)
{
tsrm_tls_set(thread_resource);
Expand Down Expand Up @@ -397,7 +444,9 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
if (resource_types_table[i].done) {
(*thread_resources_ptr)->storage[i] = NULL;
} else {
if (resource_types_table[i].fast_offset) {
if (resource_types_table[i].tls_addr) {
(*thread_resources_ptr)->storage[i] = resource_types_table[i].tls_addr();
} else if (resource_types_table[i].fast_offset) {
(*thread_resources_ptr)->storage[i] = (void *) (((char*)(*thread_resources_ptr)) + resource_types_table[i].fast_offset);
} else {
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
Expand Down Expand Up @@ -486,6 +535,7 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
* use the global pointer, we need to setup the global pointer temporarily here. */
set_thread_local_storage_resource_to(thread_resources);
/* Free up the old resource from the old thread instance */
thread_resources->thread_id = 0;
ts_free_resources(thread_resources);
free(thread_resources);
/* Allocate a new resource at the same point in the linked list, and relink the next pointer */
Expand Down Expand Up @@ -559,7 +609,7 @@ void ts_free_id(ts_rsrc_id id)
if (resource_types_table[rsrc_id].dtor) {
resource_types_table[rsrc_id].dtor(p->storage[rsrc_id]);
}
if (!resource_types_table[rsrc_id].fast_offset) {
if (!resource_types_table[rsrc_id].fast_offset && !resource_types_table[rsrc_id].tls_addr) {
free(p->storage[rsrc_id]);
}
}
Expand Down Expand Up @@ -773,7 +823,10 @@ TSRM_API void *tsrm_get_ls_cache(void)
/* Returns offset of tsrm_ls_cache slot from Thread Control Block address */
TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void)
{/*{{{*/
#if defined(__APPLE__) && defined(__x86_64__)
#if defined(TSRM_TLS_MODEL_GLOBAL_DYNAMIC)
/* No constant TCB offset under global-dynamic, can't use fast path */
return 0;
#elif defined(__APPLE__) && defined(__x86_64__)
// TODO: Implement support for fast JIT ZTS code ???
return 0;
#elif defined(__x86_64__) && defined(__GNUC__) && !defined(__FreeBSD__) && \
Expand Down
37 changes: 27 additions & 10 deletions TSRM/TSRM.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
/* Fast resource in reserved (pre-allocated) space */
TSRM_API void tsrm_reserve(size_t size);
TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
/* Must be called at startup before any other thread exists. */
TSRM_API ts_rsrc_id ts_allocate_tls_id(ts_rsrc_id *rsrc_id, void *(*tls_addr)(void), size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);

/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
Expand Down Expand Up @@ -155,9 +157,14 @@ TSRM_API bool tsrm_is_managed_thread(void);
#if !__has_attribute(tls_model) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MUSL__) || defined(__HAIKU__)
# define TSRM_TLS_MODEL_ATTR
# define TSRM_TLS_MODEL_DEFAULT
#elif __PIC__
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec")))
# define TSRM_TLS_MODEL_INITIAL_EXEC
#elif __PIC__ && !defined(__PIE__)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a PIE program can use local exec if it's the main executable. Only shared libraries (embed, extensions) need to fall back to initial-exed.

This alone would already be a small speedup (one fewer instruction per access)

# if defined(TSRM_TLS_MODEL_USE_GLOBAL_DYNAMIC)
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("global-dynamic")))
# define TSRM_TLS_MODEL_GLOBAL_DYNAMIC
# else
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec")))
# define TSRM_TLS_MODEL_INITIAL_EXEC
# endif
#else
# define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("local-exec")))
# define TSRM_TLS_MODEL_LOCAL_EXEC
Expand All @@ -175,17 +182,27 @@ TSRM_API bool tsrm_is_managed_thread(void);
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
struct _zend_tsrm_ls_cache;
#if defined(ZEND_WIN32) && !defined(LIBZEND_EXPORTS)
/* Windows can't dllexport the TLS struct, so outside Zend each module
* keeps a per-module `void *` pointer and reaches EG/CG via the resource-id indirection. */
# define ZEND_TSRMLS_CACHE_T void *
# define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *_tsrm_ls_cache TSRM_TLS_MODEL_ATTR = NULL;
# define TSRMLS_CACHE_DEFINE() TSRM_TLS void *_tsrm_ls_cache = NULL;
#else
# define ZEND_TSRMLS_CACHE_T struct _zend_tsrm_ls_cache
# define TSRMLS_MAIN_CACHE_DEFINE()
# define TSRMLS_CACHE_DEFINE()
#endif
#ifdef __cplusplus
#define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; }
#define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE; }
#define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS ZEND_TSRMLS_CACHE_T _tsrm_ls_cache TSRM_TLS_MODEL_ATTR; }
#define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS ZEND_TSRMLS_CACHE_T _tsrm_ls_cache; }
#else
#define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
#define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS ZEND_TSRMLS_CACHE_T _tsrm_ls_cache TSRM_TLS_MODEL_ATTR;
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS ZEND_TSRMLS_CACHE_T _tsrm_ls_cache;
#endif
#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
#define TSRMLS_CACHE _tsrm_ls_cache
#define TSRMLS_CACHE (*(void **) &_tsrm_ls_cache)

#ifdef __cplusplus
}
Expand Down
5 changes: 5 additions & 0 deletions Zend/Zend.m4
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ AC_MSG_RESULT([$ZEND_ZTS])
AS_VAR_IF([ZEND_ZTS], [yes], [
AC_DEFINE([ZTS], [1], [Define to 1 if thread safety (ZTS) is enabled.])
AS_VAR_APPEND([CFLAGS], [" -DZTS"])

dnl -mtls-size=12 drops the dead high-bits offset add from TLS access,
dnl valid while the thread-local block stays under 4 KiB.
AX_CHECK_COMPILE_FLAG([-mtls-size=12],
[AS_VAR_APPEND([CFLAGS], [" -mtls-size=12"])])
])

AC_MSG_CHECKING([whether to enable Zend debugging])
Expand Down
26 changes: 21 additions & 5 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,29 @@ static bool startup_done = false;
#ifdef ZTS
ZEND_API int compiler_globals_id;
ZEND_API int executor_globals_id;
ZEND_API size_t compiler_globals_offset;
ZEND_API size_t executor_globals_offset;
ZEND_TLS_API TSRM_TLS TSRM_TLS_MODEL_ATTR zend_tsrm_ls_cache _tsrm_ls_cache = {0};
#if defined(_WIN64) && defined(ZEND_TLS_DIRECT)
/* Holds &_tsrm_ls_cache in a TEB TLS slot (filled by DllMain) so EG()/CG() reach it
* with a single gs:[] load rather than the 3-load __declspec(thread) lookup. */
ZEND_TLS_API unsigned long zend_win_tsrm_cache_slot = 0;
ZEND_API void zend_win_tsrm_cache_init(bool alloc)
{
if (alloc) {
zend_win_tsrm_cache_slot = TlsAlloc();
ZEND_ASSERT(zend_win_tsrm_cache_slot < 64); /* must be a direct TEB TlsSlot */
}
TlsSetValue(zend_win_tsrm_cache_slot, &_tsrm_ls_cache);
}
#endif
/* ts_allocate_tls_id takes a callback so each thread resolves its own block.
* A plain &..._tls would capture only the registering thread's address. */
static void *executor_globals_tls_addr(void) { return &_tsrm_ls_cache.eg; }
static void *compiler_globals_tls_addr(void) { return &_tsrm_ls_cache.cg; }
static HashTable *global_function_table = NULL;
static HashTable *global_class_table = NULL;
static HashTable *global_constants_table = NULL;
static HashTable *global_auto_globals_table = NULL;
static HashTable *global_persistent_list = NULL;
TSRMLS_MAIN_CACHE_DEFINE()
# define GLOBAL_FUNCTION_TABLE global_function_table
# define GLOBAL_CLASS_TABLE global_class_table
# define GLOBAL_CONSTANTS_TABLE global_constants_table
Expand Down Expand Up @@ -801,6 +816,7 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{

static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{{ */
{
_tsrm_ls_cache.self = &_tsrm_ls_cache;
zend_startup_constants();
zend_copy_constants(executor_globals->zend_constants, GLOBAL_CONSTANTS_TABLE);
zend_init_rsrc_plist();
Expand Down Expand Up @@ -1019,8 +1035,8 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */
zend_init_rsrc_list_dtors();

#ifdef ZTS
ts_allocate_fast_id(&compiler_globals_id, &compiler_globals_offset, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
ts_allocate_fast_id(&executor_globals_id, &executor_globals_offset, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
ts_allocate_tls_id(&compiler_globals_id, compiler_globals_tls_addr, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
ts_allocate_tls_id(&executor_globals_id, executor_globals_tls_addr, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
ts_allocate_fast_id(&language_scanner_globals_id, &language_scanner_globals_offset, sizeof(zend_php_scanner_globals), (ts_allocate_ctor) php_scanner_globals_ctor, NULL);
ts_allocate_fast_id(&ini_scanner_globals_id, &ini_scanner_globals_offset, sizeof(zend_ini_scanner_globals), (ts_allocate_ctor) ini_scanner_globals_ctor, NULL);
compiler_globals = ts_resource(compiler_globals_id);
Expand Down
11 changes: 9 additions & 2 deletions Zend/zend_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@
BEGIN_EXTERN_C()
ZEND_API extern int compiler_globals_id;
ZEND_API extern int executor_globals_id;
ZEND_API extern size_t compiler_globals_offset;
ZEND_API extern size_t executor_globals_offset;
END_EXTERN_C()

#endif
Expand Down Expand Up @@ -329,6 +327,15 @@ struct _zend_executor_globals {
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};

#ifdef ZTS
struct _zend_tsrm_ls_cache {
void *cache;
void *self;
zend_executor_globals eg;
zend_compiler_globals cg;
};
#endif

#define EG_FLAGS_INITIAL (0)
#define EG_FLAGS_IN_SHUTDOWN (1<<0)
#define EG_FLAGS_OBJECT_STORE_NO_REUSE (1<<1)
Expand Down
36 changes: 34 additions & 2 deletions Zend/zend_globals_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,39 @@ typedef struct _zend_executor_globals zend_executor_globals;
typedef struct _zend_php_scanner_globals zend_php_scanner_globals;
typedef struct _zend_ini_scanner_globals zend_ini_scanner_globals;

#ifdef ZEND_WIN32
# define ZEND_TLS_API
# ifdef LIBZEND_EXPORTS
# define ZEND_TLS_DIRECT 1
# endif
#else
# define ZEND_TLS_API ZEND_API
# define ZEND_TLS_DIRECT 1
#endif

BEGIN_EXTERN_C()

#ifdef ZTS
typedef struct _zend_tsrm_ls_cache zend_tsrm_ls_cache;
# ifdef ZEND_TLS_DIRECT
extern ZEND_TLS_API TSRM_TLS TSRM_TLS_MODEL_ATTR zend_tsrm_ls_cache _tsrm_ls_cache;
/* See zenc.c: zend_win_tsrm_cache_init */
# if defined(_WIN64)
extern ZEND_TLS_API unsigned long zend_win_tsrm_cache_slot;
# define ZEND_TSRM_CACHE_PTR ((zend_tsrm_ls_cache*)__readgsqword(0x1480 + zend_win_tsrm_cache_slot * 8))
# else
# define ZEND_TSRM_CACHE_PTR (&_tsrm_ls_cache)
# endif
# endif
#endif

/* Compiler */
#ifdef ZTS
# define CG(v) ZEND_TSRMG_FAST(compiler_globals_offset, zend_compiler_globals *, v)
# ifdef ZEND_TLS_DIRECT
# define CG(v) (ZEND_TSRM_CACHE_PTR->cg.v)
# else
# define CG(v) ZEND_TSRMG(compiler_globals_id, zend_compiler_globals *, v)
# endif
#else
# define CG(v) (compiler_globals.v)
extern ZEND_API struct _zend_compiler_globals compiler_globals;
Expand All @@ -40,7 +68,11 @@ ZEND_API int zendparse(void);

/* Executor */
#ifdef ZTS
# define EG(v) ZEND_TSRMG_FAST(executor_globals_offset, zend_executor_globals *, v)
# ifdef ZEND_TLS_DIRECT
# define EG(v) (ZEND_TSRM_CACHE_PTR->eg.v)
# else
# define EG(v) ZEND_TSRMG(executor_globals_id, zend_executor_globals *, v)
# endif
#else
# define EG(v) (executor_globals.v)
extern ZEND_API zend_executor_globals executor_globals;
Expand Down
4 changes: 3 additions & 1 deletion ext/opcache/jit/ir/ir_aarch64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -5868,8 +5868,10 @@ static void ir_emit_tls(ir_ctx *ctx, ir_ref def, ir_insn *insn)
| ldr Rx(reg), [Rx(reg), #insn->op3]
|| }
||# else
|| if (insn->op2 != 0 || insn->op3 != IR_NULL) {
||//??? IR_ASSERT(insn->op2 <= LDR_STR_PIMM64);
| ldr Rx(reg), [Rx(reg), #insn->op2]
| ldr Rx(reg), [Rx(reg), #insn->op2]
|| }
||# endif
||#endif
if (IR_REG_SPILLED(ctx->regs[def][0])) {
Expand Down
21 changes: 6 additions & 15 deletions ext/opcache/jit/tls/zend_jit_tls_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,21 @@ zend_result zend_jit_resolve_tsrm_ls_cache_offsets(
size_t *module_index,
size_t *module_offset
) {
/* To find offset of "_tsrm_ls_cache" in TLS segment we perform a linear scan of local TLS memory */
/* Probably, it might be better solution */
/* Offset of _tsrm_ls_cache within this module's TLS block. */
#ifdef _WIN64
void ***tls_mem = ((void****)__readgsqword(0x58))[_tls_index];
#else
void ***tls_mem = ((void****)__readfsdword(0x2c))[_tls_index];
#endif
void *val = _tsrm_ls_cache;
size_t offset = 0;
size_t size = (char*)&_tls_end - (char*)&_tls_start;

while (offset < size) {
if (*tls_mem == val) {
*module_index = _tls_index * sizeof(void*);
*module_offset = offset;
return SUCCESS;
}
tls_mem++;
offset += sizeof(void*);
}
size_t offset = (size_t)((char*)&_tsrm_ls_cache - (char*)tls_mem);

if (offset >= size) {
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size");
return FAILURE;
}

return FAILURE;
*module_index = _tls_index * sizeof(void*);
*module_offset = offset;
return SUCCESS;
}
Loading
Loading