feat: add SYS_FUTEX_WAIT and SYS_FUTEX_WAKE syscalls; revamp desktop application categories
This commit is contained in:
1 parent
60ca9c78c7
commit
abfd9de8f6
35 files changed
+545
-70
No files matched your search
@@ -277,6 +277,17 @@ namespace montauk::abi {
|
||||
static constexpr uint64_t SYS_GETKEY_EX = 194; // (KeyEvent*, size) -> 0; blocks like SYS_GETKEY
|
||||
static constexpr uint64_t SYS_CHILDIO_WRITEKEY_EX = 195; // (childPid, const KeyEvent*, size) -> status
|
||||
|
||||
/* Futexes: process-private wait queues keyed by a user address. WAIT
|
||||
blocks only if *addr still equals `expected` (checked atomically with
|
||||
enrollment). timeoutNs: FUTEX_WAIT_FOREVER = no deadline, 0 = check
|
||||
only; rounded up to the 1 ms scheduler tick. WAIT returns 0 when woken,
|
||||
WouldBlock on value mismatch, TimedOut on deadline. WAKE returns the
|
||||
number of threads woken (count = FUTEX_WAKE_ALL wakes every waiter). */
|
||||
static constexpr uint64_t SYS_FUTEX_WAIT = 196; // (uint32_t* addr, expected, timeoutNs) -> status
|
||||
static constexpr uint64_t SYS_FUTEX_WAKE = 197; // (uint32_t* addr, count) -> woken, or status
|
||||
static constexpr uint64_t FUTEX_WAIT_FOREVER = ~0ULL;
|
||||
static constexpr uint32_t FUTEX_WAKE_ALL = 0xFFFFFFFFu;
|
||||
|
||||
/* Kernel-owned process capabilities. User identities may namespace
|
||||
per-user resources, but never participate in authorization decisions. */
|
||||
static constexpr uint64_t CAP_PROCESS_ADMIN = 1ULL << 0;
|
||||
|
||||
@@ -219,6 +219,8 @@ extern "C" {
|
||||
#define MTK_SYS_CONSENT_REPLY 193
|
||||
#define MTK_SYS_GETKEY_EX 194
|
||||
#define MTK_SYS_CHILDIO_WRITEKEY_EX 195
|
||||
#define MTK_SYS_FUTEX_WAIT 196
|
||||
#define MTK_SYS_FUTEX_WAKE 197
|
||||
/* @SYSCALLS-END */
|
||||
|
||||
/* Syscall status codes (montauk/statuscodes.h for C++). */
|
||||
@@ -240,6 +242,8 @@ extern "C" {
|
||||
#define MTK_STATUS_BUSY (-12)
|
||||
#define MTK_STATUS_BUFFER_TOO_SMALL (-13)
|
||||
#define MTK_STATUS_OUT_OF_MEMORY (-14)
|
||||
#define MTK_STATUS_TIMED_OUT (-15)
|
||||
#define MTK_STATUS_WOULD_BLOCK (-16)
|
||||
/* @STATUS-END */
|
||||
|
||||
#define MTK_SOCK_TCP 1
|
||||
@@ -491,6 +495,21 @@ static inline void mtk_sleep_ms(unsigned long ms) {
|
||||
_mtk_syscall1(MTK_SYS_SLEEP_MS, (long)ms);
|
||||
}
|
||||
|
||||
/* Futexes (process-private). mtk_futex_wait blocks while *addr == expected;
|
||||
returns 0 when woken, MTK_STATUS_TIMED_OUT, or MTK_STATUS_WOULD_BLOCK when
|
||||
the word had already changed. timeout_ns: MTK_FUTEX_WAIT_FOREVER for no
|
||||
deadline, 0 to only check. mtk_futex_wake returns the number woken. */
|
||||
#define MTK_FUTEX_WAIT_FOREVER (~0UL)
|
||||
#define MTK_FUTEX_WAKE_ALL 0xFFFFFFFFu
|
||||
|
||||
static inline int mtk_futex_wait(uint32_t *addr, uint32_t expected, unsigned long timeout_ns) {
|
||||
return (int)_mtk_syscall3(MTK_SYS_FUTEX_WAIT, (long)addr, (long)expected, (long)timeout_ns);
|
||||
}
|
||||
|
||||
static inline int mtk_futex_wake(uint32_t *addr, uint32_t count) {
|
||||
return (int)_mtk_syscall2(MTK_SYS_FUTEX_WAKE, (long)addr, (long)count);
|
||||
}
|
||||
|
||||
static inline int mtk_getpid(void) {
|
||||
return (int)_mtk_syscall0(MTK_SYS_GETPID);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ typedef enum {
|
||||
NoSuchPath = 11,
|
||||
Busy = 12,
|
||||
BufferTooSmall = 13,
|
||||
OutOfMemory = 14
|
||||
OutOfMemory = 14,
|
||||
TimedOut = 15,
|
||||
WouldBlock = 16
|
||||
} StatusCode;
|
||||
|
||||
inline const char* GetStatusText(StatusCode statusCode) {
|
||||
@@ -47,9 +49,11 @@ inline const char* GetStatusText(StatusCode statusCode) {
|
||||
"Busy", // 12
|
||||
"Buffer too small", // 13
|
||||
"Out of memory", // 14
|
||||
"Timed out", // 15
|
||||
"Operation would block", // 16
|
||||
};
|
||||
|
||||
if (statusCode > 0 && statusCode <= 14) {
|
||||
if (statusCode > 0 && statusCode <= 16) {
|
||||
return statusText[statusCode];
|
||||
} else {
|
||||
return "Unknown error";
|
||||
@@ -74,9 +78,11 @@ inline const char* GetStatusExplanationText(StatusCode statusCode) {
|
||||
0, // 12
|
||||
"The buffer supplied by the caller is too small.", // 13
|
||||
0, // 14
|
||||
0, // 15
|
||||
0, // 16
|
||||
};
|
||||
|
||||
if (statusCode > 0 && statusCode <= 14) {
|
||||
if (statusCode > 0 && statusCode <= 16) {
|
||||
if (explanationText[statusCode] != 0) {
|
||||
return explanationText[statusCode];
|
||||
}
|
||||
|
||||
@@ -148,6 +148,28 @@ namespace montauk {
|
||||
return (int)syscall0(montauk::abi::SYS_THREAD_SELF);
|
||||
}
|
||||
|
||||
// Block while *addr == expected. Returns 0 when woken by futex_wake,
|
||||
// WouldBlock if *addr had already changed, TimedOut when timeout_ns
|
||||
// elapsed (FUTEX_WAIT_FOREVER = no deadline, 0 = check only, otherwise
|
||||
// rounded up to the 1 ms tick). Futexes are private to the process.
|
||||
// A 0 return is never spurious, but always re-check the condition.
|
||||
inline int futex_wait(uint32_t* addr, uint32_t expected,
|
||||
uint64_t timeout_ns = montauk::abi::FUTEX_WAIT_FOREVER) {
|
||||
int64_t r = syscall3(montauk::abi::SYS_FUTEX_WAIT, (uint64_t)addr,
|
||||
(uint64_t)expected, timeout_ns);
|
||||
return r < 0 ? (int)-r : 0;
|
||||
}
|
||||
|
||||
// Wake up to `count` waiters on addr, longest-waiting first. Returns the
|
||||
// number woken, or a negative status for a bad address.
|
||||
inline int futex_wake(uint32_t* addr, uint32_t count = 1) {
|
||||
return (int)syscall2(montauk::abi::SYS_FUTEX_WAKE, (uint64_t)addr, (uint64_t)count);
|
||||
}
|
||||
|
||||
inline int futex_wake_all(uint32_t* addr) {
|
||||
return futex_wake(addr, montauk::abi::FUTEX_WAKE_ALL);
|
||||
}
|
||||
|
||||
// Lightweight mutex backed by a single atomic word + the kernel
|
||||
// yield syscall. Adequate for short critical sections; a heavier
|
||||
// primitive can wrap mailbox_recv when blocking semantics are needed.
|
||||
|
||||
Reference in new issue
Block a user