Skip to content

Commit f42c68c

Browse files
committed
implement r/w locks to improve performance
1 parent 551a9ef commit f42c68c

File tree

6 files changed

+140
-24
lines changed

6 files changed

+140
-24
lines changed

TSRM/TSRM.c

Lines changed: 115 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static size_t tsrm_reserved_pos = 0;
6060
static size_t tsrm_reserved_size = 0;
6161

6262
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
63-
static MUTEX_T tsrm_env_mutex; /* tsrm environ mutex */
63+
static RWLOCK_T tsrm_env_mutex; /* tsrm environ mutex */
6464

6565
/* New thread handlers */
6666
static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler = NULL;
@@ -156,7 +156,7 @@ TSRM_API bool tsrm_startup(int expected_threads, int expected_resources, int deb
156156
tsrm_reserved_pos = 0;
157157
tsrm_reserved_size = 0;
158158

159-
tsrm_env_mutex = tsrm_mutex_alloc();
159+
tsrm_env_mutex = tsrm_rwlock_alloc();
160160

161161
return 1;
162162
}/*}}}*/
@@ -212,7 +212,7 @@ TSRM_API void tsrm_shutdown(void)
212212
free(tsrm_tls_table);
213213
free(resource_types_table);
214214
tsrm_mutex_free(tsmm_mutex);
215-
tsrm_mutex_free(tsrm_env_mutex);
215+
tsrm_rwlock_free(tsrm_env_mutex);
216216
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
217217
if (tsrm_error_file!=stderr) {
218218
fclose(tsrm_error_file);
@@ -236,12 +236,20 @@ TSRM_API void tsrm_shutdown(void)
236236

237237
/* {{{ */
238238
/* environ lock api */
239-
TSRM_API void tsrm_env_lock(void) {
240-
tsrm_mutex_lock(tsrm_env_mutex);
239+
TSRM_API void tsrm_env_lock(bool write) {
240+
if (write) {
241+
tsrm_rwlock_wrlock(tsrm_env_mutex);
242+
} else {
243+
tsrm_rwlock_rlock(tsrm_env_mutex);
244+
}
241245
}
242246

243-
TSRM_API void tsrm_env_unlock(void) {
244-
tsrm_mutex_unlock(tsrm_env_mutex);
247+
TSRM_API void tsrm_env_unlock(bool write) {
248+
if (write) {
249+
tsrm_rwlock_wrunlock(tsrm_env_mutex);
250+
} else {
251+
tsrm_rwlock_runlock(tsrm_env_mutex);
252+
}
245253
} /* }}} */
246254

247255
/* enlarge the arrays for the already active threads */
@@ -648,6 +656,47 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
648656
#endif
649657
}/*}}}*/
650658

659+
/* Allocate a read-write lock */
660+
TSRM_API RWLOCK_T tsrm_rwlock_alloc(void)
661+
{/*{{{*/
662+
RWLOCK_T rwlock;
663+
#ifdef TSRM_WIN32
664+
rwlock = malloc(sizeof(SRWLOCK));
665+
if (!rwlock) {
666+
fprintf(stderr, "Failed to allocate SRWLOCK\n");
667+
return NULL;
668+
}
669+
InitializeSRWLock(rwlock);
670+
#else
671+
rwlock = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
672+
if (!rwlock) {
673+
fprintf(stderr, "Failed to allocate pthread_rwlock_t\n");
674+
return NULL;
675+
}
676+
pthread_rwlock_init(rwlock, NULL);
677+
#endif
678+
#ifdef THR_DEBUG
679+
printf("Read-Write Lock created thread: %d\n", mythreadid());
680+
#endif
681+
return rwlock;
682+
}/*}}}*/
683+
684+
/* Free a read-write lock */
685+
TSRM_API void tsrm_rwlock_free(RWLOCK_T rwlock)
686+
{/*{{{*/
687+
if (rwlock) {
688+
#ifdef TSRM_WIN32
689+
// No explicit free function for SRWLOCK, but we still free the memory.
690+
free(rwlock);
691+
#else
692+
pthread_rwlock_destroy(rwlock);
693+
free(rwlock);
694+
#endif
695+
}
696+
#ifdef THR_DEBUG
697+
printf("Read-Write Lock freed thread: %d\n", mythreadid());
698+
#endif
699+
}/*}}}*/
651700

652701
/*
653702
Lock a mutex.
@@ -664,6 +713,65 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
664713
#endif
665714
}/*}}}*/
666715

716+
/*
717+
Lock a mutex for writing.
718+
A return value of 0 indicates success
719+
*/
720+
TSRM_API int tsrm_rwlock_wrlock(RWLOCK_T rwlock)
721+
{/*{{{*/
722+
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Write locked thread: %ld", tsrm_thread_id()));
723+
#ifdef TSRM_WIN32
724+
AcquireSRWLockExclusive(rwlock);
725+
return 0;
726+
#else
727+
return pthread_rwlock_wrlock(rwlock);
728+
#endif
729+
}/*}}}*/
730+
731+
/*
732+
Lock a mutex for reading.
733+
A return value of 0 indicates success
734+
*/
735+
TSRM_API int tsrm_rwlock_rlock(RWLOCK_T rwlock)
736+
{/*{{{*/
737+
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Read locked thread: %ld", tsrm_thread_id()));
738+
#ifdef TSRM_WIN32
739+
AcquireSRWLockShared(rwlock);
740+
return 0;
741+
#else
742+
return pthread_rwlock_rdlock(rwlock);
743+
#endif
744+
}/*}}}*/
745+
746+
/*
747+
Unlock a mutex for reading.
748+
A return value of 0 indicates success
749+
*/
750+
TSRM_API int tsrm_rwlock_runlock(RWLOCK_T rwlock)
751+
{/*{{{*/
752+
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Read unlocked thread: %ld", tsrm_thread_id()));
753+
#ifdef TSRM_WIN32
754+
ReleaseSRWLockShared(rwlock);
755+
return 0;
756+
#else
757+
return pthread_rwlock_unlock(rwlock);
758+
#endif
759+
}/*}}}*/
760+
761+
/*
762+
Unlock a mutex for writing.
763+
A return value of 0 indicates success
764+
*/
765+
TSRM_API int tsrm_rwlock_wrunlock(RWLOCK_T rwlock)
766+
{/*{{{*/
767+
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Write unlocked thread: %ld", tsrm_thread_id()));
768+
#ifdef TSRM_WIN32
769+
ReleaseSRWLockExclusive(rwlock);
770+
return 0;
771+
#else
772+
return pthread_rwlock_unlock(rwlock);
773+
#endif
774+
}/*}}}*/
667775

668776
/*
669777
Unlock a mutex.

TSRM/TSRM.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ typedef int ts_rsrc_id;
6363
#ifdef TSRM_WIN32
6464
# define THREAD_T DWORD
6565
# define MUTEX_T CRITICAL_SECTION *
66+
# define RWLOCK_T SRWLOCK *
6667
#else
6768
# define THREAD_T pthread_t
6869
# define MUTEX_T pthread_mutex_t *
70+
# define RWLOCK_T pthread_rwlock_t *
6971
#endif
7072

7173
#include <signal.h>
@@ -84,8 +86,8 @@ TSRM_API bool tsrm_startup(int expected_threads, int expected_resources, int deb
8486
TSRM_API void tsrm_shutdown(void);
8587

8688
/* environ lock API */
87-
TSRM_API void tsrm_env_lock(void);
88-
TSRM_API void tsrm_env_unlock(void);
89+
TSRM_API void tsrm_env_lock(bool write);
90+
TSRM_API void tsrm_env_unlock(bool write);
8991

9092
/* allocates a new thread-safe-resource id */
9193
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
@@ -125,8 +127,14 @@ TSRM_API void tsrm_error_set(int level, const char *debug_filename);
125127
TSRM_API THREAD_T tsrm_thread_id(void);
126128
TSRM_API MUTEX_T tsrm_mutex_alloc(void);
127129
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp);
130+
TSRM_API RWLOCK_T tsrm_rwlock_alloc(void);
131+
TSRM_API void tsrm_rwlock_free(RWLOCK_T rwlock);
128132
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp);
129133
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp);
134+
TSRM_API int tsrm_rwlock_wrlock(RWLOCK_T rwlock);
135+
TSRM_API int tsrm_rwlock_wrunlock(RWLOCK_T rwlock);
136+
TSRM_API int tsrm_rwlock_rlock(RWLOCK_T rwlock);
137+
TSRM_API int tsrm_rwlock_runlock(RWLOCK_T rwlock);
130138
#ifdef HAVE_SIGPROCMASK
131139
TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset);
132140
#endif
@@ -188,8 +196,8 @@ TSRM_API bool tsrm_is_managed_thread(void);
188196

