#![no_std]
#![feature(linkage)]  // 开启弱链接特性
#![feature(panic_info_message)]


pub mod user_lang_items;
pub use user_lang_items::*;

pub mod syscall;
use syscall::*;
use buddy_system_allocator::LockedHeap;

const USER_HEAP_SIZE: usize = 16384;
static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE];

// 用户应用的分配器
#[global_allocator]
static HEAP: LockedHeap = LockedHeap::empty();


// 只要使用这个包, 那么这里就会作为bin程序的开始
#[no_mangle]
#[link_section = ".text.entry"]  // 链接到指定的段
pub extern "C" fn _start() -> ! {
    unsafe {
        HEAP.lock()
            .init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE);
    }

    sys_exit(main());  // 这里执行的main程序是我们 bin文件夹里面的main, 而不是下面的, 下面的main程序只有在bin程序没有main函数的时候才会链接
    // 正常是不会走到这一步的, 因为上面已经退出了程序
    panic!("unreachable after sys_exit!");
}

#[linkage = "weak"]  // 设置我们默认的main函数, 弱链接
#[no_mangle]
fn main() -> i32 {
    panic!("Cannot find main!");
}

// sys_waitpid如果传的是-1 则表示任何子进程退出都可以,
pub fn wait(exit_code: &mut i32) -> isize {
    loop {
        match sys_waitpid(-1, exit_code as *mut _) {
            // 如果返回-2, 说明还没有僵尸进程, 那就下一轮loop循环继续等待
            -2 => {
                sys_yield();
            }
            // 如果返回 -1 说明有任意进程结束
            // -1 or a real pid
            exit_pid => return exit_pid,
        }
    }
}

// 只检测指定pid的进程是否结束
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
    loop {
        match sys_waitpid(pid as isize, exit_code as *mut _) {
            -2 => {
                sys_yield();
            }
            // -1 or a real pid
            exit_pid => return exit_pid,
        }
    }
}

pub fn sleep(period_ms: usize) {
    let start = sys_get_time();
    while sys_get_time() < start + period_ms as isize {
        sys_yield();
    }
}