Skip to content

Commit bc269eb

Browse files
authored
Use monotonic clock for sleep (WebAssembly#753)
Currently, `sleep` calls `clock_nanosleep` with `CLOCK_REALTIME`, which unconditionally returns `ENOTSUP` on WASIp{2,3}. This PR changes this to use `CLOCK_MONOTONIC`.
1 parent e50614a commit bc269eb

5 files changed

Lines changed: 52 additions & 3 deletions

File tree

libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
4141
// Note: rmtp is ignored
4242

4343
if (clock_id != CLOCK_MONOTONIC) {
44-
// wasip2 only provides a pollable for monotonic clocks
44+
// wasip{2,3} only provide a pollable for monotonic clocks
4545
return ENOTSUP;
4646
}
4747

libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
int nanosleep(const struct timespec *rqtp, struct timespec *rem) {
1010
#if defined(__wasip2__) || defined(__wasip3__)
11-
// FIXME(WebAssembly/WASI#857): wasip2 only supports the monotonic clock for
11+
// FIXME(WebAssembly/WASI#857): wasip2/p3 only supports the monotonic clock for
1212
// sleeping.
1313
clockid_t clock = CLOCK_MONOTONIC;
1414
#else

libc-bottom-half/cloudlibc/src/libc/unistd/sleep.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,20 @@
44

55
#include <time.h>
66
#include <unistd.h>
7+
#include <wasi/version.h>
78

89
unsigned int sleep(unsigned int seconds) {
910
struct timespec ts = {.tv_sec = seconds, .tv_nsec = 0};
10-
if (clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL) != 0)
11+
// FIXME(WebAssembly/WASI#857): wasip2/p3 only supports the monotonic clock for
12+
// sleeping.
13+
#if defined(__wasip1__)
14+
clockid_t clock_id = CLOCK_REALTIME;
15+
#elif defined(__wasip2__) || defined(__wasip3__)
16+
clockid_t clock_id = CLOCK_MONOTONIC;
17+
#else
18+
#error "Unsupported WASI version"
19+
#endif
20+
if (clock_nanosleep(clock_id, 0, &ts, NULL) != 0)
1121
return seconds;
1222
return 0;
1323
}

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ add_wasilibc_test(rewinddir.c FS FAILP3)
298298
add_wasilibc_test(seekdir.c FS FAILP3)
299299
add_wasilibc_test(usleep.c)
300300
add_wasilibc_test(nanosleep.c)
301+
add_wasilibc_test(sleep.c)
301302
add_wasilibc_test(write.c FS FAILP3)
302303
add_wasilibc_test(wasi-defines.c)
303304

test/src/sleep.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "test.h"
2+
#include <errno.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <sys/time.h>
6+
#include <time.h>
7+
#include <wasi/version.h>
8+
9+
#define TEST(c) \
10+
do { \
11+
errno = 0; \
12+
if (!(c)) \
13+
t_error("%s failed (errno = %d)\n", #c, errno); \
14+
} while (0)
15+
16+
#ifdef __wasip1__
17+
#define CLOCK CLOCK_REALTIME
18+
#else
19+
#define CLOCK CLOCK_MONOTONIC
20+
#endif
21+
22+
int main(void) {
23+
// Sleep for a total of 2 seconds
24+
unsigned int seconds_to_sleep = 2;
25+
26+
struct timespec start_time, end_time;
27+
clock_gettime(CLOCK, &start_time);
28+
TEST(sleep(seconds_to_sleep) == 0);
29+
clock_gettime(CLOCK, &end_time);
30+
TEST(end_time.tv_sec - start_time.tv_sec <= 3);
31+
32+
long nanoseconds_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1E9 -
33+
start_time.tv_nsec + end_time.tv_nsec;
34+
35+
TEST(nanoseconds_elapsed >= seconds_to_sleep * 1E9);
36+
37+
return t_status;
38+
}

0 commit comments

Comments
 (0)