nx_pipe.nx source
↩ module page · 70 lines · 2218 B
1// nx_pipe.nx -- pipe(2) + pipe2(2) wrappers.
2//
3// Pipes are how forked processes communicate: parent fork()s,
4// child write to pipe[1], parent reads from pipe[0]. The build
5// tool pattern is:
6//
7// pipe(fds) # fds[0]=read end, fds[1]=write end
8// pid = fork()
9// if pid == 0: # child
10// close(fds[0])
11// dup3(fds[1], 1, 0) # redirect stdout
12// execve(...)
13// else: # parent
14// close(fds[1])
15// n = read(fds[0], buf, ...)
16//
17// Linux RV64 has no sys_pipe -- we use sys_pipe2 (number 59) with
18// flags=0. Optionally O_CLOEXEC to avoid leaking ends across exec.
19//
20// Pairs with nx_fcntl + nx_proc.
21
22// nx_safety_envelope:
23// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
24// sil_target: SIL1
25// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
26// verdict: NOT_YET_EVALUATED
27
28import "syscalls.nx"
29import "nx_fcntl.nx"
30
31const NX_SYS_PIPE2: i64 = 59
32
33// Create a pipe. fds[0] = read end, fds[1] = write end. Returns
34// 0 on success, negative errno on failure.
35func nx_pipe(fds: *i32, flags: i64) -> i64 {
36 return __syscall(NX_SYS_PIPE2, fds as i64, flags, 0, 0, 0, 0)
37}
38
39// Convenience: pipe with both ends marked close-on-exec.
40func nx_pipe_cloexec(fds: *i32) -> i64 {
41 return nx_pipe(fds, NX_O_CLOEXEC)
42}
43
44// ---- self-test ---------------------------------------------------
45
46func main() -> i64 {
47 // Allocate fds[2] (i32 each).
48 let raw: *u8 = sys_mmap(16)
49 let fds: *i32 = raw as *i32
50
51 let r: i64 = nx_pipe(fds, 0)
52 if r < 0 { return __syscall(93, 1, 0, 0, 0, 0, 0) }
53 if fds[0] < 0 { return __syscall(93, 2, 0, 0, 0, 0, 0) }
54 if fds[1] < 0 { return __syscall(93, 3, 0, 0, 0, 0, 0) }
55
56 // Write a sentinel byte to the write end + read it back.
57 let probe: *u8 = sys_mmap(8)
58 probe[0] = 0xAB
59 let nw: i64 = sys_write(fds[1], probe, 1)
60 if nw != 1 { return __syscall(93, 4, 0, 0, 0, 0, 0) }
61
62 let nr: i64 = sys_read(fds[0], probe, 1)
63 if nr != 1 { return __syscall(93, 5, 0, 0, 0, 0, 0) }
64 if probe[0] != 0xAB { return __syscall(93, 6, 0, 0, 0, 0, 0) }
65
66 sys_close(fds[0])
67 sys_close(fds[1])
68
69 return 0
70}