internals:engine

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
internals:engine [2010/04/20 10:41] – Moved FAQ here for now derickinternals:engine [2012/03/07 00:30] – [Extension Globals] cataphract
Line 5: Line 5:
   * each op_array has an array of literals (constant values)   * each op_array has an array of literals (constant values)
   * opocde operands don't contain zval directly any more but points to thistable instead   * opocde operands don't contain zval directly any more but points to thistable instead
-  * during compilation they are accessible by index e.gop_array->literals[opline->op1.constant].constant +  * during compilation they are accessible by index e.g: <code>op_array->literals[opline->op1.constant].constant</code> 
-  * the pass_two() changes indexes into pointers so during execution they are accessible by opline->op1.zv+  * the pass_two() changes indexes into pointers so during execution they are accessible by: <code>opline->op1.zv</code>
  
 +===== Objects =====
 +See [[internals:engine:objects|here]].
  
 ===== FAQ ===== ===== FAQ =====
Line 24: Line 26:
  
  
-==== Throwing Exceptions on a 64bit Architecture ====+==== Memory Management ==== 
 + 
 +  [12:00pm] scoates: ok.. last question for now, I think: should I explicitly destroy on RSHUTDOWN, or let the non-persistent flag take care of that? 
 +  [12:00pm] johannes_: always cleanup yourself 
 + 
 +Note here: while MM shutdown will take care of all allocated memory, it won't run any dtors etc., that's why it is important to clean up the resources properly - otherwise external dependencies can be messed up. And of course you'd get leaks reported in the debug mode.  
 + 
 +==== Causes for crashes ==== 
 + 
 +=== Throwing Exceptions ===
  
 If throwing exceptions results in a segmentation fault on 64bit systems only, then be sure that you have: If throwing exceptions results in a segmentation fault on 64bit systems only, then be sure that you have:
Line 31: Line 42:
 (Remark: This header is always needed. The segfault might be caused by the fact, that C defaults the return value and parameters of undefined parameters to int. In cases where pointers and/or long data types are needed this might be wrong so a wrong function call is being made. A good compiler should give a warning. --johannes) (Remark: This header is always needed. The segfault might be caused by the fact, that C defaults the return value and parameters of undefined parameters to int. In cases where pointers and/or long data types are needed this might be wrong so a wrong function call is being made. A good compiler should give a warning. --johannes)
  
