diff options
author | Ian Lynagh <igloo@earth.li> | 2013-02-06 13:14:55 +0000 |
---|---|---|
committer | Ian Lynagh <igloo@earth.li> | 2013-02-06 13:14:55 +0000 |
commit | 8c8e959fdf86281c01e3392a3860ab64524d37df (patch) | |
tree | 1a7ce4e9a397ab979e7e5b12d179a9de0f5da50a /rts/win32 | |
parent | 073583173b42c988ef8af7f1a7a5f010645bbaef (diff) | |
download | haskell-8c8e959fdf86281c01e3392a3860ab64524d37df.tar.gz |
Fix threadDelay on Windows; fixes ThreadDelay001 failures
MSDN says of Sleep:
If dwMilliseconds is greater than one tick but less than two, the
wait can be anywhere between one and two ticks, and so on.
so we need to add (milliseconds-per-tick - 1) to the amount of time we
sleep for.
Diffstat (limited to 'rts/win32')
-rw-r--r-- | rts/win32/IOManager.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/rts/win32/IOManager.c b/rts/win32/IOManager.c index 8490ed2dd7..65f5d4cf99 100644 --- a/rts/win32/IOManager.c +++ b/rts/win32/IOManager.c @@ -32,6 +32,7 @@ typedef struct IOManagerState { /* fields for keeping track of active WorkItems */ CritSection active_work_lock; WorkItem* active_work_items; + UINT sleepResolution; } IOManagerState; /* ToDo: wrap up this state via a IOManager handle instead? */ @@ -199,7 +200,7 @@ IOWorkerProc(PVOID param) * * Note: Sleep() is in milliseconds, not micros. */ - Sleep((work->workData.delayData.usecs + 999) / 1000); + Sleep(((work->workData.delayData.usecs + 999) / 1000) + iom->sleepResolution - 1); len = work->workData.delayData.usecs; complData = NULL; fd = 0; @@ -266,6 +267,19 @@ StartIOManager(void) { HANDLE hExit; WorkQueue* wq; + UINT sleepResolution; + TIMECAPS timecaps; + MMRESULT mmresult; + + mmresult = timeGetDevCaps(&timecaps, sizeof(timecaps)); + if (mmresult != MMSYSERR_NOERROR) { + return FALSE; + } + sleepResolution = timecaps.wPeriodMin; + mmresult = timeBeginPeriod(sleepResolution); + if (mmresult != MMSYSERR_NOERROR) { + return FALSE; + } wq = NewWorkQueue(); if ( !wq ) return FALSE; @@ -284,7 +298,7 @@ StartIOManager(void) free(ioMan); return FALSE; } - + ioMan->hExitEvent = hExit; InitializeCriticalSection(&ioMan->manLock); ioMan->workQueue = wq; @@ -294,6 +308,7 @@ StartIOManager(void) ioMan->requestID = 1; InitializeCriticalSection(&ioMan->active_work_lock); ioMan->active_work_items = NULL; + ioMan->sleepResolution = sleepResolution; return TRUE; } @@ -455,6 +470,7 @@ AddProcRequest ( void* proc, void ShutdownIOManager ( rtsBool wait_threads ) { int num; + MMRESULT mmresult; SetEvent(ioMan->hExitEvent); @@ -472,6 +488,12 @@ void ShutdownIOManager ( rtsBool wait_threads ) CloseHandle(ioMan->hExitEvent); DeleteCriticalSection(&ioMan->active_work_lock); DeleteCriticalSection(&ioMan->manLock); + + mmresult = timeEndPeriod(ioMan->sleepResolution); + if (mmresult != MMSYSERR_NOERROR) { + barf("timeEndPeriod failed"); + } + free(ioMan); ioMan = NULL; } |