Hi Nikita, On Thu, September 18, 2014 22:34, Nikita Popov wrote: > On Thu, Sep 18, 2014 at 5:14 PM, Anatol Belski <a...@php.net> wrote: > > >> Commit: e8b497ad8eb74273f7f44ae7e515e7a5e95b50f7 >> Author: Anatol Belski <a...@php.net> Thu, 18 Sep 2014 16:45:50 >> +0200 >> Parents: f162b3f736f07ad868abec6ea8b44a91e77d4069 >> Branches: master >> >> >> Link: >> http://git.php.net/?p=php-src.git;a=commitdiff;h=e8b497ad8eb74273f7f44ae >> 7e515e7a5e95b50f7 >> >> >> Log: >> fix CG(empty_string) init in ZTS >> >> Changed paths: >> M Zend/zend.c >> >> >> >> Diff: >> diff --git a/Zend/zend.c b/Zend/zend.c index 46719b4..6a53179 100644 --- >> a/Zend/zend.c +++ b/Zend/zend.c >> @@ -120,6 +120,7 @@ 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; +static zend_string >> *default_empty_string = NULL; >> #endif >> >> >> ZEND_API zend_utility_values zend_uv; >> @@ -514,6 +515,15 @@ static void >> compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS >> compiler_globals->static_members_table = NULL; } >> compiler_globals->script_encoding_list = NULL; + >> +#ifdef ZTS >> + compiler_globals->empty_string = zend_string_alloc(sizeof("")-1, >> 1); >> + compiler_globals->empty_string->val[0] = '\000'; >> + zend_string_hash_val(compiler_globals->empty_string); >> + compiler_globals->empty_string->gc.u.v.flags |= IS_STR_INTERNED; >> + >> + memset(compiler_globals->one_char_string, 0, >> sizeof(compiler_globals->one_char_string)); +#endif >> } >> /* }}} */ >> >> >> @@ -538,6 +548,10 @@ static void >> compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS >> pefree((char*)compiler_globals->script_encoding_list, 1); } >> compiler_globals->last_static_member = 0; + >> +#ifdef ZTS >> + free(compiler_globals->empty_string); >> +#endif >> } >> /* }}} */ >> >> > > What does this fix and how does it relate to the initialization done in > zend_interned_strings_init? > > Btw, does anyone know why we don't use interned strings in ZTS? > > > Nikita > > So CG in a new thread is first a virgin chunk of memory. zend_interned_strings_init() allocates CG(empty_string) in the master thread first. In contrary to NTS, where the request is processed using the same globals, the TS model will need to initialize all the globals for everythread. Every structure in a thread is malloc'd and then it's members go through the corresponding ctor routines (compiler_globals_ctor in this case). However the init in TS happens once per thread, not per request.
The flow in TS, very rough vision startup (init globals, master) start thread 0 (init globals, thread 0) serve request 0 serve request 1 ...... serve request n shutdown thread 0 (free globals, thread 0) ...... start thread n (init globals, thread n) serve request 0 serve request 1 ...... serve request n shutdown thread n (free globals, thread n) shutdown (free globals, master) As one can see, the globals between threads are different and have to be initialized separately. For every thread, it copies the data skeleton from the master thread, but the thread ueses them on it's own then. Why don't we use interned strings in TS - good question. After a day of debugging I'd say it were a challenge to fix some crazy bugs if one decides to do that :) Either it would need to work by the same flow as globals, say one pool per thread (which is kinda wasteful), or one would go the right way and share the pool between threads, but then having to handle all the concurrency issues. Regards Anatol -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php