aboutsummaryrefslogtreecommitdiffstats
path: root/src/clocks.c
blob: 43838ebf5fb447e68d1c50f8583054c5641f9c42 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdio.h>

#include <sys/time.h>
#include <errno.h>
#include <time.h>

#include "litmus.h"

/* CPU time consumed so far in seconds */
double cputime(void)
{
	struct timespec ts;
	int err;
	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
	if (err != 0)
		perror("clock_gettime");
	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
}

/* wall-clock time in seconds */
double wctime(void)
{
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return (tv.tv_sec + 1E-6 * tv.tv_usec);
}

/* current time, according to CLOCK_MONOTONIC */
double monotime(void)
{
	struct timespec ts;
	int err;
	err = clock_gettime(CLOCK_MONOTONIC, &ts);
	if (err != 0)
		perror("clock_gettime");
	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
}

static void do_sleep_until(struct timespec *ts, clockid_t clock_id)
{
	int err;

	do {
		/* sleep to exact absolute release time */
		err = clock_nanosleep(clock_id, TIMER_ABSTIME, ts, NULL);
		/* If we were interrupted by a signal and we didn't terminate,
		 * then keep sleeping. */
	} while (err != 0 && errno == EINTR);
}

/* Sleep until we've reached wake_up_time (in seconds) on the given timeline */
static void clock_sleep_until(double wake_up_time, clockid_t clock_id)
{
	struct timespec ts;

	/* convert from double (seconds) */
	ts.tv_sec = (time_t) wake_up_time;
	ts.tv_nsec = (wake_up_time - ts.tv_sec) * 1E9;
	
	do_sleep_until(&ts, clock_id);
}

/* Sleep until we've reached wake_up_time (in seconds) on the CLOCK_MONOTONIC 
 * timeline. */
void sleep_until_mono(double wake_up_time)
{
	clock_sleep_until(wake_up_time, CLOCK_MONOTONIC);
}

/* Sleep until we've reached wake_up_time (in seconds) on the CLOCK_MONOTONIC 
 * timeline. */
void sleep_until_wc(double wake_up_time)
{
	clock_sleep_until(wake_up_time, CLOCK_REALTIME);
}

/* Sleep until we've reached wake_up_time (in nanoseconds) on the
 * CLOCK_MONOTONIC  timeline. */
void lt_sleep_until(lt_t wake_up_time)
{
	struct timespec ts;

	/* convert from double (seconds) */
	ts.tv_sec = (time_t) ns2s(wake_up_time);
	ts.tv_nsec = (long) (wake_up_time - s2ns(ts.tv_sec));
	
	do_sleep_until(&ts, CLOCK_MONOTONIC);
}

int lt_sleep(lt_t timeout)
{
	struct timespec delay;

	delay.tv_sec  = timeout / 1000000000L;
	delay.tv_nsec = timeout % 1000000000L;
	return nanosleep(&delay, NULL);
}