1use core::{alloc::{GlobalAlloc, Layout}, ffi::{c_int, c_void}, sync::atomic::{AtomicBool, Ordering}};
5
6#[link(name = "c")]
7unsafe extern "C" {
8 fn posix_memalign(out: *mut *mut c_void, align: usize, size: usize) -> c_int;
9 fn free(ptr: *mut c_void);
10 fn mmap(address: *mut c_void, size: usize, protection: c_int, flags: c_int, fd: c_int, offset: i64) -> *mut c_void;
11 fn munmap(address: *mut c_void, size: usize) -> c_int;
12 fn sched_yield() -> c_int;
13 fn _exit(code: c_int) -> !;
14 fn write(fd: c_int, bytes: *const c_void, count: usize) -> isize;
15}
16#[link(name = "log")]
17unsafe extern "C" {
18 fn __android_log_write(priority: c_int, tag: *const u8, text: *const u8) -> c_int;
19}
20
21struct AndroidAllocator;
22#[cfg_attr(not(feature = "std"), global_allocator)]
23#[cfg_attr(feature = "std", allow(dead_code))] static ALLOC: AndroidAllocator = AndroidAllocator;
25
26unsafe impl GlobalAlloc for AndroidAllocator {
28 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
29 let mut ptr = core::ptr::null_mut();
30 let result = unsafe { posix_memalign(&mut ptr, layout.align().max(core::mem::size_of::<usize>()), layout.size().max(1)) };
32 if result == 0 { ptr.cast() } else { core::ptr::null_mut() }
33 }
34 unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
35 unsafe { free(ptr.cast()) };
37 }
38}
39
40pub unsafe fn pages_alloc(size: usize) -> *mut u8 {
44 let ptr = unsafe { mmap(core::ptr::null_mut(), size.max(1), 3, 0x22, -1, 0) };
46 if ptr as usize == usize::MAX { core::ptr::null_mut() } else { ptr.cast() }
47}
48pub unsafe fn pages_free(ptr: *mut u8, size: usize) {
52 if !ptr.is_null() {
53 unsafe { munmap(ptr.cast(), size.max(1)) };
55 }
56}
57pub fn yield_now() {
59 unsafe { sched_yield() };
61}
62pub fn exit(code: i32) -> ! {
64 unsafe { _exit(code) }
66}
67static CONSOLE: AtomicBool = AtomicBool::new(false);
69#[unsafe(no_mangle)]
71pub extern "C" fn jfgui_console() {
72 CONSOLE.store(true, Ordering::Relaxed);
73}
74fn log(bytes: &[u8], priority: i32) {
75 if CONSOLE.load(Ordering::Relaxed) {
76 unsafe { write(if priority == 6 { 2 } else { 1 }, bytes.as_ptr().cast(), bytes.len()) };
78 return;
79 }
80 for chunk in bytes.chunks(1000) {
81 let mut text = [0u8; 1001];
82 text[..chunk.len()].copy_from_slice(chunk);
83 unsafe { __android_log_write(priority, c"jfgui".as_ptr().cast(), text.as_ptr()) };
85 }
86}
87pub fn write_stdout(bytes: &[u8]) { log(bytes, 4); }
89pub fn write_stderr(bytes: &[u8]) { log(bytes, 6); }
91
92#[cfg(not(feature = "std"))]
94#[unsafe(no_mangle)]
95pub extern "C" fn rust_eh_personality() -> ! { exit(4) }