Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Python/pytime.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
#ifdef MS_WINDOWS
3
#include <windows.h>
4
#endif
5
6
#if defined(__APPLE__)
7
#include <mach/mach_time.h>   /* mach_absolute_time(), mach_timebase_info() */
8
#endif
9
10
#define _PyTime_check_mul_overflow(a, b) \
11
57
    (assert(b > 0), \
12
57
     (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \
13
57
     || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a))
14
15
/* To millisecond (10^-3) */
16
962
#define SEC_TO_MS 1000
17
18
/* To microseconds (10^-6) */
19
962
#define MS_TO_US 1000
20
0
#define SEC_TO_US (SEC_TO_MS * MS_TO_US)
21
22
/* To nanoseconds (10^-9) */
23
962
#define US_TO_NS 1000
24
962
#define MS_TO_NS (MS_TO_US * US_TO_NS)
25
962
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
26
27
/* Conversion from nanoseconds */
28
0
#define NS_TO_MS (1000 * 1000)
29
859
#define NS_TO_US (1000)
30
31
static void
32
error_time_t_overflow(void)
33
0
{
34
0
    PyErr_SetString(PyExc_OverflowError,
35
0
                    "timestamp out of range for platform time_t");
36
0
}
37
38
static void
39
_PyTime_overflow(void)
40
0
{
41
0
    PyErr_SetString(PyExc_OverflowError,
42
0
                    "timestamp too large to convert to C _PyTime_t");
43
0
}
44
45
46
_PyTime_t
47
_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
48
0
{
49
0
    _PyTime_t intpart, remaining;
50
    /* Compute (ticks * mul / div) in two parts to prevent integer overflow:
51
       compute integer part, and then the remaining part.
52
53
       (ticks * mul) / div == (ticks / div) * mul + (ticks % div) * mul / div
54
55
       The caller must ensure that "(div - 1) * mul" cannot overflow. */
56
0
    intpart = ticks / div;
57
0
    ticks %= div;
58
0
    remaining = ticks * mul;
59
0
    remaining /= div;
60
0
    return intpart * mul + remaining;
61
0
}
62
63
64
time_t
65
_PyLong_AsTime_t(PyObject *obj)
66
0
{
67
0
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
68
0
    long long val;
69
0
    val = PyLong_AsLongLong(obj);
70
#else
71
    long val;
72
    Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
73
    val = PyLong_AsLong(obj);
74
#endif
75
0
    if (val == -1 && PyErr_Occurred()) {
76
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
77
0
            error_time_t_overflow();
78
0
        }
79
0
        return -1;
80
0
    }
81
0
    return (time_t)val;
82
0
}
83
84
PyObject *
85
_PyLong_FromTime_t(time_t t)
86
2.56k
{
87
2.56k
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
88
2.56k
    return PyLong_FromLongLong((long long)t);
89
#else
90
    Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
91
    return PyLong_FromLong((long)t);
92
#endif
93
2.56k
}
94
95
/* Round to nearest with ties going to nearest even integer
96
   (_PyTime_ROUND_HALF_EVEN) */
97
static double
98
_PyTime_RoundHalfEven(double x)
99
0
{
100
0
    double rounded = round(x);
101
0
    if (fabs(x-rounded) == 0.5) {
102
        /* halfway case: round to even */
103
0
        rounded = 2.0*round(x/2.0);
104
0
    }
105
0
    return rounded;
106
0
}
107
108
static double
109
_PyTime_Round(double x, _PyTime_round_t round)
110
0
{
111
    /* volatile avoids optimization changing how numbers are rounded */
112
0
    volatile double d;
113
114
0
    d = x;
115
0
    if (round == _PyTime_ROUND_HALF_EVEN) {
116
0
        d = _PyTime_RoundHalfEven(d);
117
0
    }
118
0
    else if (round == _PyTime_ROUND_CEILING) {
119
0
        d = ceil(d);
120
0
    }
121
0
    else if (round == _PyTime_ROUND_FLOOR) {
122
0
        d = floor(d);
123
0
    }
124
0
    else {
125
0
        assert(round == _PyTime_ROUND_UP);
126
0
        d = (d >= 0.0) ? ceil(d) : floor(d);
127
0
    }
128
0
    return d;
129
0
}
130
131
static int
132
_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
133
                            long idenominator, _PyTime_round_t round)
134
0
{
135
0
    double denominator = (double)idenominator;
136
0
    double intpart;
137
    /* volatile avoids optimization changing how numbers are rounded */
138
0
    volatile double floatpart;
139
140
0
    floatpart = modf(d, &intpart);
141
142
0
    floatpart *= denominator;
143
0
    floatpart = _PyTime_Round(floatpart, round);
144
0
    if (floatpart >= denominator) {
145
0
        floatpart -= denominator;
146
0
        intpart += 1.0;
147
0
    }
148
0
    else if (floatpart < 0) {
149
0
        floatpart += denominator;
150
0
        intpart -= 1.0;
151
0
    }
152
0
    assert(0.0 <= floatpart && floatpart < denominator);
153
154
0
    if (!_Py_InIntegralTypeRange(time_t, intpart)) {
155
0
        error_time_t_overflow();
156
0
        return -1;
157
0
    }
158
0
    *sec = (time_t)intpart;
159
0
    *numerator = (long)floatpart;
160
0
    assert(0 <= *numerator && *numerator < idenominator);
161
0
    return 0;
162
0
}
163
164
static int
165
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
166
                            long denominator, _PyTime_round_t round)
167
0
{
168
0
    assert(denominator >= 1);
169
170
0
    if (PyFloat_Check(obj)) {
171
0
        double d = PyFloat_AsDouble(obj);
172
0
        if (Py_IS_NAN(d)) {
173
0
            *numerator = 0;
174
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
175
0
            return -1;
176
0
        }
177
0
        return _PyTime_DoubleToDenominator(d, sec, numerator,
178
0
                                           denominator, round);
179
0
    }
180
0
    else {
181
0
        *sec = _PyLong_AsTime_t(obj);
182
0
        *numerator = 0;
183
0
        if (*sec == (time_t)-1 && PyErr_Occurred()) {
184
0
            return -1;
185
0
        }
186
0
        return 0;
187
0
    }
188
0
}
189
190
int
191
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
192
0
{
193
0
    if (PyFloat_Check(obj)) {
194
0
        double intpart;
195
        /* volatile avoids optimization changing how numbers are rounded */
196
0
        volatile double d;
197
198
0
        d = PyFloat_AsDouble(obj);
199
0
        if (Py_IS_NAN(d)) {
200
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
201
0
            return -1;
202
0
        }
203
204
0
        d = _PyTime_Round(d, round);
205
0
        (void)modf(d, &intpart);
206
207
0
        if (!_Py_InIntegralTypeRange(time_t, intpart)) {
208
0
            error_time_t_overflow();
209
0
            return -1;
210
0
        }
211
0
        *sec = (time_t)intpart;
212
0
        return 0;
213
0
    }
214
0
    else {
215
0
        *sec = _PyLong_AsTime_t(obj);
216
0
        if (*sec == (time_t)-1 && PyErr_Occurred()) {
217
0
            return -1;
218
0
        }
219
0
        return 0;
220
0
    }
221
0
}
222
223
int
224
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
225
                         _PyTime_round_t round)
226
0
{
227
0
    return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round);
228
0
}
229
230
int
231
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
232
                        _PyTime_round_t round)
233
0
{
234
0
    return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round);
235
0
}
236
237
_PyTime_t
238
_PyTime_FromSeconds(int seconds)
239
876
{
240
876
    _PyTime_t t;
241
    /* ensure that integer overflow cannot happen, int type should have 32
242
       bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
243
       bits). */
244
876
    Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
245
876
    Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
246
247
876
    t = (_PyTime_t)seconds;
248
876
    assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
249
876
           || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
250
876
    t *= SEC_TO_NS;
251
876
    return t;
252
876
}
253
254
_PyTime_t
255
_PyTime_FromNanoseconds(_PyTime_t ns)
256
0
{
257
    /* _PyTime_t already uses nanosecond resolution, no conversion needed */
258
0
    return ns;
259
0
}
260
261
int
262
_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
263
0
{
264
0
    long long nsec;
265
0
    _PyTime_t t;
266
267
0
    if (!PyLong_Check(obj)) {
268
0
        PyErr_Format(PyExc_TypeError, "expect int, got %s",
269
0
                     Py_TYPE(obj)->tp_name);
270
0
        return -1;
271
0
    }
272
273
0
    Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
274
0
    nsec = PyLong_AsLongLong(obj);
275
0
    if (nsec == -1 && PyErr_Occurred()) {
276
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
277
0
            _PyTime_overflow();
278
0
        }
279
0
        return -1;
280
0
    }
281
282
    /* _PyTime_t already uses nanosecond resolution, no conversion needed */
283
0
    t = (_PyTime_t)nsec;
284
0
    *tp = t;
285
0
    return 0;
286
0
}
287
288
#ifdef HAVE_CLOCK_GETTIME
289
static int
290
pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
291
57
{
292
57
    _PyTime_t t, nsec;
293
57
    int res = 0;
294
295
57
    Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
296
57
    t = (_PyTime_t)ts->tv_sec;
297
298
57
    if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
299
0
        if (raise) {
300
0
            _PyTime_overflow();
301
0
        }
302
0
        res = -1;
303
0
        t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
304
0
    }
305
57
    else {
306
57
        t = t * SEC_TO_NS;
307
57
    }
308
309
57
    nsec = ts->tv_nsec;
310
    /* The following test is written for positive only nsec */
311
57
    assert(nsec >= 0);
312
57
    if (t > _PyTime_MAX - nsec) {
313
0
        if (raise) {
314
0
            _PyTime_overflow();
315
0
        }
316
0
        res = -1;
317
0
        t = _PyTime_MAX;
318
0
    }
319
57
    else {
320
57
        t += nsec;
321
57
    }
322
323
57
    *tp = t;
324
57
    return res;
325
57
}
326
327
int
328
_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
329
0
{
330
0
    return pytime_fromtimespec(tp, ts, 1);
331
0
}
332
#endif
333
334
#if !defined(MS_WINDOWS)
335
static int
336
pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
337
0
{
338
0
    _PyTime_t t, usec;
339
0
    int res = 0;
340
341
0
    Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
342
0
    t = (_PyTime_t)tv->tv_sec;
343
344
0
    if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
345
0
        if (raise) {
346
0
            _PyTime_overflow();
347
0
        }
348
0
        res = -1;
349
0
        t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
350
0
    }
351
0
    else {
352
0
        t = t * SEC_TO_NS;
353
0
    }
354
355
0
    usec = (_PyTime_t)tv->tv_usec * US_TO_NS;
356
    /* The following test is written for positive only usec */
357
0
    assert(usec >= 0);
358
0
    if (t > _PyTime_MAX - usec) {
359
0
        if (raise) {
360
0
            _PyTime_overflow();
361
0
        }
362
0
        res = -1;
363
0
        t = _PyTime_MAX;
364
0
    }
365
0
    else {
366
0
        t += usec;
367
0
    }
368
369
0
    *tp = t;
370
0
    return res;
371
0
}
372
373
int
374
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
375
0
{
376
0
    return pytime_fromtimeval(tp, tv, 1);
377
0
}
378
#endif
379
380
static int
381
_PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round,
382
                   long unit_to_ns)
383
0
{
384
    /* volatile avoids optimization changing how numbers are rounded */
385
0
    volatile double d;
386
387
    /* convert to a number of nanoseconds */
388
0
    d = value;
389
0
    d *= (double)unit_to_ns;
390
0
    d = _PyTime_Round(d, round);
391
392
0
    if (!_Py_InIntegralTypeRange(_PyTime_t, d)) {
393
0
        _PyTime_overflow();
394
0
        return -1;
395
0
    }
396
0
    *t = (_PyTime_t)d;
397
0
    return 0;
398
0
}
399
400
static int
401
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
402
                   long unit_to_ns)
403
0
{
404
0
    if (PyFloat_Check(obj)) {
405
0
        double d;
406
0
        d = PyFloat_AsDouble(obj);
407
0
        if (Py_IS_NAN(d)) {
408
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
409
0
            return -1;
410
0
        }
411
0
        return _PyTime_FromDouble(t, d, round, unit_to_ns);
412
0
    }
413
0
    else {
414
0
        long long sec;
415
0
        Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
416
417
0
        sec = PyLong_AsLongLong(obj);
418
0
        if (sec == -1 && PyErr_Occurred()) {
419
0
            if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
420
0
                _PyTime_overflow();
421
0
            }
422
0
            return -1;
423
0
        }
424
425
0
        if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
426
0
            _PyTime_overflow();
427
0
            return -1;
428
0
        }
429
0
        *t = sec * unit_to_ns;
430
0
        return 0;
431
0
    }
