]> git.proxmox.com Git - rustc.git/blob - vendor/rustix/src/runtime.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / vendor / rustix / src / runtime.rs
1 //! Low-level implementation details for libc-like runtime libraries such as
2 //! [origin].
3 //!
4 //! These functions are for implementing thread-local storage (TLS), managing
5 //! threads, loaded libraries, and other process-wide resources. Most of
6 //! `rustix` doesn't care about what other libraries are linked into the
7 //! program or what they're doing, but the features in this module generally
8 //! can only be used by one entity within a process.
9 //!
10 //! The API for these functions is not stable, and this module is
11 //! `doc(hidden)`.
12 //!
13 //! [origin]: https://github.com/sunfishcode/mustang/tree/main/origin
14 //!
15 //! # Safety
16 //!
17 //! This module is intended to be used for implementing a runtime library such
18 //! as libc. Use of these features for any other purpose is likely to create
19 //! serious problems.
20 #![allow(unsafe_code)]
21
22 #[cfg(linux_raw)]
23 use crate::ffi::CStr;
24 #[cfg(linux_raw)]
25 use crate::fs::AtFlags;
26 use crate::imp;
27 #[cfg(linux_raw)]
28 use crate::io;
29 #[cfg(linux_raw)]
30 use crate::process::Pid;
31 #[cfg(linux_raw)]
32 use core::ffi::c_void;
33 #[cfg(linux_raw)]
34 use imp::fd::AsFd;
35
36 #[cfg(linux_raw)]
37 #[cfg(target_arch = "x86")]
38 #[inline]
39 pub unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> {
40 imp::runtime::syscalls::tls::set_thread_area(u_info)
41 }
42
43 #[cfg(linux_raw)]
44 #[cfg(target_arch = "arm")]
45 #[inline]
46 pub unsafe fn arm_set_tls(data: *mut c_void) -> io::Result<()> {
47 imp::runtime::syscalls::tls::arm_set_tls(data)
48 }
49
50 #[cfg(linux_raw)]
51 #[cfg(target_arch = "x86_64")]
52 #[inline]
53 pub unsafe fn set_fs(data: *mut c_void) {
54 imp::runtime::syscalls::tls::set_fs(data)
55 }
56
57 #[cfg(linux_raw)]
58 #[inline]
59 pub unsafe fn set_tid_address(data: *mut c_void) -> Pid {
60 imp::runtime::syscalls::tls::set_tid_address(data)
61 }
62
63 /// `prctl(PR_SET_NAME, name)`
64 ///
65 /// # References
66 /// - [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
67 ///
68 /// # Safety
69 ///
70 /// This is a very low-level feature for implementing threading libraries.
71 /// See the references links above.
72 ///
73 /// [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html
74 #[cfg(linux_raw)]
75 #[inline]
76 pub unsafe fn set_thread_name(name: &CStr) -> io::Result<()> {
77 imp::runtime::syscalls::tls::set_thread_name(name)
78 }
79
80 #[cfg(linux_raw)]
81 #[cfg(target_arch = "x86")]
82 pub use imp::runtime::tls::UserDesc;
83
84 /// `syscall(SYS_exit, status)`—Exit the current thread.
85 ///
86 /// # Safety
87 ///
88 /// This is a very low-level feature for implementing threading libraries.
89 #[cfg(linux_raw)]
90 #[inline]
91 pub unsafe fn exit_thread(status: i32) -> ! {
92 imp::runtime::syscalls::tls::exit_thread(status)
93 }
94
95 /// Exit all the threads in the current process' thread group.
96 ///
97 /// This is equivalent to `_exit` and `_Exit` in libc.
98 ///
99 /// This does not all any `__cxa_atexit`, `atexit`, or any other destructors.
100 /// Most programs should use [`std::process::exit`] instead of calling this
101 /// directly.
102 ///
103 /// # References
104 /// - [POSIX `_Exit`]
105 /// - [Linux `exit_group`]
106 /// - [Linux `_Exit`]
107 ///
108 /// [POSIX `_Exit`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
109 /// [Linux `exit_group`]: https://man7.org/linux/man-pages/man2/exit_group.2.html
110 /// [Linux `_Exit`]: https://man7.org/linux/man-pages/man2/exit.2.html
111 #[doc(alias = "_exit")]
112 #[doc(alias = "_Exit")]
113 #[inline]
114 pub fn exit_group(status: i32) -> ! {
115 imp::process::syscalls::exit_group(status)
116 }
117
118 /// Return fields from the main executable segment headers ("phdrs") relevant
119 /// to initializing TLS provided to the program at startup.
120 #[cfg(linux_raw)]
121 #[inline]
122 pub fn startup_tls_info() -> StartupTlsInfo {
123 imp::runtime::tls::startup_tls_info()
124 }
125
126 /// `(getauxval(AT_PHDR), getauxval(AT_PHNUM))`—Returns the address and
127 /// number of ELF segment headers for the main executable.
128 ///
129 /// # References
130 /// - [Linux]
131 ///
132 /// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
133 #[cfg(linux_raw)]
134 #[cfg(any(target_os = "android", target_os = "linux"))]
135 #[inline]
136 pub fn exe_phdrs() -> (*const c_void, usize) {
137 imp::param::auxv::exe_phdrs()
138 }
139
140 #[cfg(linux_raw)]
141 pub use imp::runtime::tls::StartupTlsInfo;
142
143 /// `fork()`—Creates a new process by duplicating the calling process.
144 ///
145 /// On success, the pid of the child process is returned in the parent, and
146 /// `None` is returned in the child.
147 ///
148 /// Unlike its POSIX and libc counterparts, this `fork` does not invoke any
149 /// handlers (such as those registered with `pthread_atfork`).
150 ///
151 /// The program environment in the child after a `fork` and before an `execve`
152 /// is very special. All code that executes in this environment must avoid:
153 ///
154 /// - Acquiring any other locks that are held in other threads on the parent
155 /// at the time of the `fork`, as the child only contains one thread, and
156 /// attempting to acquire such locks will deadlock (though this is [not
157 /// considered unsafe]).
158 ///
159 /// - Performing any dynamic allocation using the global allocator, since
160 /// global allocators may use locks to ensure thread safety, and their locks
161 /// may not be released in the child process, so attempts to allocate may
162 /// deadlock (as described in the previous point).
163 ///
164 /// - Accessing any external state which the parent assumes it has exclusive
165 /// access to, such as a file protected by a file lock, as this could
166 /// corrupt the external state.
167 ///
168 /// - Accessing any random-number-generator state inherited from the parent,
169 /// as the parent may have the same state and generate the same random
170 /// numbers, which may violate security invariants.
171 ///
172 /// - Accessing any thread runtime state, since this function does not update
173 /// the thread id in the thread runtime, so thread runtime functions could
174 /// cause undefined behavior.
175 ///
176 /// - Accessing any memory shared with the parent, such as a [`MAP_SHARED`]
177 /// mapping, even with anonymous or [`memfd_create`] mappings, as this could
178 /// cause undefined behavior.
179 ///
180 /// - Calling any C function which isn't known to be [async-signal-safe], as
181 /// that could cause undefined behavior. The extent to which this also
182 /// applies to Rust functions is unclear at this time.
183 ///
184 /// # Safety
185 ///
186 /// The child must avoid accessing any memory shared with the parent in a
187 /// way that invokes undefined behavior. It must avoid accessing any threading
188 /// runtime functions in a way that invokes undefined behavior. And it must
189 /// avoid invoking any undefined behavior through any function that is not
190 /// guaranteed to be async-signal-safe.
191 ///
192 /// # References
193 /// - [POSIX]
194 /// - [Linux]
195 ///
196 /// # Literary interlude
197 ///
198 /// > Do not jump on ancient uncles.
199 /// > Do not yell at average mice.
200 /// > Do not wear a broom to breakfast.
201 /// > Do not ask a snake’s advice.
202 /// > Do not bathe in chocolate pudding.
203 /// > Do not talk to bearded bears.
204 /// > Do not smoke cigars on sofas.
205 /// > Do not dance on velvet chairs.
206 /// > Do not take a whale to visit
207 /// > Russell’s mother’s cousin’s yacht.
208 /// > And whatever else you do do
209 /// > It is better you
210 /// > Do not.
211 ///
212 /// - "Rules", by Karla Kuskin
213 ///
214 /// [`MAP_SHARED`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
215 /// [not considered unsafe]: https://doc.rust-lang.org/reference/behavior-not-considered-unsafe.html#deadlocks
216 /// [`memfd_create`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
217 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
218 /// [Linux]: https://man7.org/linux/man-pages/man2/fork.2.html
219 /// [async-signal-safe]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
220 #[cfg(linux_raw)]
221 pub unsafe fn fork() -> io::Result<Option<Pid>> {
222 imp::runtime::syscalls::fork()
223 }
224
225 /// `execveat(dirfd, path.as_c_str(), argv, envp, flags)`—Execute a new
226 /// command using the current process.
227 ///
228 /// # Safety
229 ///
230 /// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
231 /// their contents must be pointers to NUL-terminated byte arrays.
232 ///
233 /// # References
234 /// - [Linux]
235 ///
236 /// [Linux]: https://man7.org/linux/man-pages/man2/execveat.2.html
237 #[cfg(linux_raw)]
238 #[inline]
239 pub unsafe fn execveat<Fd: AsFd>(
240 dirfd: Fd,
241 path: &CStr,
242 argv: *const *const u8,
243 envp: *const *const u8,
244 flags: AtFlags,
245 ) -> io::Errno {
246 imp::runtime::syscalls::execveat(dirfd.as_fd(), path, argv, envp, flags)
247 }
248
249 /// `execve(path.as_c_str(), argv, envp)`—Execute a new command using the
250 /// current process.
251 ///
252 /// # Safety
253 ///
254 /// The `argv` and `envp` pointers must point to NUL-terminated arrays, and
255 /// their contents must be pointers to NUL-terminated byte arrays.
256 ///
257 /// # References
258 /// - [Linux]
259 ///
260 /// [Linux]: https://man7.org/linux/man-pages/man2/execve.2.html
261 #[cfg(linux_raw)]
262 #[inline]
263 pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8) -> io::Errno {
264 imp::runtime::syscalls::execve(path, argv, envp)
265 }