Add timers for measuring elapsed time

This commit is contained in:
2025-09-21 22:07:54 +03:00
parent 9bd2007023
commit b1870bd709
11 changed files with 565 additions and 3 deletions

View File

@@ -0,0 +1,50 @@
#include <BH/Timer.h>
BH_Timer *BH_TimerNew(void)
{
return NULL;
}
void BH_TimerFree(BH_Timer *timer)
{
BH_UNUSED(timer);
}
int BH_TimerIsMonotonic(BH_Timer *timer)
{
BH_UNUSED(timer);
return 0;
}
void BH_TimerStart(BH_Timer *timer)
{
BH_UNUSED(timer);
}
int64_t BH_TimerRestart(BH_Timer *timer)
{
BH_UNUSED(timer);
return 0;
}
int64_t BH_TimerMilliseconds(BH_Timer *timer)
{
BH_UNUSED(timer);
return 0;
}
int64_t BH_TimerNanoseconds(BH_Timer *timer)
{
BH_UNUSED(timer);
return 0;
}

139
src/Platform/Posix/Timer.c Normal file
View File

@@ -0,0 +1,139 @@
#include <BH/Timer.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#define TYPE_OLD_REALTIME 0x0000
#define TYPE_NEW_REALTIME 0x0001
#define TYPE_MONOTONIC 0x0002
struct BH_Timer
{
int type;
int64_t sec;
int64_t nsec;
};
static int checkAvailableTimer(void)
{
#if (_POSIX_TIMERS > 0) || defined(BH_USE_CLOCK_GETTIME)
struct timespec ts;
if (!clock_gettime(CLOCK_MONOTONIC, &ts))
return TYPE_MONOTONIC;
if (!clock_gettime(CLOCK_REALTIME, &ts))
return TYPE_NEW_REALTIME;
#endif
return TYPE_OLD_REALTIME;
}
static void getTimer(int type,
int64_t *sec,
int64_t *nsec)
{
struct timespec ts;
struct timeval tv;
switch (type)
{
#if (_POSIX_TIMERS > 0) || defined(BH_USE_CLOCK_GETTIME)
case TYPE_MONOTONIC:
clock_gettime(CLOCK_MONOTONIC, &ts);
*sec = ts.tv_sec;
*nsec = ts.tv_nsec;
break;
case TYPE_NEW_REALTIME:
clock_gettime(CLOCK_REALTIME, &ts);
*sec = ts.tv_sec;
*nsec = ts.tv_nsec;
break;
#endif
default:
case TYPE_OLD_REALTIME:
gettimeofday(&tv, NULL);
*sec = tv.tv_sec;
*nsec = tv.tv_usec * (uint64_t)1000;
break;
}
}
BH_Timer *BH_TimerNew(void)
{
BH_Timer *result;
result = malloc(sizeof(*result));
if (result)
{
result->type = checkAvailableTimer();
BH_TimerStart(result);
}
return result;
}
void BH_TimerFree(BH_Timer *timer)
{
free(timer);
}
int BH_TimerIsMonotonic(BH_Timer *timer)
{
return timer->type == TYPE_MONOTONIC;
}
void BH_TimerStart(BH_Timer *timer)
{
getTimer(timer->type, &timer->sec, &timer->nsec);
}
int64_t BH_TimerRestart(BH_Timer *timer)
{
int64_t oldSec, oldNsec;
oldSec = timer->sec; oldNsec = timer->nsec;
getTimer(timer->type, &timer->sec, &timer->nsec);
oldSec = timer->sec - oldSec;
oldNsec = timer->nsec - oldNsec;
return (oldSec * 1000) + (oldNsec / 1000000);
}
int64_t BH_TimerMilliseconds(BH_Timer *timer)
{
int64_t newSec, newNsec;
getTimer(timer->type, &newSec, &newNsec);
newSec -= timer->sec;
newNsec -= timer->nsec;
return (newSec * 1000) + (newNsec / 1000000);
}
int64_t BH_TimerNanoseconds(BH_Timer *timer)
{
int64_t newSec, newNsec;
getTimer(timer->type, &newSec, &newNsec);
newSec -= timer->sec;
newNsec -= timer->nsec;
return (newSec * 1000000000) + newNsec;
}

130
src/Platform/Win32/Timer.c Normal file
View File

@@ -0,0 +1,130 @@
#include <BH/Timer.h>
#include <stdlib.h>
#include <windows.h>
#define TYPE_TICKS 0x0000
#define TYPE_COUNTER 0x0001
struct BH_Timer
{
int type;
LARGE_INTEGER frequency;
int64_t sec;
int64_t nsec;
};
static int checkAvailableTimer(LARGE_INTEGER *frequency)
{
LARGE_INTEGER dummy;
if (QueryPerformanceFrequency(frequency))
{
if (QueryPerformanceCounter(&dummy))
{
return TYPE_COUNTER;
}
}
return TYPE_TICKS;
}
static void getTimer(int type,
LARGE_INTEGER *frequency,
int64_t *sec,
int64_t *nsec)
{
LARGE_INTEGER newCount;
int64_t newTicks;
switch (type)
{
case TYPE_COUNTER:
QueryPerformanceCounter(&newCount);
*sec = newCount.QuadPart / frequency->QuadPart;
*nsec = (newCount.QuadPart - *sec * frequency->QuadPart) * 1000000000 / frequency->QuadPart;
break;
default:
case TYPE_TICKS:
newTicks = GetTickCount64();
*sec = newTicks / 1000;
*nsec = (newTicks - *sec * 1000) * 1000000;
break;
}
}
BH_Timer *BH_TimerNew(void)
{
BH_Timer *result;
result = malloc(sizeof(*result));
if (result)
{
result->type = checkAvailableTimer(&result->frequency);
BH_TimerStart(result);
}
return result;
}
void BH_TimerFree(BH_Timer *timer)
{
free(timer);
}
int BH_TimerIsMonotonic(BH_Timer *timer)
{
return timer->type == TYPE_COUNTER;
}
void BH_TimerStart(BH_Timer *timer)
{
getTimer(timer->type, &timer->frequency, &timer->sec, &timer->nsec);
}
int64_t BH_TimerRestart(BH_Timer *timer)
{
int64_t oldSec, oldNsec;
oldSec = timer->sec; oldNsec = timer->nsec;
getTimer(timer->type, &timer->frequency, &timer->sec, &timer->nsec);
oldSec = timer->sec - oldSec;
oldNsec = timer->nsec - oldNsec;
return (oldSec * 1000) + (oldNsec / 1000000);
}
int64_t BH_TimerMilliseconds(BH_Timer *timer)
{
int64_t newSec, newNsec;
getTimer(timer->type, &timer->frequency, &newSec, &newNsec);
newSec -= timer->sec;
newNsec -= timer->nsec;
return (newSec * 1000) + (newNsec / 1000000);
}
int64_t BH_TimerNanoseconds(BH_Timer *timer)
{
int64_t newSec, newNsec;
getTimer(timer->type, &timer->frequency, &newSec, &newNsec);
newSec -= timer->sec;
newNsec -= timer->nsec;
return (newSec * 1000000000) + newNsec;
}