Skip to content

Commit 2dd2dca

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Implemented a faster way to access predefined TSRM resources - CG(), EG(), etc.
2 parents d349ea3 + 9499484 commit 2dd2dca

28 files changed

+245
-66
lines changed

TSRM/TSRM.c

Lines changed: 120 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef struct {
3434
size_t size;
3535
ts_allocate_ctor ctor;
3636
ts_allocate_dtor dtor;
37+
size_t fast_offset;
3738
int done;
3839
} tsrm_resource_type;
3940

@@ -47,6 +48,9 @@ static ts_rsrc_id id_count;
4748
static tsrm_resource_type *resource_types_table=NULL;
4849
static int resource_types_table_size;
4950

51+
/* Reserved space for fast globals access */
52+
static size_t tsrm_reserved_pos = 0;
53+
static size_t tsrm_reserved_size = 0;
5054

5155
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
5256

@@ -160,6 +164,10 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
160164
tsmm_mutex = tsrm_mutex_alloc();
161165

162166
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
167+
168+
tsrm_reserved_pos = 0;
169+
tsrm_reserved_size = 0;
170+
163171
return 1;
164172
}/*}}}*/
165173

@@ -187,7 +195,9 @@ TSRM_API void tsrm_shutdown(void)
187195
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
188196
resource_types_table[j].dtor(p->storage[j]);
189197
}
190-
free(p->storage[j]);
198+
if (!resource_types_table[j].fast_offset) {
199+
free(p->storage[j]);
200+
}
191201
}
192202
}
193203
free(p->storage);
@@ -222,14 +232,46 @@ TSRM_API void tsrm_shutdown(void)
222232
tsrm_new_thread_begin_handler = NULL;
223233
tsrm_new_thread_end_handler = NULL;
224234
tsrm_shutdown_handler = NULL;
235+
236+
tsrm_reserved_pos = 0;
237+
tsrm_reserved_size = 0;
225238
}/*}}}*/
226239

227240

