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 */