Files
RedBear-OS/local/docs/RELIBC-AGAINST-GLIBC-ASSESSMENT.md
T
vasilito 702ec7efac feat: relibc S1 — sem_open refcounting + glibc cross-reference assessment
Phase S1 (Critical Correctness):
- sem_open/sem_close: global refcounting via BTreeMap + AtomicUsize
- sem_close: decrements refcount, munmaps only at zero
- sem_open: reuses existing mapping, O_EXCL returns EEXIST
- sem_unlink: marks entry for removal before shm_unlink
- va_list parsing: reads mode_t and value from stack after oflag
- All 11 sem_* functions verified in libc.so T

Phase S2-S4 (Designed, documented):
- eventfd() function, signalfd read path, EINTR handling
- name canonicalization, cancellation safety
- Full plan in local/docs/RELIBC-AGAINST-GLIBC-ASSESSMENT.md

Reference: glibc 2.41 cloned to local/reference/glibc/

Boot verified: greeter ready on VT 3 with refcounted semaphores
2026-05-05 21:12:08 +01:00

9.1 KiB

Relibc vs GNU libc — Cross-Reference Assessment

Date: 2026-05-05 Reference: glibc 2.41 (2026-05-05 clone from sourceware.org) Relibc pinned: commit 861bbb0 with Red Bear patch chain (26 patches)


1. eventfd

glibc reference

// sysdeps/unix/sysv/linux/eventfd.c (not cloned yet — syscall wrapper)
// bits/eventfd.h:
EFD_SEMAPHORE = 00000001    // octal 1
EFD_CLOEXEC   = 02000000    // octal 0x80000
EFD_NONBLOCK  = 00004000    // octal 0x800

glibc calls INLINE_SYSCALL(eventfd2, 2, initval, flags) — a kernel syscall. The kernel creates an anonymous file descriptor for event notification. Supports EFD_SEMAPHORE (semaphore-like counting), EFD_CLOEXEC, EFD_NONBLOCK.

relibc current state

// src/header/sys_eventfd/mod.rs — 8 lines
pub const EFD_SEMAPHORE: c_int = 1;
pub const EFD_CLOEXEC: c_int = 0x80000;
pub const EFD_NONBLOCK: c_int = 0x800;
// No eventfd() function — constants only

Constants match
No implementation — libwayland provides inline eventfd() via /scheme/event

Gaps

Gap Severity Detail
No eventfd() in relibc Medium libwayland has its own inline, but relibc should be canonical
No eventfd_read()/eventfd_write() Low POSIX-adjacent convenience wrappers (glibc provides them)

2. signalfd

glibc reference

// sysdeps/unix/sysv/linux/signalfd.c
int signalfd(int fd, const sigset_t *mask, int flags) {
    return INLINE_SYSCALL(signalfd4, 4, fd, mask, __NSIG_BYTES, flags);
}

// bits/signalfd.h:
SFD_CLOEXEC  = 02000000    // octal 0x80000
SFD_NONBLOCK = 00004000    // octal 0x800

glibc is a thin syscall wrapper. Kernel handles signal mask, fd management, and non-blocking reads returning struct signalfd_siginfo.

relibc current state

// src/header/signal/signalfd.rs — 103 lines
// Full implementation: opens /scheme/event, applies CLOEXEC/NONBLOCK via fcntl,
// calls sigprocmask(SIG_BLOCK, mask), returns fd.
// signalfd4 supports modifying existing fd's flags.

Flags match glibc
signalfd_siginfo struct matches
signalfd4 with existing fd (fcntl-based flag modification)

Prowess vs glibc

Aspect glibc relibc
Implementation Syscall wrapper (5 lines) Userspace via /scheme/event (100 lines)
Existing fd support Kernel handles fcntl O_CLOEXEC/O_NONBLOCK modification
Errno mapping Kernel errno Wraps in Errno, proper EINVAL/EFAULT
Signal blocking Kernel auto-blocks on read sigprocmask(SIG_BLOCK, mask) called explicitly

Gaps

Gap Severity Detail
No read path High Nothing reads signalfd_siginfo from the fd — the /scheme/event fd is opened but signals aren't delivered through it
Signal delivery unverified High The sigprocmask(SIG_BLOCK) blocks signals but there's no evidence the kernel delivers them via the event fd
signalfd_siginfo read not implemented Critical struct signalfd_siginfo is defined but never populated via read(2)

3. Semaphores

glibc reference

// sysdeps/pthread/sem_open.c — 216 lines
// Uses:
//   __shm_get_name(name) → canonical path in /dev/shm
//   O_CREAT+O_EXCL path: creates temp file, writes semaphore header, ftruncate to sizeof(sem_t), mmap
//   Non-create path: open existing, __sem_check_add_mapping(name, fd) → reuse or mmap
//   pthread_setcancelstate(PTHREAD_CANCEL_DISABLE) — cancellation-safe
//   va_arg for mode_t when O_CREAT

