diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2025-09-18 12:18:50 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2025-09-18 12:18:50 (GMT) |
| commit | d9c1e8eef1830f14c4969cd7b7cdb5b560d5e133 (patch) | |
| tree | e2ef19ca5a4f985aa104ba9a44caea0a8b0f8818 | |
| parent | 8e9b212e23cbdd947070dbac3d35dbe5b21d3a8f (diff) | |
| download | tcl-d9c1e8eef1830f14c4969cd7b7cdb5b560d5e133.zip tcl-d9c1e8eef1830f14c4969cd7b7cdb5b560d5e133.tar.gz tcl-d9c1e8eef1830f14c4969cd7b7cdb5b560d5e133.tar.bz2 | |
Add Christian's spinlock patch. So we can do performance testing to see which is better, or simply keep both
| -rw-r--r-- | generic/tclInt.h | 4 | ||||
| -rwxr-xr-x | unix/configure | 12 | ||||
| -rw-r--r-- | unix/tcl.m4 | 4 | ||||
| -rw-r--r-- | unix/tclUnixThrd.c | 119 | ||||
| -rwxr-xr-x | win/configure | 6 | ||||
| -rw-r--r-- | win/tcl.m4 | 2 |
6 files changed, 133 insertions, 14 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h index 7f8d7e6..b8572f7 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -68,6 +68,7 @@ #include <stdarg.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <string.h> #include <locale.h> @@ -149,8 +150,7 @@ #elif defined(__GNUC__) #define TCL_UNREACHABLE() __builtin_unreachable() #elif defined(_MSC_VER) -#include <stdbool.h> -#define TCL_UNREACHABLE() __assume(false) +#define TCL_UNREACHABLE() __assume(0) #else #define TCL_UNREACHABLE() ((void) 0) #endif diff --git a/unix/configure b/unix/configure index 03ca289..4936082 100755 --- a/unix/configure +++ b/unix/configure @@ -4901,6 +4901,12 @@ then : printf "%s\n" "#define HAVE_PTHREAD_ATFORK 1" >>confdefs.h fi +ac_fn_c_check_func "$LINENO" "pthread_spin_lock" "ac_cv_func_pthread_spin_lock" +if test "x$ac_cv_func_pthread_spin_lock" = xyes +then : + printf "%s\n" "#define HAVE_PTHREAD_SPIN_LOCK 1" >>confdefs.h + +fi LIBS=$ac_saved_libs @@ -7437,11 +7443,11 @@ printf "%s\n" "$tcl_cv_cc_input_charset" >&6; } CFLAGS="$CFLAGS -finput-charset=UTF-8" fi - ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" -if test "x$ac_cv_header_stdbool_h" = xyes + ac_fn_c_check_header_compile "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default" +if test "x$ac_cv_header_stdatomic_h" = xyes then : -printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h +printf "%s\n" "#define HAVE_STDATOMIC_H 1" >>confdefs.h fi diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 1355017..e5f2762 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1862,7 +1862,7 @@ dnl # preprocessing tests use only CPPFLAGS. CFLAGS="$CFLAGS -finput-charset=UTF-8" fi - AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],) + AC_CHECK_HEADER(stdatomic.h, [AC_DEFINE(HAVE_STDATOMIC_H, 1, [Do we have <stdatomic.h>?])],) # Check for vfork, posix_spawnp() and friends unconditionally AC_CHECK_FUNCS(vfork posix_spawnp posix_spawn_file_actions_adddup2 posix_spawnattr_setflags) @@ -2256,7 +2256,7 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [ ac_saved_libs=$LIBS LIBS="$LIBS $THREADS_LIBS" - AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork) + AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork pthread_spin_lock) LIBS=$ac_saved_libs ]) diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index c33640f..e2f3a77 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -12,7 +12,9 @@ */ #include "tclInt.h" +#ifdef HAVE_STDATOMIC_H #include <stdatomic.h> +#endif /* HAVE_STDATOMIC_H */ #if TCL_THREADS @@ -69,6 +71,9 @@ typedef struct PMutex { pthread_mutex_t mutex; +#if defined(HAVE_PTHREAD_SPIN_LOCK) && !defined(HAVE_STDATOMIC_H) + pthread_spinlock_t lock; +#endif volatile pthread_t thread; volatile int counter; } PMutex; @@ -77,6 +82,9 @@ static void PMutexInit( PMutex *pmutexPtr) { +#if defined(HAVE_PTHREAD_SPIN_LOCK) && !defined(HAVE_STDATOMIC_H) + pthread_spin_init(&pmutexPtr->lock, PTHREAD_PROCESS_PRIVATE); +#endif pthread_mutex_init(&pmutexPtr->mutex, NULL); pmutexPtr->thread = 0; pmutexPtr->counter = 0; @@ -87,8 +95,13 @@ PMutexDestroy( PMutex *pmutexPtr) { pthread_mutex_destroy(&pmutexPtr->mutex); +#if defined(HAVE_PTHREAD_SPIN_LOCK) && !defined(HAVE_STDATOMIC_H) + pthread_spin_destroy(&pmutexPtr->lock); +#endif } +#ifdef HAVE_STDATOMIC_H + static void PMutexLock( PMutex *pmutexPtr) @@ -97,19 +110,19 @@ PMutexLock( if (__atomic_load_n(&pmutexPtr->counter, __ATOMIC_RELAXED) == 0) { pthread_mutex_lock(&pmutexPtr->mutex); __atomic_store_n(&pmutexPtr->thread, mythread, __ATOMIC_RELAXED); - } else if (__atomic_load_n (&pmutexPtr->thread, __ATOMIC_RELAXED) != mythread) { + } else if (__atomic_load_n(&pmutexPtr->thread, __ATOMIC_RELAXED) != mythread) { pthread_mutex_lock(&pmutexPtr->mutex); __atomic_store_n(&pmutexPtr->thread, mythread, __ATOMIC_RELAXED); __atomic_store_n(&pmutexPtr->counter, 0, __ATOMIC_RELAXED); } - __atomic_fetch_add(&pmutexPtr->counter, 1, __ATOMIC_RELAXED); + __atomic_add_fetch(&pmutexPtr->counter, 1, __ATOMIC_RELAXED); } static void PMutexUnlock( PMutex *pmutexPtr) { - if (__atomic_fetch_add(&pmutexPtr->counter, -1, __ATOMIC_RELAXED) == 1) { + if (__atomic_sub_fetch(&pmutexPtr->counter, 1, __ATOMIC_RELAXED) == 0) { __atomic_store_n(&pmutexPtr->thread, 0, __ATOMIC_RELAXED); pthread_mutex_unlock(&pmutexPtr->mutex); } @@ -139,6 +152,106 @@ PCondTimedWait( __atomic_store_n(&pmutexPtr->thread, pthread_self(), __ATOMIC_RELAXED); __atomic_store_n(&pmutexPtr->counter, counter, __ATOMIC_RELAXED); } + +#else /* HAVE_STDATOMIC_H */ + +static void +PMutexLock( + PMutex *pmutexPtr) +{ + bool do_lock; + +#ifdef HAVE_PTHREAD_SPIN_LOCK + pthread_spin_lock(&pmutexPtr->lock); +#endif + do_lock = (pmutexPtr->thread != pthread_self() || pmutexPtr->counter == 0); +#ifdef HAVE_PTHREAD_SPIN_LOCK + pthread_spin_unlock(&pmutexPtr->lock); +#endif + + if (do_lock) { + pthread_mutex_lock(&pmutexPtr->mutex); + pmutexPtr->thread = pthread_self(); + pmutexPtr->counter = 0; + } + pmutexPtr->counter++; +} + +static void +PMutexUnlock( + PMutex *pmutexPtr) +{ +#ifdef HAVE_PTHREAD_SPIN_LOCK + bool is_owned; + + pthread_spin_lock(&pmutexPtr->lock); + is_owned = (pmutexPtr->thread == pthread_self()); + pthread_spin_unlock(&pmutexPtr->lock); + + if (!is_owned) { + Tcl_Panic("mutex not owned"); + } +#endif + + pmutexPtr->counter--; + if (pmutexPtr->counter == 0) { + pmutexPtr->thread = 0; + pthread_mutex_unlock(&pmutexPtr->mutex); + } +} + +static void +PCondWait( + pthread_cond_t *pcondPtr, + PMutex *pmutexPtr) +{ + int counter; +#ifdef HAVE_PTHREAD_SPIN_LOCK + bool is_owned; + + pthread_spin_lock(&pmutexPtr->lock); + is_owned = (pmutexPtr->thread == pthread_self()); + pthread_spin_unlock(&pmutexPtr->lock); + + if (!is_owned) { + Tcl_Panic("mutex not owned"); + } +#endif + counter = pmutexPtr->counter; + pmutexPtr->counter = 0; + pmutexPtr->thread = 0; + pthread_cond_wait(pcondPtr, &pmutexPtr->mutex); + pmutexPtr->thread = pthread_self(); + pmutexPtr->counter = counter; +} + +static void +PCondTimedWait( + pthread_cond_t *pcondPtr, + PMutex *pmutexPtr, + struct timespec *ptime) +{ + int counter; +#ifdef HAVE_PTHREAD_SPIN_LOCK + bool is_owned; + + pthread_spin_lock(&pmutexPtr->lock); + is_owned = (pmutexPtr->thread == pthread_self()); + pthread_spin_unlock(&pmutexPtr->lock); + + if (!is_owned) { + Tcl_Panic("mutex not owned"); + } +#endif + counter = pmutexPtr->counter; + pmutexPtr->counter = 0; + pmutexPtr->thread = 0; + pthread_cond_timedwait(pcondPtr, &pmutexPtr->mutex, ptime); + pmutexPtr->thread = pthread_self(); + pmutexPtr->counter = counter; +} + +#endif /* HAVE_STDATOMIC_H */ /* * globalLock is used to serialize creation of mutexes, condition variables, diff --git a/win/configure b/win/configure index a314ab8..0ba54d1 100755 --- a/win/configure +++ b/win/configure @@ -4887,11 +4887,11 @@ printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi - ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" -if test "x$ac_cv_header_stdbool_h" = xyes + ac_fn_c_check_header_compile "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default" +if test "x$ac_cv_header_stdatomic_h" = xyes then : -printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h +printf "%s\n" "#define HAVE_STDATOMIC_H 1" >>confdefs.h fi @@ -946,7 +946,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi - AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],) + AC_CHECK_HEADER(stdatomic.h, [AC_DEFINE(HAVE_STDATOMIC_H, 1, [Do we have <stdatomic.h>?])],) # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler |
