From: sof Date: Fri, 29 Jul 2005 20:21:50 +0000 (+0000) Subject: [project @ 2005-07-29 20:21:50 by sof] X-Git-Tag: Initial_conversion_from_CVS_complete~284 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=b3de318bd2350bc3558e9e2f1bd3fe8df5b7e0cf;p=ghc-hetmet.git [project @ 2005-07-29 20:21:50 by sof] win32/AsyncIO.c:onIOComplete(), awaitRequests(): Avoid completion table overflow through the use of a semaphore. Worker threads (the producers) wait for a free event slot to appear, the RTS thread (consumer) signal slot availability once the completion event has been de-queued and processed. This bug only manifests itself in 'massively concurrent' code (>200 threads), where the threads simultaneously engage in IO through the async IO layer. conc023 and conc036 in the regression test suite are examples of such. Merge to STABLE. --- diff --git a/ghc/rts/win32/AsyncIO.c b/ghc/rts/win32/AsyncIO.c index 91495d5..acb40eb 100644 --- a/ghc/rts/win32/AsyncIO.c +++ b/ghc/rts/win32/AsyncIO.c @@ -50,6 +50,7 @@ static HANDLE abandon_req_wait; static HANDLE wait_handles[2]; static CompletedReq completedTable[MAX_REQUESTS]; static int completed_hw; +static HANDLE completed_table_sema; static int issued_reqs; static void @@ -59,11 +60,22 @@ onIOComplete(unsigned int reqID, void* buf STG_UNUSED, int errCode) { - /* Deposit result of request in queue/table */ + DWORD dwRes; + /* Deposit result of request in queue/table..when there's room. */ + dwRes = WaitForSingleObject(completed_table_sema, INFINITE); + switch (dwRes) { + case WAIT_OBJECT_0: + break; + default: + /* Not likely */ + fprintf(stderr, "onIOComplete: failed to grab table semaphore, dropping request 0x%x\n", reqID); + fflush(stderr); + return; + } EnterCriticalSection(&queue_lock); if (completed_hw == MAX_REQUESTS) { - /* Not likely */ - fprintf(stderr, "Request table overflow (%d); dropping.\n", reqID); + /* Shouldn't happen */ + fprintf(stderr, "onIOComplete: ERROR -- Request table overflow (%d); dropping.\n", reqID); fflush(stderr); } else { #if 0 @@ -147,8 +159,15 @@ startupAsyncIO() wait_handles[0] = completed_req_event; wait_handles[1] = abandon_req_wait; completed_hw = 0; - return ( completed_req_event != INVALID_HANDLE_VALUE && - abandon_req_wait != INVALID_HANDLE_VALUE ); + if ( !(completed_table_sema = CreateSemaphore (NULL, MAX_REQUESTS, MAX_REQUESTS, NULL)) ) { + DWORD rc = GetLastError(); + fprintf(stderr, "startupAsyncIO: CreateSemaphore failed 0x%x\n", rc); + fflush(stderr); + } + + return ( completed_req_event != INVALID_HANDLE_VALUE && + abandon_req_wait != INVALID_HANDLE_VALUE && + completed_table_sema != NULL ); } void @@ -275,6 +294,12 @@ start: break; } } + /* Signal that there's completed table slots available */ + if ( !ReleaseSemaphore(completed_table_sema, 1, NULL) ) { + DWORD dw = GetLastError(); + fprintf(stderr, "awaitRequests: failed to signal semaphore (error code=0x%x)\n", dw); + fflush(stderr); + } } completed_hw = 0; ResetEvent(completed_req_event);