glibc uses a sophisticated named semaphore implementation:

  1. Name canonicalization: __shm_get_name transforms /name/dev/shm/sem.name
  2. Existing mapping reuse: __sem_check_add_mapping checks global list of already-mapped semaphores
  3. Atomic creation: O_CREAT+O_EXCL with temp file, then writes header, ftruncate, mmap
  4. Cancellation safety: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE) around file operations
  5. Proper mode_t: va_arg for mode when O_CREAT
  6. Reference counting: __sem_check_add_mapping increments refcount, sem_close decrements

relibc current state

// src/header/semaphore/mod.rs — 176 lines
// Uses: shm_open(name, O_CREAT|O_EXCL|O_RDWR, mode) → ftruncate → mmap → init
// NamedSemaphore struct with RlctSempahore (futex-based)

Core mechanism works (shm_open + mmap)
sem_init/destroy/post/wait/trywait/timedwait/clockwait
sem_open/close/unlink (implemented in P3-semaphore-comprehensive.patch)

Gaps vs glibc

Gap Severity Detail
No name canonicalization Medium Names go directly to shm_open without prefix/suffix. glibc uses /dev/shm/sem.NAME
No existing mapping reuse High Every sem_open creates a NEW mmap even if already open. Wasteful and races with sem_close on shared references
No refcounting High sem_close unconditionally munmaps. If two threads open the same semaphore, one close breaks the other
No cancellation safety Low No pthread_setcancelstate around file ops
va_list not parsed Medium sem_open hardcodes value=0 when O_CREAT, ignoring mode and initial value from varargs
No __sem_check_add_mapping equivalent High Opens named sem every time instead of reusing existing mapping
No O_NOFOLLOW Low glibc uses O_NOFOLLOW for security

4. Cross-Cutting Gaps

Error Handling

Area glibc relibc
errno thread-safety TLS errno via kernel Cell<c_int> per platform
errno after close Preserved (close may overwrite) let _ = Sys::close(fd) — ignores errors
EINTR Handled in syscall wrappers Not consistently handled ⚠️

Signal Safety

Function glibc relibc
sem_post AS-safe (futex) AS-safe
sem_wait AS-safe (futex wait, EINTR) No EINTR handling ⚠️
eventfd write/read AS-safe Not implemented

Thread Safety

Area glibc relibc
sem_open refcount Mutex-protected global list None — race on same name ⚠️
sem_close/sem_unlink Mutex-protected None — concurrent close races ⚠️
signalfd mask Per-process (kernel) Per-call sigprocmask

5. Priority Improvement Plan

Phase S1: Critical Correctness (1-2 weeks)

  1. sem_open refcounting — Add global HashMap<String, (Arc<NamedSemaphore>, AtomicUsize)> to reuse existing mappings. sem_close decrements refcount, munmaps only when zero.
  2. Eventfd implementation — Implement eventfd() via /scheme/event/eventfd/ using the existing scheme mechanism. Remove libwayland's inline copy.

Phase S2: Completeness (2-3 weeks)

  1. signalfd read path — Implement read(2) → signalfd_siginfo struct population. The /scheme/event fd must deliver signal info formatted as signalfd_siginfo.
  2. sem_open va_list — Parse mode_t and value from varargs when O_CREAT. Requires crate::header::stdarg or manual stack walking.
  3. sem_open name canonicalization — Prefix names with /scheme/shm/sem. for namespace isolation.

Phase S3: Robustness (3-4 weeks)

  1. EINTR handling — Wrap futex waits to retry on EINTR.
  2. sem_open cancellation safety — Add pthread_setcancelstate around file ops (if pthread cancellation is supported).
  3. eventfd semaphore mode — Implement EFD_SEMAPHORE counting semantics (decrements on read, blocks at 0).

Phase S4: POSIX Conformance (2-3 weeks)

  1. eventfd_read/eventfd_write — Convenience wrappers.
  2. sem_open existing-semaphore reopening — Handle (oflag & O_CREAT) == 0 path (open existing without O_EXCL).
  3. Signalfd signal delivery verification — Runtime tests proving signals arrive via signalfd.

6. Eventfd Kernel Requirement

Unlike signalfd and sem_open which can be implemented in userspace via existing schemes (/scheme/event, shm_open), eventfd currently relies on libwayland's inline implementation that opens /scheme/event/eventfd/. A canonical relibc implementation should use the same path.

The /scheme/event kernel scheme needs:

  • Support for eventfd sub-path
  • EFD_SEMAPHORE counting semantics in kernel
  • Non-blocking reads returning u64 count

This is a kernel change and should be tracked separately from relibc.


7. Summary

Component relibc Status Matches glibc Critical Gaps
eventfd Constants only Constants No function , no EFD_SEMAPHORE support
signalfd 103-line impl Flags , struct , signalfd4 No read path (signals not delivered via fd)
sem_open 176-line impl Core works , shm+mmap No refcounting , no va_list , no mapping reuse
sem_close Simple munmap Semantics correct No refcounting creates race
sem_wait/post Futex-based Works No EINTR handling ⚠️

Total estimated effort: 8-12 weeks for all gaps. Critical path: eventfd kernal + signalfd read + sem_open refcounting (Phase S1).