#pragma once #include #include #include #include "termios.h" #include "mp/spinlock.h" #include "libk/resource.h" #include "libk/event.h" #define LINE_BUF_SZ 4096 struct console { struct resource res; struct termios term; size_t width, height; bool decckm; /* ── job control ─────────────────────────────────────────────────── */ int64_t fg_pgrp; /* foreground process group; 0 = none */ int64_t session; /* owning session; 0 = none */ /* ── line-discipline assembly buffer ─────────────────────────────── */ char line_buf[LINE_BUF_SZ]; size_t line_len; /* bytes currently in line_buf */ size_t line_read_off; /* drain offset (for partial reads) */ bool line_ready; /* true when a delimiter has landed */ bool lnext_pending; /* VLNEXT: next byte taken literally */ /* ── concurrent-reader serialization ─────────────────────────────── */ /* Separate from res.lock so we can hold it across the blocking * input_read() without holding res.lock. Serializes the line-assembly * loop in console_read across multiple concurrent readers (e.g. parent * + child after fork) so their bytes can't interleave on line_buf. * * Sleep-mutex serializing the line-assembly loop across concurrent * readers. We hold this across the blocking input_read() — so it MUST * be a sleep-mutex, not a spinlock (a spinlock held while the holder * sleeps in event_await would deadlock the second reader). Built on * top of the existing event primitive. */ spinlock_t read_mutex_lock; /* short-held; protects the two fields below */ bool read_mutex_held; struct event read_mutex_released; }; void console_init(void);