From: Dan Gohman Date: Mon, 29 Apr 2019 19:53:18 +0000 (-0700) Subject: Optimize lseek in the `tell` case. X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=cf366c06d1fcbbff3ce2a3dbc9fb65f625ed1534;p=wasi-libc.git Optimize lseek in the `tell` case. `lseek(x, 0, SEEK_CUR)` has no effect other than to return the current file offset. The patch here uses a macro with `__builtin_constant_p` to recognize this case and rewrite it to a library call that uses `fd_tell` rather than `fd_seek`, so that programs that don't need actual seeking don't end up importing `fd_seek`. This is also the first usage of `__wasi_fd_tell` in WASI libc, so this adds it to undefined-symbols.txt. --- diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index 4a4294f..aceb503 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -241,6 +241,7 @@ __wasilibc_init_preopen __wasilibc_register_preopened_fd __wasilibc_rmdirat __wasilibc_rmfileat +__wasilibc_tell __wcscoll_l __wcsftime_l __wcsxfrm_l diff --git a/expected/wasm32-wasi/predefined-macros.txt b/expected/wasm32-wasi/predefined-macros.txt index f4e8591..ad3c349 100644 --- a/expected/wasm32-wasi/predefined-macros.txt +++ b/expected/wasm32-wasi/predefined-macros.txt @@ -3816,6 +3816,7 @@ #define logb(x) __tg_real(logb, (x)) #define lrint(x) __tg_real_nocast(lrint, (x)) #define lround(x) __tg_real_nocast(lround, (x)) +#define lseek(fd,offset,whence) ({ off_t __f = (fd); off_t __o = (offset); off_t __w = (whence); __builtin_constant_p((offset)) && __builtin_constant_p((whence)) && __o == 0 && __w == SEEK_CUR ? __wasilibc_tell(__f) : lseek(__f, __o, __w); }) #define lseek64 lseek #define lstat64 lstat #define major(x) ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) )) diff --git a/expected/wasm32-wasi/undefined-symbols.txt b/expected/wasm32-wasi/undefined-symbols.txt index 92b9c80..75bee03 100644 --- a/expected/wasm32-wasi/undefined-symbols.txt +++ b/expected/wasm32-wasi/undefined-symbols.txt @@ -47,6 +47,7 @@ __wasi_fd_readdir __wasi_fd_renumber __wasi_fd_seek __wasi_fd_sync +__wasi_fd_tell __wasi_fd_write __wasi_path_create_directory __wasi_path_filestat_get diff --git a/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c index 108cc7e..a0e41b7 100644 --- a/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c +++ b/libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c @@ -11,7 +11,11 @@ static_assert(SEEK_CUR == __WASI_WHENCE_CUR, "Value mismatch"); static_assert(SEEK_END == __WASI_WHENCE_END, "Value mismatch"); static_assert(SEEK_SET == __WASI_WHENCE_SET, "Value mismatch"); +#ifdef __wasilibc_unmodified_upstream /* Optimize the readonly case of lseek */ off_t lseek(int fildes, off_t offset, int whence) { +#else +off_t (lseek)(int fildes, off_t offset, int whence) { +#endif __wasi_filesize_t new_offset; __wasi_errno_t error = __wasi_fd_seek(fildes, offset, whence, &new_offset); diff --git a/libc-bottom-half/headers/public/wasi/libc.h b/libc-bottom-half/headers/public/wasi/libc.h index 76c068d..f3bebf0 100644 --- a/libc-bottom-half/headers/public/wasi/libc.h +++ b/libc-bottom-half/headers/public/wasi/libc.h @@ -1,6 +1,8 @@ #ifndef __wasi_libc_h #define __wasi_libc_h +#include <__typedef_off_t.h> + #ifdef __cplusplus extern "C" { #endif @@ -10,6 +12,7 @@ int __wasilibc_register_preopened_fd(int fd, const char *path); int __wasilibc_fd_renumber(int fd, int newfd); int __wasilibc_rmfileat(int fd, const char *path); int __wasilibc_rmdirat(int fd, const char *path); +off_t __wasilibc_tell(int fd); #ifdef __cplusplus } diff --git a/libc-bottom-half/sources/__wasilibc_tell.c b/libc-bottom-half/sources/__wasilibc_tell.c new file mode 100644 index 0000000..01dcd35 --- /dev/null +++ b/libc-bottom-half/sources/__wasilibc_tell.c @@ -0,0 +1,14 @@ +#include +#include + +off_t __wasilibc_tell(int fildes) { + __wasi_filesize_t offset; + __wasi_errno_t error = __wasi_fd_tell(fildes, &offset); + if (error != 0) { + // lseek returns ESPIPE on when called on a pipe, socket, or fifo, + // which on WASI would translate into ENOTCAPABLE. + errno = error == ENOTCAPABLE ? ESPIPE : error; + return -1; + } + return offset; +} diff --git a/libc-top-half/musl/include/unistd.h b/libc-top-half/musl/include/unistd.h index 55ad0c8..4c7d7cc 100644 --- a/libc-top-half/musl/include/unistd.h +++ b/libc-top-half/musl/include/unistd.h @@ -53,6 +53,28 @@ int dup2(int, int); int dup3(int, int, int); #endif off_t lseek(int, off_t, int); +#ifdef __wasilibc_unmodified_upstream /* Optimize the readonly case of lseek */ +#else +/* + * Optimize lseek in the case where it's just returning the current offset. + * This avoids importing `__wasi_fd_seek` altogether in many common cases. + */ + +off_t __wasilibc_tell(int); + +#define lseek(fd, offset, whence) \ + ({ \ + off_t __f = (fd); \ + off_t __o = (offset); \ + off_t __w = (whence); \ + __builtin_constant_p((offset)) && \ + __builtin_constant_p((whence)) && \ + __o == 0 && \ + __w == SEEK_CUR \ + ? __wasilibc_tell(__f) \ + : lseek(__f, __o, __w); \ + }) +#endif int fsync(int); int fdatasync(int);