228-
/* allocates a new thread-safe-resource id */
229-
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
241+
/* enlarge the arrays for the already active threads */
242+
static void tsrm_update_active_threads(void)
230243
{/*{{{*/
231244
int i;
232245

246+
for (i=0; i<tsrm_tls_table_size; i++) {
247+
tsrm_tls_entry *p = tsrm_tls_table[i];
248+
249+
while (p) {
250+
if (p->count < id_count) {
251+
int j;
252+
253+
p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
254+
for (j=p->count; j<id_count; j++) {
255+
if (resource_types_table[j].fast_offset) {
256+
p->storage[j] = (void *) (((char*)p) + resource_types_table[j].fast_offset);
257+
} else {
258+
p->storage[j] = (void *) malloc(resource_types_table[j].size);
259+
}
260+
if (resource_types_table[j].ctor) {
261+
resource_types_table[j].ctor(p->storage[j]);
262+
}
263+
}
264+
p->count = id_count;
265+
}
266+
p = p->next;
267+
}
268+
}
269+
}/*}}}*/
270+
271+
272+
/* allocates a new thread-safe-resource id */
273+
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
274+
{/*{{{*/
233275
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
234276

235277
tsrm_mutex_lock(tsmm_mutex);
@@ -254,28 +296,68 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate
254296
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
255297
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
256298
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
299+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = 0;
257300
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
258301

259-
/* enlarge the arrays for the already active threads */
260-
for (i=0; i<tsrm_tls_table_size; i++) {
261-
tsrm_tls_entry *p = tsrm_tls_table[i];
302+
tsrm_update_active_threads();
303+
tsrm_mutex_unlock(tsmm_mutex);
262304

263-
while (p) {
264-
if (p->count < id_count) {
265-
int j;
305+
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
306+
return *rsrc_id;
307+
}/*}}}*/
266308

267-
p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
268-
for (j=p->count; j<id_count; j++) {
269-
p->storage[j] = (void *) malloc(resource_types_table[j].size);
270-
if (resource_types_table[j].ctor) {
271-
resource_types_table[j].ctor(p->storage[j]);
272-
}
273-
}
274-
p->count = id_count;
275-
}
276-
p = p->next;
309+
310+
/* Reserve space for fast thread-safe-resources */
311+
TSRM_API void tsrm_reserve(size_t size)
312+
{/*{{{*/
313+
tsrm_reserved_pos = 0;
314+
tsrm_reserved_size = TSRM_ALIGNED_SIZE(size);
315+
}/*}}}*/
316+
317+
318+
/* allocates a new fast thread-safe-resource id */
319+
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)
320+
{/*{{{*/
321+
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new fast resource id, %d bytes", size));
322+
323+
tsrm_mutex_lock(tsmm_mutex);
324+
325+
/* obtain a resource id */
326+
*rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
327+
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
328+
329+
size = TSRM_ALIGNED_SIZE(size);
330+
if (tsrm_reserved_size - tsrm_reserved_pos < size) {
331+
tsrm_mutex_unlock(tsmm_mutex);
332+
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate space for fast resource"));
333+
*rsrc_id = 0;
334+
*offset = 0;
335+
return 0;
336+
}
337+
338+
*offset = TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_pos;
339+
tsrm_reserved_pos += size;
340+
341+
/* store the new resource type in the resource sizes table */
342+
if (resource_types_table_size < id_count) {
343+
tsrm_resource_type *_tmp;
344+
_tmp = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
345+
if (!_tmp) {
346+
tsrm_mutex_unlock(tsmm_mutex);
347+
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
348+
*rsrc_id = 0;
349+
return 0;
277350
}
351+
resource_types_table = _tmp;
352+
resource_types_table_size = id_count;
278353
}
354+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
355+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
356+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
357+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].fast_offset = *offset;
358+
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
359+
360+
tsrm_update_active_threads();
279361
tsrm_mutex_unlock(tsmm_mutex);
280362

281363
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
@@ -288,7 +370,7 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
288370
int i;
289371

290372
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id));
291-
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
373+
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_size);
292374
(*thread_resources_ptr)->storage = NULL;
293375
if (id_count > 0) {
294376
(*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
@@ -307,9 +389,12 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
307389
for (i=0; i<id_count; i++) {
308390
if (resource_types_table[i].done) {
309391
(*thread_resources_ptr)->storage[i] = NULL;
310-
} else
311-
{
312-
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
392+
} else {
393+
if (resource_types_table[i].fast_offset) {
394+
(*thread_resources_ptr)->storage[i] = (void *) (((char*)(*thread_resources_ptr)) + resource_types_table[i].fast_offset);
395+
} else {
396+
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
397+
}
313398
if (resource_types_table[i].ctor) {
314399
resource_types_table[i].ctor((*thread_resources_ptr)->storage[i]);
315400
}
@@ -402,7 +487,9 @@ void tsrm_free_interpreter_context(void *context)
402487
}
403488
}
404489
for (i=0; i<thread_resources->count; i++) {
405-
free(thread_resources->storage[i]);
490+
if (!resource_types_table[i].fast_offset) {
491+
free(thread_resources->storage[i]);
492+
}
406493
}
407494
free(thread_resources->storage);
408495
free(thread_resources);
@@ -467,7 +554,9 @@ void ts_free_thread(void)
467554
}
468555
}
469556
for (i=0; i<thread_resources->count; i++) {
470-
free(thread_resources->storage[i]);
557+
if (!resource_types_table[i].fast_offset) {
558+
free(thread_resources->storage[i]);
559+
}
471560
}
472561
free(thread_resources->storage);
473562
if (last) {
@@ -509,7 +598,9 @@ void ts_free_worker_threads(void)
509598
}
510599
}
511600
for (i=0; i<thread_resources->count; i++) {
512-
free(thread_resources->storage[i]);
601+
if (!resource_types_table[i].fast_offset) {
602+
free(thread_resources->storage[i]);
603+
}
513604
}
514605
free(thread_resources->storage);
515606
if (last) {
@@ -553,7 +644,9 @@ void ts_free_id(ts_rsrc_id id)
553644
if (resource_types_table && resource_types_table[j].dtor) {
554645
resource_types_table[j].dtor(p->storage[j]);
555646
}
556-
free(p->storage[j]);
647+
if (!resource_types_table[j].fast_offset) {
648+
free(p->storage[j]);
649+
}
557650
p->storage[j] = NULL;
558651
}
559652
p = p->next;

