File: sleep.c

package info (click to toggle)
edk2 2025.02-10
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 271,976 kB
  • sloc: ansic: 2,110,013; asm: 263,832; perl: 227,730; python: 149,827; sh: 34,967; cpp: 21,813; makefile: 3,337; xml: 806; pascal: 721; lisp: 35; ruby: 16; sed: 6; tcl: 4
file content (116 lines) | stat: -rw-r--r-- 3,219 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <openssl/crypto.h>
#include "internal/e_os.h"

/* system-specific variants defining OSSL_sleep() */
#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)

# if defined(OPENSSL_USE_USLEEP)                        \
    || defined(__DJGPP__)                               \
    || (defined(__TANDEM) && defined(_REENTRANT))

/*
 * usleep() was made obsolete by POSIX.1-2008, and nanosleep()
 * should be used instead.  However, nanosleep() isn't implemented
 * on the platforms given above, so we still use it for those.
 * Also, OPENSSL_USE_USLEEP can be defined to enable the use of
 * usleep, if it turns out that nanosleep() is unavailable.
 */

#  include <unistd.h>
void OSSL_sleep(uint64_t millis)
{
    unsigned int s = (unsigned int)(millis / 1000);
    unsigned int us = (unsigned int)((millis % 1000) * 1000);

    if (s > 0)
        sleep(s);
    /*
     * On NonStop with the PUT thread model, thread context switch is
     * cooperative, with usleep() being a "natural" context switch point.
     * We avoid checking us > 0 here, to allow that context switch to
     * happen.
     */
    usleep(us);
}

# elif defined(__TANDEM) && !defined(_REENTRANT)

#  include <cextdecs.h(PROCESS_DELAY_)>
void OSSL_sleep(uint64_t millis)
{
    /* HPNS does not support usleep for non threaded apps */
    PROCESS_DELAY_(millis * 1000);
}

# else

/* nanosleep is defined by POSIX.1-2001 */
#  include <time.h>
void OSSL_sleep(uint64_t millis)
{
    struct timespec ts;

    ts.tv_sec = (long int) (millis / 1000);
    ts.tv_nsec = (long int) (millis % 1000) * 1000000ul;
    nanosleep(&ts, NULL);
}

# endif
#elif defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
# include <windows.h>

void OSSL_sleep(uint64_t millis)
{
    /*
     * Windows' Sleep() takes a DWORD argument, which is smaller than
     * a uint64_t, so we need to limit it to 49 days, which should be enough.
     */
    DWORD limited_millis = (DWORD)-1;

    if (millis < limited_millis)
        limited_millis = (DWORD)millis;
    Sleep(limited_millis);
}

#else
/* Fallback to a busy wait */
# include "internal/time.h"

static void ossl_sleep_secs(uint64_t secs)
{
    /*
     * sleep() takes an unsigned int argument, which is smaller than
     * a uint64_t, so it needs to be limited to 136 years which
     * should be enough even for Sleeping Beauty.
     */
    unsigned int limited_secs = UINT_MAX;

    if (secs < limited_secs)
        limited_secs = (unsigned int)secs;
    sleep(limited_secs);
}

static void ossl_sleep_millis(uint64_t millis)
{
    const OSSL_TIME finish
        = ossl_time_add(ossl_time_now(), ossl_ms2time(millis));

    while (ossl_time_compare(ossl_time_now(), finish) < 0)
        /* busy wait */ ;
}

void OSSL_sleep(uint64_t millis)
{
    ossl_sleep_secs(millis / 1000);
    ossl_sleep_millis(millis % 1000);
}
#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */