shm.ha (2486B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use errors; 5 use fs; 6 use io; 7 use path; 8 use rt; 9 use strings; 10 11 fn shm_path(name: str) (str | fs::error) = { 12 const name = strings::ltrim(name, '/'); 13 if (len(name) > rt::NAME_MAX) { 14 return errors::invalid; 15 }; 16 if (name == "." || name == "..") { 17 return errors::invalid; 18 }; 19 static let buf = path::buffer { ... }; 20 path::set(&buf, "/", name)!; 21 return path::string(&buf); 22 }; 23 24 // Opens (or creates, given [[fs::flag::CREATE]]) a global shared memory file 25 // with the given name, suitable for use with [[io::mmap]] to establish shared 26 // memory areas with other processes using the same name. 27 // 28 // The name must not contain any forward slashes (one is permissible at the 29 // start, e.g. "/example") and cannot be "." or "..". 30 // 31 // The "oflag" parameter, if provided, must include either [[fs::flag::RDONLY]] 32 // or [[fs::flag::RDWR]], and may optionally add [[fs::flag::CREATE]], 33 // [[fs::flag::EXCL]], and/or [[fs::flag::TRUNC]], which are supported on all 34 // POSIX-compatible platforms. Other platforms may support additional 35 // non-standard flags; consult the shm_open(3) manual for your target system for 36 // details. 37 // 38 // The new file descriptor always has CLOEXEC set regardless of the provided 39 // flags. If creating a new shared memory object, set its initial size with 40 // [[io::trunc]] before mapping it with [[io::mmap]]. 41 // 42 // Call [[shm_unlink]] to remove the global shared memory object. 43 export fn shm_open( 44 name: str, 45 oflag: fs::flag = fs::flag::CREATE | fs::flag::RDWR, 46 mode: fs::mode = 0o600, 47 ) (io::file | fs::error) = { 48 const path = shm_path(name)?; 49 def VALID_FLAGS: int = rt::O_RDWR | rt::O_CREAT | rt::O_EXCL | rt::O_TRUNC; 50 const oflag = (fsflags_to_bsd(oflag)? & VALID_FLAGS) | rt::O_CLOEXEC; 51 52 match (rt::shm_open(path, oflag, mode: rt::mode_t, 0, null: *const u8)) { 53 case let fd: int => 54 return fd: io::file; 55 case let err: rt::errno => 56 return errors::errno(err): fs::error; 57 }; 58 }; 59 60 // Removes the shared memory object with the given name. Processes which already 61 // hold a reference to the file may continue to use the memory associated with 62 // it. Once all processes have unmapped the associated shared memory object, or 63 // exited, the memory is released. 64 export fn shm_unlink(name: str) (void | fs::error) = { 65 const path = shm_path(name)?; 66 match (rt::shm_unlink(path)) { 67 case let err: rt::errno => 68 return errors::errno(err): fs::error; 69 case void => 70 return; 71 }; 72 };