Skip to content

Commit 5f4809c

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

File tree

2 files changed

+74
-20
lines changed

2 files changed

+74
-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: 73 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,47 @@ 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+
639+
#[cfg(not(php_zts))]
640+
pub(crate) mod lock {
641+
use parking_lot::RwLock;
642+
use std::sync::{Arc, LazyLock};
643+
644+
pub(crate) static GLOBALS_LOCK: LazyLock<Arc<RwLock<()>>> =
645+
LazyLock::new(|| Arc::new(RwLock::new(())));
646+
pub(crate) static PROCESS_GLOBALS_LOCK: LazyLock<Arc<RwLock<()>>> =
647+
LazyLock::new(|| Arc::new(RwLock::new(())));
648+
pub(crate) static SAPI_GLOBALS_LOCK: LazyLock<Arc<RwLock<()>>> =
649+
LazyLock::new(|| Arc::new(RwLock::new(())));
650+
pub(crate) static FILE_GLOBALS_LOCK: LazyLock<Arc<RwLock<()>>> =
651+
LazyLock::new(|| Arc::new(RwLock::new(())));
652+
}
653+
654+
#[cfg(php_zts)]
655+
pub(crate) mod lock {
656+
use parking_lot::{const_rwlock, RwLock};
657+
use std::sync::Arc;
658+
659+
thread_local! {
660+
pub(crate) static GLOBALS_LOCK: Arc<RwLock<()>> = Arc::new(const_rwlock(()));
661+
pub(crate) static PROCESS_GLOBALS_LOCK: Arc<RwLock<()>> = Arc::new( const_rwlock(()) );
662+
pub(crate) static SAPI_GLOBALS_LOCK: Arc<RwLock<()>> = Arc::new( const_rwlock(()) );
663+
pub(crate) static FILE_GLOBALS_LOCK: Arc<RwLock<()>> = Arc::new( const_rwlock(()) );
664+
}
665+
}
612666

613667
/// SAPI globals rwlock.
614668
///
615669
/// PHP provides no indication if the executor globals are being accessed so
616670
/// this is only effective on the Rust side.
617-
static SAPI_MODULE_LOCK: RwLock<()> = const_rwlock(());
671+
static SAPI_MODULE_LOCK: LazyLock<Arc<RwLock<()>>> = LazyLock::new(|| Arc::new(RwLock::new(())));
618672

619673
/// Wrapper guard that contains a reference to a given type `T`. Dropping a
620674
/// guard releases the lock on the relevant rwlock.
621675
pub struct GlobalReadGuard<T: 'static> {
622676
globals: &'static T,
623677
#[allow(dead_code)]
624-
guard: RwLockReadGuard<'static, ()>,
678+
guard: ArcRwLockReadGuard<RawRwLock, ()>,
625679
}
626680

627681
impl<T> Deref for GlobalReadGuard<T> {
@@ -637,7 +691,7 @@ impl<T> Deref for GlobalReadGuard<T> {
637691
pub struct GlobalWriteGuard<T: 'static> {
638692
globals: &'static mut T,
639693
#[allow(dead_code)]
640-
guard: RwLockWriteGuard<'static, ()>,
694+
guard: ArcRwLockWriteGuard<RawRwLock, ()>,
641695
}
642696

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

0 commit comments

Comments
 (0)