sleep.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright 2022-2024 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. /* system-specific variants defining OSSL_sleep() */
  12. #if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
  13. # if defined(OPENSSL_USE_USLEEP) \
  14. || defined(__DJGPP__) \
  15. || (defined(__TANDEM) && defined(_REENTRANT))
  16. /*
  17. * usleep() was made obsolete by POSIX.1-2008, and nanosleep()
  18. * should be used instead. However, nanosleep() isn't implemented
  19. * on the platforms given above, so we still use it for those.
  20. * Also, OPENSSL_USE_USLEEP can be defined to enable the use of
  21. * usleep, if it turns out that nanosleep() is unavailable.
  22. */
  23. # include <unistd.h>
  24. void OSSL_sleep(uint64_t millis)
  25. {
  26. unsigned int s = (unsigned int)(millis / 1000);
  27. unsigned int us = (unsigned int)((millis % 1000) * 1000);
  28. if (s > 0)
  29. sleep(s);
  30. /*
  31. * On NonStop with the PUT thread model, thread context switch is
  32. * cooperative, with usleep() being a "natural" context switch point.
  33. * We avoid checking us > 0 here, to allow that context switch to
  34. * happen.
  35. */
  36. usleep(us);
  37. }
  38. # elif defined(__TANDEM) && !defined(_REENTRANT)
  39. # include <cextdecs.h(PROCESS_DELAY_)>
  40. void OSSL_sleep(uint64_t millis)
  41. {
  42. /* HPNS does not support usleep for non threaded apps */
  43. PROCESS_DELAY_(millis * 1000);
  44. }
  45. # else
  46. /* nanosleep is defined by POSIX.1-2001 */
  47. # include <time.h>
  48. void OSSL_sleep(uint64_t millis)
  49. {
  50. struct timespec ts;
  51. ts.tv_sec = (long int) (millis / 1000);
  52. ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
  53. nanosleep(&ts, NULL);
  54. }
  55. # endif
  56. #elif defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
  57. # include <windows.h>
  58. void OSSL_sleep(uint64_t millis)
  59. {
  60. /*
  61. * Windows' Sleep() takes a DWORD argument, which is smaller than
  62. * a uint64_t, so we need to limit it to 49 days, which should be enough.
  63. */
  64. DWORD limited_millis = (DWORD)-1;
  65. if (millis < limited_millis)
  66. limited_millis = (DWORD)millis;
  67. Sleep(limited_millis);
  68. }
  69. #else
  70. /* Fallback to a busy wait */
  71. # include "internal/time.h"
  72. static void ossl_sleep_secs(uint64_t secs)
  73. {
  74. /*
  75. * sleep() takes an unsigned int argument, which is smaller than
  76. * a uint64_t, so it needs to be limited to 136 years which
  77. * should be enough even for Sleeping Beauty.
  78. */
  79. unsigned int limited_secs = UINT_MAX;
  80. if (secs < limited_secs)
  81. limited_secs = (unsigned int)secs;
  82. sleep(limited_secs);
  83. }
  84. static void ossl_sleep_millis(uint64_t millis)
  85. {
  86. const OSSL_TIME finish
  87. = ossl_time_add(ossl_time_now(), ossl_ms2time(millis));
  88. while (ossl_time_compare(ossl_time_now(), finish) < 0)
  89. /* busy wait */ ;
  90. }
  91. void OSSL_sleep(uint64_t millis)
  92. {
  93. ossl_sleep_secs(millis / 1000);
  94. ossl_sleep_millis(millis % 1000);
  95. }
  96. #endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */