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