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,