1
0
mirror of https://github.com/GOSTSec/sgminer synced 2025-01-10 23:08:07 +00:00

On windows use the higher accuracy timegettime function to really get 1ms clock and timer accuracy.

This commit is contained in:
Con Kolivas 2013-08-19 13:29:23 +10:00
parent e56c9a5d3b
commit 404cbdea84

113
util.c
View File

@ -807,16 +807,30 @@ void thr_info_cancel(struct thr_info *thr)
/* This is a cgminer gettimeofday wrapper. Since we always call gettimeofday /* This is a cgminer gettimeofday wrapper. Since we always call gettimeofday
* with tz set to NULL, and windows' default resolution is only 15ms, this * with tz set to NULL, and windows' default resolution is only 15ms, this
* gives us higher resolution times on windows. */ * gives us higher resolution times on windows. */
#ifndef WIN32
void cgtime(struct timeval *tv) void cgtime(struct timeval *tv)
{ {
#ifdef WIN32
timeBeginPeriod(1);
#endif
gettimeofday(tv, NULL); gettimeofday(tv, NULL);
#ifdef WIN32
timeEndPeriod(1);
#endif
} }
#else
static void dtime_to_timeval(struct timeval *tv, DWORD dtime)
{
ldiv_t tvdiv = ldiv(dtime, 1000);
tv->tv_sec = tvdiv.quot;
tv->tv_usec = tvdiv.rem * 1000;
}
void cgtime(struct timeval *tv)
{
DWORD dtime;
//timeBeginPeriod(1);
dtime = timeGetTime();
//timeEndPeriod(1);
dtime_to_timeval(tv, dtime);
}
#endif
void subtime(struct timeval *a, struct timeval *b) void subtime(struct timeval *a, struct timeval *b)
{ {
@ -857,27 +871,33 @@ void timeval_to_spec(struct timespec *spec, const struct timeval *val)
void us_to_timeval(struct timeval *val, int64_t us) void us_to_timeval(struct timeval *val, int64_t us)
{ {
val->tv_sec = us / 1000000; lldiv_t tvdiv = lldiv(us, 1000000);
val->tv_usec = us - (val->tv_sec * 1000000);
val->tv_sec = tvdiv.quot;
val->tv_usec = tvdiv.rem;
} }
void us_to_timespec(struct timespec *spec, int64_t us) void us_to_timespec(struct timespec *spec, int64_t us)
{ {
spec->tv_sec = us / 1000000; lldiv_t tvdiv = lldiv(us, 1000000);
spec->tv_nsec = (us - (spec->tv_sec * 1000000)) * 1000;
spec->tv_sec = tvdiv.quot;
spec->tv_nsec = tvdiv.rem * 1000;
} }
void ms_to_timespec(struct timespec *spec, int64_t ms) void ms_to_timespec(struct timespec *spec, int64_t ms)
{ {
spec->tv_sec = ms / 1000; lldiv_t tvdiv = lldiv(ms, 1000);
spec->tv_nsec = (ms - (spec->tv_sec * 1000)) * 1000000;
spec->tv_sec = tvdiv.quot;
spec->tv_nsec = tvdiv.quot * 1000000;
} }
void timeraddspec(struct timespec *a, const struct timespec *b) void timeraddspec(struct timespec *a, const struct timespec *b)
{ {
a->tv_sec += b->tv_sec; a->tv_sec += b->tv_sec;
a->tv_nsec += b->tv_nsec; a->tv_nsec += b->tv_nsec;
if (a->tv_nsec >+ 1000000000) { if (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000; a->tv_nsec -= 1000000000;
a->tv_sec++; a->tv_sec++;
} }
@ -885,7 +905,7 @@ void timeraddspec(struct timespec *a, const struct timespec *b)
/* These are cgminer specific sleep functions that use an absolute nanosecond /* These are cgminer specific sleep functions that use an absolute nanosecond
* resolution timer to avoid poor usleep accuracy and overruns. */ * resolution timer to avoid poor usleep accuracy and overruns. */
#ifdef CLOCK_MONOTONIC #ifndef WIN32
void cgsleep_prepare_r(struct timespec *ts_start) void cgsleep_prepare_r(struct timespec *ts_start)
{ {
clock_gettime(CLOCK_MONOTONIC, ts_start); clock_gettime(CLOCK_MONOTONIC, ts_start);
@ -900,59 +920,46 @@ static void nanosleep_abstime(struct timespec *ts_end)
} while (ret == EINTR); } while (ret == EINTR);
} }
#else #else
static void dtime_to_timespec(struct timespec *ts, DWORD dtime)
{
ldiv_t tsdiv = ldiv(dtime, 1000);
ts->tv_sec = tsdiv.quot;
ts->tv_nsec = tsdiv.rem * 1000000;
}
static DWORD timespec_to_dtime(const struct timespec *ts)
{
DWORD ret;
ret = ts->tv_sec * 1000;
ret += ts->tv_nsec / 1000000;
return ret;
}
void cgsleep_prepare_r(struct timespec *ts_start) void cgsleep_prepare_r(struct timespec *ts_start)
{ {
struct timeval tv_start; DWORD dtime;
#ifdef WIN32
timeBeginPeriod(1); timeBeginPeriod(1);
#endif dtime = timeGetTime();
gettimeofday(&tv_start, NULL); dtime_to_timespec(ts_start, dtime);
timeval_to_spec(ts_start, &tv_start);
}
static uint64_t timespec_to_ns(struct timespec *ts)
{
uint64_t ret;
ret = (uint64_t)ts->tv_sec * 1000000000;
ret += ts->tv_nsec;
return ret;
}
static uint64_t timeval_to_ns(struct timeval *tv)
{
uint64_t ret;
ret = (uint64_t)tv->tv_sec * 1000000000;
ret += tv->tv_usec * 1000;
return ret;
}
static void ns_to_timespec(struct timespec *ts, uint64_t ns)
{
ts->tv_sec = ns / 1000000000;
ts->tv_nsec = ns - ((uint64_t)ts->tv_sec * 1000000000ull);
} }
static void nanosleep_abstime(struct timespec *ts_end) static void nanosleep_abstime(struct timespec *ts_end)
{ {
uint64_t now_ns, end_ns, diff_ns; DWORD now_ms, end_ms, diff_ms;
struct timespec ts_diff; struct timespec ts_diff;
struct timeval now;
end_ns = timespec_to_ns(ts_end); end_ms = timespec_to_dtime(ts_end);
gettimeofday(&now, NULL); now_ms = timeGetTime();
now_ns = timeval_to_ns(&now); if (unlikely(now_ms >= end_ms))
if (unlikely(now_ns >= end_ns))
goto out; goto out;
diff_ns = end_ns - now_ns; diff_ms = end_ms - now_ms;
ns_to_timespec(&ts_diff, diff_ns); dtime_to_timespec(&ts_diff, diff_ms);
nanosleep(&ts_diff, NULL); nanosleep(&ts_diff, NULL);
out: out:
#ifdef WIN32
timeEndPeriod(1); timeEndPeriod(1);
#endif
} }
#endif #endif