diff --git a/Makefile b/Makefile index df3db5385..57c03f48b 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,8 @@ LIBC_BOTTOM_HALF_ALL_SOURCES := $(LIBC_BOTTOM_HALF_ALL_SOURCES) $(LIBC_BOTTOM_HA LIBWASI_EMULATED_MMAN_SOURCES = \ $(shell find $(LIBC_BOTTOM_HALF_DIR)/mman -name \*.c) +LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES = \ + $(shell find $(LIBC_BOTTOM_HALF_DIR)/clocks -name \*.c) LIBWASI_EMULATED_SIGNAL_SOURCES = \ $(shell find $(LIBC_BOTTOM_HALF_DIR)/signal -name \*.c) LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \ @@ -229,6 +231,7 @@ MUSL_PRINTSCAN_OBJS = $(call objs,$(MUSL_PRINTSCAN_SOURCES)) MUSL_PRINTSCAN_LONG_DOUBLE_OBJS = $(patsubst %.o,%.long-double.o,$(MUSL_PRINTSCAN_OBJS)) MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS = $(patsubst %.o,%.no-floating-point.o,$(MUSL_PRINTSCAN_OBJS)) LIBWASI_EMULATED_MMAN_OBJS = $(call objs,$(LIBWASI_EMULATED_MMAN_SOURCES)) +LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CLOCKS_SOURCES)) LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES)) LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES)) @@ -332,6 +335,8 @@ $(SYSROOT_LIB)/libc-printscan-no-floating-point.a: $(MUSL_PRINTSCAN_NO_FLOATING_ $(SYSROOT_LIB)/libwasi-emulated-mman.a: $(LIBWASI_EMULATED_MMAN_OBJS) +$(SYSROOT_LIB)/libwasi-emulated-process-clocks.a: $(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) + $(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) %.a: @@ -392,6 +397,9 @@ $(LIBC_TOP_HALF_ALL_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_NO -Wno-dangling-else \ -Wno-unknown-pragmas +$(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS): CFLAGS += \ + -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC) + include_dirs: $(RM) -r "$(SYSROOT)" @@ -432,6 +440,7 @@ libc: include_dirs \ $(SYSROOT_LIB)/libc-printscan-long-double.a \ $(SYSROOT_LIB)/libc-printscan-no-floating-point.a \ $(SYSROOT_LIB)/libwasi-emulated-mman.a \ + $(SYSROOT_LIB)/libwasi-emulated-process-clocks.a \ $(SYSROOT_LIB)/libwasi-emulated-signal.a finish: startup_files libc @@ -454,7 +463,7 @@ finish: startup_files libc @# LLVM PR40497, which is fixed in 9.0, but not in 8.0. @# Ignore certain llvm builtin symbols such as those starting with __mul @# since these dependencies can vary between llvm versions. - "$(WASM_NM)" --defined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/*.o \ + "$(WASM_NM)" --defined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libwasi-emulated-*.a "$(SYSROOT_LIB)"/*.o \ |grep ' [[:upper:]] ' |sed 's/.* [[:upper:]] //' |LC_ALL=C sort > "$(SYSROOT_SHARE)/defined-symbols.txt" for undef_sym in $$("$(WASM_NM)" --undefined-only "$(SYSROOT_LIB)"/libc.a "$(SYSROOT_LIB)"/libc-*.a "$(SYSROOT_LIB)"/*.o \ |grep ' U ' |sed 's/.* U //' |LC_ALL=C sort |uniq); do \ @@ -467,7 +476,7 @@ finish: startup_files libc # Generate a test file that includes all public header files. # cd "$(SYSROOT)" && \ - for header in $$(find include -type f -not -name mman.h -not -name signal.h |grep -v /bits/); do \ + for header in $$(find include -type f -not -name mman.h -not -name signal.h -not -name times.h -not -name resource.h |grep -v /bits/); do \ echo '#include <'$$header'>' | sed 's/include\///' ; \ done |LC_ALL=C sort >share/$(MULTIARCH_TRIPLE)/include-all.c ; \ cd - >/dev/null diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index eb33f4b97..657ebb81d 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -11,11 +11,14 @@ _IO_putc _IO_putc_unlocked __EINVAL __ENOMEM +__SIG_ERR +__SIG_IGN __asctime_r __assert_fail __c_dot_utf8 __c_dot_utf8_locale __c_locale +__clock __clock_gettime __cos __cosdf @@ -227,6 +230,7 @@ __strtoull_internal __strtoumax_internal __strxfrm_l __sysinfo +__sysv_signal __tan __tandf __tanl @@ -387,6 +391,7 @@ atoll basename bcmp bcopy +bsd_signal bsearch btowc bzero @@ -838,10 +843,12 @@ memset mkdir mkdirat mktime +mmap modf modff modfl mrand48 +munmap nan nanf nanl @@ -893,6 +900,7 @@ printf program_invocation_name program_invocation_short_name pselect +psignal putc putc_unlocked putchar @@ -908,6 +916,7 @@ pwrite pwritev qsort quick_exit +raise rand rand_r random @@ -969,6 +978,7 @@ setlocale setstate setvbuf shutdown +signal signgam significand significandf @@ -1030,6 +1040,7 @@ strpbrk strptime strrchr strsep +strsignal strspn strstr strtod diff --git a/expected/wasm32-wasi/include-all.c b/expected/wasm32-wasi/include-all.c index 6e8a59a85..86297f3ef 100644 --- a/expected/wasm32-wasi/include-all.c +++ b/expected/wasm32-wasi/include-all.c @@ -137,7 +137,6 @@ #include #include #include -#include #include #include #include @@ -146,7 +145,6 @@ #include #include #include -#include #include #include #include diff --git a/expected/wasm32-wasi/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt index 63c07cc25..fa1d9fcd7 100644 --- a/expected/wasm32-wasi/predefined-macros.txt +++ b/expected/wasm32-wasi/predefined-macros.txt @@ -2306,14 +2306,12 @@ #define _SYS_PARAM_H #define _SYS_RANDOM_H #define _SYS_REG_H -#define _SYS_RESOURCE_H #define _SYS_SELECT_H #define _SYS_SOCKET_H #define _SYS_STAT_H #define _SYS_SYSCALL_H #define _SYS_SYSINFO_H #define _SYS_TIMEB_H -#define _SYS_TIMES_H #define _SYS_TIMEX_H #define _SYS_TIME_H #define _SYS_TTYDEFAULTS_H diff --git a/libc-bottom-half/clocks/clock.c b/libc-bottom-half/clocks/clock.c new file mode 100644 index 000000000..6767d7393 --- /dev/null +++ b/libc-bottom-half/clocks/clock.c @@ -0,0 +1,35 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include + +_Static_assert( + CLOCKS_PER_SEC == NSEC_PER_SEC, + "This implementation assumes that `clock` is in nanoseconds" +); + +// Snapshot of the monotonic clock at the start of the program. +static __wasi_timestamp_t start; + +// Use a priority of 10 to run fairly early in the implementation-reserved +// constructor priority range. +__attribute__((constructor(10))) +static void init(void) { + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &start); +} + +// Define the libc symbol as `__clock` so that we can reliably call it +// from elsewhere in libc. +clock_t __clock(void) { + // Use `MONOTONIC` instead of `PROCESS_CPUTIME_ID` since WASI doesn't have + // an inherent concept of a process. Note that this means we'll incorrectly + // include time from other processes, so this function is only declared by + // the headers if `_WASI_EMULATED_PROCESS_CLOCKS` is defined. + __wasi_timestamp_t now = 0; + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &now); + return now - start; +} + +// Define a user-visible alias as a weak symbol. +__attribute__((__weak__, __alias__("__clock"))) +clock_t clock(void); diff --git a/libc-bottom-half/clocks/getrusage.c b/libc-bottom-half/clocks/getrusage.c new file mode 100644 index 000000000..d0113c513 --- /dev/null +++ b/libc-bottom-half/clocks/getrusage.c @@ -0,0 +1,28 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include +#include +#include + +// `clock` is a weak symbol so that application code can override it. +// We want to use the function in libc, so use the libc-internal name. +clock_t __clock(void); + +int getrusage(int who, struct rusage *r_usage) { + switch (who) { + case RUSAGE_SELF: { + __wasi_timestamp_t usertime = __clock(); + *r_usage = (struct rusage) { + .ru_utime = timestamp_to_timeval(usertime) + }; + return 0; + } + case RUSAGE_CHILDREN: + *r_usage = (struct rusage) {}; + return 0; + default: + errno = EINVAL; + return -1; + } +} diff --git a/libc-bottom-half/clocks/times.c b/libc-bottom-half/clocks/times.c new file mode 100644 index 000000000..e245569a4 --- /dev/null +++ b/libc-bottom-half/clocks/times.c @@ -0,0 +1,26 @@ +#define _WASI_EMULATED_PROCESS_CLOCKS +#include +#include +#include +#include + +_Static_assert( + CLOCKS_PER_SEC == NSEC_PER_SEC, + "This implementation assumes that `clock` is in nanoseconds" +); + +// `clock` is a weak symbol so that application code can override it. +// We want to use the function in libc, so use the libc-internal name. +clock_t __clock(void); + +clock_t times(struct tms *buffer) { + __wasi_timestamp_t user = __clock(); + *buffer = (struct tms){ + .tms_utime = user, + .tms_cutime = user + }; + + __wasi_timestamp_t realtime = 0; + (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &realtime); + return realtime; +} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c b/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c deleted file mode 100644 index bd059c4b9..000000000 --- a/libc-bottom-half/cloudlibc/src/libc/sys/resource/getrusage.c +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include - -#include -#include - -int getrusage(int who, struct rusage *r_usage) { - switch (who) { - case RUSAGE_SELF: { - __wasi_timestamp_t usertime = 0; - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 1000, - &usertime); - *r_usage = (struct rusage){ - .ru_utime = timestamp_to_timeval(usertime), - }; - return 0; - } - case RUSAGE_CHILDREN: - *r_usage = (struct rusage){}; - return 0; - default: - errno = EINVAL; - return -1; - } -} diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c b/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c deleted file mode 100644 index fdb1a38f3..000000000 --- a/libc-bottom-half/cloudlibc/src/libc/sys/times/times.c +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include - -#include -#include - -static_assert(CLOCKS_PER_SEC == NSEC_PER_SEC, - "Timestamp should need no conversion"); - -clock_t times(struct tms *buffer) { - // Obtain user time. - __wasi_timestamp_t usertime = 0; - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 0, &usertime); - *buffer = (struct tms){.tms_utime = usertime}; - - // Obtain real time. - __wasi_timestamp_t realtime = 0; - (void)__wasi_clock_time_get(__WASI_CLOCKID_MONOTONIC, 0, &realtime); - return realtime; -} diff --git a/libc-bottom-half/cloudlibc/src/libc/time/clock.c b/libc-bottom-half/cloudlibc/src/libc/time/clock.c deleted file mode 100644 index cc4b6db0c..000000000 --- a/libc-bottom-half/cloudlibc/src/libc/time/clock.c +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ -// -// SPDX-License-Identifier: BSD-2-Clause - -#include - -#include -#include -#include - -static_assert(CLOCKS_PER_SEC == NSEC_PER_SEC, - "Timestamp should need no conversion"); - -clock_t clock(void) { - __wasi_timestamp_t ts = 0; - (void)__wasi_clock_time_get(__WASI_CLOCKID_PROCESS_CPUTIME_ID, 0, &ts); - return ts; -} diff --git a/libc-top-half/musl/include/sys/param.h b/libc-top-half/musl/include/sys/param.h index ce6b80198..01411725e 100644 --- a/libc-top-half/musl/include/sys/param.h +++ b/libc-top-half/musl/include/sys/param.h @@ -28,7 +28,9 @@ #define roundup(n,d) (howmany(n,d)*(d)) #define powerof2(n) !(((n)-1) & (n)) +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_PROCESS_CLOCKS) #include +#endif #include #include diff --git a/libc-top-half/musl/include/sys/resource.h b/libc-top-half/musl/include/sys/resource.h index 8b5533115..6c3a7ff2a 100644 --- a/libc-top-half/musl/include/sys/resource.h +++ b/libc-top-half/musl/include/sys/resource.h @@ -1,3 +1,8 @@ +#ifndef _WASI_EMULATED_PROCESS_CLOCKS +#error WASI lacks process-associated clocks; to enable emulation of the `getrusage` function using \ +the wall clock, which isn't sensitive to whether the program is running or suspended, \ +compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks +#else #ifndef _SYS_RESOURCE_H #define _SYS_RESOURCE_H @@ -118,3 +123,4 @@ __REDIR(getrusage, __getrusage_time64); #endif #endif +#endif diff --git a/libc-top-half/musl/include/sys/times.h b/libc-top-half/musl/include/sys/times.h index 2256334e2..cdaeeee91 100644 --- a/libc-top-half/musl/include/sys/times.h +++ b/libc-top-half/musl/include/sys/times.h @@ -1,3 +1,8 @@ +#ifndef _WASI_EMULATED_PROCESS_CLOCKS +#error WASI lacks process-associated clocks; to enable emulation of the `times` function using \ +the wall clock, which isn't sensitive to whether the program is running or suspended, \ +compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks +#else #ifndef _SYS_TIMES_H #define _SYS_TIMES_H @@ -26,4 +31,4 @@ clock_t times (struct tms *); #endif #endif - +#endif diff --git a/libc-top-half/musl/include/time.h b/libc-top-half/musl/include/time.h index 01ba89bf1..1fb87689d 100644 --- a/libc-top-half/musl/include/time.h +++ b/libc-top-half/musl/include/time.h @@ -58,7 +58,16 @@ struct tm { #include <__header_time.h> #endif +#if defined(__wasilibc_unmodified_upstream) || defined(_WASI_EMULATED_PROCESS_CLOCKS) clock_t clock (void); +#else +__attribute__((__deprecated__( +"WASI lacks process-associated clocks; to enable emulation of the `clock` function using " +"the wall clock, which isn't sensitive to whether the program is running or suspended, " +"compile with -D_WASI_EMULATED_PROCESS_CLOCKS and link with -lwasi-emulated-process-clocks" +))) +clock_t clock (void); +#endif time_t time (time_t *); double difftime (time_t, time_t); time_t mktime (struct tm *); diff --git a/libc-top-half/musl/src/conf/sysconf.c b/libc-top-half/musl/src/conf/sysconf.c index d58da7f14..d6467b639 100644 --- a/libc-top-half/musl/src/conf/sysconf.c +++ b/libc-top-half/musl/src/conf/sysconf.c @@ -1,7 +1,9 @@ #include #include #include +#ifdef __wasilibc_unmodified_upstream // WASI has no process-level accounting #include +#endif #ifdef __wasilibc_unmodified_upstream // WASI has no realtime signals #include #endif