Skip to content

Commit 8bcd42f

Browse files
std.os.linux: resurrect shm
This reintroduces Linux's shared memory system calls which was in ziglang#7214. It also adds the externs necessary for C.
1 parent 13a9d94 commit 8bcd42f

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

lib/std/c/linux.zig

+7
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub const dl_phdr_info = linux.dl_phdr_info;
6565
pub const empty_sigset = linux.empty_sigset;
6666
pub const epoll_event = linux.epoll_event;
6767
pub const fd_t = linux.fd_t;
68+
pub const key_t = linux.key_t;
6869
pub const gid_t = linux.gid_t;
6970
pub const ifreq = linux.ifreq;
7071
pub const ino_t = linux.ino_t;
@@ -85,6 +86,7 @@ pub const siginfo_t = linux.siginfo_t;
8586
pub const sigset_t = linux.sigset_t;
8687
pub const sockaddr = linux.sockaddr;
8788
pub const socklen_t = linux.socklen_t;
89+
pub const shmid_ds = linux.shmid_ds;
8890
pub const stack_t = linux.stack_t;
8991
pub const time_t = linux.time_t;
9092
pub const timespec = linux.timespec;
@@ -344,3 +346,8 @@ pub const dirent64 = struct {
344346
type: u8,
345347
name: [256]u8,
346348
};
349+
350+
pub extern "c" fn shmget(key: key_t, size: usize, shmflg: c_int) c_int;
351+
pub extern "c" fn shmat(shmid: i32, shmaddr: ?[*]align(std.mem.page_size) u8, shmflg: c_int) ?*anyopaque;
352+
pub extern "c" fn shmctl(shmid: c_int, cmd: c_int, ds: ?*shmid_ds) c_int;
353+
pub extern "c" fn shmdt(shmaddr: *const anyopaque) c_int;

lib/std/os/linux.zig

+110
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,116 @@ pub fn munmap(address: [*]const u8, length: usize) usize {
800800
return syscall2(.munmap, @intFromPtr(address), length);
801801
}
802802

803+
pub const key_t = i32;
804+
pub const IPC = struct {
805+
pub const PRIVATE = 0;
806+
807+
/// create key if key does not exist
808+
pub const CREAT = 0x200;
809+
810+
/// fail if key exists
811+
pub const EXCL = 0x400;
812+
813+
/// return error on wait
814+
pub const NOWAIT = 0x800;
815+
816+
/// remove identifier
817+
pub const RMID = 0;
818+
819+
/// set 'ipc_perm' options
820+
pub const SET = 1;
821+
822+
/// get 'ipc_perm' options
823+
pub const STAT = 2;
824+
825+
/// get info about shared memory limits and parameters
826+
pub const INFO = 3;
827+
};
828+
829+
pub const SHM = struct {
830+
/// segment will be destroyed on last detach
831+
pub const DEST = 0x200;
832+
833+
/// segment will not be swapped
834+
pub const LOCKED = 0x400;
835+
836+
/// segment will use huge TLB pages
837+
pub const HUGETLB = 0x800;
838+
839+
pub const HUGE_SHIFT = 26;
840+
pub const HUGE_2MB = 21 << HUGE_SHIFT;
841+
pub const HUGE_1GB = 30 << HUGE_SHIFT;
842+
843+
/// don't check for reservations
844+
pub const NORESERVE = 0x1000;
845+
846+
/// attach read-only else read-write
847+
pub const RDONLY = 0x1000;
848+
849+
/// round attach address to SHMLBA
850+
pub const RND = 0x2000;
851+
852+
/// take-over region on attach
853+
pub const REMAP = 0x4000;
854+
855+
/// execution access
856+
pub const EXEC = 0x8000;
857+
858+
/// lock segment
859+
pub const LOCK = 11;
860+
861+
/// unlock segment
862+
pub const UNLOCK = 12;
863+
864+
/// get 'ipc_perm' options from kernel index
865+
pub const STAT = 13;
866+
867+
/// get info about about system resources consumed by shared memory
868+
pub const INFO = 14;
869+
870+
/// get 'ipc_perm' options from kernel index without checking read access
871+
pub const STAT_ANY = 15;
872+
};
873+
874+
pub const ipc_perm = extern struct {
875+
key: c_int,
876+
uid: uid_t,
877+
gid: gid_t,
878+
cuid: uid_t,
879+
cgid: gid_t,
880+
mode: mode_t,
881+
seq: c_ushort,
882+
};
883+
884+
pub const shmid_ds = extern struct {
885+
shm_perm: ipc_perm,
886+
shm_segsz: usize,
887+
shm_atime: time_t,
888+
shm_dtime: time_t,
889+
shm_ctime: time_t,
890+
shm_cpid: pid_t,
891+
shm_lpid: pid_t,
892+
shm_nattch: c_ulong,
893+
__pad1: c_ulong,
894+
__pad2: c_ulong,
895+
};
896+
897+
pub fn shmget(key: key_t, size: usize, shmflg: u32) usize {
898+
return syscall3(.shmget, @intCast(key), size, shmflg);
899+
}
900+
901+
pub fn shmat(shmid: u32, shmaddr: ?[*]align(std.mem.page_size) u8, shmflg: u32) usize {
902+
return syscall3(.shmat, shmid, @intFromPtr(shmaddr), shmflg);
903+
}
904+
905+
pub fn shmctl(shmid: u32, cmd: i32, ds: ?*shmid_ds) usize {
906+
return syscall3(.shmctl, shmid, @intCast(cmd), @intFromPtr(ds));
907+
}
908+
909+
pub fn shmdt(shmaddr: *const anyopaque) usize {
910+
return syscall1(.shmdt, @intFromPtr(shmaddr));
911+
}
912+
803913
pub fn poll(fds: [*]pollfd, n: nfds_t, timeout: i32) usize {
804914
if (@hasField(SYS, "poll")) {
805915
return syscall3(.poll, @intFromPtr(fds), n, @as(u32, @bitCast(timeout)));

lib/std/os/linux/test.zig

+30
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,36 @@ test "fadvise" {
121121
try expectEqual(@as(usize, 0), ret);
122122
}
123123

124+
test "shm" {
125+
const segment = linux.shmget(linux.IPC.PRIVATE, mem.page_size, linux.IPC.CREAT | 0o666);
126+
switch (linux.getErrno(segment)) {
127+
.SUCCESS => {},
128+
else => unreachable,
129+
}
130+
131+
defer {
132+
const r = linux.shmctl(@intCast(segment), linux.IPC.RMID, null);
133+
switch (linux.getErrno(r)) {
134+
.SUCCESS => {},
135+
else => unreachable,
136+
}
137+
}
138+
139+
const addr = std.os.linux.shmat(@intCast(segment), null, 0);
140+
switch (linux.getErrno(addr)) {
141+
.SUCCESS => {},
142+
else => unreachable,
143+
}
144+
145+
defer {
146+
const r = std.os.linux.shmdt(@ptrFromInt(addr));
147+
switch (linux.getErrno(r)) {
148+
.SUCCESS => {},
149+
else => unreachable,
150+
}
151+
}
152+
}
153+
124154
test {
125155
_ = linux.IoUring;
126156
}

0 commit comments

Comments
 (0)