Artifact [fb61b04109]
Not logged in

Artifact fb61b041095b0a22e4864f714b74b9477280a1e1aa41942116052e608cf1c0a1:

Attachment "spin.diff" to ticket [893f8cc5db] added by chw 2025-09-18 09:33:28.
Index: unix/tclUnixThrd.c
==================================================================
--- unix/tclUnixThrd.c
+++ unix/tclUnixThrd.c
@@ -90,25 +90,35 @@
 #define PCondWait	pthread_cond_wait
 #define PCondTimedWait	pthread_cond_timedwait
 
 #else /* !HAVE_PTHREAD_MUTEX_RECURSIVE */
 
+#if !defined(HAVE_PTHREAD_SPIN_LOCK) || (_POSIX_C_SOURCE >= 200112L)
+#define HAVE_PTHREAD_SPIN_LOCK 1
+#endif
+
 /*
  * No native support for reentrant mutexes. Emulate them with regular mutexes
  * and thread-local counters.
  */
 
 typedef struct PMutex {
     pthread_mutex_t mutex;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spinlock_t lock;
+#endif
     pthread_t thread;
     int counter;
 } PMutex;
 
 static void
 PMutexInit(
     PMutex *pmutexPtr)
 {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_init(&pmutexPtr->lock, PTHREAD_PROCESS_PRIVATE);
+#endif
     pthread_mutex_init(&pmutexPtr->mutex, NULL);
     pmutexPtr->thread = 0;
     pmutexPtr->counter = 0;
 }
 
@@ -115,17 +125,30 @@
 static void
 PMutexDestroy(
     PMutex *pmutexPtr)
 {
     pthread_mutex_destroy(&pmutexPtr->mutex);
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_destroy(&pmutexPtr->lock);
+#endif
 }
 
 static void
 PMutexLock(
     PMutex *pmutexPtr)
 {
-    if (pmutexPtr->thread != pthread_self() || pmutexPtr->counter == 0) {
+    int 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++;
@@ -133,10 +156,21 @@
 
 static void
 PMutexUnlock(
     PMutex *pmutexPtr)
 {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    int 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);
     }
@@ -145,20 +179,54 @@
 static void
 PCondWait(
     pthread_cond_t *pcondPtr,
     PMutex *pmutexPtr)
 {
+    int counter;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    int 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
+    int 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_PTHREAD_MUTEX_RECURSIVE */
 
 /*
  * globalLock is used to serialize creation of mutexes, condition variables,