Source: gauche
Version: 0.9.4-5
Severity: normal
Tags: patch

Hi,

After applying the libatomic-ops patch [1], gauche almost finishes
building on mips64el but it sometimes fails the "threads" test. I found
this was caused by a possible data race in the PORT_UNLOCK macro because
it doesn't issue a memory barrier when unlocking the lock (and so
earlier stores might be moved AFTER the unlock macro).

I've attached a patch which fixes this. I've tried to add the equivalent
for Windows (if you wanted to upstream it) but I haven't tested it
there.

Thanks,
James

[1] https://bugs.debian.org/774886
--- a/src/gauche/priv/portP.h
+++ b/src/gauche/priv/portP.h
@@ -119,7 +119,10 @@ void Scm__SetupPortsForWindows(int has_c
 /* Unlock a port P.  Assumes the calling thread has the lock */
 #define PORT_UNLOCK(p)                                  \
     do {                                                \
-        if (--p->lockCount <= 0) p->lockOwner = NULL;   \
+        if (--p->lockCount <= 0) {                      \
+            SCM_INTERNAL_SYNC();                        \
+            p->lockOwner = NULL;                        \
+        } \
     } while (0)
 
 /* Should be used while P is locked by calling thread.
--- a/src/gauche/pthread.h
+++ b/src/gauche/pthread.h
@@ -125,4 +125,7 @@ typedef pthread_mutex_t ScmInternalFastl
 #define SCM_INTERNAL_FASTLOCK_DESTROY(fl) SCM_INTERNAL_MUTEX_DESTROY(fl)
 #endif /*!HAVE_PTHREAD_SPINLOCK_T*/
 
+/* Issues a full memory barrier */
+#define SCM_INTERNAL_SYNC()                 __sync_synchronize()
+
 #endif /* GAUCHE_PTHREAD_H */
--- a/src/gauche/uthread.h
+++ b/src/gauche/uthread.h
@@ -142,4 +142,7 @@ typedef int ScmInternalCond;
 #define SCM_INTERNAL_COND_TIMEDOUT         (0)
 #define SCM_INTERNAL_COND_INTR             (0)
 
+/* Issues a full memory barrier */
+#define SCM_INTERNAL_SYNC()
+
 #endif /* GAUCHE_UTHREAD_H */
--- a/src/gauche/wthread.h
+++ b/src/gauche/wthread.h
@@ -141,4 +141,7 @@ typedef HANDLE ScmInternalFastlock;
 #define SCM_INTERNAL_FASTLOCK_UNLOCK(fl) SCM_INTERNAL_MUTEX_UNLOCK(fl)
 #define SCM_INTERNAL_FASTLOCK_DESTROY(fl) SCM_INTERNAL_MUTEX_DESTROY(fl)
 
+/* Issues a full memory barrier */
+#define SCM_INTERNAL_SYNC()                 MemoryBarrier()
+
 #endif /* GAUCHE_WTHREAD_H */

Reply via email to