Skip to content

Commit 0b2f7e3

Browse files
committed
feat(zts): set lock per thread on zts build
1 parent 1242e4d commit 0b2f7e3

File tree

2 files changed

+77
-20
lines changed

2 files changed

+77
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ exclude = ["/.github", "/.crates"]
1313

1414
[dependencies]
1515
bitflags = "2"
16-
parking_lot = "0.12"
16+
parking_lot = { version = "0.12", features = ["arc_lock"] }
1717
cfg-if = "1.0"
1818
once_cell = "1.17"
1919
anyhow = { version = "1", optional = true }

src/zend/globals.rs

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! Types related to the PHP executor, sapi and process globals.
22
3+
use parking_lot::{ArcRwLockReadGuard, ArcRwLockWriteGuard, RawRwLock, RwLock};
34
use std::collections::HashMap;
45
use std::ffi::CStr;
56
use std::ops::{Deref, DerefMut};
67
use std::slice;
78
use std::str;
8-
9-
use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard};
9+
use std::sync::{Arc, LazyLock};
1010

1111
use crate::boxed::ZBox;
1212
use 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.
621678
pub struct GlobalReadGuard<T: 'static> {
622679
globals: &'static T,
623680
#[allow(dead_code)]
624-
guard: RwLockReadGuard<'static, ()>,
681+
guard: ArcRwLockReadGuard<RawRwLock, ()>,
625682
}
626683

627684
impl<T> Deref for GlobalReadGuard<T> {
@@ -637,7 +694,7 @@ impl<T> Deref for GlobalReadGuard<T> {
637694
pub struct GlobalWriteGuard<T: 'static> {
638695
globals: &'static mut T,
639696
#[allow(dead_code)]
640-
guard: RwLockWriteGuard<'static, ()>,
697+
guard: ArcRwLockWriteGuard<RawRwLock, ()>,
641698
}
642699

643700
impl<T> Deref for GlobalWriteGuard<T> {

0 commit comments

Comments
 (0)