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