aboutsummaryrefslogtreecommitdiff
path: root/src/Platform/Posix/Timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Platform/Posix/Timer.c')
-rw-r--r--src/Platform/Posix/Timer.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/Platform/Posix/Timer.c b/src/Platform/Posix/Timer.c
new file mode 100644
index 0000000..0b68036
--- /dev/null
+++ b/src/Platform/Posix/Timer.c
@@ -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;
+}