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 (assert(b > 0), \ 12 (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ 13 || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a)) 14 15 /* To millisecond (10^-3) */ 16 #define SEC_TO_MS 1000 17 18 /* To microseconds (10^-6) */ 19 #define MS_TO_US 1000 20 #define SEC_TO_US (SEC_TO_MS * MS_TO_US) 21 22 /* To nanoseconds (10^-9) */ 23 #define US_TO_NS 1000 24 #define MS_TO_NS (MS_TO_US * US_TO_NS) 25 #define SEC_TO_NS (SEC_TO_MS * MS_TO_NS) 26 27 /* Conversion from nanoseconds */ 28 #define NS_TO_MS (1000 * 1000) 29 #define NS_TO_US (1000) 30 31 static void 32 error_time_t_overflow(void) 33 { 34 PyErr_SetString(PyExc_OverflowError, 35 "timestamp out of range for platform time_t"); 36 } 37 38 time_t 39 _PyLong_AsTime_t(PyObject *obj) 40 { 41 #if SIZEOF_TIME_T == SIZEOF_LONG_LONG 42 long long val; 43 val = PyLong_AsLongLong(obj); 44 #else 45 long val; 46 Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long)); 47 val = PyLong_AsLong(obj); 48 #endif 49 if (val == -1 && PyErr_Occurred()) { 50 if (PyErr_ExceptionMatches(PyExc_OverflowError)) 51 error_time_t_overflow(); 52 return -1; 53 } 54 return (time_t)val; 55 } 56 57 PyObject * 58 _PyLong_FromTime_t(time_t t) 59 { 60 #if SIZEOF_TIME_T == SIZEOF_LONG_LONG 61 return PyLong_FromLongLong((long long)t); 62 #else 63 Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long)); 64 return PyLong_FromLong((long)t); 65 #endif 66 } 67 68 /* Round to nearest with ties going to nearest even integer 69 (_PyTime_ROUND_HALF_EVEN) */ 70 static double 71 _PyTime_RoundHalfEven(double x) 72 { 73 double rounded = round(x); 74 if (fabs(x-rounded) == 0.5) 75 /* halfway case: round to even */ 76 rounded = 2.0*round(x/2.0); 77 return rounded; 78 } 79 80 static double 81 _PyTime_Round(double x, _PyTime_round_t round) 82 { 83 /* volatile avoids optimization changing how numbers are rounded */ 84 volatile double d; 85 86 d = x; 87 if (round == _PyTime_ROUND_HALF_EVEN) 88 d = _PyTime_RoundHalfEven(d); 89 else if (round == _PyTime_ROUND_CEILING) 90 d = ceil(d); 91 else 92 d = floor(d); 93 return d; 94 } 95 96 static int 97 _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, 98 double denominator, _PyTime_round_t round) 99 { 100 double intpart, err; 101 /* volatile avoids optimization changing how numbers are rounded */ 102 volatile double floatpart; 103 104 floatpart = modf(d, &intpart); 105 106 floatpart *= denominator; 107 floatpart = _PyTime_Round(floatpart, round); 108 if (floatpart >= denominator) { 109 floatpart -= denominator; 110 intpart += 1.0; 111 } 112 else if (floatpart < 0) { 113 floatpart += denominator; 114 intpart -= 1.0; 115 } 116 assert(0.0 <= floatpart && floatpart < denominator); 117 118 *sec = (time_t)intpart; 119 *numerator = (long)floatpart; 120 121 err = intpart - (double)*sec; 122 if (err <= -1.0 || err >= 1.0) { 123 error_time_t_overflow(); 124 return -1; 125 } 126 return 0; 127 } 128 129 static int 130 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, 131 double denominator, _PyTime_round_t round) 132 { 133 assert(denominator <= (double)LONG_MAX); 134 135 if (PyFloat_Check(obj)) { 136 double d = PyFloat_AsDouble(obj); 137 return _PyTime_DoubleToDenominator(d, sec, numerator, 138 denominator, round); 139 } 140 else { 141 *sec = _PyLong_AsTime_t(obj); 142 *numerator = 0; 143 if (*sec == (time_t)-1 && PyErr_Occurred()) 144 return -1; 145 return 0; 146 } 147 } 148 149 int 150 _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) 151 { 152 if (PyFloat_Check(obj)) { 153 double intpart, err; 154 /* volatile avoids optimization changing how numbers are rounded */ 155 volatile double d; 156 157 d = PyFloat_AsDouble(obj); 158 d = _PyTime_Round(d, round); 159 (void)modf(d, &intpart); 160 161 *sec = (time_t)intpart; 162 err = intpart - (double)*sec; 163 if (err <= -1.0 || err >= 1.0) { 164 error_time_t_overflow(); 165 return -1; 166 } 167 return 0; 168 } 169 else { 170 *sec = _PyLong_AsTime_t(obj); 171 if (*sec == (time_t)-1 && PyErr_Occurred()) 172 return -1; 173 return 0; 174 } 175 } 176 177 int 178 _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, 179 _PyTime_round_t round) 180 { 181 int res; 182 res = _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round); 183 assert(0 <= *nsec && *nsec < SEC_TO_NS); 184 return res; 185 } 186 187 int 188 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, 189 _PyTime_round_t round) 190 { 191 int res; 192 res = _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round); 193 assert(0 <= *usec && *usec < SEC_TO_US); 194 return res; 195 } 196 197 static void 198 _PyTime_overflow(void) 199 { 200 PyErr_SetString(PyExc_OverflowError, 201 "timestamp too large to convert to C _PyTime_t"); 202 } 203 204 _PyTime_t 205 _PyTime_FromSeconds(int seconds) 206 { 207 _PyTime_t t; 208 t = (_PyTime_t)seconds; 209 /* ensure that integer overflow cannot happen, int type should have 32 210 bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30 211 bits). */ 212 Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS); 213 Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS); 214 assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS) 215 || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS)); 216 t *= SEC_TO_NS; 217 return t; 218 } 219 220 _PyTime_t 221 _PyTime_FromNanoseconds(long long ns) 222 { 223 _PyTime_t t; 224 Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t)); 225 t = Py_SAFE_DOWNCAST(ns, long long, _PyTime_t); 226 return t; 227 } 228 229 #ifdef HAVE_CLOCK_GETTIME 230 static int 231 _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise) 232 { 233 _PyTime_t t; 234 int res = 0; 235 236 Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t)); 237 t = (_PyTime_t)ts->tv_sec; 238 239 if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { 240 if (raise) 241 _PyTime_overflow(); 242 res = -1; 243 } 244 t = t * SEC_TO_NS; 245 246 t += ts->tv_nsec; 247 248 *tp = t; 249 return res; 250 } 251 #elif !defined(MS_WINDOWS) 252 static int 253 _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise) 254 { 255 _PyTime_t t; 256 int res = 0; 257 258 Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t)); 259 t = (_PyTime_t)tv->tv_sec; 260 261 if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { 262 if (raise) 263 _PyTime_overflow(); 264 res = -1; 265 } 266 t = t * SEC_TO_NS; 267 268 t += (_PyTime_t)tv->tv_usec * US_TO_NS; 269 270 *tp = t; 271 return res; 272 } 273 #endif 274 275 static int 276 _PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round, 277 long unit_to_ns) 278 { 279 double err; 280 /* volatile avoids optimization changing how numbers are rounded */ 281 volatile double d; 282 283 /* convert to a number of nanoseconds */ 284 d = value; 285 d *= (double)unit_to_ns; 286 d = _PyTime_Round(d, round); 287 288 *t = (_PyTime_t)d; 289 err = d - (double)*t; 290 if (fabs(err) >= 1.0) { 291 _PyTime_overflow(); 292 return -1; 293 } 294 return 0; 295 } 296 297 static int 298 _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, 299 long unit_to_ns) 300 { 301 if (PyFloat_Check(obj)) { 302 double d; 303 d = PyFloat_AsDouble(obj); 304 return _PyTime_FromFloatObject(t, d, round, unit_to_ns); 305 } 306 else { 307 long long sec; 308 Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t)); 309 310 sec = PyLong_AsLongLong(obj); 311 if (sec == -1 && PyErr_Occurred()) { 312 if (PyErr_ExceptionMatches(PyExc_OverflowError)) 313 _PyTime_overflow(); 314 return -1; 315 } 316 317 if (_PyTime_check_mul_overflow(sec, unit_to_ns)) { 318 _PyTime_overflow(); 319 return -1; 320 } 321 *t = sec * unit_to_ns; 322 return 0; 323 } 324 } 325 326 int 327 _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) 328 { 329 return _PyTime_FromObject(t, obj, round, SEC_TO_NS); 330 } 331 332 int 333 _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) 334 { 335 return _PyTime_FromObject(t, obj, round, MS_TO_NS); 336 } 337 338 double 339 _PyTime_AsSecondsDouble(_PyTime_t t) 340 { 341 /* volatile avoids optimization changing how numbers are rounded */ 342 volatile double d; 343 344 if (t % SEC_TO_NS == 0) { 345 _PyTime_t secs; 346 /* Divide using integers to avoid rounding issues on the integer part. 347 1e-9 cannot be stored exactly in IEEE 64-bit. */ 348 secs = t / SEC_TO_NS; 349 d = (double)secs; 350 } 351 else { 352 d = (double)t; 353 d /= 1e9; 354 } 355 return d; 356 } 357 358 PyObject * 359 _PyTime_AsNanosecondsObject(_PyTime_t t) 360 { 361 Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t)); 362 return PyLong_FromLongLong((long long)t); 363 } 364 365 static _PyTime_t 366 _PyTime_Divide(const _PyTime_t t, const _PyTime_t k, 367 const _PyTime_round_t round) 368 { 369 assert(k > 1); 370 if (round == _PyTime_ROUND_HALF_EVEN) { 371 _PyTime_t x, r, abs_r; 372 x = t / k; 373 r = t % k; 374 abs_r = Py_ABS(r); 375 if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) { 376 if (t >= 0) 377 x++; 378 else 379 x--; 380 } 381 return x; 382 } 383 else if (round == _PyTime_ROUND_CEILING) { 384 if (t >= 0) 385 return (t + k - 1) / k; 386 else 387 return t / k; 388 } 389 else { 390 if (t >= 0) 391 return t / k; 392 else 393 return (t - (k - 1)) / k; 394 } 395 } 396 397 _PyTime_t 398 _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) 399 { 400 return _PyTime_Divide(t, NS_TO_MS, round); 401 } 402 403 _PyTime_t 404 _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) 405 { 406 return _PyTime_Divide(t, NS_TO_US, round); 407 } 408 409 static int 410 _PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us, 411 _PyTime_round_t round) 412 { 413 _PyTime_t secs, ns; 414 int usec; 415 int res = 0; 416 417 secs = t / SEC_TO_NS; 418 ns = t % SEC_TO_NS; 419 420 usec = (int)_PyTime_Divide(ns, US_TO_NS, round); 421 if (usec < 0) { 422 usec += SEC_TO_US; 423 if (secs != _PyTime_MIN) 424 secs -= 1; 425 else 426 res = -1; 427 } 428 else if (usec >= SEC_TO_US) { 429 usec -= SEC_TO_US; 430 if (secs != _PyTime_MAX) 431 secs += 1; 432 else 433 res = -1; 434 } 435 assert(0 <= usec && usec < SEC_TO_US); 436 437 *p_secs = secs; 438 *p_us = usec; 439 440 return res; 441 } 442 443 static int 444 _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, 445 _PyTime_round_t round, int raise) 446 { 447 _PyTime_t secs, secs2; 448 int us; 449 int res; 450 451 res = _PyTime_AsTimeval_impl(t, &secs, &us, round); 452 453 #ifdef MS_WINDOWS 454 tv->tv_sec = (long)secs; 455 #else 456 tv->tv_sec = secs; 457 #endif 458 tv->tv_usec = us; 459 460 secs2 = (_PyTime_t)tv->tv_sec; 461 if (res < 0 || secs2 != secs) { 462 if (raise) 463 error_time_t_overflow(); 464 return -1; 465 } 466 return 0; 467 } 468 469 int 470 _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) 471 { 472 return _PyTime_AsTimevalStruct_impl(t, tv, round, 1); 473 } 474 475 int 476 _PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) 477 { 478 return _PyTime_AsTimevalStruct_impl(t, tv, round, 0); 479 } 480 481 int 482 _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, 483 _PyTime_round_t round) 484 { 485 _PyTime_t secs; 486 int res; 487 488 res = _PyTime_AsTimeval_impl(t, &secs, us, round); 489 490 *p_secs = secs; 491 492 if (res < 0 || (_PyTime_t)*p_secs != secs) { 493 error_time_t_overflow(); 494 return -1; 495 } 496 return 0; 497 } 498 499 500 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) 501 int 502 _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts) 503 { 504 _PyTime_t secs, nsec; 505 506 secs = t / SEC_TO_NS; 507 nsec = t % SEC_TO_NS; 508 if (nsec < 0) { 509 nsec += SEC_TO_NS; 510 secs -= 1; 511 } 512 ts->tv_sec = (time_t)secs; 513 assert(0 <= nsec && nsec < SEC_TO_NS); 514 ts->tv_nsec = nsec; 515 516 if ((_PyTime_t)ts->tv_sec != secs) { 517 error_time_t_overflow(); 518 return -1; 519 } 520 return 0; 521 } 522 #endif 523 524 static int 525 pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) 526 { 527 #ifdef MS_WINDOWS 528 FILETIME system_time; 529 ULARGE_INTEGER large; 530 531 assert(info == NULL || raise); 532 533 GetSystemTimeAsFileTime(&system_time); 534 large.u.LowPart = system_time.dwLowDateTime; 535 large.u.HighPart = system_time.dwHighDateTime; 536 /* 11,644,473,600,000,000,000: number of nanoseconds between 537 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap 538 days). */ 539 *tp = large.QuadPart * 100 - 11644473600000000000; 540 if (info) { 541 DWORD timeAdjustment, timeIncrement; 542 BOOL isTimeAdjustmentDisabled, ok; 543 544 info->implementation = "GetSystemTimeAsFileTime()"; 545 info->monotonic = 0; 546 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, 547 &isTimeAdjustmentDisabled); 548 if (!ok) { 549 PyErr_SetFromWindowsErr(0); 550 return -1; 551 } 552 info->resolution = timeIncrement * 1e-7; 553 info->adjustable = 1; 554 } 555 556 #else /* MS_WINDOWS */ 557 int err; 558 #ifdef HAVE_CLOCK_GETTIME 559 struct timespec ts; 560 #else 561 struct timeval tv; 562 #endif 563 564 assert(info == NULL || raise); 565 566 #ifdef HAVE_CLOCK_GETTIME 567 err = clock_gettime(CLOCK_REALTIME, &ts); 568 if (err) { 569 if (raise) 570 PyErr_SetFromErrno(PyExc_OSError); 571 return -1; 572 } 573 if (_PyTime_FromTimespec(tp, &ts, raise) < 0) 574 return -1; 575 576 if (info) { 577 struct timespec res; 578 info->implementation = "clock_gettime(CLOCK_REALTIME)"; 579 info->monotonic = 0; 580 info->adjustable = 1; 581 if (clock_getres(CLOCK_REALTIME, &res) == 0) 582 info->resolution = res.tv_sec + res.tv_nsec * 1e-9; 583 else 584 info->resolution = 1e-9; 585 } 586 #else /* HAVE_CLOCK_GETTIME */ 587 588 /* test gettimeofday() */ 589 #ifdef GETTIMEOFDAY_NO_TZ 590 err = gettimeofday(&tv); 591 #else 592 err = gettimeofday(&tv, (struct timezone *)NULL); 593 #endif 594 if (err) { 595 if (raise) 596 PyErr_SetFromErrno(PyExc_OSError); 597 return -1; 598 } 599 if (_PyTime_FromTimeval(tp, &tv, raise) < 0) 600 return -1; 601 602 if (info) { 603 info->implementation = "gettimeofday()"; 604 info->resolution = 1e-6; 605 info->monotonic = 0; 606 info->adjustable = 1; 607 } 608 #endif /* !HAVE_CLOCK_GETTIME */ 609 #endif /* !MS_WINDOWS */ 610 return 0; 611 } 612 613 _PyTime_t 614 _PyTime_GetSystemClock(void) 615 { 616 _PyTime_t t; 617 if (pygettimeofday(&t, NULL, 0) < 0) { 618 /* should not happen, _PyTime_Init() checked the clock at startup */ 619 assert(0); 620 621 /* use a fixed value instead of a random value from the stack */ 622 t = 0; 623 } 624 return t; 625 } 626 627 int 628 _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info) 629 { 630 return pygettimeofday(t, info, 1); 631 } 632 633 static int 634 pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise) 635 { 636 #if defined(MS_WINDOWS) 637 ULONGLONG ticks; 638 _PyTime_t t; 639 640 assert(info == NULL || raise); 641 642 ticks = GetTickCount64(); 643 Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t)); 644 t = (_PyTime_t)ticks; 645 646 if (_PyTime_check_mul_overflow(t, MS_TO_NS)) { 647 if (raise) { 648 _PyTime_overflow(); 649 return -1; 650 } 651 /* Hello, time traveler! */ 652 assert(0); 653 } 654 *tp = t * MS_TO_NS; 655 656 if (info) { 657 DWORD timeAdjustment, timeIncrement; 658 BOOL isTimeAdjustmentDisabled, ok; 659 info->implementation = "GetTickCount64()"; 660 info->monotonic = 1; 661 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, 662 &isTimeAdjustmentDisabled); 663 if (!ok) { 664 PyErr_SetFromWindowsErr(0); 665 return -1; 666 } 667 info->resolution = timeIncrement * 1e-7; 668 info->adjustable = 0; 669 } 670 671 #elif defined(__APPLE__) 672 static mach_timebase_info_data_t timebase; 673 uint64_t time; 674 675 if (timebase.denom == 0) { 676 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot 677 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ 678 (void)mach_timebase_info(&timebase); 679 } 680 681 time = mach_absolute_time(); 682 683 /* apply timebase factor */ 684 time *= timebase.numer; 685 time /= timebase.denom; 686 687 *tp = time; 688 689 if (info) { 690 info->implementation = "mach_absolute_time()"; 691 info->resolution = (double)timebase.numer / timebase.denom * 1e-9; 692 info->monotonic = 1; 693 info->adjustable = 0; 694 } 695 696 #else 697 struct timespec ts; 698 #ifdef CLOCK_HIGHRES 699 const clockid_t clk_id = CLOCK_HIGHRES; 700 const char *implementation = "clock_gettime(CLOCK_HIGHRES)"; 701 #else 702 const clockid_t clk_id = CLOCK_MONOTONIC; 703 const char *implementation = "clock_gettime(CLOCK_MONOTONIC)"; 704 #endif 705 706 assert(info == NULL || raise); 707 708 if (clock_gettime(clk_id, &ts) != 0) { 709 if (raise) { 710 PyErr_SetFromErrno(PyExc_OSError); 711 return -1; 712 } 713 return -1; 714 } 715 716 if (info) { 717 struct timespec res; 718 info->monotonic = 1; 719 info->implementation = implementation; 720 info->adjustable = 0; 721 if (clock_getres(clk_id, &res) != 0) { 722 PyErr_SetFromErrno(PyExc_OSError); 723 return -1; 724 } 725 info->resolution = res.tv_sec + res.tv_nsec * 1e-9; 726 } 727 if (_PyTime_FromTimespec(tp, &ts, raise) < 0) 728 return -1; 729 #endif 730 return 0; 731 } 732 733 _PyTime_t 734 _PyTime_GetMonotonicClock(void) 735 { 736 _PyTime_t t; 737 if (pymonotonic(&t, NULL, 0) < 0) { 738 /* should not happen, _PyTime_Init() checked that monotonic clock at 739 startup */ 740 assert(0); 741 742 /* use a fixed value instead of a random value from the stack */ 743 t = 0; 744 } 745 return t; 746 } 747 748 int 749 _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) 750 { 751 return pymonotonic(tp, info, 1); 752 } 753 754 int 755 _PyTime_Init(void) 756 { 757 _PyTime_t t; 758 759 /* ensure that the system clock works */ 760 if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) 761 return -1; 762 763 /* ensure that the operating system provides a monotonic clock */ 764 if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) 765 return -1; 766 767 return 0; 768 } 769 770 int 771 _PyTime_localtime(time_t t, struct tm *tm) 772 { 773 #ifdef MS_WINDOWS 774 int error; 775 776 error = localtime_s(tm, &t); 777 if (error != 0) { 778 errno = error; 779 PyErr_SetFromErrno(PyExc_OSError); 780 return -1; 781 } 782 return 0; 783 #else /* !MS_WINDOWS */ 784 if (localtime_r(&t, tm) == NULL) { 785 #ifdef EINVAL 786 if (errno == 0) 787 errno = EINVAL; 788 #endif 789 PyErr_SetFromErrno(PyExc_OSError); 790 return -1; 791 } 792 return 0; 793 #endif /* MS_WINDOWS */ 794 } 795 796 int 797 _PyTime_gmtime(time_t t, struct tm *tm) 798 { 799 #ifdef MS_WINDOWS 800 int error; 801 802 error = gmtime_s(tm, &t); 803 if (error != 0) { 804 errno = error; 805 PyErr_SetFromErrno(PyExc_OSError); 806 return -1; 807 } 808 return 0; 809 #else /* !MS_WINDOWS */ 810 if (gmtime_r(&t, tm) == NULL) { 811 #ifdef EINVAL 812 if (errno == 0) 813 errno = EINVAL; 814 #endif 815 PyErr_SetFromErrno(PyExc_OSError); 816 return -1; 817 } 818 return 0; 819 #endif /* MS_WINDOWS */ 820 } 821