summaryrefslogtreecommitdiff
path: root/TSRM
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-03-14 03:01:01 +0300
committerDmitry Stogov <dmitry@zend.com>2019-03-14 03:01:01 +0300
commit9499484ed2f0377678b2b4d88573327ee0e4ce6d (patch)
tree2253189b70e711565902d2c372fe5d93ce111358 /TSRM
parenta1b7bc0c8148eaf728fccdffe147e3bc0c03f18e (diff)
downloadphp-git-9499484ed2f0377678b2b4d88573327ee0e4ce6d.tar.gz
Implemented a faster way to access predefined TSRM resources - CG(), EG(), etc.
Diffstat (limited to 'TSRM')
-rw-r--r--TSRM/TSRM.c147
-rw-r--r--TSRM/TSRM.h16
2 files changed, 136 insertions, 27 deletions
diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c
index 67f6722945..670c260678 100644
--- a/TSRM/TSRM.c
+++ b/TSRM/TSRM.c
@@ -34,6 +34,7 @@ typedef struct {
size_t size;
ts_allocate_ctor ctor;
ts_allocate_dtor dtor;
+ size_t fast_offset;
int done;
} tsrm_resource_type;
@@ -47,6 +48,9 @@ static ts_rsrc_id id_count;
static tsrm_resource_type *resource_types_table=NULL;
static int resource_types_table_size;
+/* Reserved space for fast globals access */
+static size_t tsrm_reserved_pos = 0;
+static size_t tsrm_reserved_size = 0;
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
@@ -160,6 +164,10 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
tsmm_mutex = tsrm_mutex_alloc();
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
+
+ tsrm_reserved_pos = 0;
+ tsrm_reserved_size = 0;
+
return 1;
}/*}}}*/
@@ -187,7 +195,9 @@ TSRM_API void tsrm_shutdown(void)
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
resource_types_table[j].dtor(p->storage[j]);
}
- free(p->storage[j]);
+ if (!resource_types_table[j].fast_offset) {
+ free(p->storage[j]);
+ }
}
}
free(p->storage);
@@ -222,14 +232,46 @@ TSRM_API void tsrm_shutdown(void)
tsrm_new_thread_begin_handler = NULL;
tsrm_new_thread_end_handler = NULL;
tsrm_shutdown_handler = NULL;
+
+ tsrm_reserved_pos = 0;
+ tsrm_reserved_size = 0;
}/*}}}*/
-/* allocates a new thread-safe-resource id */
-TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
+/* enlarge the arrays for the already active threads */
+static void tsrm_update_active_threads(void)
{/*{{{*/
int i;
+ for (i=0; i<tsrm_tls_table_size; i++) {
+ tsrm_tls_entry *p = tsrm_tls_table[i];
+
+ while (p) {
+ if (p->count < id_count) {
+ int j;
+
+ 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) {
+ p->storage[j] = (void *) (((char*)p) + resource_types_table[j].fast_offset);
+ } else {
+ p->storage[j] = (void *) malloc(resource_types_table[j].size);
+ }
+ if (resource_types_table[j].ctor) {
+ resource_types_table[j].ctor(p->storage[j]);
+ }
+ }
+ p->count = id_count;
+ }
+ p = p->next;
+ }
+ }
+}/*}}}*/
+
+
+/* allocates a new thread-safe-resource id */
+TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
+{/*{{{*/
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
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
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)].done = 0;
- /* enlarge the arrays for the already active threads */
- for (i=0; i<tsrm_tls_table_size; i++) {
- tsrm_tls_entry *p = tsrm_tls_table[i];
+ tsrm_update_active_threads();
+ tsrm_mutex_unlock(tsmm_mutex);
- while (p) {
- if (p->count < id_count) {
- int j;
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
+ return *rsrc_id;
+}/*}}}*/
- p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
- for (j=p->count; j<id_count; j++) {
- p->storage[j] = (void *) malloc(resource_types_table[j].size);
- if (resource_types_table[j].ctor) {
- resource_types_table[j].ctor(p->storage[j]);
- }
- }
- p->count = id_count;
- }
- p = p->next;
+
+/* Reserve space for fast thread-safe-resources */
+TSRM_API void tsrm_reserve(size_t size)
+{/*{{{*/
+ tsrm_reserved_pos = 0;
+ tsrm_reserved_size = TSRM_ALIGNED_SIZE(size);
+}/*}}}*/
+
+
+/* allocates a new fast thread-safe-resource id */
+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)
+{/*{{{*/
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new fast resource id, %d bytes", size));
+
+ tsrm_mutex_lock(tsmm_mutex);
+
+ /* obtain a resource id */
+ *rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
+
+ size = TSRM_ALIGNED_SIZE(size);
+ if (tsrm_reserved_size - tsrm_reserved_pos < size) {
+ tsrm_mutex_unlock(tsmm_mutex);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate space for fast resource"));
+ *rsrc_id = 0;
+ *offset = 0;
+ return 0;
+ }
+
+ *offset = TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_pos;
+ tsrm_reserved_pos += size;
+
+ /* store the new resource type in the resource sizes table */
+ 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_mutex_unlock(tsmm_mutex);
+ TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
+ *rsrc_id = 0;
+ 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 = *offset;
+ 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 resource id %d", *rsrc_id));
@@ -288,7 +370,7 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_
int i;
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id));
- (*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
+ (*thread_resources_ptr) = (tsrm_tls_entry *) malloc(TSRM_ALIGNED_SIZE(sizeof(tsrm_tls_entry)) + tsrm_reserved_size);
(*thread_resources_ptr)->storage = NULL;
if (id_count > 0) {
(*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_
for (i=0; i<id_count; i++) {
if (resource_types_table[i].done) {
(*thread_resources_ptr)->storage[i] = NULL;
- } else
- {
- (*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
+ } 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);
+ }
if (resource_types_table[i].ctor) {
resource_types_table[i].ctor((*thread_resources_ptr)->storage[i]);
}
@@ -402,7 +487,9 @@ void tsrm_free_interpreter_context(void *context)
}
}
for (i=0; i<thread_resources->count; i++) {
- free(thread_resources->storage[i]);
+ if (!resource_types_table[i].fast_offset) {
+ free(thread_resources->storage[i]);
+ }
}
free(thread_resources->storage);
free(thread_resources);
@@ -467,7 +554,9 @@ void ts_free_thread(void)
}
}
for (i=0; i<thread_resources->count; i++) {
- free(thread_resources->storage[i]);
+ if (!resource_types_table[i].fast_offset) {
+ free(thread_resources->storage[i]);
+ }
}
free(thread_resources->storage);
if (last) {
@@ -509,7 +598,9 @@ void ts_free_worker_threads(void)
}
}
for (i=0; i<thread_resources->count; i++) {
- free(thread_resources->storage[i]);
+ if (!resource_types_table[i].fast_offset) {
+ free(thread_resources->storage[i]);
+ }
}
free(thread_resources->storage);
if (last) {
@@ -553,7 +644,9 @@ void ts_free_id(ts_rsrc_id id)
if (resource_types_table && resource_types_table[j].dtor) {
resource_types_table[j].dtor(p->storage[j]);
}
- free(p->storage[j]);
+ if (!resource_types_table[j].fast_offset) {
+ free(p->storage[j]);
+ }
p->storage[j] = NULL;
}
p = p->next;
diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h
index 061459e77d..a14e31e1f0 100644
--- a/TSRM/TSRM.h
+++ b/TSRM/TSRM.h
@@ -57,6 +57,14 @@ typedef uintptr_t tsrm_uintptr_t;
#include <TLS.h>
#endif
+#if SIZEOF_SIZE_T == 4
+# define TSRM_ALIGNED_SIZE(size) \
+ (((size) + INT32_C(15)) & ~INT32_C(15))
+#else
+# define TSRM_ALIGNED_SIZE(size) \
+ (((size) + INT64_C(15)) & ~INT64_C(15))
+#endif
+
typedef int ts_rsrc_id;
/* Define THREAD_T and MUTEX_T */
@@ -94,6 +102,10 @@ TSRM_API void tsrm_shutdown(void);
/* allocates a new thread-safe-resource id */
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
+/* 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);
+
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
#define ts_resource(id) ts_resource_ex(id, NULL)
@@ -162,9 +174,13 @@ TSRM_API const char *tsrm_api_name(void);
#define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_get_ls_cache()
#define TSRMG(id, type, element) (TSRMG_BULK(id, type)->element)
#define TSRMG_BULK(id, type) ((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)])
+#define TSRMG_FAST(offset, type, element) (TSRMG_FAST_BULK(offset, type)->element)
+#define TSRMG_FAST_BULK(offset, type) ((type) (((char*) tsrm_get_ls_cache())+(offset)))
#define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element)
#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)))
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
#if ZEND_DEBUG