]> git.proxmox.com Git - wasi-libc.git/commitdiff
Optimize lseek in the `tell` case.
authorDan Gohman <sunfish@mozilla.com>
Mon, 29 Apr 2019 19:53:18 +0000 (12:53 -0700)
committerDan Gohman <sunfish@mozilla.com>
Tue, 30 Apr 2019 23:19:05 +0000 (16:19 -0700)
`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.

expected/wasm32-wasi/defined-symbols.txt
expected/wasm32-wasi/predefined-macros.txt
expected/wasm32-wasi/undefined-symbols.txt
libc-bottom-half/cloudlibc/src/libc/unistd/lseek.c
libc-bottom-half/headers/public/wasi/libc.h
libc-bottom-half/sources/__wasilibc_tell.c [new file with mode: 0644]
libc-top-half/musl/include/unistd.h

index 4a4294f526dc23f40a37df8f879c82309dfd27ce..aceb503398ab4b5b2c6176d62679a47f33fbecc7 100644 (file)
@@ -241,6 +241,7 @@ __wasilibc_init_preopen
 __wasilibc_register_preopened_fd
 __wasilibc_rmdirat
 __wasilibc_rmfileat
+__wasilibc_tell
 __wcscoll_l
 __wcsftime_l
 __wcsxfrm_l
index f4e859197dd35c97cae1ea39859f0ca2df484a36..ad3c3494bdf2ff461f4ef9f2e2b368bc99eb248f 100644 (file)
 #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) ))
index 92b9c802c8723266a67307cf0029b3ae862a00b6..75bee0304f1b6b8ed5f6ac507fe744254ee54c8d 100644 (file)
@@ -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
index 108cc7e749e6cad84d4da303a93c112d76da3189..a0e41b70867a9e8d653f3197858518bcff65aae2 100644 (file)
@@ -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);
index 76c068d918d32395b1679d263905b3394f969c69..f3bebf033693faa110ae26b0b09d81bf7875a392 100644 (file)
@@ -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 (file)
index 0000000..01dcd35
--- /dev/null
@@ -0,0 +1,14 @@
+#include <wasi/core.h>
+#include <errno.h>
+
+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;
+}
index 55ad0c8c0c924edd57390cdfce207c6121014315..4c7d7cc31d4a61a8fe50a964bf93ec007c8ebfd7 100644 (file)
@@ -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);