432
0
}
433
434
int
435
_PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
436
0
{
437
0
    return _PyTime_FromObject(t, obj, round, SEC_TO_NS);
438
0
}
439
440
int
441
_PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
442
0
{
443
0
    return _PyTime_FromObject(t, obj, round, MS_TO_NS);
444
0
}
445
446
double
447
_PyTime_AsSecondsDouble(_PyTime_t t)
448
29
{
449
    /* volatile avoids optimization changing how numbers are rounded */
450
29
    volatile double d;
451
452
29
    if (t % SEC_TO_NS == 0) {
453
0
        _PyTime_t secs;
454
        /* Divide using integers to avoid rounding issues on the integer part.
455
           1e-9 cannot be stored exactly in IEEE 64-bit. */
456
0
        secs = t / SEC_TO_NS;
457
0
        d = (double)secs;
458
0
    }
459
29
    else {
460
29
        d = (double)t;
461
29
        d /= 1e9;
462
29
    }
463
29
    return d;
464
29
}
465
466
PyObject *
467
_PyTime_AsNanosecondsObject(_PyTime_t t)
468
0
{
469
0
    Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t));
470
0
    return PyLong_FromLongLong((long long)t);
471
0
}
472
473
static _PyTime_t
474
_PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
475
               const _PyTime_round_t round)
476
859
{
477
859
    assert(k > 1);
478
859
    if (round == _PyTime_ROUND_HALF_EVEN) {
479
0
        _PyTime_t x, r, abs_r;
480
0
        x = t / k;
481
0
        r = t % k;
482
0
        abs_r = Py_ABS(r);
483
0
        if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
484
0
            if (t >= 0) {
485
0
                x++;
486
0
            }
487
0
            else {
488
0
                x--;
489
0
            }
490
0
        }
491
0
        return x;
492
0
    }
493
859
    else if (round == _PyTime_ROUND_CEILING) {
494
859
        if (t >= 0) {
495
1
            return (t + k - 1) / k;
496
1
        }
497
858
        else {
498
858
            return t / k;
499
858
        }
500
859
    }
501
0
    else if (round == _PyTime_ROUND_FLOOR){
502
0
        if (t >= 0) {
503
0
            return t / k;
504
0
        }
505
0
        else {
506
0
            return (t - (k - 1)) / k;
507
0
        }
508
0
    }
509
0
    else {
510
0
        assert(round == _PyTime_ROUND_UP);
511
0
        if (t >= 0) {
512
0
            return (t + k - 1) / k;
513
0
        }
514
0
        else {
515
0
            return (t - (k - 1)) / k;
516
0
        }
517
0
    }
518
859
}
519
520
_PyTime_t
521
_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)
522
0
{
523
0
    return _PyTime_Divide(t, NS_TO_MS, round);
524
0
}
525
526
_PyTime_t
527
_PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
528
859
{
529
859
    return _PyTime_Divide(t, NS_TO_US, round);
530
859
}
531
532
static int
533
_PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us,
534
                       _PyTime_round_t round)
535
0
{
536
0
    _PyTime_t secs, ns;
537
0
    int usec;
538
0
    int res = 0;
539
540
0
    secs = t / SEC_TO_NS;
541
0
    ns = t % SEC_TO_NS;
542
543
0
    usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
544
0
    if (usec < 0) {
545
0
        usec += SEC_TO_US;
546
0
        if (secs != _PyTime_MIN) {
547
0
            secs -= 1;
548
0
        }
549
0
        else {
550
0
            res = -1;
551
0
        }
552
0
    }
553
0
    else if (usec >= SEC_TO_US) {
554
0
        usec -= SEC_TO_US;
555
0
        if (secs != _PyTime_MAX) {
556
0
            secs += 1;
557
0
        }
558
0
        else {
559
0
            res = -1;
560
0
        }
561
0
    }
562
0
    assert(0 <= usec && usec < SEC_TO_US);
563
564
0
    *p_secs = secs;
565
0
    *p_us = usec;
566
567
0
    return res;
568
0
}
569
570
static int
571
_PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,
572
                             _PyTime_round_t round, int raise)
