123 lines
2.6 KiB
C
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);
|
|
}
|