X-Git-Url: https://pd.if.org/git/?p=pdclib;a=blobdiff_plain;f=platform%2Fwin32%2Ffunctions%2Fthreads%2Fmtx_timedlock.c;fp=platform%2Fwin32%2Ffunctions%2Fthreads%2Fmtx_timedlock.c;h=07edc0c82e0463c7beedc2b8198f5fb4f9600130;hp=0000000000000000000000000000000000000000;hb=3b357986c8ac26f3aee1033c49c28f58c3cd2fb4;hpb=3979dd45fb1088cc27bcde72f0d4a51c80035e4f diff --git a/platform/win32/functions/threads/mtx_timedlock.c b/platform/win32/functions/threads/mtx_timedlock.c new file mode 100644 index 0000000..07edc0c --- /dev/null +++ b/platform/win32/functions/threads/mtx_timedlock.c @@ -0,0 +1,58 @@ +#ifndef REGTEST +#include +#include +#include + +int mtx_timedlock(mtx_t *_PDCLIB_restrict mtx, + const struct timespec *_PDCLIB_restrict until) +{ + DWORD myId = GetCurrentThreadId(); + + if(mtx->_ThreadId == myId) { + mtx->_NestCount++; + return thrd_success; + } + + + for(;;) { + LONG prev = InterlockedCompareExchange(&mtx->_ThreadId, myId, 0); + if(prev == 0) + return thrd_success; + + struct timespec now; + int32_t msToWait = 0; + if(timespec_get(&now, TIME_UTC) != TIME_UTC) { + // timespec_get must work! + return thrd_error; + } else { + int64_t deltaSec = (int64_t)until->tv_sec - now.tv_sec; + long deltaNsec = (long)until->tv_nsec - now.tv_nsec; + + if(INT32_MAX / 2000U < deltaSec) { + // Risk of overflow - do a shorter timeout on this iteration + msToWait = INT32_MAX / 2; + } else { + msToWait = deltaSec * 1000 + deltaNsec / 1000; + } + } + + if(msToWait < 0) { + return thrd_timeout; + } + + DWORD rv = WaitForSingleObject(mtx->_WaitEvHandle, msToWait); + if(rv != WAIT_OBJECT_0 && rv != WAIT_TIMEOUT) + return thrd_error; + } +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif \ No newline at end of file