Artifact [c1b70eb643]
Not logged in

Artifact c1b70eb643b1a7b068b237c3479f961c68e64bf1ee88b8336da4bc721d00fb0a:

Attachment "spin2.diff" to ticket [893f8cc5db] added by chw 2025-09-19 04:59:13.
Index: unix/tclUnixThrd.c
==================================================================
--- unix/tclUnixThrd.c
+++ unix/tclUnixThrd.c
@@ -90,75 +90,177 @@
 #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)
 {
     pthread_mutex_init(&pmutexPtr->mutex, NULL);
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_init(&pmutexPtr->lock, PTHREAD_PROCESS_PRIVATE);
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
     pmutexPtr->thread = 0;
     pmutexPtr->counter = 0;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
 }
 
 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) {
+    pthread_t self = pthread_self();;
+
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    if ((pmutexPtr->thread != self || pmutexPtr->counter == 0)) {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spin_unlock(&pmutexPtr->lock);
+#endif
 	pthread_mutex_lock(&pmutexPtr->mutex);
-	pmutexPtr->thread = pthread_self();
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spin_lock(&pmutexPtr->lock);
+#endif
+	pmutexPtr->thread = self;
 	pmutexPtr->counter = 0;
     }
     pmutexPtr->counter++;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
 }
 
 static void
 PMutexUnlock(
     PMutex *pmutexPtr)
 {
+    pthread_t self = pthread_self();
+    int do_unlock;
+
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    if (pmutexPtr->thread != self) {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spin_unlock(&pmutexPtr->lock);
+#endif
+	Tcl_Panic("mutex not owned");
+    }
+    do_unlock = 0;
     pmutexPtr->counter--;
     if (pmutexPtr->counter == 0) {
 	pmutexPtr->thread = 0;
+	do_unlock = 1;
+    }
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
+    if (do_unlock) {
 	pthread_mutex_unlock(&pmutexPtr->mutex);
     }
 }
 
 static void
 PCondWait(
     pthread_cond_t *pcondPtr,
     PMutex *pmutexPtr)
 {
+    pthread_t self = pthread_self();
+    int counter;
+
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    if (pmutexPtr->thread != self) {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spin_unlock(&pmutexPtr->lock);
+#endif
+	Tcl_Panic("mutex not owned");
+    }
+    counter = pmutexPtr->counter;
+    pmutexPtr->counter = 0;
+    pmutexPtr->thread = 0;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
     pthread_cond_wait(pcondPtr, &pmutexPtr->mutex);
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    pmutexPtr->thread = self;
+    pmutexPtr->counter = counter;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
 }
 
 static void
 PCondTimedWait(
     pthread_cond_t *pcondPtr,
     PMutex *pmutexPtr,
     struct timespec *ptime)
 {
+    pthread_t self = pthread_self();
+    int counter;
+
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    if (pmutexPtr->thread != self) {
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+	pthread_spin_unlock(&pmutexPtr->lock);
+#endif
+	Tcl_Panic("mutex not owned");
+    }
+    counter = pmutexPtr->counter;
+    pmutexPtr->counter = 0;
+    pmutexPtr->thread = 0;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
     pthread_cond_timedwait(pcondPtr, &pmutexPtr->mutex, ptime);
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_lock(&pmutexPtr->lock);
+#endif
+    pmutexPtr->thread = self;
+    pmutexPtr->counter = counter;
+#ifdef HAVE_PTHREAD_SPIN_LOCK
+    pthread_spin_unlock(&pmutexPtr->lock);
+#endif
 }
 #endif /* HAVE_PTHREAD_MUTEX_RECURSIVE */
 
 /*
  * globalLock is used to serialize creation of mutexes, condition variables,