issue in copying the hash table(Reposted third time)

php.internals

Kamesh Jayachandran

22 years ago
Hi All, Sorry to repost for the third time. I want the clarification regarding copying the global_class_table to thread specific compiler_globals->class_table in compiler_globals_ctor in Zend/zend.c. According to me memcpy should copy 'whatever source points to' to 'destination'. Our class_table hashtable structure looks like this, char *key; zend_class_entry** value; So memcpy should copy only whatever (zend_class_entry**) points to which is semantically wrong good candidate for Segmentation fault. No way memcpy can do double dereferencing for this case. Somehow in Linux when i compile it with maintainer-zts-mode memcpy copies the data fine. I verified all the internal classes. Thread specific class_table is in sink with the global_class_table. Please clarify. Thanks in Advance With regards Kamesh Jayachandran

Andi Gutmans

22 years ago
I don't quite understand the question. Can you rephrase what exactly is bothering you? Andi At 03:46 AM 6/28/2004 +0530, Kamesh Jayachandran wrote:

Kamesh Jayachandran

22 years ago
Hi Andi, In Zend/zend.c function name is compiler_globals_ctor This function is defined inside the #ifdef ZTS macro Line of concern zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry)); If I am correct our global_class_table is a hash table of classname versus zend_class_entry**. In this case while making a copy og global_class_table to thread specific class_table in a deep fashion. zend_hash_copy has to do the double dereferencing which it can't being a generic fuinction. So my contention is The above line should be the following zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry*)); If sharing of class entries are desired across threads. Else We should write a custom class_table deep copy function. Hope I made it clear. Awaiting for your comments. With regards Kamesh Jayachandran On Mon, 28 Jun 2004 07:58:59 -0700, "Andi Gutmans" <andi@zend.com> said:

Kamesh Jayachandran

22 years ago
Did I make the problem statement clear?. With regards Kamesh Jayachandran On Mon, 28 Jun 2004 22:57:38 -0700, "Kamesh Jayachandran" <kameshj@fastmail.fm> said:

Kamesh Jayachandran

22 years ago
Hi All, Can someone clarify me on this?. With regards Kamesh Jayachandran On Mon, 05 Jul 2004 01:25:51 -0700, "Kamesh Jayachandran" <kameshj@fastmail.fm> said:

Moriyoshi Koizumi

22 years ago
On 2004/07/07, at 14:18, Kamesh Jayachandran wrote:
>>> In this case while making a copy og global_class_table to thread >>> specific class_table in a deep fashion. zend_hash_copy has to do the >>> double dereferencing which it can't being a generic fuinction.
Sorry, but I don't quite understand what you meant in the above paragraph. Is it a threading / race related issue that you are pointing out here? As far as I know, only the global class table is shared across threads and is duplicated to emulate fork() behaviour, as the compiler global is actually a thread specific value (that is, a separate instance is prepared for each thread.) Moriyoshi

Kamesh Jayachandran

22 years ago
Hi Moriyoshi, Thanks for replying. My question is very simple. Please answer the following question. 1)Zend has global_class_table of type HashTable with a key as the class name ('char*') and value of type 'zend_class_entry**'. True or False? As I look at the code the above statement seems to be true. If it is the case to duplicate the global_class_table for each thread, we need to double dereferencing for each class in the global_class_table.(As the value is of type zend_class_entry** in the HashTable.) Having this deep copy implementation inside zend_hash_copy which is a generic function responsible for copying any two hash table cannot be used for this specific case of double dereferencing. My statement about this global_class_table copy is not correct. But somehow it is working. If the answer to the above question is False. I can show the piece of code from where I have come to a answer of 'True'. Thanks With regards Kamesh Jayachandran On Wed, 7 Jul 2004 23:50:59 +0900, "Moriyoshi Koizumi" <moriyoshi@at.wakwak.com> said:

Moriyoshi Koizumi

22 years ago
On 2004/07/08, at 1:04, Kamesh Jayachandran wrote:
> My question is very simple. > Please answer the following question. > 1)Zend has global_class_table of type HashTable with a key as the class > name ('char*') and value of type 'zend_class_entry**'. True or False?
Keys are just strings and associated values are of zend_class_entry *. ZendEngine's HashTable may seem a quirk. It passes a pointer to the given value, not the holding value itself (of type zend_class_entry *, in this case). Is there something wrong with this? Moriyoshi

Kamesh Jayachandran

22 years ago
Hi Moriyoshi, File: Zend/zend_compile.c Function: do_bind_class <some code snippet> zend_class_entry *ce zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL) <some code snippet> From the above zend_hash_add I came to a conclusion that class_table is a HashTable of string versus zend_class_entry**. Am I incorrect? Whereas for function table do_bind_function zend_function *function; zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL) My argument is deep copy of hashtable using hash_copy will work in case of function table not in case of class_table because of double dereferencing needed in case of class_table. In fact we invoke zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry)); in Zend/zend.c in a function compiler_globals_ctor The last parameter sizeof(zend_class_entry) of value say 292 to zend_hash_copy indicate it to dereference the value of one of the hashtable entry. This value is of type zend_class_entry** which when dereferenced once gives rise to zend_class_entry* the corresponding memcpy function copies 292 bytes from this zend_class_entry * which is not correct. For details look at INIT_DATA macro in zend_hash.c Thanks in advance With regards Kamesh Jayachandran On Thu, 8 Jul 2004 02:25:21 +0900, "Moriyoshi Koizumi" <moriyoshi@at.wakwak.com> said:

Moriyoshi Koizumi

22 years ago
On 2004/07/08, at 14:41, Kamesh Jayachandran wrote:
> The last parameter sizeof(zend_class_entry) of value say 292 to > zend_hash_copy indicate it to dereference the value of one of the > hashtable entry. > This value is of type zend_class_entry** which when dereferenced once > gives rise to zend_class_entry* the corresponding memcpy function > copies > 292 bytes from this zend_class_entry * which is not correct. > For details look at INIT_DATA macro in zend_hash.c
This makes sense. So, your intention is just to make the line in question to reduce unnecessary malloc()'s and memcpy()'s. zend_hash_copy(compiler_globals->class_table, ... , sizeof(zend_class_entry)); Although this can eventually work, the newly built hash table CG(class_table) will hold the redundant space of sizeof(zend_class_entry) - sizeof(zend_class_entry *) bytes per class entry. And then you pointed out the above line should go like zend_hash_copy(compiler_globals->class_table, ... , sizeof(zend_class_entry *)); This appears a typo because the global function table, which is a hash table that contains instances of zend_function (not zend_function *), is also copied by zend_hash_copy() with the last argument being sizeof(zend_function). zend_hash_copy(compiler_globals->function_table, ... , sizeof(zend_function)); ... Did I get it right? Regards, Moriyoshi