libcdsb/tests/src/time.c
2022-06-03 11:54:22 +03:00

123 lines
2.6 KiB
C

/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include <stdlib.h>
#include <string.h>
#ifndef __USE_MISC
#define __USE_MISC
#endif
#include <unistd.h>
#include <sys/resource.h>
#include <sys/times.h>
#include "../include/time.h"
typedef struct timer_internal {
struct rusage begin;
struct rusage end;
struct rusage br;
unsigned long offset;
struct {
int isbr:1;
int isend:1;
};
} TIMER_INFO;
void timer_init(TIMER* timer) {
TIMER_INFO *t;
if (!(t = timer->info = malloc(sizeof(TIMER_INFO))))
abort();
memset(t, 0, sizeof(*t));
}
void timer_start(TIMER* timer) {
TIMER_INFO *t = timer->info;
if (t->isend)
return;
if (t->isbr) {
struct rusage br;
if (getrusage(RUSAGE_SELF, &br) < 0)
abort();
t->offset += br.ru_utime.tv_sec * 1000000 - t->br.ru_utime.tv_sec * 1000000;
t->offset -= t->br.ru_utime.tv_usec;
t->offset += br.ru_utime.tv_usec;
memset(&t->br, 0, sizeof(t->br));
t->isbr = 0;
} else if (getrusage(RUSAGE_SELF, &t->begin) < 0)
abort();
}
void timer_pause (TIMER* timer) {
TIMER_INFO *t = timer->info;
if (t->isend)
return;
if (!t->isbr) {
if (getrusage(RUSAGE_SELF, &t->br) < 0)
abort();
t->isbr = 1;
}
}
void timer_stop (TIMER* timer) {
TIMER_INFO *t = timer->info;
if (t->isend)
return;
if (getrusage(RUSAGE_SELF, &t->end) < 0)
abort();
if (t->isbr) {
t->offset += t->end.ru_utime.tv_sec * 1000000 - t->br.ru_utime.tv_sec * 1000000;
t->offset -= t->br.ru_utime.tv_usec;
t->offset += t->end.ru_utime.tv_usec;
memset(&t->br, 0, sizeof(t->br));
t->isbr = 0;
}
t->isend = 1;
}
void timer_free (TIMER* timer) {
free(timer->info);
}
vtype_ldouble timer_value(TIMER* timer) {
static char empty[sizeof(struct rusage)] = { 0 };
TIMER_INFO *t = timer->info;
struct rusage _;
struct rusage *end;
vtype_ldouble value;
if (memcmp(&t->begin, empty, sizeof(struct rusage)) == 0) {
return 0;
}
if (!t->isend) {
if (getrusage(RUSAGE_SELF, end = &_) < 0)
abort();
} else end = &t->end;
value = end->ru_utime.tv_sec * 1000000 - t->begin.ru_utime.tv_sec * 1000000;
value -= t->begin.ru_utime.tv_usec;
value += end->ru_utime.tv_usec;
value -= t->offset;
return value / 1000000;
}
void psleep(unsigned long microsec) {
usleep(microsec);
}