[runtime] add initial changes to support cygwin
pthread_mutex_timedwait is not supported on cygwin, so
an alternate implementation of UMLRTMutex is required.
This version has manifested two known problems to date:
1. Bug 469428: On Linux, deadlock appeared to occur, resulting in
two threads waiting on the UMLRTMutexGuard associated with the
RTS global lock mutex - one thread while giving the global lock,
one thread while taking the global lock.
2. Bug 469429: On Windows, (cygwin version) the rts-computer test
model crashes shortly after de-registering the ComputerStatus
service port.
Change-Id: I7399febb290f97aac3e8abfc3b1d627480d5e87b
Signed-off-by: Barry Maher <bmaher@gpinc.ca>
diff --git a/rts/include/umlrtmutex.hh b/rts/include/umlrtmutex.hh
index 650695d..3cab899 100644
--- a/rts/include/umlrtmutex.hh
+++ b/rts/include/umlrtmutex.hh
@@ -19,6 +19,15 @@
// Currently not os-indepedent.
// Bug 32 tracks move of this implementation to +/os/linux.
+class UMLRTMutexGuard
+{
+public:
+ UMLRTMutexGuard ( pthread_mutex_t & m_ ) : mutex(m_) { pthread_mutex_lock( &mutex ); }
+ ~ UMLRTMutexGuard ( ) { pthread_mutex_unlock( &mutex ); }
+private:
+ pthread_mutex_t mutex;
+};
+
class UMLRTMutex
{
public:
@@ -33,14 +42,16 @@
void take(void);
// Wait only so many milliseconds.
- // Timed - returns non-zero for success, zero for timeout.
- int take( uint32_t msec );
+ // Timed - returns true for success, false for timeout.
+ bool take( uint32_t msec );
// Give it back.
void give(void);
private:
- pthread_mutex_t mutex;
+ pthread_mutex_t guard;
+ pthread_cond_t condition;
+ bool locked;
};
#endif // UMLRTMUTEX_HH
diff --git a/rts/umlrt/umlrtmutex.cc b/rts/umlrt/umlrtmutex.cc
index 4a24598..513cce2 100644
--- a/rts/umlrt/umlrtmutex.cc
+++ b/rts/umlrt/umlrtmutex.cc
@@ -19,31 +19,28 @@
// Bug 32 tracks the move of this implementation to +/os/linux/osmutex.cc
-UMLRTMutex::UMLRTMutex()
+UMLRTMutex::UMLRTMutex() : guard(), condition(), locked(false)
{
- pthread_mutex_init(&mutex, NULL);
-}
-
-// Can create a mutex which starts life as taken already.
-UMLRTMutex::UMLRTMutex( bool taken )
-{
- if (taken)
- {
- take();
- }
+ pthread_mutex_init(&guard, NULL);
+ pthread_cond_init(&condition, NULL);
}
UMLRTMutex::~UMLRTMutex()
{
- pthread_mutex_destroy(&mutex);
+ pthread_mutex_destroy(&guard);
+ pthread_cond_destroy(&condition);
}
+
// Wait forever for mutex.
void UMLRTMutex::take()
{
- if (pthread_mutex_lock(&mutex) < 0)
+ UMLRTMutexGuard g(guard);
+
+ while (locked)
{
- FATAL_ERRNO("pthread_mutex_lock");
+ pthread_cond_wait(&condition, &guard);
}
+ locked = true;
}
// Timed - returns non-zero for success, zero for timeout.
@@ -52,23 +49,29 @@
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
-int UMLRTMutex::take( uint32_t msec )
+bool UMLRTMutex::take( uint32_t msec )
{
struct timespec timeout;
- int success = !0;
-
UMLRTTimespec::timespecAbsAddMsec( &timeout, msec );
- if (pthread_mutex_timedlock(&mutex, &timeout) < 0)
+
+ UMLRTMutexGuard g(guard);
+
+ while (locked)
{
- int errno_ = errno;
- if (errno_ != ETIMEDOUT)
+ if (pthread_cond_timedwait(&condition, &guard, &timeout) != 0)
{
- FATAL_ERRNO("pthread_mutex_timedlock");
+ int errno_ = errno;
+ if (errno_ != ETIMEDOUT)
+ {
+ FATAL_ERRNO("pthread_cond_timedwait");
+ }
+ return false; // Timed out - return error indication.
}
- success = 0;
}
- return success;
+ locked = true;
+ return true; // Obtained lock within timeout.
}
+
#if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406)
#pragma GCC diagnostic pop
#endif
@@ -76,9 +79,8 @@
// Give mutex back.
void UMLRTMutex::give()
{
- if (pthread_mutex_unlock(&mutex) < 0)
- {
- FATAL_ERRNO("pthread_mutex_unlock");
- }
+ UMLRTMutexGuard g(guard);
+ locked = false;
+ pthread_cond_signal(&condition);
}
diff --git a/rts/umlrt/umlrtprioritymessagequeue.cc b/rts/umlrt/umlrtprioritymessagequeue.cc
index f49ee11..f9e3415 100644
--- a/rts/umlrt/umlrtprioritymessagequeue.cc
+++ b/rts/umlrt/umlrtprioritymessagequeue.cc
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
// See umlrtprioritymessagequeue.hh for documentation.
diff --git a/rts/umlrt/umlrttimerqueue.cc b/rts/umlrt/umlrttimerqueue.cc
index 1160758..1d04bc0 100644
--- a/rts/umlrt/umlrttimerqueue.cc
+++ b/rts/umlrt/umlrttimerqueue.cc
@@ -18,6 +18,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
// See umlrttimerqueue.hh for documentation.