#include <openssl/crypto.h>
#include "internal/e_os.h"
+#include "internal/time.h"
/* system-specific variants defining OSSL_sleep() */
-#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
+#if (defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)) && !defined(OPENSSL_USE_SLEEP_BUSYLOOP)
# if defined(OPENSSL_USE_USLEEP) \
|| defined(__DJGPP__) \
*/
# include <unistd.h>
-void OSSL_sleep(uint64_t millis)
+static void ossl_sleep_millis(uint64_t millis)
{
unsigned int s = (unsigned int)(millis / 1000);
unsigned int us = (unsigned int)((millis % 1000) * 1000);
# elif defined(__TANDEM) && !defined(_REENTRANT)
# include <cextdecs.h(PROCESS_DELAY_)>
-void OSSL_sleep(uint64_t millis)
+static void ossl_sleep_millis(uint64_t millis)
{
/* HPNS does not support usleep for non threaded apps */
PROCESS_DELAY_(millis * 1000);
/* nanosleep is defined by POSIX.1-2001 */
# include <time.h>
-void OSSL_sleep(uint64_t millis)
+static void ossl_sleep_millis(uint64_t millis)
{
struct timespec ts;
#elif defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
# include <windows.h>
-void OSSL_sleep(uint64_t millis)
+static void ossl_sleep_millis(uint64_t millis)
{
/*
* Windows' Sleep() takes a DWORD argument, which is smaller than
#else
/* Fallback to a busy wait */
-# include "internal/time.h"
+# define USE_SLEEP_SECS
static void ossl_sleep_secs(uint64_t secs)
{
while (ossl_time_compare(ossl_time_now(), finish) < 0)
/* busy wait */ ;
}
+#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
void OSSL_sleep(uint64_t millis)
{
- ossl_sleep_secs(millis / 1000);
- ossl_sleep_millis(millis % 1000);
+ OSSL_TIME now = ossl_time_now();
+ OSSL_TIME finish = ossl_time_add(now, ossl_ms2time(millis));
+ uint64_t left = millis;
+
+#if defined(USE_SLEEP_SECS)
+ do {
+ ossl_sleep_secs(left / 1000);
+ now = ossl_time_now();
+ left = ossl_time2ms(ossl_time_subtract(finish, now));
+ } while (ossl_time_compare(now, finish) < 0 && left > 1000);
+
+ if (ossl_time_compare(now, finish) >= 0)
+ return;
+#endif
+
+ do {
+ ossl_sleep_millis(left);
+ now = ossl_time_now();
+ left = ossl_time2ms(ossl_time_subtract(finish, now));
+ } while (ossl_time_compare(now, finish) < 0);
}
-#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
#include "internal/numbers.h"
#include "internal/time.h"
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
+# include <signal.h>
+#endif
+
static int test_sanity_null_zero(void)
{
char *p;
return CRYPTO_memcmp("ab", "cd", 2);
}
-static int test_sanity_sleep(void)
+static const struct sleep_test_vector {
+ uint64_t val;
+} sleep_test_vectors[] = { { 0 }, { 1 }, { 999 }, { 1000 } };
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
+static void
+alrm_handler(int sig)
+{
+}
+#endif /* defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L */
+
+static int test_sanity_sleep(int i)
{
+ const struct sleep_test_vector * const td = sleep_test_vectors + i;
OSSL_TIME start = ossl_time_now();
- uint64_t seconds;
+ uint64_t ms;
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
/*
- * On any reasonable system this must sleep at least one second
- * but not more than 20.
- * Assuming there is no interruption.
+ * Set up an interrupt timer to check that OSSL_sleep doesn't return early
+ * due to interrupts.
*/
- OSSL_sleep(1000);
+ do {
+ static const struct sigaction sa = { .sa_handler = alrm_handler };
+ static const struct itimerval it = { .it_value.tv_usec = 111111 };
+ sigset_t mask;
+
+ if (sigaction(SIGALRM, &sa, NULL)) {
+ TEST_perror("test_sanity_sleep: sigaction");
+ break;
+ }
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
+ TEST_perror("test_sanity_sleep: sigprocmask");
+ break;
+ }
+
+ if (setitimer(ITIMER_REAL, &it, NULL)) {
+ TEST_perror("test_sanity_sleep: arm setitimer");
+ break;
+ }
+ } while (0);
+#endif /* defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L */
- seconds = ossl_time2seconds(ossl_time_subtract(ossl_time_now(), start));
+ /*
+ * On any reasonable system this must sleep at least the specified time
+ * but not more than 20 seconds more than that.
+ */
+ OSSL_sleep(td->val);
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
+ /* disarm the timer */
+ do {
+ if (setitimer(ITIMER_REAL, NULL, NULL)) {
+ TEST_perror("test_sanity_sleep: disarm setitimer");
+ break;
+ }
+ } while (0);
+#endif /* defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L */
- if (!TEST_uint64_t_ge(seconds, 1) || !TEST_uint64_t_le(seconds, 20))
- return 0;
+ ms = ossl_time2ms(ossl_time_subtract(ossl_time_now(), start));
+
+ if (!TEST_uint64_t_ge(ms, td->val) + !TEST_uint64_t_le(ms, td->val + 20000))
+ return 0;
return 1;
}
ADD_TEST(test_sanity_unsigned_conversion);
ADD_TEST(test_sanity_range);
ADD_TEST(test_sanity_memcmp);
- ADD_TEST(test_sanity_sleep);
+ ADD_ALL_TESTS(test_sanity_sleep, OSSL_NELEM(sleep_test_vectors));
return 1;
}