sleep.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/crypto.h>
  10. #include "internal/e_os.h"
  11. #include "internal/time.h"
  12. /* system-specific variants defining OSSL_sleep() */
  13. #if (defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)) \
  14. && !defined(OPENSSL_USE_SLEEP_BUSYLOOP)
  15. # include <unistd.h>
  16. static void ossl_sleep_millis(uint64_t millis)
  17. {
  18. # ifdef OPENSSL_SYS_VXWORKS
  19. struct timespec ts;
  20. ts.tv_sec = (long int) (millis / 1000);
  21. ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
  22. nanosleep(&ts, NULL);
  23. # elif defined(__TANDEM) && !defined(_REENTRANT)
  24. # include <cextdecs.h(PROCESS_DELAY_)>
  25. /* HPNS does not support usleep for non threaded apps */
  26. PROCESS_DELAY_(millis * 1000);
  27. # else
  28. unsigned int s = (unsigned int)(millis / 1000);
  29. unsigned int us = (unsigned int)((millis % 1000) * 1000);
  30. if (s > 0)
  31. sleep(s);
  32. usleep(us);
  33. # endif
  34. }
  35. #elif defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
  36. # include <windows.h>
  37. static void ossl_sleep_millis(uint64_t millis)
  38. {
  39. /*
  40. * Windows' Sleep() takes a DWORD argument, which is smaller than
  41. * a uint64_t, so we need to limit it to 49 days, which should be enough.
  42. */
  43. DWORD limited_millis = (DWORD)-1;
  44. if (millis < limited_millis)
  45. limited_millis = (DWORD)millis;
  46. Sleep(limited_millis);
  47. }
  48. #else
  49. /* Fallback to a busy wait */
  50. # define USE_SLEEP_SECS
  51. static void ossl_sleep_secs(uint64_t secs)
  52. {
  53. /*
  54. * sleep() takes an unsigned int argument, which is smaller than
  55. * a uint64_t, so it needs to be limited to 136 years which
  56. * should be enough even for Sleeping Beauty.
  57. */
  58. unsigned int limited_secs = UINT_MAX;
  59. if (secs < limited_secs)
  60. limited_secs = (unsigned int)secs;
  61. sleep(limited_secs);
  62. }
  63. static void ossl_sleep_millis(uint64_t millis)
  64. {
  65. const OSSL_TIME finish
  66. = ossl_time_add(ossl_time_now(), ossl_ms2time(millis));
  67. while (ossl_time_compare(ossl_time_now(), finish) < 0)
  68. /* busy wait */ ;
  69. }
  70. #endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
  71. void OSSL_sleep(uint64_t millis)
  72. {
  73. OSSL_TIME now = ossl_time_now();
  74. OSSL_TIME finish = ossl_time_add(now, ossl_ms2time(millis));
  75. uint64_t left = millis;
  76. #if defined(USE_SLEEP_SECS)
  77. do {
  78. ossl_sleep_secs(left / 1000);
  79. now = ossl_time_now();
  80. left = ossl_time2ms(ossl_time_subtract(finish, now));
  81. } while (ossl_time_compare(now, finish) < 0 && left > 1000);
  82. if (ossl_time_compare(now, finish) >= 0)
  83. return;
  84. #endif
  85. do {
  86. ossl_sleep_millis(left);
  87. now = ossl_time_now();
  88. left = ossl_time2ms(ossl_time_subtract(finish, now));
  89. } while (ossl_time_compare(now, finish) < 0);
  90. }