summaryrefslogtreecommitdiff
path: root/rts/win32
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2013-02-06 13:14:55 +0000
committerIan Lynagh <igloo@earth.li>2013-02-06 13:14:55 +0000
commit8c8e959fdf86281c01e3392a3860ab64524d37df (patch)
tree1a7ce4e9a397ab979e7e5b12d179a9de0f5da50a /rts/win32
parent073583173b42c988ef8af7f1a7a5f010645bbaef (diff)
downloadhaskell-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.c26
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;
}