TSRM/TSRM.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ typedef uintptr_t tsrm_uintptr_t;
5757
#include <TLS.h>
5858
#endif
5959

60+
#if SIZEOF_SIZE_T == 4
61+
# define TSRM_ALIGNED_SIZE(size) \
62+
(((size) + INT32_C(15)) & ~INT32_C(15))
63+
#else
64+
# define TSRM_ALIGNED_SIZE(size) \
65+
(((size) + INT64_C(15)) & ~INT64_C(15))
66+
#endif
67+
6068
typedef int ts_rsrc_id;
6169

6270
/* Define THREAD_T and MUTEX_T */
@@ -94,6 +102,10 @@ TSRM_API void tsrm_shutdown(void);
94102
/* allocates a new thread-safe-resource id */
95103
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
96104

105+
/* Fast resource in reserved (pre-allocated) space */
106+
TSRM_API void tsrm_reserve(size_t size);
107+
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);
108+
97109
/* fetches the requested resource for the current thread */
98110
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
99111
#define ts_resource(id) ts_resource_ex(id, NULL)
@@ -162,9 +174,13 @@ TSRM_API const char *tsrm_api_name(void);
162174
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_get_ls_cache()
163175
#define TSRMG(id, type, element) (TSRMG_BULK(id, type)->element)
164176
#define TSRMG_BULK(id, type) ((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)])
177+
#define TSRMG_FAST(offset, type, element) (TSRMG_FAST_BULK(offset, type)->element)
178+
#define TSRMG_FAST_BULK(offset, type) ((type) (((char*) tsrm_get_ls_cache())+(offset)))
165179

166180
#define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element)
167181
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
182+
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
183+
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
168184
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
169185
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
170186
#if ZEND_DEBUG

Zend/zend.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ static size_t global_map_ptr_last = 0;
3838
#ifdef ZTS
3939
ZEND_API int compiler_globals_id;
4040
ZEND_API int executor_globals_id;
41+
ZEND_API size_t compiler_globals_offset;
42+
ZEND_API size_t executor_globals_offset;
4143
static HashTable *global_function_table = NULL;
4244
static HashTable *global_class_table = NULL;
4345
static HashTable *global_constants_table = NULL;
@@ -868,10 +870,10 @@ int zend_startup(zend_utility_functions *utility_functions) /* {{{ */
868870
zend_init_rsrc_list_dtors();
869871

870872
#ifdef ZTS
871-
ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
872-
ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
873-
ts_allocate_id(&language_scanner_globals_id, sizeof(zend_php_scanner_globals), (ts_allocate_ctor) php_scanner_globals_ctor, NULL);
874-
ts_allocate_id(&ini_scanner_globals_id, sizeof(zend_ini_scanner_globals), (ts_allocate_ctor) ini_scanner_globals_ctor, NULL);
873+
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);
874+
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);
875+
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);
876+
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);
875877
compiler_globals = ts_resource(compiler_globals_id);
876878
executor_globals = ts_resource(executor_globals_id);
877879

Zend/zend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@
5555

