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

Reply via email to