remove cancellation points in stdio
authorRich Felker <dalias@aerifal.cx>
Sat, 13 Jun 2015 20:53:02 +0000 (20:53 +0000)
committerRich Felker <dalias@aerifal.cx>
Sat, 13 Jun 2015 20:53:02 +0000 (20:53 +0000)
commit 58165923890865a6ac042fafce13f440ee986fd9 added these optional
cancellation points on the basis that cancellable stdio could be
useful, to unblock threads stuck on stdio operations that will never
complete. however, the only way to ensure that cancellation can
achieve this is to violate the rules for side effects when
cancellation is acted upon, discarding knowledge of any partial data
transfer already completed. our implementation exhibited this behavior
and was thus non-conforming.

in addition to improving correctness, removing these cancellation
points moderately reduces code size, and should significantly improve
performance on i386, where sysenter/syscall instructions can be used
instead of "int $128" for non-cancellable syscalls.

src/stdio/__stdio_read.c
src/stdio/__stdio_write.c
src/stdio/fopen.c

index 5947344438b30559206d0966210455c28a9c6615..f8fa6d3bf381bd5356e0f3c7bac33286f828ea25 100644 (file)
@@ -1,12 +1,5 @@
 #include "stdio_impl.h"
 #include <sys/uio.h>
-#include <pthread.h>
-
-static void cleanup(void *p)
-{
-       FILE *f = p;
-       if (!f->lockcount) __unlockfile(f);
-}
 
 size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
 {
@@ -16,9 +9,7 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
        };
        ssize_t cnt;
 
-       pthread_cleanup_push(cleanup, f);
-       cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
-       pthread_cleanup_pop(0);
+       cnt = syscall(SYS_readv, f->fd, iov, 2);
        if (cnt <= 0) {
                f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
                return cnt;
index 8c89389a574eb6061131cd926f2322f9a0967837..d2d89475b0f9429dca8b538b689f97c27bbe5fee 100644 (file)
@@ -1,12 +1,5 @@
 #include "stdio_impl.h"
 #include <sys/uio.h>
-#include <pthread.h>
-
-static void cleanup(void *p)
-{
-       FILE *f = p;
-       if (!f->lockcount) __unlockfile(f);
-}
 
 size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
 {
@@ -19,9 +12,7 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
        int iovcnt = 2;
        ssize_t cnt;
        for (;;) {
-               pthread_cleanup_push(cleanup, f);
-               cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
-               pthread_cleanup_pop(0);
+               cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
                if (cnt == rem) {
                        f->wend = f->buf + f->buf_size;
                        f->wpos = f->wbase = f->buf;
@@ -34,11 +25,8 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
                }
                rem -= cnt;
                if (cnt > iov[0].iov_len) {
-                       f->wpos = f->wbase = f->buf;
                        cnt -= iov[0].iov_len;
                        iov++; iovcnt--;
-               } else if (iovcnt == 2) {
-                       f->wbase += cnt;
                }
                iov[0].iov_base = (char *)iov[0].iov_base + cnt;
                iov[0].iov_len -= cnt;
index 07bdb6e866d163ee2404b266161395075125f269..252f08241b3a313c057b3c6d8fc6baa1e8278c43 100644 (file)
@@ -18,7 +18,7 @@ FILE *fopen(const char *restrict filename, const char *restrict mode)
        /* Compute the flags to pass to open() */
        flags = __fmodeflags(mode);
 
-       fd = sys_open_cp(filename, flags, 0666);
+       fd = sys_open(filename, flags, 0666);
        if (fd < 0) return 0;
        if (flags & O_CLOEXEC)
                __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC);