-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathcompat.c
143 lines (118 loc) · 3.44 KB
/
compat.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
133
134
135
136
137
138
139
140
141
142
143
#include "compat.h"
#include <string.h>
#include <assert.h>
#if VMPROF_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#else
#include <time.h>
#include <sys/time.h>
#endif
static int _vmp_profile_fileno = -1;
int vmp_profile_fileno(void) {
return _vmp_profile_fileno;
}
void vmp_set_profile_fileno(int fileno) {
_vmp_profile_fileno = fileno;
}
#ifndef VMPROF_WINDOWS
int vmp_write_all(const char *buf, size_t bufsize)
{
ssize_t count;
if (_vmp_profile_fileno == -1) {
return -1;
}
while (bufsize > 0) {
count = write(_vmp_profile_fileno, buf, bufsize);
if (count <= 0)
return -1; /* failed */
buf += count;
bufsize -= count;
}
return 0;
}
#endif
int vmp_write_meta(const char * key, const char * value)
{
char marker = MARKER_META;
long x = (long)strlen(key);
vmp_write_all(&marker, 1);
vmp_write_all((char*)&x, sizeof(long));
vmp_write_all(key, x);
x = (long)strlen(value);
vmp_write_all((char*)&x, sizeof(long));
vmp_write_all(value, x);
return 0;
}
/**
* Write the time and zone now.
*/
struct timezone_buf {
int64_t tv_sec;
int64_t tv_usec;
};
#define __SIZE (1+sizeof(struct timezone_buf)+8)
#ifdef VMPROF_UNIX
int vmp_write_time_now(int marker) {
char buffer[__SIZE];
struct timezone_buf buf;
(void)memset(&buffer, 0, __SIZE);
assert((marker == MARKER_TRAILER || marker == MARKER_TIME_N_ZONE) && \
"marker must be either a trailer or time_n_zone!");
struct timeval tv;
time_t now;
struct tm tm;
/* copy over to the struct */
if (gettimeofday(&tv, NULL) != 0) {
return -1;
}
if (time(&now) == (time_t)-1) {
return -1;
}
if (localtime_r(&now, &tm) == NULL) {
return -1;
}
buf.tv_sec = tv.tv_sec;
buf.tv_usec = tv.tv_usec;
// IF we really support time zones:
// use a cross platform datetime library that outputs iso8601 strings
// strncpy(((char*)buffer)+__SIZE-8, tm.tm_zone, 8);
buffer[0] = marker;
(void)memcpy(buffer+1, &buf, sizeof(struct timezone_buf));
vmp_write_all(buffer, __SIZE);
return 0;
}
#endif
#ifdef VMPROF_WINDOWS
int vmp_write_time_now(int marker) {
char buffer[__SIZE];
struct timezone_buf buf;
/**
* http://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
*/
// Note: some broken versions only have 8 trailing zero's, the correct
// epoch has 9 trailing zero's
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
(void)memset(&buffer, 0, __SIZE);
assert((marker == MARKER_TRAILER || marker == MARKER_TIME_N_ZONE) && \
"marker must be either a trailer or time_n_zone!");
GetSystemTime( &system_time );
SystemTimeToFileTime( &system_time, &file_time );
time = ((uint64_t)file_time.dwLowDateTime ) ;
time += ((uint64_t)file_time.dwHighDateTime) << 32;
buf.tv_sec = ((time - EPOCH) / 10000000L);
buf.tv_usec = (system_time.wMilliseconds * 1000);
// time zone not implemented on windows
// IF we really support time zones:
// use a cross platform datetime library that outputs iso8601 strings
memset(((char*)buffer)+__SIZE-8, 0, 8);
buffer[0] = marker;
(void)memcpy(buffer+1, &buf, sizeof(struct timezone_buf));
vmp_write_all(buffer, __SIZE);
return 0;
}
#endif
#undef __SIZE