shm.ha (2320B)
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]], other flags are silently 34 // ignored if set. 35 // 36 // The new file descriptor always has CLOEXEC set regardless of the provided 37 // flags. If creating a new shared memory object, set its initial size with 38 // [[io::trunc]] before mapping it with [[io::mmap]]. 39 // 40 // Call [[shm_unlink]] to remove the global shared memory object. 41 export fn shm_open( 42 name: str, 43 oflag: fs::flag = fs::flag::CREATE | fs::flag::RDWR, 44 mode: fs::mode = 0o600, 45 ) (io::file | fs::error) = { 46 const path = shm_path(name)?; 47 def VALID_FLAGS: int = rt::O_RDWR | rt::O_CREAT | rt::O_EXCL | rt::O_TRUNC; 48 const oflag = (fsflags_to_bsd(oflag)? & VALID_FLAGS) | rt::O_CLOEXEC; 49 50 match (rt::shm_open(path, oflag, mode: rt::mode_t)) { 51 case let fd: int => 52 return fd: io::file; 53 case let err: rt::errno => 54 return errors::errno(err): fs::error; 55 }; 56 }; 57 58 // Removes the shared memory object with the given name. Processes which already 59 // hold a reference to the file may continue to use the memory associated with 60 // it. Once all processes have unmapped the associated shared memory object, or 61 // exited, the memory is released. 62 export fn shm_unlink(name: str) (void | fs::error) = { 63 const path = shm_path(name)?; 64 match (rt::shm_unlink(path)) { 65 case let err: rt::errno => 66 return errors::errno(err): fs::error; 67 case void => 68 return; 69 }; 70 };