Use re-entrant locks on stdio

This commit is contained in:
Justine Tunney 2022-05-22 08:13:13 -07:00
parent 4e9662cbc7
commit 1f229e4efc
78 changed files with 427 additions and 179 deletions

View file

@ -22,6 +22,7 @@
//
// @param rdi has stream pointer
// @see clearerr_unlocked()
// @threadsafe
clearerr:
mov %rdi,%r11
ezlea clearerr_unlocked,ax

View file

@ -23,6 +23,7 @@
// @param rdi has file stream object pointer
// @note EOF doesn't count
// @see feof_unlocked()
// @threadsafe
feof: mov %rdi,%r11
ezlea feof_unlocked,ax
jmp stdio_unlock

View file

@ -23,6 +23,7 @@
// @param rdi has file stream object pointer
// @note EOF doesn't count
// @see ferror_unlocked()
// @threadsafe
ferror: mov %rdi,%r11
ezlea ferror_unlocked,ax
jmp stdio_unlock

View file

@ -20,10 +20,14 @@
// Blocks until data from stream buffer is written out.
//
// @param rdi is the stream handle
// @param rdi is the stream handle, or 0 for all streams
// @return 0 on success or -1 w/ errno
// @see fflush_unlocked()
fflush: mov %rdi,%r11
ezlea fflush_unlocked,ax
// @threadsafe
fflush: ezlea fflush_unlocked,ax
test %rdi,%rdi
jz 1f
mov %rdi,%r11
jmp stdio_unlock
1: jmp *%rax
.endfn fflush,globl

View file

@ -23,6 +23,7 @@
// @param rdi has stream object pointer
// @return byte in range 0..255, or -1 w/ errno
// @see fgetc_unlocked()
// @threadsafe
fgetc: mov %rdi,%r11
ezlea fgetc_unlocked,ax
jmp stdio_unlock

View file

@ -30,6 +30,7 @@
// @return rax has rdi on success, NULL on error or
// NULL if EOF happens with zero chars read
// @see fgets_unlocked()
// @threadsafe
fgets: mov %rdx,%r11
ezlea fgets_unlocked,ax
jmp stdio_unlock

View file

@ -23,6 +23,7 @@
// @param rdi has stream object pointer
// @return wide character or -1 on EOF or error
// @see fgetwc_unlocked()
// @threadsafe
fgetwc: mov %rdi,%r11
ezlea fgetwc_unlocked,ax
jmp stdio_unlock

View file

@ -28,6 +28,7 @@
// @param rsi is size of rdi buffer
// @param rsi is file stream object pointer
// @see fgetws_unlocked()
// @threadsafe
fgetws: mov %rdx,%r11
ezlea fgetws_unlocked,ax
jmp stdio_unlock

View file

@ -22,6 +22,7 @@
//
// @param rdi has file stream object pointer
// @see fileno_unlocked()
// @threadsafe
fileno: mov %rdi,%r11
ezlea fileno_unlocked,ax
jmp stdio_unlock

View file

@ -24,6 +24,7 @@
// @param rsi has stream object pointer
// @return c as unsigned char if written or -1 w/ errno
// @see fputc_unlocked()
// @threadsafe
fputc: mov %rsi,%r11
ezlea fputc_unlocked,ax
jmp stdio_unlock

View file

@ -28,6 +28,7 @@
// @param rsi is file object stream pointer
// @return strlen(rdi) on success or -1 w/ errno
// @see fputs_unlocked()
// @threadsafe
fputs: mov %rsi,%r11
ezlea fputs_unlocked,ax
jmp stdio_unlock

View file

@ -24,6 +24,7 @@
// @param rsi has file object stream pointer
// @return rax is wide character if written or -1 w/ errno
// @see fputwc_unlocked()
// @threadsafe
fputwc: mov %rsi,%r11
ezlea fputwc_unlocked,ax
jmp stdio_unlock

View file

@ -28,6 +28,7 @@
// @param rsi is file object stream pointer
// @return strlen(rdi) on success or -1 w/ errno
// @see fputws_unlocked()
// @threadsafe
fputws: mov %rsi,%r11
ezlea fputws_unlocked,ax
jmp stdio_unlock

View file

@ -26,6 +26,7 @@
// @param rcx has file object stream pointer
// @return count on success, [0,count) on EOF, 0 on error or count==0
// @see fread_unlocked()
// @threadsafe
fread: mov %rcx,%r11
ezlea fread_unlocked,ax
jmp stdio_unlock

View file

@ -0,0 +1,37 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
// Repositions open file stream.
//
// This function flushes the buffer (unless it's currently in the EOF
// state) and then calls lseek() on the underlying file. If the stream
// is in the EOF state, this function can be used to restore it without
// needing to reopen the file.
//
// @param rdi is stream handle
// @param rsi is offset is the byte delta
// @param rdx is whence and can be SEET_SET, SEEK_CUR, or SEEK_END
// @return 0 on success or -1 w/ errno
// @see fflush_unlocked()
// @threadsafe
fseeko: mov %rdi,%r11
ezlea fseeko_unlocked,ax
jmp stdio_unlock
.endfn fseeko,globl

