k8clock moved to separate dir
[k8muffin.git] / src / libk8clock / k8clock.c
blobc8eda1c24fcea8a2a5e123a2e80205ff015ba949
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
9 */
10 #include <ctype.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
15 #include "k8clock.h"
18 k8clock_type k8clock_initialized = K8CLOCK_ERROR;
19 k8clock_t clk;
22 #ifndef CLOCK_MONOTONIC_RAW
23 # define K8CLOCK_CLOCK_TYPE CLOCK_MONOTONIC_RAW
24 #else
25 # define K8CLOCK_CLOCK_TYPE CLOCK_MONOTONIC
26 #endif
29 static k8clock_type k8clock_check_source (void) {
30 FILE *fl = fopen("/sys/devices/system/clocksource/clocksource0/current_clocksource", "r");
31 char buf[128];
32 if (fl == NULL) {
33 fprintf(stderr, "WARNING: can't determine clock source!\n");
34 return K8CLOCK_OTHER;
36 memset(buf, 0, sizeof(buf));
37 if (fgets(buf, sizeof(buf)-1, fl) == NULL) {
38 fclose(fl);
39 fprintf(stderr, "WARNING: can't determine clock source!\n");
40 return K8CLOCK_OTHER;
42 fclose(fl);
43 while (buf[0] && isspace(buf[strlen(buf)-1])) buf[strlen(buf)-1] = 0;
44 //fprintf(stderr, "clock source: %s\n", buf);
45 return (strcasecmp(buf, "hpet") == 0 ? K8CLOCK_HPET : K8CLOCK_OTHER);
49 __attribute__((constructor)) static void k8clock_ctor (void) {
50 if (k8clock_initialized == K8CLOCK_ERROR) {
51 struct timespec cres;
52 k8clock_initialized = k8clock_check_source();
53 if (clock_getres(K8CLOCK_CLOCK_TYPE, &cres) != 0) {
54 fprintf(stderr, "ERROR: can't get clock resolution!\n");
55 k8clock_initialized = K8CLOCK_ERROR;
56 return;
58 //fprintf(stderr, "CLOCK_MONOTONIC: %ld:%ld\n", cres.tv_sec, cres.tv_nsec);
59 if (cres.tv_sec > 0 || cres.tv_nsec > (long)1000000*10 /*10 ms*/) {
60 fprintf(stderr, "ERROR: real-time clock resolution is too low!\n");
61 k8clock_initialized = K8CLOCK_ERROR;
62 return;
64 k8clock_init(&clk);
69 void k8clock_init (k8clock_t *clk) {
70 if (clk != NULL && k8clock_initialized != K8CLOCK_ERROR) {
71 if (clock_gettime(K8CLOCK_CLOCK_TYPE, &clk->stt) != 0) {
72 fprintf(stderr, "ERROR: can't get real-time clock value!\n");
78 uint64_t k8clock_ms (k8clock_t *clk) {
79 if (clk != NULL && k8clock_initialized != K8CLOCK_ERROR) {
80 struct timespec ts;
81 if (clock_gettime(K8CLOCK_CLOCK_TYPE, &ts) != 0) {
82 fprintf(stderr, "ERROR: can't get real-time clock value!\n");
83 return 0;
85 // ah, ignore nanoseconds in clk->stt here: we need only 'differential' time, and it can start with something weird
86 return ((int64_t)(ts.tv_sec-clk->stt.tv_sec))*1000+(ts.tv_nsec-clk->stt.tv_nsec)/1000000+1;
88 return 0;
92 uint64_t k8clock_micro (k8clock_t *clk) {
93 if (clk != NULL && k8clock_initialized != K8CLOCK_ERROR) {
94 struct timespec ts;
95 if (clock_gettime(K8CLOCK_CLOCK_TYPE, &ts) != 0) {
96 fprintf(stderr, "ERROR: can't get real-time clock value!\n");
97 return 0;
99 // ah, ignore nanoseconds in clk->stt here: we need only 'differential' time, and it can start with something weird
100 return ((int64_t)(ts.tv_sec-clk->stt.tv_sec))*1000000+(ts.tv_nsec-clk->stt.tv_nsec)/1000+1;
102 return 0;
106 uint64_t k8clock (void) {
107 return k8clock_ms(&clk);
111 uint64_t k8clockmicro (void) {
112 return k8clock_micro(&clk);