11//! Types related to the PHP executor, sapi and process globals.
22
3+ use parking_lot:: { ArcRwLockReadGuard , ArcRwLockWriteGuard , RawRwLock , RwLock } ;
34use std:: collections:: HashMap ;
45use std:: ffi:: CStr ;
56use std:: ops:: { Deref , DerefMut } ;
67use std:: slice;
78use std:: str;
8-
9- use parking_lot:: { const_rwlock, RwLock , RwLockReadGuard , RwLockWriteGuard } ;
9+ use std:: sync:: { Arc , LazyLock } ;
1010
1111use crate :: boxed:: ZBox ;
1212use crate :: exception:: PhpResult ;
@@ -51,7 +51,11 @@ impl ExecutorGlobals {
5151 // return an invalid pointer.
5252 let globals = unsafe { ext_php_rs_executor_globals ( ) . as_ref ( ) }
5353 . expect ( "Static executor globals were invalid" ) ;
54- let guard = GLOBALS_LOCK . read ( ) ;
54+ #[ cfg( not( php_zts) ) ]
55+ let guard = lock:: GLOBALS_LOCK . read_arc ( ) ;
56+ #[ cfg( php_zts) ]
57+ let guard = lock:: GLOBALS_LOCK . with ( |l| l. read_arc ( ) ) ;
58+
5559 GlobalReadGuard { globals, guard }
5660 }
5761
@@ -67,7 +71,10 @@ impl ExecutorGlobals {
6771 // return an invalid pointer.
6872 let globals = unsafe { ext_php_rs_executor_globals ( ) . as_mut ( ) }
6973 . expect ( "Static executor globals were invalid" ) ;
70- let guard = GLOBALS_LOCK . write ( ) ;
74+ #[ cfg( not( php_zts) ) ]
75+ let guard = lock:: GLOBALS_LOCK . write_arc ( ) ;
76+ #[ cfg( php_zts) ]
77+ let guard = lock:: GLOBALS_LOCK . with ( |l| l. write_arc ( ) ) ;
7178 GlobalWriteGuard { globals, guard }
7279 }
7380
@@ -198,7 +205,7 @@ impl SapiModule {
198205 // return an invalid pointer.
199206 let globals = unsafe { ext_php_rs_sapi_module ( ) . as_ref ( ) }
200207 . expect ( "Static executor globals were invalid" ) ;
201- let guard = SAPI_MODULE_LOCK . read ( ) ;
208+ let guard = SAPI_MODULE_LOCK . read_arc ( ) ;
202209 GlobalReadGuard { globals, guard }
203210 }
204211
@@ -214,7 +221,7 @@ impl SapiModule {
214221 // return an invalid pointer.
215222 let globals = unsafe { ext_php_rs_sapi_module ( ) . as_mut ( ) }
216223 . expect ( "Static executor globals were invalid" ) ;
217- let guard = SAPI_MODULE_LOCK . write ( ) ;
224+ let guard = SAPI_MODULE_LOCK . write_arc ( ) ;
218225 GlobalWriteGuard { globals, guard }
219226 }
220227}
@@ -234,7 +241,11 @@ impl ProcessGlobals {
234241 // SAFETY: PHP executor globals are statically declared therefore should never
235242 // return an invalid pointer.
236243 let globals = unsafe { & * ext_php_rs_process_globals ( ) } ;
237- let guard = PROCESS_GLOBALS_LOCK . read ( ) ;
244+ #[ cfg( not( php_zts) ) ]
245+ let guard = lock:: PROCESS_GLOBALS_LOCK . read_arc ( ) ;
246+ #[ cfg( php_zts) ]
247+ let guard = lock:: PROCESS_GLOBALS_LOCK . with ( |l| l. read_arc ( ) ) ;
248+
238249 GlobalReadGuard { globals, guard }
239250 }
240251
@@ -249,7 +260,11 @@ impl ProcessGlobals {
249260 // SAFETY: PHP executor globals are statically declared therefore should never
250261 // return an invalid pointer.
251262 let globals = unsafe { & mut * ext_php_rs_process_globals ( ) } ;
252- let guard = PROCESS_GLOBALS_LOCK . write ( ) ;
263+ #[ cfg( not( php_zts) ) ]
264+ let guard = lock:: PROCESS_GLOBALS_LOCK . write_arc ( ) ;
265+ #[ cfg( php_zts) ]
266+ let guard = lock:: PROCESS_GLOBALS_LOCK . with ( |l| l. write_arc ( ) ) ;
267+
253268 GlobalWriteGuard { globals, guard }
254269 }
255270
@@ -357,7 +372,10 @@ impl SapiGlobals {
357372 // SAFETY: PHP executor globals are statically declared therefore should never
358373 // return an invalid pointer.
359374 let globals = unsafe { & * ext_php_rs_sapi_globals ( ) } ;
360- let guard = SAPI_GLOBALS_LOCK . read ( ) ;
375+ #[ cfg( not( php_zts) ) ]
376+ let guard = lock:: SAPI_GLOBALS_LOCK . read_arc ( ) ;
377+ #[ cfg( php_zts) ]
378+ let guard = lock:: SAPI_GLOBALS_LOCK . with ( |l| l. read_arc ( ) ) ;
361379 GlobalReadGuard { globals, guard }
362380 }
363381
@@ -372,7 +390,10 @@ impl SapiGlobals {
372390 // SAFETY: PHP executor globals are statically declared therefore should never
373391 // return an invalid pointer.
374392 let globals = unsafe { & mut * ext_php_rs_sapi_globals ( ) } ;
375- let guard = SAPI_GLOBALS_LOCK . write ( ) ;
393+ #[ cfg( not( php_zts) ) ]
394+ let guard = lock:: SAPI_GLOBALS_LOCK . write_arc ( ) ;
395+ #[ cfg( php_zts) ]
396+ let guard = lock:: SAPI_GLOBALS_LOCK . with ( |l| l. write_arc ( ) ) ;
376397 GlobalWriteGuard { globals, guard }
377398 }
378399
@@ -576,7 +597,11 @@ impl FileGlobals {
576597 // return an invalid pointer.
577598 let globals = unsafe { ext_php_rs_file_globals ( ) . as_ref ( ) }
578599 . expect ( "Static file globals were invalid" ) ;
579- let guard = FILE_GLOBALS_LOCK . read ( ) ;
600+ #[ cfg( not( php_zts) ) ]
601+ let guard = lock:: FILE_GLOBALS_LOCK . read_arc ( ) ;
602+ #[ cfg( php_zts) ]
603+ let guard = lock:: FILE_GLOBALS_LOCK . with ( |l| l. read_arc ( ) ) ;
604+
580605 GlobalReadGuard { globals, guard }
581606 }
582607
@@ -591,7 +616,12 @@ impl FileGlobals {
591616 // SAFETY: PHP executor globals are statically declared therefore should never
592617 // return an invalid pointer.
593618 let globals = unsafe { & mut * ext_php_rs_file_globals ( ) } ;
594- let guard = SAPI_GLOBALS_LOCK . write ( ) ;
619+
620+ #[ cfg( not( php_zts) ) ]
621+ let guard = lock:: FILE_GLOBALS_LOCK . write_arc ( ) ;
622+ #[ cfg( php_zts) ]
623+ let guard = lock:: FILE_GLOBALS_LOCK . with ( |l| l. write_arc ( ) ) ;
624+
595625 GlobalWriteGuard { globals, guard }
596626 }
597627
@@ -605,23 +635,50 @@ impl FileGlobals {
605635///
606636/// PHP provides no indication if the executor globals are being accessed so
607637/// this is only effective on the Rust side.
608- static GLOBALS_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
609- static PROCESS_GLOBALS_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
610- static SAPI_GLOBALS_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
611- static FILE_GLOBALS_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
638+ #[ cfg( not( php_zts) ) ]
639+ pub ( crate ) mod lock {
640+ use parking_lot:: RwLock ;
641+ use std:: sync:: { Arc , LazyLock } ;
642+
643+ pub ( crate ) static GLOBALS_LOCK : LazyLock < Arc < RwLock < ( ) > > > =
644+ LazyLock :: new ( || Arc :: new ( RwLock :: new ( ( ) ) ) ) ;
645+ pub ( crate ) static PROCESS_GLOBALS_LOCK : LazyLock < Arc < RwLock < ( ) > > > =
646+ LazyLock :: new ( || Arc :: new ( RwLock :: new ( ( ) ) ) ) ;
647+ pub ( crate ) static SAPI_GLOBALS_LOCK : LazyLock < Arc < RwLock < ( ) > > > =
648+ LazyLock :: new ( || Arc :: new ( RwLock :: new ( ( ) ) ) ) ;
649+ pub ( crate ) static FILE_GLOBALS_LOCK : LazyLock < Arc < RwLock < ( ) > > > =
650+ LazyLock :: new ( || Arc :: new ( RwLock :: new ( ( ) ) ) ) ;
651+ }
652+
653+ /// Executor globals rwlock.
654+ ///
655+ /// PHP provides no indication if the executor globals are being accessed so
656+ /// this is only effective on the Rust side.
657+ #[ cfg( php_zts) ]
658+ pub ( crate ) mod lock {
659+ use parking_lot:: { const_rwlock, RwLock } ;
660+ use std:: sync:: Arc ;
661+
662+ thread_local ! {
663+ pub ( crate ) static GLOBALS_LOCK : Arc <RwLock <( ) >> = Arc :: new( const_rwlock( ( ) ) ) ;
664+ pub ( crate ) static PROCESS_GLOBALS_LOCK : Arc <RwLock <( ) >> = Arc :: new( const_rwlock( ( ) ) ) ;
665+ pub ( crate ) static SAPI_GLOBALS_LOCK : Arc <RwLock <( ) >> = Arc :: new( const_rwlock( ( ) ) ) ;
666+ pub ( crate ) static FILE_GLOBALS_LOCK : Arc <RwLock <( ) >> = Arc :: new( const_rwlock( ( ) ) ) ;
667+ }
668+ }
612669
613670/// SAPI globals rwlock.
614671///
615672/// PHP provides no indication if the executor globals are being accessed so
616673/// this is only effective on the Rust side.
617- static SAPI_MODULE_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
674+ static SAPI_MODULE_LOCK : LazyLock < Arc < RwLock < ( ) > > > = LazyLock :: new ( || Arc :: new ( RwLock :: new ( ( ) ) ) ) ;
618675
619676/// Wrapper guard that contains a reference to a given type `T`. Dropping a
620677/// guard releases the lock on the relevant rwlock.
621678pub struct GlobalReadGuard < T : ' static > {
622679 globals : & ' static T ,
623680 #[ allow( dead_code) ]
624- guard : RwLockReadGuard < ' static , ( ) > ,
681+ guard : ArcRwLockReadGuard < RawRwLock , ( ) > ,
625682}
626683
627684impl < T > Deref for GlobalReadGuard < T > {
@@ -637,7 +694,7 @@ impl<T> Deref for GlobalReadGuard<T> {
637694pub struct GlobalWriteGuard < T : ' static > {
638695 globals : & ' static mut T ,
639696 #[ allow( dead_code) ]
640- guard : RwLockWriteGuard < ' static , ( ) > ,
697+ guard : ArcRwLockWriteGuard < RawRwLock , ( ) > ,
641698}
642699
643700impl < T > Deref for GlobalWriteGuard < T > {
0 commit comments