189197
#else /* non ZTS */
190198

191-
#define tsrm_env_lock()
192-
#define tsrm_env_unlock()
199+
#define tsrm_env_lock(write)
200+
#define tsrm_env_unlock(write)
193201

194202
#define TSRMG_STATIC(id, type, element)
195203
#define TSRMLS_MAIN_CACHE_EXTERN()

ext/standard/basic_functions.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,9 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
448448
BG(strtok_string) = NULL;
449449
}
450450
#ifdef HAVE_PUTENV
451-
tsrm_env_lock();
451+
tsrm_env_lock(true);
452452
zend_hash_destroy(&BG(putenv_ht));
453-
tsrm_env_unlock();
453+
tsrm_env_unlock(true);
454454
#endif
455455

456456
if (BG(umask) != -1) {
@@ -687,7 +687,7 @@ PHPAPI zend_string *php_getenv(const char *str, size_t str_len) {
687687
}
688688
}
689689
#else
690-
tsrm_env_lock();
690+
tsrm_env_lock(false);
691691

692692
/* system method returns a const */
693693
char *ptr = getenv(str);
@@ -696,7 +696,7 @@ PHPAPI zend_string *php_getenv(const char *str, size_t str_len) {
696696
result = zend_string_init(ptr, strlen(ptr), 0);
697697
}
698698

