summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2025-09-18 12:18:50 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2025-09-18 12:18:50 (GMT)
commitd9c1e8eef1830f14c4969cd7b7cdb5b560d5e133 (patch)
treee2ef19ca5a4f985aa104ba9a44caea0a8b0f8818
parent8e9b212e23cbdd947070dbac3d35dbe5b21d3a8f (diff)
downloadtcl-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.h4
-rwxr-xr-xunix/configure12
-rw-r--r--unix/tcl.m44
-rw-r--r--unix/tclUnixThrd.c119
-rwxr-xr-xwin/configure6
-rw-r--r--win/tcl.m42
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
diff --git a/win/tcl.m4 b/win/tcl.m4
index 1394081..1102438 100644
--- a/win/tcl.m4
+++ b/win/tcl.m4
@@ -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