From ff803bf792e75b7b37083838becee6b6e5a9aa4d Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 5 May 2019 11:03:17 -0400 Subject: [PATCH] And implemented 128-bit muldiv on Windows. --- test/initmain.c | 6 ++++++ test/lib/timer.c | 45 ++++++++++++++++++++++++++++++++++++++++ test/lib/timer.h | 1 + test/lib/timer_windows.c | 16 ++++++-------- test/lib/timerpriv.h | 2 ++ 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/test/initmain.c b/test/initmain.c index 4a44b0e7..cf794e79 100644 --- a/test/initmain.c +++ b/test/initmain.c @@ -147,6 +147,12 @@ static void queueThread(void *data) uiQueueMain(queued, p); } +/* +TODO if I remove the uiQuit() from this test on Windows, I will occasionally get +=== RUN TestQueueMain_DifferentThread + ../test/initmain.c:161: uiMain() timed out (5s) +--- FAIL: TestQueueMain_DifferentThread (4.9989539s) +*/ testingTest(QueueMain_DifferentThread) { threadThread *thread; diff --git a/test/lib/timer.c b/test/lib/timer.c index fd158f32..01e27902 100644 --- a/test/lib/timer.c +++ b/test/lib/timer.c @@ -305,3 +305,48 @@ void timerprivMulDivUint64(uint64_t x, uint64_t y, uint64_t z, timerprivInt128 * int128FromUint64(z, &c); int128MulDiv64(&a, &b, &c, quot); } + +int64_t timerprivInt128ToInt64(const timerprivInt128 *n, int64_t min, int64_t max, int64_t minCap, int64_t maxCap) +{ + if (n->neg) { + int64_t ret; + + if (n->high > 0) + return minCap; + if (n->low > (uint64_t) INT64_MAX) { + // we can't safely convert n->low to int64_t +#if INT64_MIN == -INT64_MAX + // in this case, we can't store -n->low in an int64_t at all! + // therefore, it must be out of range + return minCap; +#else + // in this case, INT64_MIN == -INT64_MAX - 1 + if (n->low > ((uint64_t) INT64_MAX) + 1) + // we still can't store -n->low in an int64_t + return minCap; + // only one option left + ret = INT64_MIN; +#endif + } else { + // -n->low can safely be stored in an int64_t, so do so + ret = (int64_t) (n->low); + ret = -ret; + } + if (ret < min) + return minCap; + return ret; + } + if (n->high > 0) + return maxCap; + if (n->low > (uint64_t) max) + return maxCap; + return (int64_t) (n->low); +} + +uint64_t timerprivInt128ToUint64(const timerprivInt128 *n, uint64_t max, uint64_t maxCap) +{ + if (n->neg) + return 0; + // TODO + return 0; +} diff --git a/test/lib/timer.h b/test/lib/timer.h index 760c6ff3..65a64634 100644 --- a/test/lib/timer.h +++ b/test/lib/timer.h @@ -5,6 +5,7 @@ typedef int64_t timerDuration; typedef int64_t timerTime; +#define timerTimeMin ((timerTime) INT64_MIN) #define timerTimeMax ((timerTime) INT64_MAX) #define timerNanosecond ((timerDuration) 1) diff --git a/test/lib/timer_windows.c b/test/lib/timer_windows.c index fb4e4bfe..e8f705b2 100644 --- a/test/lib/timer_windows.c +++ b/test/lib/timer_windows.c @@ -15,6 +15,7 @@ #include #include #include "timer.h" +#include "timerpriv.h" static HRESULT lastErrorCodeToHRESULT(DWORD lastError) { @@ -181,18 +182,13 @@ timerTime timerMonotonicNow(void) timerDuration timerTimeSub(timerTime end, timerTime start) { LARGE_INTEGER qpf; - timerDuration qpnsQuot, qpnsRem; - timerTime c; - timerDuration ret; + timerprivInt128 quot; QueryPerformanceFrequency(&qpf); - qpnsQuot = timerSecond / qpf.QuadPart; - qpnsRem = timerSecond % qpf.QuadPart; - c = end - start; - - ret = ((timerDuration) c) * qpnsQuot; - ret += (c * qpnsRem) / qpf.QuadPart; - return ret; + timerprivMulDivInt64(end - start, timerSecond, qpf.QuadPart, "); + return timerprivInt128ToInt64(", + INT64_MIN, INT64_MAX, + timerTimeMin, timerTimeMax); } // note: the idea for the SetThreadContext() nuttery is from https://www.codeproject.com/Articles/71529/Exception-Injection-Throwing-an-Exception-in-Other diff --git a/test/lib/timerpriv.h b/test/lib/timerpriv.h index 37fc7173..5cf3b03b 100644 --- a/test/lib/timerpriv.h +++ b/test/lib/timerpriv.h @@ -10,3 +10,5 @@ struct timerprivInt128 { extern void timerprivMulDivInt64(int64_t x, int64_t y, int64_t z, timerprivInt128 *quot); extern void timerprivMulDivUint64(uint64_t x, uint64_t y, uint64_t z, timerprivInt128 *quot); +extern int64_t timerprivInt128ToInt64(const timerprivInt128 *n, int64_t min, int64_t max, int64_t minCap, int64_t maxCap); +extern uint64_t timerprivInt128ToUint64(const timerprivInt128 *n, uint64_t max, uint64_t maxCap);