699-
tsrm_env_unlock();
699+
tsrm_env_unlock(false);
700700
return result;
701701
#endif
702702
}
@@ -772,7 +772,7 @@ PHP_FUNCTION(putenv)
772772
pe.key = zend_string_init(setting, setting_len, 0);
773773
}
774774

775-
tsrm_env_lock();
775+
tsrm_env_lock(true);
776776
zend_hash_del(&BG(putenv_ht), pe.key);
777777

778778
/* find previous value */
@@ -807,7 +807,7 @@ PHP_FUNCTION(putenv)
807807
}
808808
/* valw may be NULL, but the failed conversion still needs to be checked. */
809809
if (!keyw || !valw && value) {
810-
tsrm_env_unlock();
810+
tsrm_env_unlock(true);
811811
free(pe.putenv_string);
812812
zend_string_release(pe.key);
813813
free(keyw);
@@ -835,7 +835,7 @@ PHP_FUNCTION(putenv)
835835
tzset();
836836
}
837837
#endif
838-
tsrm_env_unlock();
838+
tsrm_env_unlock(true);
839839
#ifdef PHP_WIN32
840840
free(keyw);
841841
free(valw);

ext/standard/info.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag)
968968
SECTION("Environment");
969969
php_info_print_table_start();
970970
php_info_print_table_header(2, "Variable", "Value");
971-
tsrm_env_lock();
971+
tsrm_env_lock(false);
972972
for (env=environ; env!=NULL && *env !=NULL; env++) {
973973
tmp1 = estrdup(*env);
974974
if (!(tmp2=strchr(tmp1,'='))) { /* malformed entry? */
@@ -980,7 +980,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag)
980980
php_info_print_table_row(2, tmp1, tmp2);
981981
efree(tmp1);
982982
}
983-
tsrm_env_unlock();
983+
tsrm_env_unlock(false);
984984
php_info_print_table_end();
985985
}
986986

main/php_variables.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ static zend_always_inline void import_environment_variable(HashTable *ht, char *
628628

629629
static void _php_import_environment_variables(zval *array_ptr)
630630
{
631-
tsrm_env_lock();
631+
tsrm_env_lock(false);
632632

633633
#ifndef PHP_WIN32
634634
for (char **env = environ; env != NULL && *env != NULL; env++) {
@@ -646,7 +646,7 @@ static void _php_import_environment_variables(zval *array_ptr)
646646
FreeEnvironmentStringsW(environmentw);
647647
#endif
648648

649-
tsrm_env_unlock();
649+
tsrm_env_unlock(false);
650650
}
651651

652652
static void _php_load_environment_variables(zval *array_ptr)

sapi/litespeed/lsapi_main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static void litespeed_php_import_environment_variables(zval *array_ptr)
234234
return;
235235
}
236236

237-
tsrm_env_lock();
237+
tsrm_env_lock(false);
238238
for (env = environ; env != NULL && *env != NULL; env++) {
239239
p = strchr(*env, '=');
240240
if (!p) { /* malformed entry? */
@@ -249,7 +249,7 @@ static void litespeed_php_import_environment_variables(zval *array_ptr)
249249
t[nlen] = '\0';
250250
add_variable(t, nlen, p + 1, strlen( p + 1 ), array_ptr);
251251
}
252-
tsrm_env_unlock();
252+
tsrm_env_unlock(false);
253253
if (t != buf && t != NULL) {
254254
efree(t);
255255
}

0 commit comments

Comments
 (0)