View file

@ -26,6 +26,7 @@
// @param rcx has file object stream pointer
// @return count on success, [0,count) on EOF, 0 on error or count==0
// @see fwrite_unlocked()
// @threadsafe
fwrite: mov %rcx,%r11
ezlea fwrite_unlocked,ax
jmp stdio_unlock

View file

@ -23,6 +23,7 @@
// @param rdi has file stream object pointer
// @return byte in range 0..255, or -1 w/ errno
// @see fgetc_unlocked()
// @threadsafe
getc: mov %rdi,%r11
ezlea fgetwc_unlocked,ax
jmp stdio_unlock

View file

@ -22,6 +22,7 @@
//
// @return byte in range 0..255, or -1 w/ errno
// @see fgetc_unlocked()
// @threadsafe
getchar:
mov stdin(%rip),%rdi
mov %rdi,%r11

View file

@ -23,6 +23,7 @@
// @param rdi has file stream object pointer
// @return wide character or -1 on EOF or error
// @see fgetwc_unlocked()
// @threadsafe
getwc: mov %rdi,%r11
ezlea fgetwc_unlocked,ax
jmp stdio_unlock

View file

@ -22,6 +22,7 @@
//
// @return wide character or -1 on EOF or error
// @see fgetwc_unlocked()
// @threadsafe
getwchar:
mov stdin(%rip),%rdi
mov %rdi,%r11

View file

@ -24,6 +24,7 @@
// @param rsi has stream object pointer
// @return c as unsigned char if written or -1 w/ errno
// @see fputc_unlocked()
// @threadsafe
putc: mov %rsi,%r11
ezlea fputc_unlocked,ax
jmp stdio_unlock

View file

@ -23,6 +23,7 @@
// @param rdi has character
// @return c (as unsigned char) if written or -1 w/ errno
// @see fputc_unlocked()
// @threadsafe
putchar:
mov stdout(%rip),%rsi
mov %rsi,%r11

View file

@ -24,6 +24,7 @@
// @param rsi has file object
// @return wc if written or -1 w/ errno
// @see putwc_unlocked()
// @threadsafe
putwc: mov %rsi,%r11
ezlea fputwc_unlocked,ax
jmp stdio_unlock

View file

@ -23,6 +23,7 @@
// @param rdi has wide character
// @return wc if written or -1 w/ errno
// @see fputwc_unlocked()
// @threadsafe
putwchar:
mov stdout(%rip),%rsi
mov %rsi,%r11

View file

@ -18,53 +18,54 @@
*/
#include "libc/macros.internal.h"
#define LOCK 0x2c /* see struct file in stdio.h */
// Wrapper for applying locking to stdio functions.
//
// This function is intended to be called by thunks.
//
// @param rax has the delegate function pointer
// @param rax is stdio function pointer
// @param rdi is passed along as an arg
// @param rsi is passed along as an arg
// @param rdx is passed along as an arg
// @param rcx is passed along as an arg
// @param r8 is passed along as an arg
// @param r9 is passed along as an arg
// @param r10 is passed along as an arg
// @param r11 has the FILE* obj pointer
// @return rax is passed along as result
// @return rdx is passed along as result
// @threadsafe
stdio_unlock:
push %rbp
mov %rsp,%rbp
.profilable
// acquires mutex
push %rcx
push %rax
push %rdi
push %rsi
push %rdx
mov $1,%cl
0: mov LOCK(%r11),%dl # optimistic
test %dl,%dl
je 2f
1: pause # hyperyield
jmp 0b
2: mov %ecx,%edx
xchg LOCK(%r11),%dl # locks bus!
test %dl,%dl
jne 1b
pop %rdx
push %rcx
push %r11
mov %r11,%rdi
call flockfile
pop %r11
pop %rcx
pop %rdx
pop %rsi
pop %rdi
pop %rax
// calls delegate
push %rsi
push %r11
push %rsi # align stack
call *%rax
pop %r11
pop %rsi
pop %r11
// releases mutex
movb $0,LOCK(%r11)
push %rax
push %rdx
mov %r11,%rdi
call funlockfile
pop %rdx
pop %rax
pop %rbp
ret

View file

@ -24,6 +24,7 @@
// @param rds has stream object pointer
// @return rax has rdi on success or -1 w/ errno
// @see ungetc_unlocked()
// @threadsafe
ungetc: mov %rsi,%r11
ezlea ungetc_unlocked,ax
jmp stdio_unlock

View file

@ -24,6 +24,7 @@
// @param rds has stream object pointer
// @return rax has rdi on success or -1 w/ errno
// @see ungetwc_unlocked()
// @threadsafe
ungetwc:
mov %rsi,%r11
ezlea ungetwc_unlocked,ax