From 647147725684ba43503caca4c83eb9173e1d949f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 4 Mar 2022 04:10:36 +0100 Subject: [PATCH] ext/opcache: use C11 atomics for "restart_in" Cheaper than fcntl(F_SETLK). The same is done already on Windows, so if that works, why not use it everywhere? (Of course, only if the compiler supports this C11 feature.) As a bonus, the code in this commit also works on C++ via C++11 std::atomic, just in case somebody adds some C++ code to the opcache extension one day. --- ext/opcache/ZendAccelerator.c | 26 +++++++++++++++----------- ext/opcache/ZendAccelerator.h | 16 +++++++++++++++- ext/opcache/config.m4 | 2 ++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 709a647a31c78..48a07760d981d 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -135,7 +135,11 @@ static void preload_shutdown(void); static void preload_activate(void); static void preload_restart(void); -#ifdef ZEND_WIN32 +#ifdef HAVE_STDATOMIC_H +# define INCREMENT(v) (++ZCSG(v)) +# define DECREMENT(v) (--ZCSG(v)) +# define LOCKVAL(v) atomic_load(&ZCSG(v)) +#elif defined(ZEND_WIN32) # define INCREMENT(v) InterlockedIncrement64(&ZCSG(v)) # define DECREMENT(v) InterlockedDecrement64(&ZCSG(v)) # define LOCKVAL(v) (ZCSG(v)) @@ -273,7 +277,7 @@ static ZEND_INI_MH(accel_include_path_on_modify) static inline void accel_restart_enter(void) { -#ifdef ZEND_WIN32 +#ifdef INCREMENT INCREMENT(restart_in); #else struct flock restart_in_progress; @@ -292,7 +296,7 @@ static inline void accel_restart_enter(void) static inline void accel_restart_leave(void) { -#ifdef ZEND_WIN32 +#ifdef DECREMENT ZCSG(restart_in_progress) = false; DECREMENT(restart_in); #else @@ -313,7 +317,9 @@ static inline void accel_restart_leave(void) static inline int accel_restart_is_active(void) { if (ZCSG(restart_in_progress)) { -#ifndef ZEND_WIN32 +#ifdef LOCKVAL + return LOCKVAL(restart_in) != 0; +#else struct flock restart_check; restart_check.l_type = F_WRLCK; @@ -331,8 +337,6 @@ static inline int accel_restart_is_active(void) } else { return 1; } -#else - return LOCKVAL(restart_in) != 0; #endif } return 0; @@ -341,7 +345,7 @@ static inline int accel_restart_is_active(void) /* Creates a read lock for SHM access */ static inline zend_result accel_activate_add(void) { -#ifdef ZEND_WIN32 +#ifdef INCREMENT SHM_UNPROTECT(); INCREMENT(mem_usage); SHM_PROTECT(); @@ -364,7 +368,7 @@ static inline zend_result accel_activate_add(void) /* Releases a lock for SHM access */ static inline void accel_deactivate_sub(void) { -#ifdef ZEND_WIN32 +#ifdef DECREMENT if (ZCG(counted)) { SHM_UNPROTECT(); DECREMENT(mem_usage); @@ -387,7 +391,7 @@ static inline void accel_deactivate_sub(void) static inline void accel_unlock_all(void) { -#ifdef ZEND_WIN32 +#ifdef DECREMENT accel_deactivate_sub(); #else struct flock mem_usage_unlock_all; @@ -828,7 +832,7 @@ static void accel_use_shm_interned_strings(void) HANDLE_UNBLOCK_INTERRUPTIONS(); } -#ifndef ZEND_WIN32 +#ifndef LOCKVAL static inline void kill_all_lockers(struct flock *mem_usage_check) { int tries; @@ -895,7 +899,7 @@ static inline void kill_all_lockers(struct flock *mem_usage_check) static inline int accel_is_inactive(void) { -#ifdef ZEND_WIN32 +#ifdef LOCKVAL if (LOCKVAL(mem_usage) == 0) { return SUCCESS; } diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index bc92854c35576..6ecc2c2bc9df1 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -55,6 +55,14 @@ #include "zend_accelerator_hash.h" #include "zend_accelerator_debug.h" +#ifdef HAVE_STDATOMIC_H +# ifdef __cplusplus +# include +# else +# include +# endif +#endif // HAVE_STDATOMIC_H + #ifndef PHPAPI # ifdef ZEND_WIN32 # define PHPAPI __declspec(dllimport) @@ -261,7 +269,13 @@ typedef struct _zend_accel_shared_globals { bool restart_pending; zend_accel_restart_reason restart_reason; bool cache_status_before_restart; -#ifdef ZEND_WIN32 +#ifdef HAVE_STDATOMIC_H +# ifdef __cplusplus + std::atomic_llong mem_usage, restart_in; +# else + atomic_llong mem_usage, restart_in; +# endif +#elif defined(ZEND_WIN32) LONGLONG mem_usage; LONGLONG restart_in; #endif diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 2a83fa2455974..c9fa6a7e57e4f 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -23,6 +23,8 @@ if test "$PHP_OPCACHE" != "no"; then dnl Always build as shared extension ext_shared=yes + AC_CHECK_HEADERS([stdatomic.h]) + if test "$PHP_HUGE_CODE_PAGES" = "yes"; then AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) fi