sleep.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright 2022 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. void OSSL_sleep(uint64_t millis)
  14. {
  15. # ifdef OPENSSL_SYS_VXWORKS
  16. struct timespec ts;
  17. ts.tv_sec = (long int) (millis / 1000);
  18. ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
  19. nanosleep(&ts, NULL);
  20. # elif defined(__TANDEM)
  21. # if !defined(_REENTRANT)
  22. # include <cextdecs.h(PROCESS_DELAY_)>
  23. /* HPNS does not support usleep for non threaded apps */
  24. PROCESS_DELAY_(millis * 1000);
  25. # elif defined(_SPT_MODEL_)
  26. # include <spthread.h>
  27. # include <spt_extensions.h>
  28. usleep(millis * 1000);
  29. # else
  30. usleep(millis * 1000);
  31. # endif
  32. # else
  33. usleep(millis * 1000);
  34. # endif
  35. }
  36. #elif defined(_WIN32)
  37. # include <windows.h>
  38. void OSSL_sleep(uint64_t millis)
  39. {
  40. /*
  41. * Windows' Sleep() takes a DWORD argument, which is smaller than
  42. * a uint64_t, so we need to split the two to shut the compiler up.
  43. */
  44. DWORD dword_times;
  45. DWORD i;
  46. dword_times = (DWORD)(millis >> (8 * sizeof(DWORD)));
  47. millis &= (DWORD)-1;
  48. if (dword_times > 0) {
  49. for (i = dword_times; i-- > 0;)
  50. Sleep((DWORD)-1);
  51. /*
  52. * The loop above slept 1 millisec less on each iteration than it
  53. * should, this compensates by sleeping as many milliseconds as there
  54. * were iterations. Yes, this is nit picky!
  55. */
  56. Sleep(dword_times);
  57. }
  58. /* Now, sleep the remaining milliseconds */
  59. Sleep((DWORD)(millis));
  60. }
  61. #else
  62. /* Fallback to a busy wait */
  63. # include "internal/time.h"
  64. static void ossl_sleep_secs(uint64_t secs)
  65. {
  66. /*
  67. * sleep() takes an unsigned int argument, which is smaller than
  68. * a uint64_t, so it needs to be called in smaller increments.
  69. */
  70. unsigned int uint_times;
  71. unsigned int i;
  72. uint_times = (unsigned int)(secs >> (8 * sizeof(unsigned int)));
  73. if (uint_times > 0) {
  74. for (i = uint_times; i-- > 0;)
  75. sleep((unsigned int)-1);
  76. /*
  77. * The loop above slept 1 second less on each iteration than it
  78. * should, this compensates by sleeping as many seconds as there were
  79. * iterations. Yes, this is nit picky!
  80. */
  81. sleep(uint_times);
  82. }
  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__) */