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,