5656
#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
5757
#define ZEND_TSRMG TSRMG_STATIC
58+
#define ZEND_TSRMG_FAST TSRMG_FAST_STATIC
5859
#define ZEND_TSRMLS_CACHE_EXTERN() TSRMLS_CACHE_EXTERN()
5960
#define ZEND_TSRMLS_CACHE_DEFINE() TSRMLS_CACHE_DEFINE()
6061
#define ZEND_TSRMLS_CACHE_UPDATE() TSRMLS_CACHE_UPDATE()
6162
#define ZEND_TSRMLS_CACHE TSRMLS_CACHE
6263
#else
6364
#define ZEND_TSRMG TSRMG
65+
#define ZEND_TSRMG_FAST TSRMG_FAST
6466
#define ZEND_TSRMLS_CACHE_EXTERN()
6567
#define ZEND_TSRMLS_CACHE_DEFINE()
6668
#define ZEND_TSRMLS_CACHE_UPDATE()

Zend/zend_alloc.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,7 +2371,8 @@ typedef struct _zend_alloc_globals {
23712371

23722372
#ifdef ZTS
23732373
static int alloc_globals_id;
2374-
# define AG(v) ZEND_TSRMG(alloc_globals_id, zend_alloc_globals *, v)
2374+
static size_t alloc_globals_offset;
2375+
# define AG(v) ZEND_TSRMG_FAST(alloc_globals_offset, zend_alloc_globals *, v)
23752376
#else
23762377
# define AG(v) (alloc_globals.v)
23772378
static zend_alloc_globals alloc_globals;
@@ -2736,7 +2737,7 @@ static void alloc_globals_dtor(zend_alloc_globals *alloc_globals)
27362737
ZEND_API void start_memory_manager(void)
27372738
{
27382739
#ifdef ZTS
2739-
ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
2740+
ts_allocate_fast_id(&alloc_globals_id, &alloc_globals_offset, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
27402741
#else
27412742
alloc_globals_ctor(&alloc_globals);
27422743
#endif
@@ -2958,3 +2959,10 @@ ZEND_API void * __zend_realloc(void *p, size_t len)
29582959
}
29592960
zend_out_of_memory();
29602961
}
2962+
2963+
#ifdef ZTS
2964+
size_t zend_mm_globals_size(void)
2965+
{
2966+
return sizeof(zend_alloc_globals);
2967+
}
2968+
#endif

Zend/zend_alloc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,10 @@ static void apc_init_heap(void)
398398
399399
*/
400400

401+
#ifdef ZTS
402+
size_t zend_mm_globals_size(void);
403+
#endif
404+
401405
END_EXTERN_C()
402406

403407
#endif

Zend/zend_gc.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ typedef struct _zend_gc_globals {
211211

212212
#ifdef ZTS
213213
static int gc_globals_id;
214-
#define GC_G(v) ZEND_TSRMG(gc_globals_id, zend_gc_globals *, v)
214+
static size_t gc_globals_offset;
215+
#define GC_G(v) ZEND_TSRMG_FAST(gc_globals_offset, zend_gc_globals *, v)
215216
#else
216217
#define GC_G(v) (gc_globals.v)
217218
static zend_gc_globals gc_globals;
@@ -442,7 +443,7 @@ static void gc_globals_ctor_ex(zend_gc_globals *gc_globals)
442443
void gc_globals_ctor(void)
443444
{
444445
#ifdef ZTS
445-
ts_allocate_id(&gc_globals_id, sizeof(zend_gc_globals), (ts_allocate_ctor) gc_globals_ctor_ex, (ts_allocate_dtor) root_buffer_dtor);
446+
ts_allocate_fast_id(&gc_globals_id, &gc_globals_offset, sizeof(zend_gc_globals), (ts_allocate_ctor) gc_globals_ctor_ex, (ts_allocate_dtor) root_buffer_dtor);
446447
#else
447448
gc_globals_ctor_ex(&gc_globals);
448449
#endif
@@ -1575,3 +1576,10 @@ ZEND_API void zend_gc_get_status(zend_gc_status *status)
15751576
status->threshold = GC_G(gc_threshold);
15761577
status->num_roots = GC_G(num_roots);
15771578
}
1579+
1580+
#ifdef ZTS
1581+
size_t zend_gc_globals_size(void)
1582+
{
1583+
return sizeof(zend_gc_globals);
1584+
}
1585+
#endif

0 commit comments

Comments
 (0)