if(mtx->_WaitEvHandle == NULL)\r
return thrd_error;\r
\r
- mtx->_State = -1;\r
mtx->_ThreadId = 0;\r
mtx->_NestCount = 0;;\r
\r
return thrd_success;\r
}\r
\r
- DWORD res = InterlockedIncrement(&mtx->_State);\r
- if(res == 0) {\r
- mtx->_ThreadId = myId;\r
- return thrd_success;\r
+ for(;;) {\r
+ LONG prev = InterlockedCompareExchange(&mtx->_ThreadId, myId, 0);\r
+ if(prev == 0)\r
+ return thrd_success;\r
+\r
+ DWORD rv = WaitForSingleObject(mtx->_WaitEvHandle, INFINITE);\r
+ if(rv != WAIT_OBJECT_0)\r
+ return thrd_error;\r
}\r
-\r
- // If that increment didn't leave the state == 0, then we have contention\r
- // -> block on the wait event handle\r
- DWORD rv = WaitForSingleObject(mtx->_WaitEvHandle, INFINITE);\r
- if(rv != WAIT_OBJECT_0) \r
- return thrd_error;\r
-\r
- // We now own the mutex - so set it up for our use\r
- mtx->_ThreadId = myId;\r
- return thrd_success;\r
}\r
#endif\r
\r
--- /dev/null
+#ifndef REGTEST\r
+#include <threads.h>\r
+#include <windows.h>\r
+#include <stdint.h>\r
+\r
+int mtx_timedlock(mtx_t *_PDCLIB_restrict mtx, \r
+ const struct timespec *_PDCLIB_restrict until)\r
+{\r
+ DWORD myId = GetCurrentThreadId();\r
+\r
+ if(mtx->_ThreadId == myId) {\r
+ mtx->_NestCount++;\r
+ return thrd_success;\r
+ }\r
+\r
+\r
+ for(;;) {\r
+ LONG prev = InterlockedCompareExchange(&mtx->_ThreadId, myId, 0);\r
+ if(prev == 0)\r
+ return thrd_success;\r
+\r
+ struct timespec now;\r
+ int32_t msToWait = 0;\r
+ if(timespec_get(&now, TIME_UTC) != TIME_UTC) {\r
+ // timespec_get must work!\r
+ return thrd_error;\r
+ } else {\r
+ int64_t deltaSec = (int64_t)until->tv_sec - now.tv_sec;\r
+ long deltaNsec = (long)until->tv_nsec - now.tv_nsec;\r
+\r
+ if(INT32_MAX / 2000U < deltaSec) {\r
+ // Risk of overflow - do a shorter timeout on this iteration\r
+ msToWait = INT32_MAX / 2;\r
+ } else {\r
+ msToWait = deltaSec * 1000 + deltaNsec / 1000;\r
+ }\r
+ }\r
+\r
+ if(msToWait < 0) {\r
+ return thrd_timeout;\r
+ }\r
+\r
+ DWORD rv = WaitForSingleObject(mtx->_WaitEvHandle, msToWait);\r
+ if(rv != WAIT_OBJECT_0 && rv != WAIT_TIMEOUT)\r
+ return thrd_error;\r
+ }\r
+}\r
+#endif\r
+\r
+#ifdef TEST\r
+#include <_PDCLIB_test.h>\r
+\r
+int main( void )\r
+{\r
+ return TEST_RESULTS;\r
+}\r
+\r
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef REGTEST\r
+#include <threads.h>\r
+#include <windows.h>\r
+\r
+int mtx_trylock(mtx_t *mtx)\r
+{\r
+ DWORD myId = GetCurrentThreadId();\r
+\r
+ if(mtx->_ThreadId == myId) {\r
+ mtx->_NestCount++;\r
+ return thrd_success;\r
+ }\r
+\r
+ if(mtx->_ThreadId != 0)\r
+ return thrd_busy;\r
+\r
+ LONG prev = InterlockedCompareExchange(&mtx->_ThreadId, myId, 0);\r
+ if(prev == 0)\r
+ return thrd_success;\r
+ else\r
+ return thrd_busy;\r
+}\r
+#endif\r
+\r
+#ifdef TEST\r
+#include <_PDCLIB_test.h>\r
+\r
+int main( void )\r
+{\r
+ return TEST_RESULTS;\r
+}\r
+\r
+#endif
\ No newline at end of file
}\r
\r
mtx->_ThreadId = 0;\r
-\r
- DWORD res = InterlockedDecrement(&mtx->_State);\r
- if(res == (DWORD) -1) {\r
- // We reset the state to -1; success!\r
- return thrd_success;\r
- }\r
-\r
DWORD rv = SetEvent(mtx->_WaitEvHandle);\r
if(rv == 0) {\r
_PDCLIB_w32errno();\r
return thrd_error;\r
}\r
-\r
return thrd_success;\r
}\r
#endif\r
#define _PDCLIB_MTX_T struct _PDCLIB_mtx \r
\r
struct _PDCLIB_mtx {\r
- void * _WaitEvHandle;\r
- volatile signed long _State;\r
- volatile unsigned int _ThreadId;\r
- volatile unsigned int _NestCount;\r
+ void * _WaitEvHandle;\r
+ volatile unsigned long _ThreadId; \r
+ volatile unsigned int _NestCount;\r
};\r
\r
#define _PDCLIB_TSS_T struct _PDCLIB_tss *\r