573
0
{
574
0
    _PyTime_t secs, secs2;
575
0
    int us;
576
0
    int res;
577
578
0
    res = _PyTime_AsTimeval_impl(t, &secs, &us, round);
579
580
#ifdef MS_WINDOWS
581
    tv->tv_sec = (long)secs;
582
#else
583
0
    tv->tv_sec = secs;
584
0
#endif
585
0
    tv->tv_usec = us;
586
587
0
    secs2 = (_PyTime_t)tv->tv_sec;
588
0
    if (res < 0 || secs2 != secs) {
589
0
        if (raise) {
590
0
            error_time_t_overflow();
591
0
        }
592
0
        return -1;
593
0
    }
594
0
    return 0;
595
0
}
596
597
int
598
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
599
0
{
600
0
    return _PyTime_AsTimevalStruct_impl(t, tv, round, 1);
601
0
}
602
603
int
604
_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
605
0
{
606
0
    return _PyTime_AsTimevalStruct_impl(t, tv, round, 0);
607
0
}
608
609
int
610
_PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
611
                        _PyTime_round_t round)
612
0
{
613
0
    _PyTime_t secs;
614
0
    int res;
615
616
0
    res = _PyTime_AsTimeval_impl(t, &secs, us, round);
617
618
0
    *p_secs = secs;
619
620
0
    if (res < 0 || (_PyTime_t)*p_secs != secs) {
621
0
        error_time_t_overflow();
622
0
        return -1;
623
0
    }
624
0
    return 0;
625
0
}
626
627
628
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
629
int
630
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
631
0
{
632
0
    _PyTime_t secs, nsec;
633
634
0
    secs = t / SEC_TO_NS;
635
0
    nsec = t % SEC_TO_NS;
636
0
    if (nsec < 0) {
637
0
        nsec += SEC_TO_NS;
638
0
        secs -= 1;
639
0
    }
640
0
    ts->tv_sec = (time_t)secs;
641
0
    assert(0 <= nsec && nsec < SEC_TO_NS);
642
0
    ts->tv_nsec = nsec;
643
644
0
    if ((_PyTime_t)ts->tv_sec != secs) {
645
0
        error_time_t_overflow();
646
0
        return -1;
647
0
    }
648
0
    return 0;
649
0
}
650
#endif
651
652
static int
653
pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
654
29
{
655
#ifdef MS_WINDOWS
656
    FILETIME system_time;
657
    ULARGE_INTEGER large;
658
659
    assert(info == NULL || raise);
660
661
    GetSystemTimeAsFileTime(&system_time);
662
    large.u.LowPart = system_time.dwLowDateTime;
663
    large.u.HighPart = system_time.dwHighDateTime;
664
    /* 11,644,473,600,000,000,000: number of nanoseconds between
665
       the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
666
       days). */
667
    *tp = large.QuadPart * 100 - 11644473600000000000;
668
    if (info) {
669
        DWORD timeAdjustment, timeIncrement;
670
        BOOL isTimeAdjustmentDisabled, ok;
671
672
        info->implementation = "GetSystemTimeAsFileTime()";
673
        info->monotonic = 0;
674
        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
675
                                     &isTimeAdjustmentDisabled);
676
        if (!ok) {
677
            PyErr_SetFromWindowsErr(0);
678
            return -1;
679
        }
680
        info->resolution = timeIncrement * 1e-7;
681
        info->adjustable = 1;
682
    }
683
684
#else   /* MS_WINDOWS */
685
29
    int err;
686
29
#ifdef HAVE_CLOCK_GETTIME
687
29
    struct timespec ts;
688
#else
689
    struct timeval tv;
690
#endif
691
692
29
    assert(info == NULL || raise);
693
694
29
#ifdef HAVE_CLOCK_GETTIME
695
29
    err = clock_gettime(CLOCK_REALTIME, &ts);
696
29
    if (err) {
697
0
        if (raise) {
698
0
            PyErr_SetFromErrno(PyExc_OSError);
699
0
        }
700
0
        return -1;
701
0
    }
702
29
    if (pytime_fromtimespec(tp, &ts, raise) < 0) {
703
0
        return -1;
704
0
    }
705
706
29
    if (info) {
707
0
        struct timespec res;
708
0
        info->implementation = "clock_gettime(CLOCK_REALTIME)";
709
0
        info->monotonic = 0;
710
0
        info->adjustable = 1;
711
0
        if (clock_getres(CLOCK_REALTIME, &res) == 0) {
712
0
            info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
713
0
        }
714
0
        else {
715
0
            info->resolution = 1e-9;
716
0
        }
717
0
    }
718
#else   /* HAVE_CLOCK_GETTIME */
719
720
     /* test gettimeofday() */
