| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* This software is copyright (c) 2010 by Leon Timmermans . |
|
3
|
|
|
|
|
|
|
* |
|
4
|
|
|
|
|
|
|
* This is free software; you can redistribute it and/or modify it under |
|
5
|
|
|
|
|
|
|
* the same terms as perl itself. |
|
6
|
|
|
|
|
|
|
* |
|
7
|
|
|
|
|
|
|
*/ |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT |
|
10
|
|
|
|
|
|
|
#define PERL_REENTR_API 1 |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#include "EXTERN.h" |
|
13
|
|
|
|
|
|
|
#include "perl.h" |
|
14
|
|
|
|
|
|
|
#include "XSUB.h" |
|
15
|
|
|
|
|
|
|
#define NEED_mg_findext |
|
16
|
|
|
|
|
|
|
#include "ppport.h" |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
#include |
|
19
|
|
|
|
|
|
|
#include |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
#define die_sys(format) Perl_croak(aTHX_ format, strerror(errno)) |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
typedef struct { const char* key; STRLEN key_length; clockid_t value; } map[]; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
static map clocks = { |
|
26
|
|
|
|
|
|
|
{ STR_WITH_LEN("realtime") , CLOCK_REALTIME } |
|
27
|
|
|
|
|
|
|
#ifdef CLOCK_MONOTONIC |
|
28
|
|
|
|
|
|
|
, { STR_WITH_LEN("monotonic"), CLOCK_MONOTONIC } |
|
29
|
|
|
|
|
|
|
#endif |
|
30
|
|
|
|
|
|
|
#ifdef CLOCK_PROCESS_CPUTIME_ID |
|
31
|
|
|
|
|
|
|
, { STR_WITH_LEN("process"), CLOCK_PROCESS_CPUTIME_ID } |
|
32
|
|
|
|
|
|
|
#endif |
|
33
|
|
|
|
|
|
|
#ifdef CLOCK_THREAD_CPUTIME_ID |
|
34
|
|
|
|
|
|
|
, { STR_WITH_LEN("thread"), CLOCK_THREAD_CPUTIME_ID } |
|
35
|
|
|
|
|
|
|
#endif |
|
36
|
|
|
|
|
|
|
#ifdef CLOCK_BOOTTIME |
|
37
|
|
|
|
|
|
|
, { STR_WITH_LEN("boottime"), CLOCK_BOOTTIME } |
|
38
|
|
|
|
|
|
|
#endif |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
#ifdef CLOCK_REALTIME_COARSE |
|
41
|
|
|
|
|
|
|
, { STR_WITH_LEN("realtime_coarse"), CLOCK_REALTIME_COARSE } |
|
42
|
|
|
|
|
|
|
#endif |
|
43
|
|
|
|
|
|
|
#ifdef CLOCK_REALTIME_ALARM |
|
44
|
|
|
|
|
|
|
, { STR_WITH_LEN("realtime_alarm"), CLOCK_REALTIME_ALARM } |
|
45
|
|
|
|
|
|
|
#endif |
|
46
|
|
|
|
|
|
|
#ifdef CLOCK_REALTIME_PRECISE |
|
47
|
|
|
|
|
|
|
, { STR_WITH_LEN("realtime_precise"), CLOCK_REALTIME_PRECISE } |
|
48
|
|
|
|
|
|
|
#endif |
|
49
|
|
|
|
|
|
|
#if defined CLOCK_HIGHRES |
|
50
|
|
|
|
|
|
|
, { STR_WITH_LEN("highres"), CLOCK_HIGHRES } |
|
51
|
|
|
|
|
|
|
#endif |
|
52
|
|
|
|
|
|
|
#ifdef CLOCK_MONOTONIC_RAW |
|
53
|
|
|
|
|
|
|
, { STR_WITH_LEN("monotonic_raw"), CLOCK_MONOTONIC_RAW } |
|
54
|
|
|
|
|
|
|
#endif |
|
55
|
|
|
|
|
|
|
#ifdef CLOCK_MONOTONIC_COARSE |
|
56
|
|
|
|
|
|
|
, { STR_WITH_LEN("monotonic_coarse"), CLOCK_MONOTONIC_COARSE } |
|
57
|
|
|
|
|
|
|
#endif |
|
58
|
|
|
|
|
|
|
#ifdef CLOCK_MONOTONIC_PRECISE |
|
59
|
|
|
|
|
|
|
, { STR_WITH_LEN("monotonic_precise"), CLOCK_MONOTONIC_PRECISE } |
|
60
|
|
|
|
|
|
|
#endif |
|
61
|
|
|
|
|
|
|
#if defined CLOCK_PROF |
|
62
|
|
|
|
|
|
|
, { STR_WITH_LEN("prof"), CLOCK_PROF } |
|
63
|
|
|
|
|
|
|
#endif |
|
64
|
|
|
|
|
|
|
#ifdef CLOCK_UPTIME |
|
65
|
|
|
|
|
|
|
, { STR_WITH_LEN("uptime"), CLOCK_UPTIME } |
|
66
|
|
|
|
|
|
|
#endif |
|
67
|
|
|
|
|
|
|
#ifdef CLOCK_UPTIME_PRECISE |
|
68
|
|
|
|
|
|
|
, { STR_WITH_LEN("uptime_precise"), CLOCK_UPTIME_PRECISE } |
|
69
|
|
|
|
|
|
|
#endif |
|
70
|
|
|
|
|
|
|
#ifdef CLOCK_UPTIME_FAST |
|
71
|
|
|
|
|
|
|
, { STR_WITH_LEN("uptime_fast"), CLOCK_UPTIME_FAST } |
|
72
|
|
|
|
|
|
|
#endif |
|
73
|
|
|
|
|
|
|
#ifdef CLOCK_BOOTTIME_ALARM |
|
74
|
|
|
|
|
|
|
, { STR_WITH_LEN("boottime_alarm"), CLOCK_BOOTTIME_ALARM } |
|
75
|
|
|
|
|
|
|
#endif |
|
76
|
|
|
|
|
|
|
#ifdef CLOCK_VIRTUAL |
|
77
|
|
|
|
|
|
|
, { STR_WITH_LEN("virtual"), CLOCK_VIRTUAL } |
|
78
|
|
|
|
|
|
|
#endif |
|
79
|
|
|
|
|
|
|
#ifdef CLOCK_TAI |
|
80
|
|
|
|
|
|
|
, { STR_WITH_LEN("tai"), CLOCK_TAI } |
|
81
|
|
|
|
|
|
|
#endif |
|
82
|
|
|
|
|
|
|
}; |
|
83
|
|
|
|
|
|
|
|
|
84
|
4
|
|
|
|
|
|
static clockid_t S_get_clockid(pTHX_ SV* clock_name) { |
|
85
|
|
|
|
|
|
|
int i; |
|
86
|
|
|
|
|
|
|
STRLEN length; |
|
87
|
4
|
|
|
|
|
|
const char* clock_ptr = SvPV(clock_name, length); |
|
88
|
5
|
50
|
|
|
|
|
for (i = 0; i < sizeof clocks / sizeof *clocks; ++i) { |
|
89
|
5
|
100
|
|
|
|
|
if (clocks[i].key_length == length && strEQ(clock_ptr, clocks[i].key)) |
|
|
|
50
|
|
|
|
|
|
|
90
|
4
|
|
|
|
|
|
return clocks[i].value; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "No such timer '%s' known", SvPV_nolen(clock_name)); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
#define get_clockid(name) S_get_clockid(aTHX_ name) |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
#define NANO_SECONDS 1000000000 |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
static NV timespec_to_nv(struct timespec* time) { |
|
99
|
1
|
|
|
|
|
|
return time->tv_sec + time->tv_nsec / (double)NANO_SECONDS; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
|
|
102
|
5
|
|
|
|
|
|
static void nv_to_timespec(NV input, struct timespec* output) { |
|
103
|
5
|
|
|
|
|
|
output->tv_sec = (time_t) floor(input); |
|
104
|
5
|
|
|
|
|
|
output->tv_nsec = (long) ((input - output->tv_sec) * NANO_SECONDS); |
|
105
|
5
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
#if defined(SIGEV_THREAD_ID) && defined(SYS_gettid) |
|
108
|
|
|
|
|
|
|
#include |
|
109
|
|
|
|
|
|
|
#define gettid() syscall(SYS_gettid) |
|
110
|
|
|
|
|
|
|
#ifndef sigev_notify_thread_id |
|
111
|
|
|
|
|
|
|
#define sigev_notify_thread_id _sigev_un._tid |
|
112
|
|
|
|
|
|
|
#endif |
|
113
|
|
|
|
|
|
|
#endif |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
#if defined(_POSIX_CLOCK_SELECTION) && _POSIX_CLOCK_SELECTION >= 0 |
|
116
|
5
|
|
|
|
|
|
static int my_clock_nanosleep(pTHX_ clockid_t clockid, int flags, const struct timespec* request, struct timespec* remain) { |
|
117
|
|
|
|
|
|
|
int ret; |
|
118
|
5
|
|
|
|
|
|
ret = clock_nanosleep(clockid, flags, request, remain); |
|
119
|
5
|
100
|
|
|
|
|
if (ret != 0) { |
|
120
|
2
|
|
|
|
|
|
errno = ret; |
|
121
|
2
|
50
|
|
|
|
|
if (ret != EINTR) |
|
122
|
0
|
|
|
|
|
|
die_sys("Could not sleep: %s"); |
|
123
|
|
|
|
|
|
|
} |
|
124
|
5
|
|
|
|
|
|
return ret; |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
#endif |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#define clock_nanosleep(clockid, flags, request, remain) my_clock_nanosleep(aTHX_ clockid, flags, request, remain) |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
#if defined(USE_ITHREADS) && defined(_POSIX_THREAD_CPUTIME) && _POSIX_THREAD_CPUTIME >= 0 |
|
131
|
|
|
|
|
|
|
static pthread_t* S_get_pthread(pTHX_ SV* thread_handle) { |
|
132
|
|
|
|
|
|
|
SV* tmp; |
|
133
|
|
|
|
|
|
|
pthread_t* ret; |
|
134
|
|
|
|
|
|
|
dSP; |
|
135
|
|
|
|
|
|
|
ENTER; |
|
136
|
|
|
|
|
|
|
SAVETMPS; |
|
137
|
|
|
|
|
|
|
PUSHMARK(SP); |
|
138
|
|
|
|
|
|
|
PUSHs(thread_handle); |
|
139
|
|
|
|
|
|
|
PUTBACK; |
|
140
|
|
|
|
|
|
|
call_method("_handle", G_SCALAR); |
|
141
|
|
|
|
|
|
|
SPAGAIN; |
|
142
|
|
|
|
|
|
|
tmp = POPs; |
|
143
|
|
|
|
|
|
|
ret = INT2PTR(pthread_t* ,SvUV(tmp)); |
|
144
|
|
|
|
|
|
|
FREETMPS; |
|
145
|
|
|
|
|
|
|
LEAVE; |
|
146
|
|
|
|
|
|
|
return ret; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
#define get_pthread(handle) S_get_pthread(aTHX_ handle) |
|
149
|
|
|
|
|
|
|
#endif |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
#define undef &PL_sv_undef |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
typedef struct _timer_init { |
|
154
|
|
|
|
|
|
|
clockid_t clockid; |
|
155
|
|
|
|
|
|
|
IV signo; |
|
156
|
|
|
|
|
|
|
IV ident; |
|
157
|
|
|
|
|
|
|
struct itimerspec itimer; |
|
158
|
|
|
|
|
|
|
int flags; |
|
159
|
|
|
|
|
|
|
} timer_init; |
|
160
|
|
|
|
|
|
|
|
|
161
|
4
|
|
|
|
|
|
static void S_timer_init_gather(pTHX_ timer_init* result, SV** begin, size_t items) { |
|
162
|
|
|
|
|
|
|
int i; |
|
163
|
|
|
|
|
|
|
Zero(result, 1, timer_init); |
|
164
|
|
|
|
|
|
|
result->clockid = CLOCK_REALTIME; |
|
165
|
15
|
100
|
|
|
|
|
for(i = 0; i < items; i += 2) { |
|
166
|
|
|
|
|
|
|
const char* current; |
|
167
|
|
|
|
|
|
|
STRLEN curlen; |
|
168
|
11
|
|
|
|
|
|
SV *key = begin[i], *value = begin[i+1]; |
|
169
|
11
|
|
|
|
|
|
current = SvPV(key, curlen); |
|
170
|
11
|
100
|
|
|
|
|
if (curlen == 5) { |
|
171
|
6
|
100
|
|
|
|
|
if (strEQ(current, "clock")) |
|
172
|
1
|
50
|
|
|
|
|
result->clockid = SvROK(value) ? SvUV(SvRV(value)) : get_clockid(value); |
|
173
|
5
|
100
|
|
|
|
|
else if (strEQ(current, "value")) |
|
174
|
4
|
|
|
|
|
|
nv_to_timespec(SvNV(value), &result->itimer.it_value); |
|
175
|
1
|
50
|
|
|
|
|
else if (strEQ(current, "ident")) |
|
176
|
1
|
|
|
|
|
|
result->ident = SvIV(value); |
|
177
|
|
|
|
|
|
|
else |
|
178
|
0
|
|
|
|
|
|
goto fail; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
5
|
100
|
|
|
|
|
else if (curlen == 6 && strEQ(current, "signal")) |
|
|
|
50
|
|
|
|
|
|
|
181
|
4
|
50
|
|
|
|
|
result->signo = (SvIOK(value) || looks_like_number(value)) ? SvIV(value) : whichsig(SvPV_nolen(value)); |
|
|
|
0
|
|
|
|
|
|
|
182
|
1
|
50
|
|
|
|
|
else if (curlen == 8) { |
|
183
|
1
|
50
|
|
|
|
|
if (strEQ(current, "interval")) |
|
184
|
1
|
|
|
|
|
|
nv_to_timespec(SvNV(value), &result->itimer.it_interval); |
|
185
|
0
|
0
|
|
|
|
|
else if (strEQ(current, "absolute")) |
|
186
|
0
|
|
|
|
|
|
result->flags |= TIMER_ABSTIME; |
|
187
|
|
|
|
|
|
|
else |
|
188
|
0
|
|
|
|
|
|
goto fail; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
else |
|
191
|
0
|
|
|
|
|
|
fail: Perl_croak(aTHX_ "Unknown option '%s'", current); |
|
192
|
|
|
|
|
|
|
} |
|
193
|
4
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
#define timer_init_gather(init, begin, items) S_timer_init_gather(aTHX_ init, begin, items) |
|
195
|
|
|
|
|
|
|
|
|
196
|
4
|
|
|
|
|
|
static timer_t S_timer_new(pTHX_ timer_init* para) { |
|
197
|
|
|
|
|
|
|
timer_t timer; |
|
198
|
4
|
|
|
|
|
|
struct sigevent event = { 0 }; |
|
199
|
|
|
|
|
|
|
|
|
200
|
4
|
50
|
|
|
|
|
if (para->signo < 0) |
|
201
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "No valid signal was given"); |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
#ifdef gettid |
|
204
|
|
|
|
|
|
|
event.sigev_notify = SIGEV_THREAD_ID; |
|
205
|
|
|
|
|
|
|
event.sigev_notify_thread_id = gettid(); |
|
206
|
|
|
|
|
|
|
#else |
|
207
|
|
|
|
|
|
|
event.sigev_notify = SIGEV_SIGNAL; |
|
208
|
|
|
|
|
|
|
#endif |
|
209
|
4
|
|
|
|
|
|
event.sigev_signo = para->signo; |
|
210
|
4
|
|
|
|
|
|
event.sigev_value.sival_int = para->ident; |
|
211
|
|
|
|
|
|
|
|
|
212
|
4
|
50
|
|
|
|
|
if (timer_create(para->clockid, &event, &timer) < 0) |
|
213
|
0
|
|
|
|
|
|
die_sys("Couldn't create timer: %s"); |
|
214
|
4
|
50
|
|
|
|
|
if (timer_settime(timer, para->flags, ¶->itimer, NULL) < 0) |
|
215
|
0
|
|
|
|
|
|
die_sys("Couldn't set_time: %s"); |
|
216
|
|
|
|
|
|
|
|
|
217
|
4
|
|
|
|
|
|
return timer; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
#define timer_new(para) S_timer_new(aTHX_ para) |
|
220
|
|
|
|
|
|
|
|
|
221
|
1
|
|
|
|
|
|
void timespec_add(struct timespec* left, const struct timespec* right) { |
|
222
|
1
|
|
|
|
|
|
left->tv_sec += right->tv_sec; |
|
223
|
1
|
|
|
|
|
|
left->tv_nsec += right->tv_nsec; |
|
224
|
2
|
100
|
|
|
|
|
while (left->tv_nsec > 1000000000) { |
|
225
|
1
|
|
|
|
|
|
left->tv_nsec -= 1000000000; |
|
226
|
1
|
|
|
|
|
|
left->tv_sec++; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
1
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
static const struct timespec no_time = { 0, 0 }; |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
typedef timer_t POSIX__RT__Timer; |
|
233
|
|
|
|
|
|
|
typedef clockid_t POSIX__RT__Clock; |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
#define XS_unpack_clockid_t(sv) get_clockid(sv) |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
MODULE = POSIX::RT::Timer PACKAGE = POSIX::RT::Timer |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
PROTOTYPES: DISABLED |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
POSIX::RT::Timer new(SV* class, timer_init args, ...) |
|
242
|
|
|
|
|
|
|
CODE: |
|
243
|
3
|
|
|
|
|
|
RETVAL = timer_new(&args); |
|
244
|
|
|
|
|
|
|
OUTPUT: |
|
245
|
|
|
|
|
|
|
RETVAL |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
UV handle(POSIX::RT::Timer timer) |
|
248
|
|
|
|
|
|
|
CODE: |
|
249
|
|
|
|
|
|
|
RETVAL = (UV)timer; |
|
250
|
|
|
|
|
|
|
OUTPUT: |
|
251
|
|
|
|
|
|
|
RETVAL |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
void get_timeout(POSIX::RT::Timer timer) |
|
254
|
|
|
|
|
|
|
PREINIT: |
|
255
|
|
|
|
|
|
|
struct itimerspec value; |
|
256
|
|
|
|
|
|
|
PPCODE: |
|
257
|
0
|
0
|
|
|
|
|
if (timer_gettime(timer, &value) == -1) |
|
258
|
0
|
|
|
|
|
|
die_sys("Couldn't get_time: %s"); |
|
259
|
0
|
0
|
|
|
|
|
mXPUSHn(timespec_to_nv(&value.it_value)); |
|
260
|
0
|
0
|
|
|
|
|
if (GIMME_V == G_ARRAY) |
|
261
|
0
|
0
|
|
|
|
|
mXPUSHn(timespec_to_nv(&value.it_interval)); |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
void set_timeout(POSIX::RT::Timer timer, struct timespec new_value, struct timespec new_interval = no_time, bool abstime = FALSE) |
|
264
|
|
|
|
|
|
|
PREINIT: |
|
265
|
|
|
|
|
|
|
struct itimerspec old_itimer; |
|
266
|
|
|
|
|
|
|
PPCODE: |
|
267
|
1
|
|
|
|
|
|
struct itimerspec new_itimer = { new_value, new_interval }; |
|
268
|
1
|
50
|
|
|
|
|
if (timer_settime(timer, (abstime ? TIMER_ABSTIME : 0), &new_itimer, &old_itimer) == -1) |
|
269
|
0
|
|
|
|
|
|
die_sys("Couldn't set_time: %s"); |
|
270
|
1
|
50
|
|
|
|
|
mXPUSHn(timespec_to_nv(&old_itimer.it_value)); |
|
271
|
1
|
50
|
|
|
|
|
if (GIMME_V == G_ARRAY) |
|
272
|
0
|
0
|
|
|
|
|
mXPUSHn(timespec_to_nv(&old_itimer.it_interval)); |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
IV get_overrun(POSIX::RT::Timer timer) |
|
275
|
|
|
|
|
|
|
CODE: |
|
276
|
0
|
|
|
|
|
|
RETVAL = timer_getoverrun(timer); |
|
277
|
0
|
0
|
|
|
|
|
if (RETVAL == -1) |
|
278
|
0
|
|
|
|
|
|
die_sys("Couldn't get_overrun: %s"); |
|
279
|
|
|
|
|
|
|
OUTPUT: |
|
280
|
|
|
|
|
|
|
RETVAL |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
void DESTROY(POSIX::RT::Timer timer) |
|
283
|
|
|
|
|
|
|
CODE: |
|
284
|
4
|
|
|
|
|
|
timer_delete(timer); |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
MODULE = POSIX::RT::Timer PACKAGE = POSIX::RT::Clock |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
PROTOTYPES: DISABLED |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
POSIX::RT::Clock new(SV* class, clockid_t clockid = CLOCK_REALTIME) |
|
291
|
|
|
|
|
|
|
CODE: |
|
292
|
|
|
|
|
|
|
RETVAL = clockid; |
|
293
|
|
|
|
|
|
|
OUTPUT: |
|
294
|
|
|
|
|
|
|
RETVAL |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
UV handle(POSIX::RT::Clock clock) |
|
297
|
|
|
|
|
|
|
CODE: |
|
298
|
0
|
0
|
|
|
|
|
RETVAL = (UV)clock; |
|
299
|
|
|
|
|
|
|
OUTPUT: |
|
300
|
|
|
|
|
|
|
RETVAL |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
#if defined(_POSIX_CPUTIME) && _POSIX_CPUTIME >= 0 |
|
303
|
|
|
|
|
|
|
POSIX::RT::Clock get_cpuclock(SV* class, SV* pid = undef) |
|
304
|
|
|
|
|
|
|
CODE: |
|
305
|
1
|
50
|
|
|
|
|
if (SvOK(pid) && SvROK(pid) && sv_derived_from(pid, "threads")) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
#if defined(USE_ITHREADS) && defined(_POSIX_THREAD_CPUTIME) && _POSIX_THREAD_CPUTIME >= 0 |
|
307
|
|
|
|
|
|
|
pthread_t* handle = get_pthread(pid); |
|
308
|
|
|
|
|
|
|
if (pthread_getcpuclockid(*handle, &RETVAL) != 0) |
|
309
|
|
|
|
|
|
|
die_sys("Could not get cpuclock: %s"); |
|
310
|
|
|
|
|
|
|
#else |
|
311
|
0
|
|
|
|
|
|
Perl_croak(aTHX_ "Can't get CPU time for threads"); |
|
312
|
|
|
|
|
|
|
#endif |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
else { |
|
315
|
1
|
50
|
|
|
|
|
if (clock_getcpuclockid(SvOK(pid) ? SvIV(pid) : 0, &RETVAL) != 0) |
|
|
|
50
|
|
|
|
|
|
|
316
|
0
|
|
|
|
|
|
die_sys("Could not get cpuclock: %s"); |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
OUTPUT: |
|
319
|
|
|
|
|
|
|
RETVAL |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
#endif |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
void get_clocks(...) |
|
324
|
|
|
|
|
|
|
PREINIT: |
|
325
|
|
|
|
|
|
|
size_t i; |
|
326
|
|
|
|
|
|
|
const size_t max = sizeof clocks / sizeof *clocks; |
|
327
|
|
|
|
|
|
|
PPCODE: |
|
328
|
12
|
100
|
|
|
|
|
for (i = 0; i < max; ++i) |
|
329
|
11
|
50
|
|
|
|
|
mXPUSHp(clocks[i].key, clocks[i].key_length); |
|
330
|
1
|
|
|
|
|
|
PUTBACK; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
struct timespec get_time(POSIX::RT::Clock clockid) |
|
333
|
|
|
|
|
|
|
CODE: |
|
334
|
8
|
50
|
|
|
|
|
if (clock_gettime(clockid, &RETVAL) == -1) |
|
335
|
0
|
|
|
|
|
|
die_sys("Couldn't get time: %s"); |
|
336
|
|
|
|
|
|
|
OUTPUT: |
|
337
|
|
|
|
|
|
|
RETVAL |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
void set_time(POSIX::RT::Clock clockid, struct timespec time) |
|
340
|
|
|
|
|
|
|
CODE: |
|
341
|
0
|
0
|
|
|
|
|
if (clock_settime(clockid, &time) == -1) |
|
342
|
0
|
|
|
|
|
|
die_sys("Couldn't set time: %s"); |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
struct timespec get_resolution(POSIX::RT::Clock clockid) |
|
345
|
|
|
|
|
|
|
CODE: |
|
346
|
1
|
50
|
|
|
|
|
if (clock_getres(clockid, &RETVAL) == -1) |
|
347
|
0
|
|
|
|
|
|
die_sys("Couldn't get resolution: %s"); |
|
348
|
|
|
|
|
|
|
OUTPUT: |
|
349
|
|
|
|
|
|
|
RETVAL |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
POSIX::RT::Timer timer(POSIX::RT::Clock clockid, timer_init args, ...) |
|
352
|
|
|
|
|
|
|
CODE: |
|
353
|
1
|
|
|
|
|
|
args.clockid = clockid; |
|
354
|
1
|
|
|
|
|
|
RETVAL = timer_new(&args); |
|
355
|
|
|
|
|
|
|
OUTPUT: |
|
356
|
|
|
|
|
|
|
RETVAL |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
#if defined(_POSIX_CLOCK_SELECTION) && _POSIX_CLOCK_SELECTION >= 0 |
|
359
|
|
|
|
|
|
|
struct timespec sleep(POSIX::RT::Clock clockid, struct timespec time, bool abstime = FALSE) |
|
360
|
|
|
|
|
|
|
PREINIT: |
|
361
|
|
|
|
|
|
|
struct timespec remain_time; |
|
362
|
|
|
|
|
|
|
int flags; |
|
363
|
|
|
|
|
|
|
CODE: |
|
364
|
3
|
|
|
|
|
|
flags = abstime ? TIMER_ABSTIME : 0; |
|
365
|
|
|
|
|
|
|
|
|
366
|
3
|
100
|
|
|
|
|
if (clock_nanosleep(clockid, flags, &time, &remain_time) == EINTR) |
|
367
|
1
|
50
|
|
|
|
|
RETVAL = abstime ? time : remain_time; |
|
368
|
|
|
|
|
|
|
else |
|
369
|
|
|
|
|
|
|
RETVAL = no_time; |
|
370
|
|
|
|
|
|
|
OUTPUT: |
|
371
|
|
|
|
|
|
|
RETVAL |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
NV sleep_deeply(POSIX::RT::Clock clockid, struct timespec time, bool abstime = FALSE) |
|
374
|
|
|
|
|
|
|
PREINIT: |
|
375
|
|
|
|
|
|
|
CODE: |
|
376
|
0
|
0
|
|
|
|
|
if (!abstime) { |
|
377
|
|
|
|
|
|
|
struct timespec current_time; |
|
378
|
1
|
50
|
|
|
|
|
if (clock_gettime(clockid, ¤t_time) == -1) |
|
379
|
0
|
|
|
|
|
|
die_sys("Couldn't get time: %s"); |
|
380
|
1
|
|
|
|
|
|
timespec_add(&time, ¤t_time); |
|
381
|
|
|
|
|
|
|
} |
|
382
|
2
|
100
|
|
|
|
|
while (clock_nanosleep(clockid, TIMER_ABSTIME, &time, NULL) == EINTR); |
|
383
|
|
|
|
|
|
|
RETVAL = 0; |
|
384
|
|
|
|
|
|
|
OUTPUT: |
|
385
|
|
|
|
|
|
|
RETVAL |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
#endif |