1pub use imp::*;
7
8#[cfg(windows)]
9mod imp {
10 #[link(name = "kernel32", kind = "raw-dylib")]
11 unsafe extern "system" {
12 fn GetStdHandle(n: u32) -> isize;
13 fn WriteFile(h: isize, buf: *const u8, n: u32, done: *mut u32, ov: usize) -> i32;
14 fn ExitProcess(code: u32) -> !;
15 fn VirtualAlloc(addr: usize, size: usize, typ: u32, prot: u32) -> *mut u8;
16 fn VirtualFree(addr: *mut u8, size: usize, typ: u32) -> i32;
17 fn SwitchToThread() -> i32;
18 }
19
20 pub fn yield_now() {
22 unsafe { SwitchToThread() };
24 }
25
26 pub fn exit(code: i32) -> ! {
27 unsafe { ExitProcess(code as u32) }
29 }
30
31 fn write_handle(n: u32, b: &[u8]) {
32 let mut off = 0;
33 while off < b.len() {
34 let chunk = (b.len() - off).min(1 << 30);
35 let mut done = 0u32;
36 let ok = unsafe { WriteFile(GetStdHandle(n), b.as_ptr().add(off), chunk as u32, &mut done, 0) };
38 if ok == 0 || done == 0 {
39 break;
40 }
41 off += done as usize;
42 }
43 }
44
45 pub fn write_stdout(b: &[u8]) {
46 write_handle(-11i32 as u32, b)
47 }
48
49 pub fn write_stderr(b: &[u8]) {
50 write_handle(-12i32 as u32, b)
51 }
52
53 pub unsafe fn pages_alloc(n: usize) -> *mut u8 {
58 unsafe { VirtualAlloc(0, n, 0x3000, 4) }
60 }
61
62 pub unsafe fn pages_free(p: *mut u8, _n: usize) {
65 unsafe { VirtualFree(p, 0, 0x8000) };
66 }
67
68 #[cfg(not(feature = "std"))]
70 #[unsafe(no_mangle)]
71 pub static _fltused: i32 = 0;
72
73 #[cfg(not(feature = "std"))]
74 #[unsafe(no_mangle)]
75 pub extern "C" fn __CxxFrameHandler3() -> ! {
76 exit(4)
77 }
78
79 #[cfg(not(feature = "std"))]
81 core::arch::global_asm!(
82 ".globl __chkstk",
83 "__chkstk:",
84 " push rcx",
85 " push rax",
86 " cmp rax, 4096",
87 " lea rcx, [rsp + 24]",
88 " jb 2f",
89 "1:",
90 " sub rcx, 4096",
91 " test [rcx], rcx",
92 " sub rax, 4096",
93 " cmp rax, 4096",
94 " ja 1b",
95 "2:",
96 " sub rcx, rax",
97 " test [rcx], rcx",
98 " pop rax",
99 " pop rcx",
100 " ret",
101 );
102}
103
104#[cfg(target_os = "linux")]
105mod imp {
106 use core::arch::asm;
107
108 pub use crate::kernel::*;
109
110 #[inline]
113 pub unsafe fn syscall6(n: usize, a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> isize {
114 let r: isize;
115 unsafe {
116 asm!("syscall", inlateout("rax") n as isize => r, in("rdi") a, in("rsi") b, in("rdx") c,
117 in("r10") d, in("r8") e, in("r9") f, lateout("rcx") _, lateout("r11") _, options(nostack));
118 }
119 r
120 }
121
122 #[inline]
125 pub unsafe fn syscall3(n: usize, a: usize, b: usize, c: usize) -> isize {
126 unsafe { syscall6(n, a, b, c, 0, 0, 0) }
127 }
128
129 #[inline]
134 pub unsafe fn poll(fds: usize, n: usize, ms: i32) -> isize {
135 let mut ts = [(ms / 1000) as i64, (ms % 1000) as i64 * 1_000_000];
137 let timeout = if ms < 0 { 0 } else { ts.as_mut_ptr() as usize };
138 unsafe { syscall6(SYS_PPOLL, fds, n, timeout, 0, 8, 0) }
140 }
141
142 #[inline]
148 pub unsafe fn clone(flags: usize, stack: usize, parent_tid: usize, child_tid: usize, tls: usize) -> isize {
149 let [a, b, c] = clone_args(parent_tid, child_tid, tls);
150 unsafe { syscall6(SYS_CLONE, flags, stack, a, b, c, 0) }
151 }
152
153 #[inline]
158 pub unsafe fn fork() -> isize {
159 unsafe { clone(17, 0, 0, 0, 0) }
160 }
161
162 #[inline]
168 pub unsafe fn dup2(old: usize, new: usize) -> isize {
169 if old == new {
170 let r = unsafe { syscall3(SYS_FCNTL, old, 1, 0) };
172 return if r < 0 { r } else { old as isize };
173 }
174 unsafe { syscall3(SYS_DUP3, old, new, 0) }
175 }
176
177 #[inline]
182 pub unsafe fn rename(old: usize, new: usize) -> isize {
183 let r = unsafe { syscall6(SYS_RENAMEAT2, AT_FDCWD, old, AT_FDCWD, new, 0, 0) };
184 if r != -38 {
185 return r; }
187 unsafe { syscall6(SYS_RENAMEAT, AT_FDCWD, old, AT_FDCWD, new, 0, 0) }
188 }
189
190 pub fn exit(code: i32) -> ! {
191 unsafe { syscall3(SYS_EXIT_GROUP, code as usize, 0, 0) };
193 loop {}
194 }
195
196 pub fn yield_now() {
198 unsafe { syscall3(SYS_SCHED_YIELD, 0, 0, 0) };
200 }
201
202 pub fn write_fd(fd: usize, b: &[u8]) {
203 let mut off = 0;
204 while off < b.len() {
205 let r = unsafe { syscall3(SYS_WRITE, fd, b.as_ptr() as usize + off, b.len() - off) };
207 if r == -4 {
208 continue; }
210 if r == -11 {
211 let mut pfd = [fd as i32, 4]; unsafe { poll(pfd.as_mut_ptr() as usize, 1, -1) };
216 continue;
217 }
218 if r <= 0 {
219 break;
220 }
221 off += r as usize;
222 }
223 }
224
225 pub fn write_stdout(b: &[u8]) {
226 write_fd(1, b)
227 }
228
229 pub fn write_stderr(b: &[u8]) {
230 write_fd(2, b)
231 }
232
233 pub unsafe fn pages_alloc(n: usize) -> *mut u8 {
238 let r = unsafe { syscall6(SYS_MMAP, 0, n, 3, 0x22, usize::MAX, 0) };
240 if r < 0 {
241 return core::ptr::null_mut();
242 }
243 if n >= 4 << 20 {
244 unsafe { syscall3(SYS_MADVISE, r as usize, n, 14) };
248 }
249 r as *mut u8
250 }
251
252 pub unsafe fn pages_free(p: *mut u8, n: usize) {
255 unsafe { syscall3(SYS_MUNMAP, p as usize, n, 0) };
256 }
257
258 #[cfg(not(feature = "std"))]
260 #[unsafe(no_mangle)]
261 pub extern "C" fn rust_eh_personality() {}
262
263 #[cfg(not(feature = "std"))]
264 #[unsafe(no_mangle)]
265 pub extern "C" fn _Unwind_Resume() -> ! {
266 exit(4)
267 }
268}