@@ -13,7 +13,8 @@ use crate::exception::PhpResult;
1313#[ cfg( php82) ]
1414use crate :: ffi:: zend_atomic_bool_store;
1515use crate :: ffi:: {
16- _sapi_module_struct, _zend_executor_globals, ext_php_rs_executor_globals,
16+ _sapi_module_struct, _zend_executor_globals, _zend_compiler_globals,
17+ ext_php_rs_executor_globals, ext_php_rs_compiler_globals,
1718 ext_php_rs_file_globals, ext_php_rs_process_globals, ext_php_rs_sapi_globals,
1819 ext_php_rs_sapi_module, php_core_globals, php_file_globals, sapi_globals_struct,
1920 sapi_header_struct, sapi_headers_struct, sapi_request_info, zend_ini_entry,
@@ -35,9 +36,6 @@ use super::linked_list::ZendLinkedListIterator;
3536/// Stores global variables used in the PHP executor.
3637pub type ExecutorGlobals = _zend_executor_globals ;
3738
38- /// Stores the SAPI module used in the PHP executor.
39- pub type SapiModule = _sapi_module_struct ;
40-
4139impl ExecutorGlobals {
4240 /// Returns a reference to the PHP executor globals.
4341 ///
@@ -226,6 +224,69 @@ impl ExecutorGlobals {
226224 }
227225}
228226
227+ pub type CompilerGlobals = _zend_compiler_globals ;
228+
229+ impl CompilerGlobals {
230+ /// Returns a reference to the PHP compiler globals.
231+ ///
232+ /// The compiler globals are guarded by a [`RwLock`]. There can be multiple
233+ /// immutable references at one time but only ever one mutable reference.
234+ /// Attempting to retrieve the globals while already holding the global
235+ /// guard will lead to a deadlock. Dropping the globals guard will release
236+ /// the lock.
237+ ///
238+ /// # Panics
239+ ///
240+ /// * If static executor globals are not set
241+ pub fn get ( ) -> GlobalReadGuard < Self > {
242+ // SAFETY: PHP compiler globals are statically declared therefore should never
243+ // return an invalid pointer.
244+ let globals = unsafe { ext_php_rs_compiler_globals ( ) . as_ref ( ) }
245+ . expect ( "Static compiler globals were invalid" ) ;
246+
247+ cfg_if:: cfg_if! {
248+ if #[ cfg( php_zts) ] {
249+ let guard = lock:: GLOBALS_LOCK . with( |l| l. read_arc( ) ) ;
250+ } else {
251+ let guard = lock:: GLOBALS_LOCK . read_arc( ) ;
252+ }
253+ }
254+
255+ GlobalReadGuard { globals, guard }
256+ }
257+
258+ /// Returns a mutable reference to the PHP compiler globals.
259+ ///
260+ /// The compiler globals are guarded by a [`RwLock`]. There can be multiple
261+ /// immutable references at one time but only ever one mutable reference.
262+ /// Attempting to retrieve the globals while already holding the global
263+ /// guard will lead to a deadlock. Dropping the globals guard will release
264+ /// the lock.
265+ ///
266+ /// # Panics
267+ ///
268+ /// * If static compiler globals are not set
269+ pub fn get_mut ( ) -> GlobalWriteGuard < Self > {
270+ // SAFETY: PHP compiler globals are statically declared therefore should never
271+ // return an invalid pointer.
272+ let globals = unsafe { ext_php_rs_compiler_globals ( ) . as_mut ( ) }
273+ . expect ( "Static compiler globals were invalid" ) ;
274+
275+ cfg_if:: cfg_if! {
276+ if #[ cfg( php_zts) ] {
277+ let guard = lock:: GLOBALS_LOCK . with( |l| l. write_arc( ) ) ;
278+ } else {
279+ let guard = lock:: GLOBALS_LOCK . write_arc( ) ;
280+ }
281+ }
282+
283+ GlobalWriteGuard { globals, guard }
284+ }
285+ }
286+
287+ /// Stores the SAPI module used in the PHP executor.
288+ pub type SapiModule = _sapi_module_struct ;
289+
229290impl SapiModule {
230291 /// Returns a reference to the PHP SAPI module.
231292 ///
@@ -835,3 +896,26 @@ impl<T> DerefMut for GlobalWriteGuard<T> {
835896 self . globals
836897 }
837898}
899+
900+ #[ cfg( test) ]
901+ mod tests {
902+ use super :: * ;
903+
904+ #[ test]
905+ fn test_executor_globals ( ) {
906+ let state = ExecutorGlobals :: get ( ) . active ;
907+ ExecutorGlobals :: get_mut ( ) . active = !state;
908+ let changed = ExecutorGlobals :: get ( ) . active ;
909+ ExecutorGlobals :: get_mut ( ) . active = state;
910+ assert_eq ! ( changed, !state) ;
911+ }
912+
913+ #[ test]
914+ fn test_compiler_globals ( ) {
915+ let state = CompilerGlobals :: get ( ) . in_compilation ;
916+ CompilerGlobals :: get_mut ( ) . in_compilation = !state;
917+ let changed = CompilerGlobals :: get ( ) . in_compilation ;
918+ CompilerGlobals :: get_mut ( ) . in_compilation = state;
919+ assert_eq ! ( changed, !state) ;
920+ }
921+ }
0 commit comments