721
#ifdef GETTIMEOFDAY_NO_TZ
722
    err = gettimeofday(&tv);
723
#else
724
    err = gettimeofday(&tv, (struct timezone *)NULL);
725
#endif
726
    if (err) {
727
        if (raise) {
728
            PyErr_SetFromErrno(PyExc_OSError);
729
        }
730
        return -1;
731
    }
732
    if (pytime_fromtimeval(tp, &tv, raise) < 0) {
733
        return -1;
734
    }
735
736
    if (info) {
737
        info->implementation = "gettimeofday()";
738
        info->resolution = 1e-6;
739
        info->monotonic = 0;
740
        info->adjustable = 1;
741
    }
742
#endif   /* !HAVE_CLOCK_GETTIME */
743
29
#endif   /* !MS_WINDOWS */
744
29
    return 0;
745
29
}
746
747
_PyTime_t
748
_PyTime_GetSystemClock(void)
749
15
{
750
15
    _PyTime_t t;
751
15
    if (pygettimeofday(&t, NULL, 0) < 0) {
752
        /* should not happen, _PyTime_Init() checked the clock at startup */
753
0
        Py_UNREACHABLE();
754
0
    }
755
15
    return t;
756
15
}
757
758
int
759
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
760
14
{
761
14
    return pygettimeofday(t, info, 1);
762
14
}
763
764
static int
765
pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
766
28
{
767
#if defined(MS_WINDOWS)
768
    ULONGLONG ticks;
769
    _PyTime_t t;
770
771
    assert(info == NULL || raise);
772
773
    ticks = GetTickCount64();
774
    Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t));
775
    t = (_PyTime_t)ticks;
776
777
    if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
778
        if (raise) {
779
            _PyTime_overflow();
780
            return -1;
781
        }
782
        /* Hello, time traveler! */
783
        Py_UNREACHABLE();
784
    }
785
    *tp = t * MS_TO_NS;
786
787
    if (info) {
788
        DWORD timeAdjustment, timeIncrement;
789
        BOOL isTimeAdjustmentDisabled, ok;
790
        info->implementation = "GetTickCount64()";
791
        info->monotonic = 1;
792
        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
793
                                     &isTimeAdjustmentDisabled);
794
        if (!ok) {
795
            PyErr_SetFromWindowsErr(0);
796
            return -1;
797
        }
798
        info->resolution = timeIncrement * 1e-7;
799
        info->adjustable = 0;
800
    }
801
802
#elif defined(__APPLE__)
803
    static mach_timebase_info_data_t timebase;
804
    static uint64_t t0 = 0;
805
    uint64_t ticks;
806
807
    if (timebase.denom == 0) {
808
        /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
809
           fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
810
        (void)mach_timebase_info(&timebase);
811
812
        /* Sanity check: should never occur in practice */
813
        if (timebase.numer < 1 || timebase.denom < 1) {
814
            PyErr_SetString(PyExc_RuntimeError,
815
                            "invalid mach_timebase_info");
816
            return -1;
817
        }
818
819
        /* Check that timebase.numer and timebase.denom can be casted to
820
           _PyTime_t. In practice, timebase uses uint32_t, so casting cannot
821
           overflow. At the end, only make sure that the type is uint32_t
822
           (_PyTime_t is 64-bit long). */
823
        assert(sizeof(timebase.numer) < sizeof(_PyTime_t));
824
        assert(sizeof(timebase.denom) < sizeof(_PyTime_t));
825
826
        /* Make sure that (ticks * timebase.numer) cannot overflow in
827
           _PyTime_MulDiv(), with ticks < timebase.denom.
828
829
           Known time bases:
830
831
           * always (1, 1) on Intel
832
           * (1000000000, 33333335) or (1000000000, 25000000) on PowerPC
833
834
           None of these time bases can overflow with 64-bit _PyTime_t, but
835
           check for overflow, just in case. */
836
        if ((_PyTime_t)timebase.numer > _PyTime_MAX / (_PyTime_t)timebase.denom) {
837
            PyErr_SetString(PyExc_OverflowError,
838
                            "mach_timebase_info is too large");
839
            return -1;
840
        }
841
842
        t0 = mach_absolute_time();
843
    }
844
845
    if (info) {
846
        info->implementation = "mach_absolute_time()";
847
        info->resolution = (double)timebase.numer / (double)timebase.denom * 1e-9;
848
        info->monotonic = 1;
849
        info->adjustable = 0;
850
    }
