Update documentation for keymgmt export utils
[openssl.git] / crypto / sleep.c
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
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 void OSSL_sleep(uint64_t millis)
17 {
18 # ifdef OPENSSL_SYS_VXWORKS
19     struct timespec ts;
20
21     ts.tv_sec = (long int) (millis / 1000);
22     ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
23     nanosleep(&ts, NULL);
24 # elif defined(__TANDEM)
25 #  if !defined(_REENTRANT)
26 #   include <cextdecs.h(PROCESS_DELAY_)>
27
28     /* HPNS does not support usleep for non threaded apps */
29     PROCESS_DELAY_(millis * 1000);
30 #  elif defined(_SPT_MODEL_)
31 #   include <spthread.h>
32 #   include <spt_extensions.h>
33
34     usleep(millis * 1000);
35 #  else
36     usleep(millis * 1000);
37 #  endif
38 # else
39     usleep(millis * 1000);
40 # endif
41 }
42 #elif defined(_WIN32)
43 # include <windows.h>
44
45 void OSSL_sleep(uint64_t millis)
46 {
47     /*
48      * Windows' Sleep() takes a DWORD argument, which is smaller than
49      * a uint64_t, so we need to split the two to shut the compiler up.
50      */
51     DWORD dword_times;
52     DWORD i;
53
54     dword_times = (DWORD)(millis >> (8 * sizeof(DWORD)));
55     millis &= (DWORD)-1;
56     if (dword_times > 0) {
57         for (i = dword_times; i-- > 0;)
58             Sleep((DWORD)-1);
59         /*
60          * The loop above slept 1 millisec less on each iteration than it
61          * should, this compensates by sleeping as many milliseconds as there
62          * were iterations.  Yes, this is nit picky!
63          */
64         Sleep(dword_times);
65     }
66
67     /* Now, sleep the remaining milliseconds */
68     Sleep((DWORD)(millis));
69 }
70 #else
71 /* Fallback to a busy wait */
72 # include "internal/time.h"
73
74 static void ossl_sleep_secs(uint64_t secs)
75 {
76     /*
77      * sleep() takes an unsigned int argument, which is smaller than
78      * a uint64_t, so it needs to be called in smaller increments.
79      */
80     unsigned int uint_times;
81     unsigned int i;
82
83     uint_times = (unsigned int)(secs >> (8 * sizeof(unsigned int)));
84     if (uint_times > 0) {
85         for (i = uint_times; i-- > 0;)
86             sleep((unsigned int)-1);
87         /*
88          * The loop above slept 1 second less on each iteration than it
89          * should, this compensates by sleeping as many seconds as there were
90          * iterations.  Yes, this is nit picky!
91          */
92         sleep(uint_times);
93     }
94 }
95
96 static void ossl_sleep_millis(uint64_t millis)
97 {
98     const OSSL_TIME finish
99         = ossl_time_add(ossl_time_now(), ossl_ms2time(millis));
100
101     while (ossl_time_compare(ossl_time_now(), finish) < 0)
102         /* busy wait */ ;
103 }
104
105 void OSSL_sleep(uint64_t millis)
106 {
107     ossl_sleep_secs(millis / 1000);
108     ossl_sleep_millis(millis % 1000);
109 }
110 #endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */