-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibVT.c
132 lines (101 loc) · 3.7 KB
/
libVT.c
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <poll.h>
#define SECONDS_TO_NS 1000000000
#define US_TO_NS 1000
static unsigned int tdf = 20;
inline unsigned long long timespec_to_ns(const struct timespec *tp) {
return tp->tv_sec * SECONDS_TO_NS + tp->tv_nsec;
}
inline unsigned long long timeval_to_ns(const struct timeval *tv) {
return tv->tv_sec * SECONDS_TO_NS + tv->tv_usec * US_TO_NS;
}
inline void ns_to_timespec(unsigned long long ns, struct timespec *tp) {
tp->tv_sec = ns / SECONDS_TO_NS;
tp->tv_nsec = ns % SECONDS_TO_NS;
}
inline void ns_to_timeval(unsigned long long ns, struct timeval *tv) {
tv->tv_sec = ns / SECONDS_TO_NS;
tv->tv_usec = (ns % SECONDS_TO_NS) / US_TO_NS;
}
// Find the library version of the function that we are wrapping
static void get_next_fn(void** next_fn, char* fn) {
char* msg;
if(!*next_fn){
*next_fn = dlsym(RTLD_NEXT, fn);
if ((msg = dlerror()) != NULL) {
fprintf(stderr, "dlopen failed on %s: %s\n", fn, msg);
exit(1);
}
}
}
// Wrapped clock_gettime()
// Assumes the app only uses one clk_id... should eventually redo to handle multiple.
int clock_gettime(clockid_t clk_id, struct timespec *tp) {
static int (*next_clock_gettime)(clockid_t, struct timespec*) = NULL;
get_next_fn((void**)&next_clock_gettime, "clock_gettime");
int rc = next_clock_gettime(clk_id, tp);
unsigned long long now = timespec_to_ns(tp);
ns_to_timespec(now / tdf, tp);
return rc;
}
// Wrapped gettimeofday()
int gettimeofday(struct timeval *tv, struct timezone *tz) {
static int (*next_gettimeofday)(struct timeval*, struct timezone*) = NULL;
get_next_fn((void**)&next_gettimeofday, "gettimeofday");
int rc = next_gettimeofday(tv, tz);
unsigned long long now = timeval_to_ns(tv);
ns_to_timeval(now / tdf, tv);
return rc;
}
// Wrapped sleep()
unsigned int sleep(unsigned int seconds) {
static unsigned int (*next_sleep)(unsigned int);
get_next_fn((void**)&next_sleep, "sleep");
return next_sleep(seconds * tdf);
}
// Wrapped usleep()
int usleep(useconds_t usec) {
static unsigned int (*next_usleep)(unsigned int);
get_next_fn((void**)&next_usleep, "usleep");
return next_usleep(usec * tdf);
}
// Wrapped alarm()
unsigned int alarm(unsigned int seconds) {
static unsigned int (*next_alarm)(unsigned int);
get_next_fn((void**)&next_alarm, "alarm");
return next_alarm(seconds * tdf);
}
// Wrapped select()
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) {
static int (*next_select)(int, fd_set*, fd_set*, fd_set*, struct timeval *) = NULL;
get_next_fn((void**)&next_select, "select");
if (timeout) {
unsigned long long t = timeval_to_ns(timeout);
ns_to_timeval(t * tdf, timeout);
}
return next_select(nfds, readfds, writefds, exceptfds, timeout);
}
// Wrapped poll()
int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
static int (*next_poll)(struct pollfd*, nfds_t, int);
get_next_fn((void**)&next_poll, "poll");
return next_poll(fds, nfds, timeout * tdf);
}
// Wrapped setitimer()
int setitimer(__itimer_which_t which, const struct itimerval *new_value,
struct itimerval *old_value) {
static int (*next_setitimer)(__itimer_which_t, const struct itimerval*,
struct itimerval*) = NULL;
get_next_fn((void**)&next_setitimer, "setitimer");
unsigned long long next_val = timeval_to_ns(&new_value->it_interval);
unsigned long long curr_val = timeval_to_ns(&new_value->it_value);
struct itimerval nv;
ns_to_timeval(next_val * tdf, &nv.it_interval);
ns_to_timeval(curr_val * tdf, &nv.it_value);
return next_setitimer(which, &nv, old_value);
}