[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.