Expand the scope of the event_buf_mutex to cover io_manager_event
authorSimon Marlow <marlowsd@gmail.com>
Tue, 20 Apr 2010 12:20:26 +0000 (12:20 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Tue, 20 Apr 2010 12:20:26 +0000 (12:20 +0000)
I once saw a failure that I think was due to a race on
io_manager_event, this should fix it.

rts/win32/ThrIOManager.c

index 35f1b5e..054f568 100644 (file)
@@ -21,6 +21,15 @@ static HANDLE io_manager_event = INVALID_HANDLE_VALUE;
 // spurios wakeups are returned as zero.\r
 // console events are ((event<<1) | 1)\r
 \r
+#if defined(THREADED_RTS)\r
+\r
+#define EVENT_BUFSIZ 256\r
+Mutex event_buf_mutex;\r
+StgWord32 event_buf[EVENT_BUFSIZ];\r
+nat next_event;\r
+\r
+#endif\r
+\r
 HANDLE\r
 getIOManagerEvent (void)\r
 {\r
@@ -30,6 +39,8 @@ getIOManagerEvent (void)
 #ifdef THREADED_RTS\r
     HANDLE hRes;\r
 \r
+    ACQUIRE_LOCK(&event_buf_mutex);\r
+\r
     if (io_manager_event == INVALID_HANDLE_VALUE) {\r
         hRes = CreateEvent ( NULL, // no security attrs\r
                              TRUE, // manual reset\r
@@ -40,25 +51,18 @@ getIOManagerEvent (void)
             stg_exit(EXIT_FAILURE);\r
         }\r
         io_manager_event = hRes;\r
-        return hRes;\r
     } else {\r
-        return io_manager_event;\r
+        hRes = io_manager_event;\r
     }\r
+\r
+    RELEASE_LOCK(&event_buf_mutex);\r
+    return hRes;\r
 #else\r
     return NULL;\r
 #endif\r
 }\r
 \r
 \r
-#if defined(THREADED_RTS)\r
-\r
-#define EVENT_BUFSIZ 256\r
-Mutex event_buf_mutex;\r
-StgWord32 event_buf[EVENT_BUFSIZ];\r
-nat next_event;\r
-\r
-#endif\r
-\r
 HsWord32\r
 readIOManagerEvent (void)\r
 {\r
@@ -67,8 +71,9 @@ readIOManagerEvent (void)
 #if defined(THREADED_RTS)\r
     HsWord32 res;\r
 \r
+    ACQUIRE_LOCK(&event_buf_mutex);\r
+\r
     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
-        ACQUIRE_LOCK(&event_buf_mutex);\r
         if (next_event == 0) {\r
             res = 0; // no event to return\r
         } else {\r
@@ -80,10 +85,12 @@ readIOManagerEvent (void)
                 }\r
             }\r
         }\r
-        RELEASE_LOCK(&event_buf_mutex);\r
     } else {\r
         res = 0;\r
     }\r
+\r
+    RELEASE_LOCK(&event_buf_mutex);\r
+\r
     // debugBelch("readIOManagerEvent: %d\n", res);\r
     return res;\r
 #else\r
@@ -95,9 +102,10 @@ void
 sendIOManagerEvent (HsWord32 event)\r
 {\r
 #if defined(THREADED_RTS)\r
+    ACQUIRE_LOCK(&event_buf_mutex);\r
+\r
     // debugBelch("sendIOManagerEvent: %d\n", event);\r
     if (io_manager_event != INVALID_HANDLE_VALUE) {\r
-        ACQUIRE_LOCK(&event_buf_mutex);\r
         if (next_event == EVENT_BUFSIZ) {\r
             errorBelch("event buffer overflowed; event dropped");\r
         } else {\r
@@ -107,8 +115,9 @@ sendIOManagerEvent (HsWord32 event)
             }        \r
             event_buf[next_event++] = (StgWord32)event;\r
         }\r
-        RELEASE_LOCK(&event_buf_mutex);\r
     }\r
+\r
+    RELEASE_LOCK(&event_buf_mutex);\r
 #endif\r
 }    \r
 \r
@@ -126,7 +135,9 @@ ioManagerDie (void)
     // IO_MANAGER_DIE must be idempotent, as it is called\r
     // repeatedly by shutdownCapability().  Try conc059(threaded1) to\r
     // illustrate the problem.\r
+    ACQUIRE_LOCK(&event_buf_mutex);\r
     io_manager_event = INVALID_HANDLE_VALUE;\r
+    RELEASE_LOCK(&event_buf_mutex);\r
     // ToDo: wait for the IO manager to pick up the event, and\r
     // then release the Event and Mutex objects we've allocated.\r
 }\r