851
852
    ticks = mach_absolute_time();
853
    /* Use a "time zero" to reduce precision loss when converting time
854
       to floatting point number, as in time.monotonic(). */
855
    ticks -= t0;
856
    *tp = _PyTime_MulDiv(ticks,
857
                         (_PyTime_t)timebase.numer,
858
                         (_PyTime_t)timebase.denom);
859
860
#elif defined(__hpux)
861
    hrtime_t time;
862
863
    time = gethrtime();
864
    if (time == -1) {
865
        if (raise) {
866
            PyErr_SetFromErrno(PyExc_OSError);
867
        }
868
        return -1;
869
    }
870
871
    *tp = time;
872
873
    if (info) {
874
        info->implementation = "gethrtime()";
875
        info->resolution = 1e-9;
876
        info->monotonic = 1;
877
        info->adjustable = 0;
878
    }
879
880
#else
881
28
    struct timespec ts;
882
#ifdef CLOCK_HIGHRES
883
    const clockid_t clk_id = CLOCK_HIGHRES;
884
    const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
885
#else
886
28
    const clockid_t clk_id = CLOCK_MONOTONIC;
887
28
    const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
888
28
#endif
889
890
28
    assert(info == NULL || raise);
891
892
28
    if (clock_gettime(clk_id, &ts) != 0) {
893
0
        if (raise) {
894
0
            PyErr_SetFromErrno(PyExc_OSError);
895
0
            return -1;
896
0
        }
897
0
        return -1;
898
0
    }
899
900
28
    if (info) {
901
0
        struct timespec res;
902
0
        info->monotonic = 1;
903
0
        info->implementation = implementation;
904
0
        info->adjustable = 0;
905
0
        if (clock_getres(clk_id, &res) != 0) {
906
0
            PyErr_SetFromErrno(PyExc_OSError);
907
0
            return -1;
908
0
        }
909
0
        info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
910
0
    }
911
28
    if (pytime_fromtimespec(tp, &ts, raise) < 0) {
912
0
        return -1;
913
0
    }
914
28
#endif
915
28
    return 0;
916
28
}
917
918
_PyTime_t
919
_PyTime_GetMonotonicClock(void)
920
0
{
921
0
    _PyTime_t t;
922
0
    if (pymonotonic(&t, NULL, 0) < 0) {
923
        /* should not happen, _PyTime_Init() checked that monotonic clock at
924
           startup */
925
0
        Py_UNREACHABLE();
926
0
    }
927
0
    return t;
928
0
}
929
930
int
931
_PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
932
28
{
933
28
    return pymonotonic(tp, info, 1);
934
28
}
935
936
937
#ifdef MS_WINDOWS
938
static int
939
win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info)
940
{
941
    static LONGLONG frequency = 0;
942
    static LONGLONG t0 = 0;
943
    LARGE_INTEGER now;
944
    LONGLONG ticksll;
945
    _PyTime_t ticks;
946
947
    if (frequency == 0) {
948
        LARGE_INTEGER freq;
949
        if (!QueryPerformanceFrequency(&freq)) {
950
            PyErr_SetFromWindowsErr(0);
951
            return -1;
952
        }
953
        frequency = freq.QuadPart;
954
955
        /* Sanity check: should never occur in practice */
956
        if (frequency < 1) {
957
            PyErr_SetString(PyExc_RuntimeError,
958
                            "invalid QueryPerformanceFrequency");
959
            return -1;
960
        }
961
962
        /* Check that frequency can be casted to _PyTime_t.
963
964
           Make also sure that (ticks * SEC_TO_NS) cannot overflow in
965
           _PyTime_MulDiv(), with ticks < frequency.
966
967
           Known QueryPerformanceFrequency() values:
968
969
           * 10,000,000 (10 MHz): 100 ns resolution
970
           * 3,579,545 Hz (3.6 MHz): 279 ns resolution
971
972
           None of these frequencies can overflow with 64-bit _PyTime_t, but
973
           check for overflow, just in case. */
974
        if (frequency > _PyTime_MAX
975
            || frequency > (LONGLONG)_PyTime_MAX / (LONGLONG)SEC_TO_NS) {
976
            PyErr_SetString(PyExc_OverflowError,
977
                            "QueryPerformanceFrequency is too large");
978
            return -1;
979
        }
980
981
        QueryPerformanceCounter(&now);
982
        t0 = now.QuadPart;
983
    }
984
985
    if (info) {
986
        info->implementation = "QueryPerformanceCounter()";
987
        info->resolution = 1.0 / (double)frequency;
988
        info->monotonic = 1;
989
        info->adjustable = 0;
990
    }
991
992
    QueryPerformanceCounter(&now);
993
    ticksll = now.QuadPart;
994
995
    /* Use a "time zero" to reduce precision loss when converting time
996
       to floatting point number, as in time.perf_counter(). */
997
    ticksll -= t0;
998
999
    /* Make sure that casting LONGLONG to _PyTime_t cannot overflow,
1000
       both types are signed */
1001
    Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
1002
    ticks = (_PyTime_t)ticksll;
1003
1004
    *tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency);
