File Coverage

Nanos.xs
Criterion Covered Total %
statement 25 27 92.5
branch 16 24 66.6
condition n/a
subroutine n/a
pod n/a
total 41 51 80.3


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include
5              
6             #ifdef HAS_CLOCK_GETTIME
7             #include
8             #include
9             #include
10             #endif
11              
12             #ifdef HAS_WINHR
13             #include
14             #endif
15              
16             #if defined(HAS_CLOCK_GETTIME) || defined(HAS_WINHR)
17             static void
18 13           get_hrtime(int use_realtime, uint64_t *sec_out, uint64_t *nsec_out)
19             {
20             #ifdef HAS_CLOCK_GETTIME
21             {
22             struct timespec ts;
23 13           clockid_t clock_id = use_realtime ? CLOCK_REALTIME : CLOCK_MONOTONIC;
24 13 50         if (clock_gettime(clock_id, &ts) != 0) {
25 0           croak("hrtime(): clock_gettime() failed: %s", strerror(errno));
26             }
27 13           *sec_out = (uint64_t)ts.tv_sec;
28 13           *nsec_out = (uint64_t)ts.tv_nsec;
29             }
30             #else
31             if (use_realtime) {
32             FILETIME ft;
33             ULARGE_INTEGER ul;
34             GetSystemTimePreciseAsFileTime(&ft);
35             ul.LowPart = ft.dwLowDateTime;
36             ul.HighPart = ft.dwHighDateTime;
37             ul.QuadPart -= 116444736000000000ULL;
38             *sec_out = ul.QuadPart / 10000000ULL;
39             *nsec_out = (ul.QuadPart % 10000000ULL) * 100ULL;
40             } else {
41             LARGE_INTEGER freq, counter;
42             int64_t remainder;
43             if (!QueryPerformanceFrequency(&freq)) {
44             croak("hrtime(): QueryPerformanceFrequency() failed");
45             }
46             if (!QueryPerformanceCounter(&counter)) {
47             croak("hrtime(): QueryPerformanceCounter() failed");
48             }
49             *sec_out = (uint64_t)(counter.QuadPart / freq.QuadPart);
50             remainder = counter.QuadPart % freq.QuadPart;
51             *nsec_out = (uint64_t)((remainder * 1000000000LL) / freq.QuadPart);
52             }
53             #endif
54 13           }
55             #endif
56              
57             MODULE = Time::Nanos PACKAGE = Time::Nanos
58              
59             PROTOTYPES: DISABLE
60              
61             void
62             hrtime(...)
63             PPCODE:
64             #if !defined(HAS_CLOCK_GETTIME) && !defined(HAS_WINHR)
65             croak("hrtime(): high-resolution clock is not available on this platform");
66             #else
67             {
68             uint64_t sec_part, nsec_part;
69 14           int want_list = 0;
70 14           int use_realtime = 0;
71              
72 14 100         if (items > 0 && SvTRUE(ST(0))) {
    50          
73 4           want_list = 1;
74             }
75              
76             {
77             STRLEN len;
78             const char *clock_name;
79 14           SV *sv = get_sv("Time::Nanos::CLOCK", GV_ADD);
80              
81 14 50         if (!sv || !SvOK(sv)) {
    50          
82             /* undef → default to monotonic */
83 0           use_realtime = 0;
84             } else {
85 14           clock_name = SvPV(sv, len);
86 14 100         if (len == 9 && strnEQ(clock_name, "monotonic", 9)) {
    50          
87 2           use_realtime = 0;
88 12 100         } else if (len == 8 && strnEQ(clock_name, "realtime", 8)) {
    50          
89 11           use_realtime = 1;
90             } else {
91 1           croak("hrtime(): unknown clock source '%s' (valid: 'monotonic', 'realtime')", clock_name);
92             }
93             }
94             }
95              
96 13           get_hrtime(use_realtime, &sec_part, &nsec_part);
97              
98 13 100         if (want_list) {
99 4 50         EXTEND(SP, 2);
100 4           PUSHs(sv_2mortal(newSVuv((UV)sec_part)));
101 4           PUSHs(sv_2mortal(newSVuv((UV)nsec_part)));
102             } else {
103 9 50         EXTEND(SP, 1);
104 9           PUSHs(sv_2mortal(newSVuv(
105             (UV)(sec_part * 1000000000ULL + nsec_part)
106             )));
107             }
108             }
109             #endif