-==== Not yet categorized ====+==== Hashes ====
   [11:58am] scoates: what's the difference between zend_hash_[add] and zend_hash_quick_[add] ?   [11:58am] scoates: what's the difference between zend_hash_[add] and zend_hash_quick_[add] ?
   [11:58am] scoates: removal of gofaster loops? (-:   [11:58am] scoates: removal of gofaster loops? (-:
   [11:58am] Derick: with the 2nd one you can provide an already calculated hash-list index   [11:58am] Derick: with the 2nd one you can provide an already calculated hash-list index
-  [11:58am] Derick: plus some spaces  
  
   [11:59am] scoates: and the hashtable will automatically grow on _add, right? the length passed to init is just a hint?   [11:59am] scoates: and the hashtable will automatically grow on _add, right? the length passed to init is just a hint?
   [11:59am] johannes_: right   [11:59am] johannes_: right
 +===== Unsorted =====
  
-  [12:00pm] scoates: ok.. last question for now, think: should I explicitly destroy on RSHUTDOWN, or let the non-persistent flag take care of that? +Add your random stuff here. I'll move it/update it/fix it (Derick)
-  [12:00pm] johannes_: always cleanup yourself +
-  [12:02pm] Derick: just like mommy told you +
-  [12:02pm] Derick: :)+
  
-Note herewhile MM shutdown will take care of all allocated memory, it won'run any dtors etc., that's why it is important to clean up the resources properly otherwise external dependencies can be messed upAnd of course you'd get leaks reported in the debug mode+How to get %%__LINE__ and __FILE__%%? 
 +  * zend_get_executed_filename() and zend_get_executed_lineno() 
 + 
 +How do I detect the SAPI? 
 +  * The fastest way [to detect CLI] would beif (sapi_module.phpinfo_as_text) { ... } 
 +  * sapi_module is a true global, not a TSRM protected one 
 +  * sapi_module.name and sapi_module.pretty_name contain the name as char* 
 +  * sapi_module.phpinfo_as_text is a flag which can be set by different SAPIs to request text only phpinfo() output, currently only CLI and embed do that afaik, CGI does not. 
 + 
 + 
 +==== Extension Globals ===== 
 + 
 +To use extension globals (which are either true globals or thread local globals, depending on whether ZTS is enabled), follow these steps: 
 + 
 +- In php_extname.h, declare which global variables you need with: 
 + 
 +<code> 
 +ZEND_BEGIN_MODULE_GLOBALS(extname) 
 + int var1; 
 + char *var2; 
 + .... 
 +ZEND_END_MODULE_GLOBALS(extname) 
 +</code>  
 + 
 +This will declare a structure (typedef'd to zend_extname_globals) that will hold all your globals. 
 + 
 +- In php_extname.hadd <code>ZEND_EXTERN_MODULE_GLOBALS(extname);</code>. This will produce an allusion that will allow you to access the globals from every compile unit that includes php_extname.h In particular, this produces an allusion to an integer named extname_globals_id in ZTS builds or directly to a zend_extname_globals named extname_globals in non-ZTS builds. 
 + 
 +- In php_extname.h, define a macro named EXTNAME_G, like this: 
 +<code> 
 +#ifdef ZTS 
 +# define EXTNAME_G(v) TSRMG(extname_globals_id, zend_extname_globals *, v) 
 +#else 
 +# define EXTNAME_G(v) (extname_globals.v) 
 +#endif 
 +</code> 
 + 
 +This will allow you to access the globals in a consistent manner in both ZTS and non-ZTS builds, like this: 
 + 
 +<code>EXTNAME_G(var1)</code> 
 + 
 +- Now that you have declared the type that aggregates the globals and the variable that holds the globals, you must define the globals. In extname.c, add 
 + 
 +<code>ZEND_DECLARE_MODULE_GLOBALS(extname);</code> 
 + 
 +This produces a tentative definition of extname_globals_id or extname_globals (depending on whether it's a ZTS or non-ZTS build). 
 + 
 +- If you needn'do any startup operations on your variables, you would already have function extension globals in non-ZTS buildsTipicallyyou will also want to initialize some extension globals (for instance, to allocate some memory for the var2 extension global above) -- this is done with globals constructors and destructors. To make it work in ZTS builds and allow such operations, add the following to your zend_module_entry: 
 + 
 +<code> 
 +zend_module_entry extname_module_entry = { 
 + ... 
 + ZEND_MODULE_INFO_N(extname), 
 + PHP_EXTNAME_VERSION, 
 + ZEND_MODULE_GLOBALS(extname), 
 + ZEND_MODULE_GLOBALS_CTOR_N(extname), //may be NULL 
 + ZEND_MODULE_GLOBALS_DTOR_N(extname), //may be NULL 
 + ... 
 +
 +</code> 
 + 
 +Note: do not use ZEND_INIT_MODULE_GLOBALS/ts_allocate_id. If used a shared extension, they will provoke an attempt to call the destructor after the module has been unloaded! Also, for all that is holy, do NOT initialize globals on MINIT (EXTNAME_G(var_ptr) = NULL), that won't work correctly in ZTS as it won't initialize the value in all threads. 
 + 
 +Now define the constructor and destructor functions: 
 + 
 +<code> 
 +ZEND_MODULE_GLOBALS_CTOR_D(extname) 
 +
 + extname_globals->arg2 = pemalloc(1024, 1); 
 +
 + 
 +ZEND_MODULE_GLOBALS_DTOR_D(extname) 
 +
 + pefree(extname_globals->arg2, 1); 
 +
 +</code> 
 + 
 +The globals constructor and destructor are NOT execute per-request, they are part of the module startup/shutdown. The globals can store data across requestsIf you need to do per-request operations to the globals, use module-activate and module-deactivate callbacks.
  
 +Note: ZEND_MODULE_GLOBALS_CTOR_D will declare a function as receiving a zend_extname_globals*, not void* and zend_module_entry is supposed to contain a function pointer type that receives void*. I think this violates the C standard (the declarations are incompatible), but should however by safe since the arguments have the same size.
internals/engine.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1