feat(stdio): getline/getdelim/stream locking

This commit is contained in:
2026-09-05 17:18:18 -04:00
parent 14c6fd6cf6
commit a2f7c33601
7 changed files with 1625 additions and 13 deletions
+64 -11
View File
@@ -25,25 +25,48 @@
*
* The helper prototypes below are shared with the formatted-I/O todos
* (16: vfprintf, 17: vfscanf) so they operate on the same buffer state.
*
* Locking (todo 18): the process is single-threaded until the thread
* todo (#45) lands, so flockfile/ftrylockfile/funlockfile only track
* ownership state here. `lock` is the recursion depth (0 = unlocked),
* `lock_owner` the owning thread's FS base while locked. When real
* threads arrive, the same todo turns `lock` into the actual per-stream
* lock word (blocking acquisition, mutex/cond state) and these two
* fields become the bookkeeping that makes flockfile recursive.
*
* Memory streams (todo 18): fmemopen/open_memstream build a FILE whose
* `mem` points at an opaque backend (defined in fmemopen.c) instead of a
* descriptor. Whenever `mem` is non-NULL the buffered core below calls
* back into fmemopen.c's stdio_mem_* hooks in place of every descriptor
* syscall, so the position invariant above is unchanged: the backend
* simply acts as an in-memory device with the same kernel-position
* semantics (reads advance it past the read-ahead, writes advance it on
* flush, discards rewind it to the logical position).
*/
#include <stdio.h>
#include "../internal/libc.h"
/* Opaque memory-stream backend (fmemopen/open_memstream, todo 18). */
struct vlibc_memstream;
struct vlibc_FILE
{
unsigned char *buf; /* buffer base: library- or user-supplied */
unsigned char *rpos; /* read mode: next byte to deliver */
unsigned char *rstop; /* read mode: end of valid buffered data */
unsigned char *wpos; /* write mode: next byte to store */
unsigned char *wstop; /* write mode: end of the buffer */
int fd; /* underlying descriptor; -1 when closed */
int flags; /* F_* bits below */
size_t buf_size; /* usable buffer size; 0 = not yet sized */
off_t pos; /* position per the invariant above */
struct vlibc_FILE *next; /* registry link for fflush(NULL) */
unsigned char ungot; /* pushed-back byte when F_PUSHED */
unsigned char *buf; /* buffer base: library- or user-supplied */
unsigned char *rpos; /* read mode: next byte to deliver */
unsigned char *rstop; /* read mode: end of valid buffered data */
unsigned char *wpos; /* write mode: next byte to store */
unsigned char *wstop; /* write mode: end of the buffer */
int fd; /* underlying descriptor; -1 when closed */
int flags; /* F_* bits below */
size_t buf_size; /* usable buffer size; 0 = not yet sized */
off_t pos; /* position per the invariant above */
struct vlibc_FILE *next; /* registry link for fflush(NULL) */
unsigned char ungot; /* pushed-back byte when F_PUSHED */
int lock; /* flockfile recursion depth; 0 = unlocked */
void *lock_owner; /* owning thread's FS base while locked */
struct vlibc_memstream *mem; /* memory-stream backend, or NULL */
};
/* Stream flags. */
@@ -94,4 +117,34 @@ stdio_parse_mode(const char *mode, int *m, int *oflags);
hidden off_t
stdio_lseek(int fd, off_t off, int whence);
/*
* Memory-stream device hooks (fmemopen.c, todo 18). The stdio core calls
* these in place of the descriptor syscalls whenever f->mem is set:
*
* - stdio_mem_flush: write the pending cache to the backing region
* (stdio_flush's device-write half, F_APPEND included).
* - stdio_mem_refill: read the next cache-full from the region
* (stdio_refill's device-read half).
* - stdio_mem_discard: rewind the device to the logical position,
* discarding unread cached data (stdio_discard_read's seek half).
* - stdio_mem_lseek: resolve a SEEK_SET/SEEK_END target against the
* region (used by fseeko instead of stdio_lseek on memory streams).
* - stdio_mem_close: run on fclose before the FILE is released
* (open_memstream's final NUL/size sync, owned-buffer release).
*/
hidden int
stdio_mem_flush(FILE *f);
hidden void
stdio_mem_refill(FILE *f);
hidden int
stdio_mem_discard(FILE *f);
hidden off_t
stdio_mem_lseek(FILE *f, off_t off, int whence);
hidden void
stdio_mem_close(FILE *f);
#endif /* VLIBC_STDIO_STDIO_IMPL_H */