1005
    return 0;
1006
}
1007
#endif
1008
1009
1010
int
1011
_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
1012
14
{
1013
#ifdef MS_WINDOWS
1014
    return win_perf_counter(t, info);
1015
#else
1016
14
    return _PyTime_GetMonotonicClockWithInfo(t, info);
1017
14
#endif
1018
14
}
1019
1020
1021
_PyTime_t
1022
_PyTime_GetPerfCounter(void)
1023
0
{
1024
0
    _PyTime_t t;
1025
0
    if (_PyTime_GetPerfCounterWithInfo(&t, NULL)) {
1026
0
        Py_UNREACHABLE();
1027
0
    }
1028
0
    return t;
1029
0
}
1030
1031
1032
int
1033
_PyTime_Init(void)
1034
14
{
1035
    /* check that time.time(), time.monotonic() and time.perf_counter() clocks
1036
       are working properly to not have to check for exceptions at runtime. If
1037
       a clock works once, it cannot fail in next calls. */
1038
14
    _PyTime_t t;
1039
14
    if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) {
1040
0
        return -1;
1041
0
    }
1042
14
    if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) {
1043
0
        return -1;
1044
0
    }
1045
14
    if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) {
1046
0
        return -1;
1047
0
    }
1048
14
    return 0;
1049
14
}
1050
1051
int
1052
_PyTime_localtime(time_t t, struct tm *tm)
1053
28
{
1054
#ifdef MS_WINDOWS
1055
    int error;
1056
1057
    error = localtime_s(tm, &t);
1058
    if (error != 0) {
1059
        errno = error;
1060
        PyErr_SetFromErrno(PyExc_OSError);
1061
        return -1;
1062
    }
1063
    return 0;
1064
#else /* !MS_WINDOWS */
1065
1066
#ifdef _AIX
1067
    /* bpo-34373: AIX does not return NULL if t is too small or too large */
1068
    if (t < -2145916800 /* 1902-01-01 */
1069
       || t > 2145916800 /* 2038-01-01 */) {
1070
        errno = EINVAL;
1071
        PyErr_SetString(PyExc_OverflowError,
1072
                        "localtime argument out of range");
1073
        return -1;
1074
    }
1075
#endif
1076
1077
28
    errno = 0;
1078
28
    if (localtime_r(&t, tm) == NULL) {
1079
0
        if (errno == 0) {
1080
0
            errno = EINVAL;
1081
0
        }
1082
0
        PyErr_SetFromErrno(PyExc_OSError);
1083
0
        return -1;
1084
0
    }
1085
28
    return 0;
1086
28
#endif /* MS_WINDOWS */
1087
28
}
1088
1089
int
1090
_PyTime_gmtime(time_t t, struct tm *tm)
1091
0
{
1092
#ifdef MS_WINDOWS
1093
    int error;
1094
1095
    error = gmtime_s(tm, &t);
1096
    if (error != 0) {
1097
        errno = error;
1098
        PyErr_SetFromErrno(PyExc_OSError);
1099
        return -1;
1100
    }
1101
    return 0;
1102
#else /* !MS_WINDOWS */
1103
0
    if (gmtime_r(&t, tm) == NULL) {
1104
0
#ifdef EINVAL
1105
0
        if (errno == 0) {
1106
0
            errno = EINVAL;
1107
0
        }
1108
0
#endif
1109
0
        PyErr_SetFromErrno(PyExc_OSError);
1110
0
        return -1;
1111
0
    }
1112
0
    return 0;
1113
0
#endif /* MS_WINDOWS */
1114
0
}