]> pd.if.org Git - pdclib/blob - platform/win32/functions/threads/mtx_timedlock.c
dos2unix
[pdclib] / platform / win32 / functions / threads / mtx_timedlock.c
1 #ifndef REGTEST
2 #include <threads.h>
3 #include <windows.h>
4 #include <stdint.h>
5
6 int mtx_timedlock(mtx_t *_PDCLIB_restrict mtx, 
7                   const struct timespec *_PDCLIB_restrict until)
8 {
9     DWORD myId = GetCurrentThreadId();
10
11     if(mtx->_ThreadId == (long) myId) {
12         mtx->_NestCount++;
13         return thrd_success;
14     }
15
16
17     for(;;) {
18         LONG prev = InterlockedCompareExchange(&mtx->_ThreadId, myId, 0);
19         if(prev == 0)
20             return thrd_success;
21
22         struct timespec now;
23         int32_t msToWait = 0;
24         if(timespec_get(&now, TIME_UTC) != TIME_UTC) {
25             // timespec_get must work!
26             return thrd_error;
27         } else {
28             int64_t deltaSec  = (int64_t)until->tv_sec  - now.tv_sec;
29             long    deltaNsec = (long)until->tv_nsec - now.tv_nsec;
30
31             if(INT32_MAX / 2000U < deltaSec) {
32                 // Risk of overflow - do a shorter timeout on this iteration
33                 msToWait = INT32_MAX / 2;
34             } else {
35                 msToWait = deltaSec * 1000 + deltaNsec / 1000;
36             }
37         }
38
39         if(msToWait < 0) {
40             return thrd_timeout;
41         }
42
43         DWORD rv = WaitForSingleObject(mtx->_WaitEvHandle, msToWait);
44         if(rv != WAIT_OBJECT_0 && rv != WAIT_TIMEOUT)
45             return thrd_error;
46     }
47 }
48 #endif
49
50 #ifdef TEST
51 #include "_PDCLIB_test.h"
52
53 int main( void )
54 {
55     return TEST_RESULTS;
56 }
57
58 #endif