فهرست منبع

Link allocator (#3)

* 连接Allocator

* 连接Allocator

* pal

* pal
GnoCiYeH 8 ماه پیش
والد
کامیت
b4db606949

+ 14 - 0
.vscode/settings.json

@@ -0,0 +1,14 @@
+{
+    "rust-analyzer.linkedProjects": [
+        "./Cargo.toml",
+        "./Cargo.toml",
+        "./Cargo.toml",
+        "./Cargo.toml"
+    ],
+
+    "rust-analyzer.cargo.target": "x86_64-unknown-dragonos",
+    "files.associations": {
+        "errno.h": "c",
+        "stdint.h": "c"
+    }
+}

+ 3 - 0
Cargo.toml

@@ -7,6 +7,9 @@ edition = "2021"
 
 [dependencies]
 
+[target.'cfg(target_os = "dragonos")'.dependencies]
+# Development
+dragonos-dsc = { git = "https://github.com/DragonOS-Community/dsc.git", rev = "d6e4fd8" }
 
 # 构建时依赖项
 [build-dependencies]

+ 15 - 0
build.rs

@@ -0,0 +1,15 @@
+extern crate cc;
+
+fn main() {
+    #[cfg(target_os = "linux")]
+    cc::Build::new()
+        .flag("-nostdlib")
+        .file("src/platform/c/dragonos_malloc.c")
+        .compile("dragonos_malloc");
+    #[cfg(not(target_os = "linux"))]
+    cc::Build::new()
+        .flag("-nostdinc")
+        .flag("-nostdlib")
+        .file("src/platform/c/dragonos_malloc.c")
+        .compile("dragonos_malloc");
+}

+ 68 - 0
init_dragonos_toolchain.sh

@@ -0,0 +1,68 @@
+# 当前脚本用于初始化自定义的Rust工具链
+if [ -z "$(which cargo)" ]; then
+    echo "尚未安装Rust,请先安装Rust"
+    exit 1
+fi
+
+# 是否强制覆盖已有的工具链配置文件
+FORCE=0
+
+while getopts "f" arg
+do
+    case $arg in
+        f)
+            FORCE=1
+            ;;
+        ?)
+            echo "unkonw argument"
+            exit 1
+        ;;
+    esac
+done
+
+DRAGONOS_UNKNOWN_ELF_PATH=$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-dragonos
+mkdir -p ${DRAGONOS_UNKNOWN_ELF_PATH}/lib
+echo $DRAGONOS_UNKNOWN_ELF_PATH
+
+# 判断是否已经存在工具链配置文件
+if [ -f "${DRAGONOS_UNKNOWN_ELF_PATH}/target.json" ]; then
+    if [ $FORCE -eq 0 ]; then
+        echo "已存在工具链配置文件,如需重新初始化,请使用-f参数"
+        exit 0
+    fi
+fi
+
+# 设置工具链配置文件
+echo   \
+"{\
+    \"arch\": \"x86_64\",
+    \"code-model\": \"kernel\",
+    \"cpu\": \"x86-64\",
+    \"os\": \"dragonos\",
+    \"target-endian\": \"little\",
+    \"target-pointer-width\": \"64\",
+    \"target-c-int-width\": \"32\",
+    \"data-layout\": \"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128\",
+    \"disable-redzone\": true,
+    \"features\": \"-3dnow,-3dnowa,-avx,-avx2\",
+    \"linker\": \"rust-lld\",
+    \"linker-flavor\": \"ld.lld\",
+    \"llvm-target\": \"x86_64-unknown-none\",
+    \"max-atomic-width\": 64,
+    \"panic-strategy\": \"abort\",
+    \"position-independent-executables\": true,
+    \"relro-level\": \"full\",
+    \"stack-probes\": {
+      \"kind\": \"inline-or-call\",
+      \"min-llvm-version-for-inline\": [
+        16,
+        0,
+        0
+      ]
+    },
+    \"static-position-independent-executables\": true,
+    \"supported-sanitizers\": [
+      \"kcfi\"
+    ],
+    \"target-pointer-width\": \"64\"
+}" > ${DRAGONOS_UNKNOWN_ELF_PATH}/target.json || exit 1

+ 11 - 0
src/header/dirent/mod.rs

@@ -0,0 +1,11 @@
+use crate::platform::types::{ino_t, off_t, c_ushort, c_uchar,c_char};
+
+#[repr(C)]
+#[derive(Clone)]
+pub struct dirent {
+    pub d_ino: ino_t,
+    pub d_off: off_t,
+    pub d_reclen: c_ushort,
+    pub d_type: c_uchar,
+    pub d_name: [c_char; 256],
+}

+ 7 - 0
src/header/mod.rs

@@ -0,0 +1,7 @@
+pub mod time;
+pub mod sys_stat;
+pub mod sys_statvfs;
+pub mod dirent;
+pub mod sys_resource;
+pub mod sys_time;
+pub mod sys_utsname;

+ 7 - 0
src/header/sys_resource/mod.rs

@@ -0,0 +1,7 @@
+pub type rlim_t = u64;
+
+#[repr(C)]
+pub struct rlimit {
+    pub rlim_cur: rlim_t,
+    pub rlim_max: rlim_t,
+}

+ 27 - 0
src/header/sys_stat/mod.rs

@@ -0,0 +1,27 @@
+use crate::platform::types::*;
+
+use super::time::timespec;
+
+#[repr(C)]
+#[derive(Default)]
+pub struct stat {
+    pub st_dev: dev_t,
+    pub st_ino: ino_t,
+    pub st_nlink: nlink_t,
+    pub st_mode: mode_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_size: off_t,
+    pub st_blksize: blksize_t,
+    pub st_blocks: blkcnt_t,
+
+    pub st_atim: timespec,
+    pub st_mtim: timespec,
+    pub st_ctim: timespec,
+
+    // Compared to glibc, our struct is for some reason 24 bytes too small.
+    // Accessing atime works, so clearly the struct isn't incorrect...
+    // This works.
+    pub _pad: [c_char; 24],
+}

+ 18 - 0
src/header/sys_statvfs/mod.rs

@@ -0,0 +1,18 @@
+use crate::platform::types::{c_ulong, fsblkcnt_t, fsfilcnt_t};
+
+
+#[repr(C)]
+#[derive(Default)]
+pub struct statvfs {
+    pub f_bsize: c_ulong,
+    pub f_frsize: c_ulong,
+    pub f_blocks: fsblkcnt_t,
+    pub f_bfree: fsblkcnt_t,
+    pub f_bavail: fsblkcnt_t,
+    pub f_files: fsfilcnt_t,
+    pub f_ffree: fsfilcnt_t,
+    pub f_favail: fsfilcnt_t,
+    pub f_fsid: c_ulong,
+    pub f_flag: c_ulong,
+    pub f_namemax: c_ulong,
+}

+ 14 - 0
src/header/sys_time/mod.rs

@@ -0,0 +1,14 @@
+use crate::platform::types::{time_t, suseconds_t, c_int};
+
+#[repr(C)]
+#[derive(Default)]
+pub struct timeval {
+    pub tv_sec: time_t,
+    pub tv_usec: suseconds_t,
+}
+#[repr(C)]
+#[derive(Default)]
+pub struct timezone {
+    pub tz_minuteswest: c_int,
+    pub tz_dsttime: c_int,
+}

+ 13 - 0
src/header/sys_utsname/mod.rs

@@ -0,0 +1,13 @@
+use crate::platform::types::c_char;
+
+pub const UTSLENGTH: usize = 65;
+
+#[repr(C)]
+pub struct utsname {
+    pub sysname: [c_char; UTSLENGTH],
+    pub nodename: [c_char; UTSLENGTH],
+    pub release: [c_char; UTSLENGTH],
+    pub version: [c_char; UTSLENGTH],
+    pub machine: [c_char; UTSLENGTH],
+    pub domainname: [c_char; UTSLENGTH],
+}

+ 10 - 0
src/header/time/mod.rs

@@ -0,0 +1,10 @@
+use core::ffi::c_long;
+
+use crate::platform::types::time_t;
+
+#[repr(C)]
+#[derive(Default)]
+pub struct timespec {
+    pub tv_sec: time_t,
+    pub tv_nsec: c_long,
+}

+ 3 - 2
src/lib.rs

@@ -3,9 +3,10 @@
 
 extern crate alloc;
 
-use allocator::{Allocator, NEWALLOCATOR};
+use crate::platform::allocator::{Allocator, NEWALLOCATOR};
 
-mod allocator;
+mod platform;
+mod header;
 
 #[global_allocator]
 static ALLOCATOR: Allocator = NEWALLOCATOR;

+ 70 - 0
src/platform/allocator/dragonos_malloc.rs

@@ -0,0 +1,70 @@
+use core::{alloc::GlobalAlloc, ffi::c_void, ptr::null_mut};
+
+extern "C" {
+    fn _dragonos_free(ptr: *mut c_void) -> *mut c_void;
+    fn _dragonos_malloc(size: usize) -> *mut c_void;
+    fn _dragonos_chunk_length(ptr: *mut c_void) -> usize;
+}
+
+pub struct Allocator;
+
+pub const NEWALLOCATOR: Allocator = Allocator;
+
+unsafe impl GlobalAlloc for Allocator {
+    unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
+        let size = align_up(layout.size(), layout.align());
+
+        return alloc(size);
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: core::alloc::Layout) {
+        free(ptr);
+    }
+    unsafe fn realloc(
+        &self,
+        ptr: *mut u8,
+        layout: core::alloc::Layout,
+        new_size: usize,
+    ) -> *mut u8 {
+        let size = align_up(new_size, layout.align());
+        return realloc(ptr, size);
+    }
+}
+
+pub unsafe fn alloc(size: usize) -> *mut u8 {
+    return _dragonos_malloc(size) as *mut u8;
+}
+
+pub unsafe fn free(ptr: *mut u8) {
+    _dragonos_free(ptr as *mut c_void);
+}
+
+fn align_up(addr: usize, align: usize) -> usize {
+    return (addr + align - 1) & !(align - 1);
+}
+
+pub unsafe fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
+    if ptr.is_null() {
+        return alloc(size);
+    }
+    if size == 0 {
+        free(ptr);
+        return null_mut();
+    }
+
+    let old_len = _dragonos_chunk_length(ptr as *mut c_void) - 16;
+
+    // 暴力实现
+
+    let new_ptr = alloc(size);
+    if new_ptr.is_null() {
+        return null_mut();
+    }
+
+    let copy_len = if old_len < size { old_len } else { size };
+    core::ptr::copy_nonoverlapping(ptr, new_ptr, copy_len);
+
+    free(ptr);
+
+    return new_ptr;
+}

+ 4 - 0
src/platform/allocator/mod.rs

@@ -0,0 +1,4 @@
+pub mod dragonos_malloc;
+mod test;
+pub use dragonos_malloc::Allocator;
+pub use dragonos_malloc::NEWALLOCATOR;

+ 75 - 0
src/platform/allocator/test.rs

@@ -0,0 +1,75 @@
+#[cfg(test)]
+mod tests {
+    use crate::platform::allocator::Allocator;
+    use core::alloc::{GlobalAlloc, Layout};
+
+    #[test]
+    fn test_allocation_and_deallocation() {
+        let allocator = Allocator;
+
+        let size = 1024; // 分配 1024 字节的内存
+
+        unsafe {
+            // 使用 Allocator 分配内存
+            let layout = Layout::from_size_align(size, 1).unwrap();
+            let ptr = allocator.alloc(layout);
+
+            assert!(!ptr.is_null()); // 确保分配成功
+
+            // 使用 Allocator 释放内存
+            allocator.dealloc(ptr, layout);
+        }
+    }
+
+    #[test]
+    fn test_alignment() {
+        let allocator = Allocator;
+
+        let size = 1024;
+        let align = 16;
+
+        unsafe {
+            let layout = Layout::from_size_align(size, align).unwrap();
+            let ptr = allocator.alloc(layout);
+
+            assert!(!ptr.is_null());
+            assert_eq!(ptr as usize % align, 0);
+
+            allocator.dealloc(ptr, layout);
+        }
+    }
+
+    #[test]
+    fn test_multiple_allocations() {
+        let allocator = Allocator;
+
+        let sizes = [100, 200, 300, 400, 500];
+
+        unsafe {
+            for &size in &sizes {
+                let layout = Layout::from_size_align(size, 1).unwrap();
+                let ptr = allocator.alloc(layout);
+
+                assert!(!ptr.is_null());
+
+                allocator.dealloc(ptr, layout);
+            }
+        }
+    }
+
+    #[test]
+    fn test_large_allocation() {
+        let allocator = Allocator;
+
+        let size = 1024 * 1024; // 1MB
+
+        unsafe {
+            let layout = Layout::from_size_align(size, 1).unwrap();
+            let ptr = allocator.alloc(layout);
+
+            assert!(!ptr.is_null());
+
+            allocator.dealloc(ptr, layout);
+        }
+    }
+}

+ 286 - 0
src/platform/c/dragonos_include/errno.h

@@ -0,0 +1,286 @@
+#ifndef _RELIBC_ERRNO_H
+#define _RELIBC_ERRNO_H
+
+#include <bits/errno.h>
+
+#define EPERM 1
+
+#define ENOENT 2
+
+#define ESRCH 3
+
+#define EINTR 4
+
+#define EIO 5
+
+#define ENXIO 6
+
+#define E2BIG 7
+
+#define ENOEXEC 8
+
+#define EBADF 9
+
+#define ECHILD 10
+
+#define EAGAIN 11
+
+#define ENOMEM 12
+
+#define EACCES 13
+
+#define EFAULT 14
+
+#define ENOTBLK 15
+
+#define EBUSY 16
+
+#define EEXIST 17
+
+#define EXDEV 18
+
+#define ENODEV 19
+
+#define ENOTDIR 20
+
+#define EISDIR 21
+
+#define EINVAL 22
+
+#define ENFILE 23
+
+#define EMFILE 24
+
+#define ENOTTY 25
+
+#define ETXTBSY 26
+
+#define EFBIG 27
+
+#define ENOSPC 28
+
+#define ESPIPE 29
+
+#define EROFS 30
+
+#define EMLINK 31
+
+#define EPIPE 32
+
+#define EDOM 33
+
+#define ERANGE 34
+
+#define EDEADLK 35
+
+#define ENAMETOOLONG 36
+
+#define ENOLCK 37
+
+#define ENOSYS 38
+
+#define ENOTEMPTY 39
+
+#define ELOOP 40
+
+#define EWOULDBLOCK 41
+
+#define EWOULDBLOCK EAGAIN
+
+#define ENOMSG 42
+
+#define EIDRM 43
+
+#define ECHRNG 44
+
+#define EL2NSYNC 45
+
+#define EL3HLT 46
+
+#define EL3RST 47
+
+#define ELNRNG 48
+
+#define EUNATCH 49
+
+#define ENOCSI 50
+
+#define EL2HLT 51
+
+#define EBADE 52
+
+#define EBADR 53
+
+#define EXFULL 54
+
+#define ENOANO 55
+
+#define EBADRQC 56
+
+#define EBADSLT 57
+
+#define EDEADLOCK 58
+
+#define EBFONT 59
+
+#define ENOSTR 60
+
+#define ENODATA 61
+
+#define ETIME 62
+
+#define ENOSR 63
+
+#define ENONET 64
+
+#define ENOPKG 65
+
+#define EREMOTE 66
+
+#define ENOLINK 67
+
+#define EADV 68
+
+#define ESRMNT 69
+
+#define ECOMM 70
+
+#define EPROTO 71
+
+#define EMULTIHOP 72
+
+#define EDOTDOT 73
+
+#define EBADMSG 74
+
+#define EOVERFLOW 75
+
+#define ENOTUNIQ 76
+
+#define EBADFD 77
+
+#define EREMCHG 78
+
+#define ELIBACC 79
+
+#define ELIBBAD 80
+
+#define ELIBSCN 81
+
+#define ELIBMAX 82
+
+#define ELIBEXEC 83
+
+#define EILSEQ 84
+
+#define ERESTART 85
+
+#define ESTRPIPE 86
+
+#define EUSERS 87
+
+#define ENOTSOCK 88
+
+#define EDESTADDRREQ 89
+
+#define EMSGSIZE 90
+
+#define EPROTOTYPE 91
+
+#define ENOPROTOOPT 92
+
+#define EPROTONOSUPPORT 93
+
+#define ESOCKTNOSUPPORT 94
+
+#define EOPNOTSUPP 95
+
+#define EPFNOSUPPORT 96
+
+#define EAFNOSUPPORT 97
+
+#define EADDRINUSE 98
+
+#define EADDRNOTAVAIL 99
+
+#define ENETDOWN 100
+
+#define ENETUNREACH 101
+
+#define ENETRESET 102
+
+#define ECONNABORTED 103
+
+#define ECONNRESET 104
+
+#define ENOBUFS 105
+
+#define EISCONN 106
+
+#define ENOTCONN 107
+
+#define ESHUTDOWN 108
+
+#define ETOOMANYREFS 109
+
+#define ETIMEDOUT 110
+
+#define ECONNREFUSED 111
+
+#define EHOSTDOWN 112
+
+#define EHOSTUNREACH 113
+
+#define EALREADY 114
+
+#define EINPROGRESS 115
+
+#define ESTALE 116
+
+#define EUCLEAN 117
+
+#define ENOTNAM 118
+
+#define ENAVAIL 119
+
+#define EISNAM 120
+
+#define EREMOTEIO 121
+
+#define EDQUOT 122
+
+#define ENOMEDIUM 123
+
+#define EMEDIUMTYPE 124
+
+#define ECANCELED 125
+
+#define ENOKEY 126
+
+#define EKEYEXPIRED 127
+
+#define EKEYREVOKED 128
+
+#define EKEYREJECTED 129
+
+#define EOWNERDEAD 130
+
+#define ENOTRECOVERABLE 131
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+int *__errno(void);
+
+int *__errno_location(void);
+
+char **__program_invocation_name(void);
+
+char **__program_invocation_short_name(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif /* _RELIBC_ERRNO_H */

+ 367 - 0
src/platform/c/dragonos_include/stdint.h

@@ -0,0 +1,367 @@
+/* Copyright (C) 2008-2018 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/*
+ * ISO C Standard:  7.18  Integer types  <stdint.h>
+ */
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+/* 7.8.1.1 Exact-width integer types */
+
+#ifdef __INT8_TYPE__
+typedef __INT8_TYPE__ int8_t;
+#endif
+#ifdef __INT16_TYPE__
+typedef __INT16_TYPE__ int16_t;
+#endif
+#ifdef __INT32_TYPE__
+typedef __INT32_TYPE__ int32_t;
+#endif
+#ifdef __INT64_TYPE__
+typedef __INT64_TYPE__ int64_t;
+#endif
+#ifdef __UINT8_TYPE__
+typedef __UINT8_TYPE__ uint8_t;
+#endif
+#ifdef __UINT16_TYPE__
+typedef __UINT16_TYPE__ uint16_t;
+#endif
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ uint32_t;
+#endif
+#ifdef __UINT64_TYPE__
+typedef __UINT64_TYPE__ uint64_t;
+#endif
+
+/* 7.8.1.2 Minimum-width integer types */
+
+typedef __INT_LEAST8_TYPE__ int_least8_t;
+typedef __INT_LEAST16_TYPE__ int_least16_t;
+typedef __INT_LEAST32_TYPE__ int_least32_t;
+typedef __INT_LEAST64_TYPE__ int_least64_t;
+typedef __UINT_LEAST8_TYPE__ uint_least8_t;
+typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+typedef __UINT_LEAST64_TYPE__ uint_least64_t;
+
+/* 7.8.1.3 Fastest minimum-width integer types */
+
+typedef __INT_FAST8_TYPE__ int_fast8_t;
+typedef __INT_FAST16_TYPE__ int_fast16_t;
+typedef __INT_FAST32_TYPE__ int_fast32_t;
+typedef __INT_FAST64_TYPE__ int_fast64_t;
+typedef __UINT_FAST8_TYPE__ uint_fast8_t;
+typedef __UINT_FAST16_TYPE__ uint_fast16_t;
+typedef __UINT_FAST32_TYPE__ uint_fast32_t;
+typedef __UINT_FAST64_TYPE__ uint_fast64_t;
+
+/* 7.8.1.4 Integer types capable of holding object pointers */
+
+#ifdef __INTPTR_TYPE__
+typedef __INTPTR_TYPE__ intptr_t;
+#endif
+#ifdef __UINTPTR_TYPE__
+typedef __UINTPTR_TYPE__ uintptr_t;
+#endif
+
+/* 7.8.1.5 Greatest-width integer types */
+
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+
+#if (!defined __cplusplus || __cplusplus >= 201103L \
+     || defined __STDC_LIMIT_MACROS)
+
+/* 7.18.2 Limits of specified-width integer types */
+
+#ifdef __INT8_MAX__
+# undef INT8_MAX
+# define INT8_MAX __INT8_MAX__
+# undef INT8_MIN
+# define INT8_MIN (-INT8_MAX - 1)
+#endif
+#ifdef __UINT8_MAX__
+# undef UINT8_MAX
+# define UINT8_MAX __UINT8_MAX__
+#endif
+#ifdef __INT16_MAX__
+# undef INT16_MAX
+# define INT16_MAX __INT16_MAX__
+# undef INT16_MIN
+# define INT16_MIN (-INT16_MAX - 1)
+#endif
+#ifdef __UINT16_MAX__
+# undef UINT16_MAX
+# define UINT16_MAX __UINT16_MAX__
+#endif
+#ifdef __INT32_MAX__
+# undef INT32_MAX
+# define INT32_MAX __INT32_MAX__
+# undef INT32_MIN
+# define INT32_MIN (-INT32_MAX - 1)
+#endif
+#ifdef __UINT32_MAX__
+# undef UINT32_MAX
+# define UINT32_MAX __UINT32_MAX__
+#endif
+#ifdef __INT64_MAX__
+# undef INT64_MAX
+# define INT64_MAX __INT64_MAX__
+# undef INT64_MIN
+# define INT64_MIN (-INT64_MAX - 1)
+#endif
+#ifdef __UINT64_MAX__
+# undef UINT64_MAX
+# define UINT64_MAX __UINT64_MAX__
+#endif
+
+#undef INT_LEAST8_MAX
+#define INT_LEAST8_MAX __INT_LEAST8_MAX__
+#undef INT_LEAST8_MIN
+#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
+#undef UINT_LEAST8_MAX
+#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
+#undef INT_LEAST16_MAX
+#define INT_LEAST16_MAX __INT_LEAST16_MAX__
+#undef INT_LEAST16_MIN
+#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
+#undef UINT_LEAST16_MAX
+#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
+#undef INT_LEAST32_MAX
+#define INT_LEAST32_MAX __INT_LEAST32_MAX__
+#undef INT_LEAST32_MIN
+#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
+#undef UINT_LEAST32_MAX
+#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
+#undef INT_LEAST64_MAX
+#define INT_LEAST64_MAX __INT_LEAST64_MAX__
+#undef INT_LEAST64_MIN
+#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
+#undef UINT_LEAST64_MAX
+#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
+
+#undef INT_FAST8_MAX
+#define INT_FAST8_MAX __INT_FAST8_MAX__
+#undef INT_FAST8_MIN
+#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
+#undef UINT_FAST8_MAX
+#define UINT_FAST8_MAX __UINT_FAST8_MAX__
+#undef INT_FAST16_MAX
+#define INT_FAST16_MAX __INT_FAST16_MAX__
+#undef INT_FAST16_MIN
+#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
+#undef UINT_FAST16_MAX
+#define UINT_FAST16_MAX __UINT_FAST16_MAX__
+#undef INT_FAST32_MAX
+#define INT_FAST32_MAX __INT_FAST32_MAX__
+#undef INT_FAST32_MIN
+#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
+#undef UINT_FAST32_MAX
+#define UINT_FAST32_MAX __UINT_FAST32_MAX__
+#undef INT_FAST64_MAX
+#define INT_FAST64_MAX __INT_FAST64_MAX__
+#undef INT_FAST64_MIN
+#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
+#undef UINT_FAST64_MAX
+#define UINT_FAST64_MAX __UINT_FAST64_MAX__
+
+#ifdef __INTPTR_MAX__
+# undef INTPTR_MAX
+# define INTPTR_MAX __INTPTR_MAX__
+# undef INTPTR_MIN
+# define INTPTR_MIN (-INTPTR_MAX - 1)
+#endif
+#ifdef __UINTPTR_MAX__
+# undef UINTPTR_MAX
+# define UINTPTR_MAX __UINTPTR_MAX__
+#endif
+
+#undef INTMAX_MAX
+#define INTMAX_MAX __INTMAX_MAX__
+#undef INTMAX_MIN
+#define INTMAX_MIN (-INTMAX_MAX - 1)
+#undef UINTMAX_MAX
+#define UINTMAX_MAX __UINTMAX_MAX__
+
+/* 7.18.3 Limits of other integer types */
+
+#undef PTRDIFF_MAX
+#define PTRDIFF_MAX __PTRDIFF_MAX__
+#undef PTRDIFF_MIN
+#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
+
+#undef SIG_ATOMIC_MAX
+#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
+#undef SIG_ATOMIC_MIN
+#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
+
+#undef SIZE_MAX
+#define SIZE_MAX __SIZE_MAX__
+
+#undef WCHAR_MAX
+#define WCHAR_MAX __WCHAR_MAX__
+#undef WCHAR_MIN
+#define WCHAR_MIN __WCHAR_MIN__
+
+#undef WINT_MAX
+#define WINT_MAX __WINT_MAX__
+#undef WINT_MIN
+#define WINT_MIN __WINT_MIN__
+
+#endif /* (!defined __cplusplus || __cplusplus >= 201103L
+	   || defined __STDC_LIMIT_MACROS)  */
+
+#if (!defined __cplusplus || __cplusplus >= 201103L \
+     || defined __STDC_CONSTANT_MACROS)
+
+#undef INT8_C
+#define INT8_C(c) __INT8_C(c)
+#undef INT16_C
+#define INT16_C(c) __INT16_C(c)
+#undef INT32_C
+#define INT32_C(c) __INT32_C(c)
+#undef INT64_C
+#define INT64_C(c) __INT64_C(c)
+#undef UINT8_C
+#define UINT8_C(c) __UINT8_C(c)
+#undef UINT16_C
+#define UINT16_C(c) __UINT16_C(c)
+#undef UINT32_C
+#define UINT32_C(c) __UINT32_C(c)
+#undef UINT64_C
+#define UINT64_C(c) __UINT64_C(c)
+#undef INTMAX_C
+#define INTMAX_C(c) __INTMAX_C(c)
+#undef UINTMAX_C
+#define UINTMAX_C(c) __UINTMAX_C(c)
+
+#endif /* (!defined __cplusplus || __cplusplus >= 201103L
+	   || defined __STDC_CONSTANT_MACROS) */
+
+#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
+/* TS 18661-1 widths of integer types.  */
+
+#ifdef __INT8_TYPE__
+# undef INT8_WIDTH
+# define INT8_WIDTH 8
+#endif
+#ifdef __UINT8_TYPE__
+# undef UINT8_WIDTH
+# define UINT8_WIDTH 8
+#endif
+#ifdef __INT16_TYPE__
+# undef INT16_WIDTH
+# define INT16_WIDTH 16
+#endif
+#ifdef __UINT16_TYPE__
+# undef UINT16_WIDTH
+# define UINT16_WIDTH 16
+#endif
+#ifdef __INT32_TYPE__
+# undef INT32_WIDTH
+# define INT32_WIDTH 32
+#endif
+#ifdef __UINT32_TYPE__
+# undef UINT32_WIDTH
+# define UINT32_WIDTH 32
+#endif
+#ifdef __INT64_TYPE__
+# undef INT64_WIDTH
+# define INT64_WIDTH 64
+#endif
+#ifdef __UINT64_TYPE__
+# undef UINT64_WIDTH
+# define UINT64_WIDTH 64
+#endif
+
+#undef INT_LEAST8_WIDTH
+#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
+#undef UINT_LEAST8_WIDTH
+#define UINT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
+#undef INT_LEAST16_WIDTH
+#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
+#undef UINT_LEAST16_WIDTH
+#define UINT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
+#undef INT_LEAST32_WIDTH
+#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
+#undef UINT_LEAST32_WIDTH
+#define UINT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
+#undef INT_LEAST64_WIDTH
+#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
+#undef UINT_LEAST64_WIDTH
+#define UINT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
+
+#undef INT_FAST8_WIDTH
+#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__
+#undef UINT_FAST8_WIDTH
+#define UINT_FAST8_WIDTH __INT_FAST8_WIDTH__
+#undef INT_FAST16_WIDTH
+#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__
+#undef UINT_FAST16_WIDTH
+#define UINT_FAST16_WIDTH __INT_FAST16_WIDTH__
+#undef INT_FAST32_WIDTH
+#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__
+#undef UINT_FAST32_WIDTH
+#define UINT_FAST32_WIDTH __INT_FAST32_WIDTH__
+#undef INT_FAST64_WIDTH
+#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__
+#undef UINT_FAST64_WIDTH
+#define UINT_FAST64_WIDTH __INT_FAST64_WIDTH__
+
+#ifdef __INTPTR_TYPE__
+# undef INTPTR_WIDTH
+# define INTPTR_WIDTH __INTPTR_WIDTH__
+#endif
+#ifdef __UINTPTR_TYPE__
+# undef UINTPTR_WIDTH
+# define UINTPTR_WIDTH __INTPTR_WIDTH__
+#endif
+
+#undef INTMAX_WIDTH
+#define INTMAX_WIDTH __INTMAX_WIDTH__
+#undef UINTMAX_WIDTH
+#define UINTMAX_WIDTH __INTMAX_WIDTH__
+
+#undef PTRDIFF_WIDTH
+#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__
+
+#undef SIG_ATOMIC_WIDTH
+#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__
+
+#undef SIZE_WIDTH
+#define SIZE_WIDTH __SIZE_WIDTH__
+
+#undef WCHAR_WIDTH
+#define WCHAR_WIDTH __WCHAR_WIDTH__
+
+#undef WINT_WIDTH
+#define WINT_WIDTH __WINT_WIDTH__
+
+#define SIZE_MAX UINT64_MAX
+#endif
+
+typedef long sig_atomic_t;
+
+#endif /* _GCC_STDINT_H */

+ 333 - 0
src/platform/c/dragonos_include/stdio.h

@@ -0,0 +1,333 @@
+#ifndef _RELIBC_STDIO_H
+#define _RELIBC_STDIO_H
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define EOF -1
+
+#define BUFSIZ 1024
+
+#define UNGET 8
+
+#define FILENAME_MAX 4096
+
+#define F_PERM 1
+
+#define F_NORD 4
+
+#define F_NOWR 8
+
+#define F_EOF 16
+
+#define F_ERR 32
+
+#define F_SVB 64
+
+#define F_APP 128
+
+#define F_BADJ 256
+
+#define SEEK_SET 0
+
+#define SEEK_CUR 1
+
+#define SEEK_END 2
+
+#define _IOFBF 0
+
+#define _IOLBF 1
+
+#define _IONBF 2
+
+#define L_tmpnam 7
+
+#define TMP_MAX 2147483647
+
+/**
+ * This struct gets exposed to the C API.
+ */
+typedef struct FILE FILE;
+
+typedef off_t fpos_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+extern FILE *stdin;
+
+extern FILE *stdout;
+
+extern FILE *stderr;
+
+/**
+ * Clears EOF and ERR indicators on a stream
+ */
+void clearerr(FILE *stream);
+
+/**
+ * Close a file
+ * This function does not guarentee that the file buffer will be flushed or that the file
+ * descriptor will be closed, so if it is important that the file be written to, use `fflush()`
+ * prior to using this function.
+ */
+int fclose(FILE *stream);
+
+/**
+ * Open a file from a file descriptor
+ */
+FILE *fdopen(int fildes, const char *mode);
+
+/**
+ * Check for EOF
+ */
+int feof(FILE *stream);
+
+/**
+ * Check for ERR
+ */
+int ferror(FILE *stream);
+
+/**
+ * Flush output to stream, or sync read position
+ * Ensure the file is unlocked before calling this function, as it will attempt to lock the file
+ * itself.
+ */
+int fflush(FILE *stream);
+
+/**
+ * Get a single char from a stream
+ */
+int fgetc(FILE *stream);
+
+/**
+ * Get the position of the stream and store it in pos
+ */
+int fgetpos(FILE *stream, fpos_t *pos);
+
+/**
+ * Get a string from the stream
+ */
+char *fgets(char *original, int max, FILE *stream);
+
+/**
+ * Get the underlying file descriptor
+ */
+int fileno(FILE *stream);
+
+/**
+ * Lock the file
+ * Do not call any functions other than those with the `_unlocked` postfix while the file is
+ * locked
+ */
+void flockfile(FILE *file);
+
+/**
+ * Open the file in mode `mode`
+ */
+FILE *fopen(const char *filename, const char *mode);
+
+/**
+ * Clear the buffers of a stream
+ * Ensure the file is unlocked before calling this function, as it will attempt to lock the file
+ * itself.
+ */
+void __fpurge(FILE *stream);
+
+/**
+ * Insert a character into the stream
+ */
+int fputc(int c, FILE *stream);
+
+/**
+ * Insert a string into a stream
+ */
+int fputs(const char *s, FILE *stream);
+
+/**
+ * Read `nitems` of size `size` into `ptr` from `stream`
+ */
+size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
+
+FILE *freopen(const char *filename, const char *mode, FILE *stream);
+
+/**
+ * Seek to an offset `offset` from `whence`
+ */
+int fseek(FILE *stream, long offset, int whence);
+
+/**
+ * Seek to an offset `offset` from `whence`
+ */
+int fseeko(FILE *stream, off_t off, int whence);
+
+/**
+ * Seek to a position `pos` in the file from the beginning of the file
+ */
+int fsetpos(FILE *stream, const fpos_t *pos);
+
+/**
+ * Get the current position of the cursor in the file
+ */
+long ftell(FILE *stream);
+
+/**
+ * Get the current position of the cursor in the file
+ */
+off_t ftello(FILE *stream);
+
+/**
+ * Try to lock the file. Returns 0 for success, 1 for failure
+ */
+int ftrylockfile(FILE *file);
+
+/**
+ * Unlock the file
+ */
+void funlockfile(FILE *file);
+
+/**
+ * Write `nitems` of size `size` from `ptr` to `stream`
+ */
+size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
+
+/**
+ * Get a single char from a stream
+ */
+int getc(FILE *stream);
+
+/**
+ * Get a single char from `stdin`
+ */
+int getchar(void);
+
+/**
+ * Get a char from a stream without locking the stream
+ */
+int getc_unlocked(FILE *stream);
+
+/**
+ * Get a char from `stdin` without locking `stdin`
+ */
+int getchar_unlocked(void);
+
+/**
+ * Get a string from `stdin`
+ */
+char *gets(char *s);
+
+/**
+ * Get an integer from `stream`
+ */
+int getw(FILE *stream);
+
+int pclose(FILE *stream);
+
+void perror(const char *s);
+
+FILE *popen(const char *command, const char *mode);
+
+/**
+ * Put a character `c` into `stream`
+ */
+int putc(int c, FILE *stream);
+
+/**
+ * Put a character `c` into `stdout`
+ */
+int putchar(int c);
+
+/**
+ * Put a character `c` into `stream` without locking `stream`
+ */
+int putc_unlocked(int c, FILE *stream);
+
+/**
+ * Put a character `c` into `stdout` without locking `stdout`
+ */
+int putchar_unlocked(int c);
+
+/**
+ * Put a string `s` into `stdout`
+ */
+int puts(const char *s);
+
+/**
+ * Put an integer `w` into `stream`
+ */
+int putw(int w, FILE *stream);
+
+/**
+ * Delete file or directory `path`
+ */
+int remove(const char *path);
+
+int rename(const char *oldpath, const char *newpath);
+
+/**
+ * Rewind `stream` back to the beginning of it
+ */
+void rewind(FILE *stream);
+
+/**
+ * Reset `stream` to use buffer `buf`. Buffer must be `BUFSIZ` in length
+ */
+void setbuf(FILE *stream, char *buf);
+
+/**
+ * Reset `stream` to use buffer `buf` of size `size`
+ * If this isn't the meaning of unsafe, idk what is
+ */
+int setvbuf(FILE *stream, char *buf, int mode, size_t size);
+
+char *tempnam(const char *dir, const char *pfx);
+
+FILE *tmpfile(void);
+
+char *tmpnam(char *s);
+
+/**
+ * Push character `c` back onto `stream` so it'll be read next
+ */
+int ungetc(int c, FILE *stream);
+
+int vfprintf(FILE *file, const char *format, va_list ap);
+
+int vprintf(const char *format, va_list ap);
+
+int vasprintf(char **strp, const char *format, va_list ap);
+
+int vsnprintf(char *s, size_t n, const char *format, va_list ap);
+
+int vsprintf(char *s, const char *format, va_list ap);
+
+int vfscanf(FILE *file, const char *format, va_list ap);
+
+int vscanf(const char *format, va_list ap);
+
+int vsscanf(const char *s, const char *format, va_list ap);
+
+ssize_t __getline(char **lineptr, size_t *n, FILE *stream);
+
+ssize_t __getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
+
+size_t __fpending(FILE *stream);
+
+int __freadable(FILE *stream);
+
+int __fwritable(FILE *stream);
+
+int __freading(FILE *stream);
+
+int __fwriting(FILE *stream);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif /* _RELIBC_STDIO_H */
+
+#include <bits/stdio.h>

+ 265 - 0
src/platform/c/dragonos_include/unistd.h

@@ -0,0 +1,265 @@
+#ifndef _RELIBC_UNISTD_H
+#define _RELIBC_UNISTD_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#define F_OK 0
+
+#define R_OK 4
+
+#define W_OK 2
+
+#define X_OK 1
+
+#define SEEK_SET 0
+
+#define SEEK_CUR 1
+
+#define SEEK_END 2
+
+#define F_ULOCK 0
+
+#define F_LOCK 1
+
+#define F_TLOCK 2
+
+#define F_TEST 3
+
+#define STDIN_FILENO 0
+
+#define STDOUT_FILENO 1
+
+#define STDERR_FILENO 2
+
+#define _PC_LINK_MAX 0
+
+#define _PC_MAX_CANON 1
+
+#define _PC_MAX_INPUT 2
+
+#define _PC_NAME_MAX 3
+
+#define _PC_PATH_MAX 4
+
+#define _PC_PIPE_BUF 5
+
+#define _PC_CHOWN_RESTRICTED 6
+
+#define _PC_NO_TRUNC 7
+
+#define _PC_VDISABLE 8
+
+#define _PC_SYNC_IO 9
+
+#define _PC_ASYNC_IO 10
+
+#define _PC_PRIO_IO 11
+
+#define _PC_SOCK_MAXBUF 12
+
+#define _PC_FILESIZEBITS 13
+
+#define _PC_REC_INCR_XFER_SIZE 14
+
+#define _PC_REC_MAX_XFER_SIZE 15
+
+#define _PC_REC_MIN_XFER_SIZE 16
+
+#define _PC_REC_XFER_ALIGN 17
+
+#define _PC_ALLOC_SIZE_MIN 18
+
+#define _PC_SYMLINK_MAX 19
+
+#define _PC_2_SYMLINKS 20
+
+#define _SC_ARG_MAX 0
+
+#define _SC_CHILD_MAX 1
+
+#define _SC_CLK_TCK 2
+
+#define _SC_NGROUPS_MAX 3
+
+#define _SC_OPEN_MAX 4
+
+#define _SC_STREAM_MAX 5
+
+#define _SC_TZNAME_MAX 6
+
+#define _SC_VERSION 29
+
+#define _SC_PAGESIZE 30
+
+#define _SC_PAGE_SIZE 30
+
+#define _SC_RE_DUP_MAX 44
+
+#define _SC_GETPW_R_SIZE_MAX 70
+
+#define _SC_LOGIN_NAME_MAX 71
+
+#define _SC_TTY_NAME_MAX 72
+
+#define _SC_SYMLOOP_MAX 173
+
+#define _SC_HOST_NAME_MAX 180
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+extern char *optarg;
+
+extern int optind;
+
+extern int opterr;
+
+extern int optopt;
+
+void _exit(int status);
+
+int access(const char *path, int mode);
+
+unsigned int alarm(unsigned int seconds);
+
+int chdir(const char *path);
+
+int chroot(const char *path);
+
+int chown(const char *path, uid_t owner, gid_t group);
+
+int close(int fildes);
+
+int dup(int fildes);
+
+int dup2(int fildes, int fildes2);
+
+int execv(const char *path, char *const *argv);
+
+int execve(const char *path, char *const *argv, char *const *envp);
+
+int execvp(const char *file, char *const *argv);
+
+int fchown(int fildes, uid_t owner, gid_t group);
+
+int fchdir(int fildes);
+
+pid_t fork(void);
+
+int fsync(int fildes);
+
+int ftruncate(int fildes, off_t length);
+
+char *getcwd(char *buf, size_t size);
+
+gid_t getegid(void);
+
+uid_t geteuid(void);
+
+gid_t getgid(void);
+
+int gethostname(char *name, size_t len);
+
+char *getlogin(void);
+
+int getlogin_r(char *name, size_t namesize);
+
+int getpagesize(void);
+
+pid_t getpgid(pid_t pid);
+
+pid_t getpgrp(void);
+
+pid_t getpid(void);
+
+pid_t getppid(void);
+
+pid_t getsid(pid_t pid);
+
+uid_t getuid(void);
+
+char *getwd(char *path_name);
+
+int isatty(int fd);
+
+int lchown(const char *path, uid_t owner, gid_t group);
+
+int link(const char *path1, const char *path2);
+
+off_t lseek(int fildes, off_t offset, int whence);
+
+int pipe(int *fildes);
+
+int pipe2(int *fildes, int flags);
+
+ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
+
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
+
+ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
+
+ssize_t read(int fildes, const void *buf, size_t nbyte);
+
+ssize_t readlink(const char *path, char *buf, size_t bufsize);
+
+int rmdir(const char *path);
+
+int setgid(gid_t gid);
+
+int setpgid(pid_t pid, pid_t pgid);
+
+pid_t setpgrp(void);
+
+int setregid(gid_t rgid, gid_t egid);
+
+int setreuid(uid_t ruid, uid_t euid);
+
+int setuid(uid_t uid);
+
+unsigned int sleep(unsigned int seconds);
+
+void swab(const void *src, void *dest, ssize_t nbytes);
+
+int symlink(const char *path1, const char *path2);
+
+pid_t tcgetpgrp(int fd);
+
+int tcsetpgrp(int fd, pid_t pgrp);
+
+int truncate(const char *path, off_t length);
+
+char *ttyname(int fildes);
+
+int ttyname_r(int fildes, char *name, size_t namesize);
+
+useconds_t ualarm(useconds_t usecs, useconds_t interval);
+
+int unlink(const char *path);
+
+int usleep(useconds_t useconds);
+
+ssize_t write(int fildes, const void *buf, size_t nbyte);
+
+int brk(void *addr);
+
+void *sbrk(intptr_t incr);
+
+int getopt(int argc, char *const *argv, const char *optstring);
+
+long fpathconf(int _fildes, int name);
+
+long pathconf(const char *_path, int name);
+
+long sysconf(int name);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif /* _RELIBC_UNISTD_H */
+
+#include <bits/fcntl.h>
+#include <bits/unistd.h>

+ 430 - 0
src/platform/c/dragonos_malloc.c

@@ -0,0 +1,430 @@
+// Copyright (C) DragonOS Community  longjin
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+// Or you can visit https://www.gnu.org/licenses/gpl-2.0.html
+
+#include <dragonos_include/errno.h>
+#include <dragonos_include/stdint.h>
+#include <dragonos_include/stdio.h>
+#include <dragonos_include/unistd.h>
+
+#define PAGE_4K_SHIFT 12
+#define PAGE_2M_SHIFT 21
+#define PAGE_1G_SHIFT 30
+#define PAGE_GDT_SHIFT 39
+
+/***************************/
+
+// 不同大小的页的容量
+#define PAGE_4K_SIZE (1UL << PAGE_4K_SHIFT)
+#define PAGE_2M_SIZE (1UL << PAGE_2M_SHIFT)
+#define PAGE_1G_SIZE (1UL << PAGE_1G_SHIFT)
+
+// 屏蔽低于x的数值
+#define PAGE_4K_MASK (~(PAGE_4K_SIZE - 1))
+#define PAGE_2M_MASK (~(PAGE_2M_SIZE - 1))
+
+#define ALIGN_UP16(x) (((x) + 15) & ~15)
+#define PAGE_ALIGN_UP(x) (((x) + PAGE_4K_SIZE - 1) & PAGE_4K_MASK)
+
+// 将addr按照x的上边界对齐
+// #define PAGE_4K_ALIGN(addr) (((unsigned long)(addr) + PAGE_4K_SIZE - 1) & PAGE_4K_MASK)
+// #define PAGE_2M_ALIGN(addr) (((unsigned long)(addr) + PAGE_2M_SIZE - 1) & PAGE_2M_MASK)
+
+/**
+ * @brief 显式链表的结点
+ *
+ */
+typedef struct malloc_mem_chunk_t
+{
+    uint64_t length; // 整个块所占用的内存区域的大小
+    uint64_t padding;
+    struct malloc_mem_chunk_t *prev; // 上一个结点的指针
+    struct malloc_mem_chunk_t *next; // 下一个结点的指针
+} malloc_mem_chunk_t;
+
+static uint64_t brk_base_addr = 0;    // 堆区域的内存基地址
+static uint64_t brk_max_addr = 0;     // 堆区域的内存最大地址
+static uint64_t brk_managed_addr = 0; // 堆区域已经被管理的地址
+
+// 空闲链表
+//  按start_addr升序排序
+static malloc_mem_chunk_t *malloc_free_list = NULL;
+static malloc_mem_chunk_t *malloc_free_list_end = NULL; // 空闲链表的末尾结点
+
+static uint64_t count_last_free_size = 0; // 统计距离上一次回收内存,已经free了多少内存
+
+/**
+ * @brief 将块插入空闲链表
+ *
+ * @param ck 待插入的块
+ */
+static void malloc_insert_free_list(malloc_mem_chunk_t *ck);
+
+/**
+ * @brief 当堆顶空闲空间大于2个页的空间的时候,释放1个页
+ *
+ */
+static void release_brk();
+
+/**
+ * @brief 在链表中检索符合要求的空闲块(best fit)
+ *
+ * @param size 块的大小
+ * @return malloc_mem_chunk_t*
+ */
+static malloc_mem_chunk_t *malloc_query_free_chunk_bf(uint64_t size)
+{
+    // 在满足best fit的前提下,尽可能的使分配的内存在低地址
+    //  使得总的堆内存可以更快被释放
+
+    if (malloc_free_list == NULL)
+    {
+        return NULL;
+    }
+    malloc_mem_chunk_t *ptr = malloc_free_list;
+    malloc_mem_chunk_t *best = NULL;
+    // printf("query size=%d", size);
+    while (ptr != NULL)
+    {
+        // printf("ptr->length=%#010lx\n", ptr->length);
+        if (ptr->length == size)
+        {
+            best = ptr;
+            break;
+        }
+
+        if (ptr->length > size)
+        {
+            if (best == NULL)
+                best = ptr;
+            else if (best->length > ptr->length)
+                best = ptr;
+        }
+        ptr = ptr->next;
+    }
+
+    return best;
+}
+
+/**
+ * @brief 在链表中检索符合要求的空闲块(first fit)
+ *
+ * @param size
+ * @return malloc_mem_chunk_t*
+ */
+static malloc_mem_chunk_t *malloc_query_free_chunk_ff(uint64_t size)
+{
+    if (malloc_free_list == NULL)
+        return NULL;
+    malloc_mem_chunk_t *ptr = malloc_free_list;
+
+    while (ptr)
+    {
+        if (ptr->length >= size)
+        {
+            return ptr;
+        }
+        ptr = ptr->next;
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief 扩容malloc管理的内存区域
+ *
+ * @param size 扩大的内存大小
+ */
+static int malloc_enlarge(int64_t size)
+{
+    if (brk_base_addr == 0) // 第一次调用,需要初始化
+    {
+        brk_base_addr = sbrk(0);
+        // printf("brk_base_addr=%#018lx\n", brk_base_addr);
+        brk_managed_addr = brk_base_addr;
+        brk_max_addr = sbrk(0);
+    }
+
+    int64_t free_space = brk_max_addr - brk_managed_addr;
+    // printf("size=%ld\tfree_space=%ld\n", size, free_space);
+    if (free_space < size) // 现有堆空间不足
+    {
+        if (sbrk(PAGE_ALIGN_UP(size - free_space)) != (void *)(-1))
+            brk_max_addr = sbrk((0));
+        else
+        {
+            // put_string("malloc_enlarge(): no_mem\n", COLOR_YELLOW, COLOR_BLACK);
+            return -ENOMEM;
+        }
+
+        // printf("brk max addr = %#018lx\n", brk_max_addr);
+    }
+
+    // 扩展管理的堆空间
+    // 在新分配的内存的底部放置header
+    // printf("managed addr = %#018lx\n", brk_managed_addr);
+    malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)brk_managed_addr;
+    new_ck->length = brk_max_addr - brk_managed_addr;
+    // printf("new_ck->start_addr=%#018lx\tbrk_max_addr=%#018lx\tbrk_managed_addr=%#018lx\n", (uint64_t)new_ck,
+    // brk_max_addr, brk_managed_addr);
+    new_ck->prev = NULL;
+    new_ck->next = NULL;
+    brk_managed_addr = brk_max_addr;
+
+    malloc_insert_free_list(new_ck);
+
+    return 0;
+}
+
+/**
+ * @brief 合并空闲块
+ *
+ */
+static void malloc_merge_free_chunk()
+{
+    if (malloc_free_list == NULL)
+        return;
+    malloc_mem_chunk_t *ptr = malloc_free_list->next;
+    while (ptr != NULL)
+    {
+        // 内存块连续
+        if (((uint64_t)(ptr->prev) + ptr->prev->length == (uint64_t)ptr))
+        {
+            // printf("merged %#018lx  and %#018lx\n", (uint64_t)ptr, (uint64_t)(ptr->prev));
+            // 将ptr与前面的空闲块合并
+            ptr->prev->length += ptr->length;
+            ptr->prev->next = ptr->next;
+            if (ptr->next == NULL)
+                malloc_free_list_end = ptr->prev;
+            else
+                ptr->next->prev = ptr->prev;
+            // 由于内存组成结构的原因,不需要free掉header
+            ptr = ptr->prev;
+        }
+        ptr = ptr->next;
+    }
+}
+
+/**
+ * @brief 将块插入空闲链表
+ *
+ * @param ck 待插入的块
+ */
+static void malloc_insert_free_list(malloc_mem_chunk_t *ck)
+{
+    if (malloc_free_list == NULL) // 空闲链表为空
+    {
+        malloc_free_list = ck;
+        malloc_free_list_end = ck;
+        ck->prev = ck->next = NULL;
+        return;
+    }
+    else
+    {
+
+        malloc_mem_chunk_t *ptr = malloc_free_list;
+        while (ptr != NULL)
+        {
+            if ((uint64_t)ptr < (uint64_t)ck)
+            {
+                if (ptr->next == NULL) // 当前是最后一个项
+                {
+                    ptr->next = ck;
+                    ck->next = NULL;
+                    ck->prev = ptr;
+                    malloc_free_list_end = ck;
+                    break;
+                }
+                else if ((uint64_t)(ptr->next) > (uint64_t)ck)
+                {
+                    ck->prev = ptr;
+                    ck->next = ptr->next;
+                    ptr->next = ck;
+                    ck->next->prev = ck;
+                    break;
+                }
+            }
+            else // 在ptr之前插入
+            {
+
+                if (ptr->prev == NULL) // 是第一个项
+                {
+                    malloc_free_list = ck;
+                    ck->prev = NULL;
+                    ck->next = ptr;
+                    ptr->prev = ck;
+                    break;
+                }
+                else
+                {
+                    ck->prev = ptr->prev;
+                    ck->next = ptr;
+                    ck->prev->next = ck;
+                    ptr->prev = ck;
+                    break;
+                }
+            }
+            ptr = ptr->next;
+        }
+    }
+}
+
+/**
+ * @brief 获取一块堆内存
+ *
+ * @param size 内存大小
+ * @return void* 内存空间的指针
+ *
+ * 分配内存的时候,结点的prev next指针所占用的空间被当做空闲空间分配出去
+ */
+void *_dragonos_malloc(ssize_t size)
+{
+    // 计算需要分配的块的大小
+    if (size < sizeof(malloc_mem_chunk_t) - 16)
+        size = sizeof(malloc_mem_chunk_t);
+    else
+    {
+        size += 16;
+    }
+    // 16字节对齐
+    size = ALIGN_UP16(size);
+
+    // 采用best fit
+    malloc_mem_chunk_t *ck = malloc_query_free_chunk_bf(size);
+
+    if (ck == NULL) // 没有空闲块
+    {
+
+        // printf("no free blocks\n");
+        // 尝试合并空闲块
+        malloc_merge_free_chunk();
+        ck = malloc_query_free_chunk_bf(size);
+
+        // 找到了合适的块
+        if (ck)
+            goto found;
+
+        // printf("before enlarge\n");
+        // 找不到合适的块,扩容堆区域
+        if (malloc_enlarge(size) == -ENOMEM)
+            return (void *)-ENOMEM; // 内存不足
+
+        malloc_merge_free_chunk(); // 扩容后运行合并,否则会导致碎片
+
+        // 扩容后再次尝试获取
+
+        ck = malloc_query_free_chunk_bf(size);
+    }
+found:;
+
+    // printf("ck = %#018lx\n", (uint64_t)ck);
+    if (ck == NULL)
+        return (void *)-ENOMEM;
+    // printf("ck->prev=%#018lx ck->next=%#018lx\n", ck->prev, ck->next);
+    // 分配空闲块
+    // 从空闲链表取出
+    if (ck->prev == NULL) // 当前是链表的第一个块
+    {
+        malloc_free_list = ck->next;
+    }
+    else
+        ck->prev->next = ck->next;
+
+    if (ck->next != NULL) // 当前不是最后一个块
+        ck->next->prev = ck->prev;
+    else
+        malloc_free_list_end = ck->prev;
+
+    // 当前块剩余的空间还能容纳多一个结点的空间,则分裂当前块
+    if ((int64_t)(ck->length) - size > sizeof(malloc_mem_chunk_t))
+    {
+        // printf("seperate\n");
+        malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)(((uint64_t)ck) + size);
+        new_ck->length = ck->length - size;
+        new_ck->prev = new_ck->next = NULL;
+        // printf("new_ck=%#018lx, new_ck->length=%#010lx\n", (uint64_t)new_ck, new_ck->length);
+        ck->length = size;
+        malloc_insert_free_list(new_ck);
+    }
+    // printf("malloc done: %#018lx, length=%#018lx\n", ((uint64_t)ck + sizeof(uint64_t)), ck->length);
+    // 此时链表结点的指针的空间被分配出去
+    return (void *)((uint64_t)ck + 2 * sizeof(uint64_t));
+}
+
+/**
+ * @brief 当堆顶空闲空间大于2个页的空间的时候,释放1个页
+ *
+ */
+static void release_brk()
+{
+    // 先检测最顶上的块
+    // 由于块按照开始地址排列,因此找最后一个块
+    if (malloc_free_list_end == NULL)
+    {
+        printf("release(): free list end is null. \n");
+        return;
+    }
+    if ((uint64_t)malloc_free_list_end + malloc_free_list_end->length == brk_max_addr &&
+        (uint64_t)malloc_free_list_end <= brk_max_addr - (PAGE_2M_SIZE << 1))
+    {
+        int64_t delta = ((brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK) - PAGE_2M_SIZE;
+        // printf("(brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK=%#018lx\n ", (brk_max_addr -
+        // (uint64_t)malloc_free_list_end) & PAGE_2M_MASK); printf("PAGE_2M_SIZE=%#018lx\n", PAGE_2M_SIZE);
+        // printf("tdfghgbdfggkmfn=%#018lx\n ", (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK -
+        // PAGE_2M_SIZE); printf("delta=%#018lx\n ", delta);
+        if (delta <= 0) // 不用释放内存
+            return;
+        sbrk(-delta);
+        brk_max_addr = sbrk(0);
+        brk_managed_addr = brk_max_addr;
+
+        malloc_free_list_end->length = brk_max_addr - (uint64_t)malloc_free_list_end;
+    }
+}
+/**
+ * @brief 释放一块堆内存
+ *
+ * @param ptr 堆内存的指针
+ */
+void _dragonos_free(void *ptr)
+{
+    // 找到结点(此时prev和next都处于未初始化的状态)
+    malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - 2 * sizeof(uint64_t));
+    // printf("free(): addr = %#018lx\t len=%#018lx\n", (uint64_t)ck, ck->length);
+    count_last_free_size += ck->length;
+
+    malloc_insert_free_list(ck);
+
+    if (count_last_free_size > PAGE_2M_SIZE)
+    {
+        count_last_free_size = 0;
+        malloc_merge_free_chunk();
+        release_brk();
+    }
+}
+
+/**
+ * @brief 根据分配出去的指针获取堆内存块的长度
+ * 
+ * @param ptr 分配出去的指针
+ * 
+ * @return 堆内存块的长度
+*/
+uint64_t _dragonos_chunk_length(void *ptr)
+{
+    malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - 2 * sizeof(uint64_t));
+    return ck->length;
+}

+ 335 - 0
src/platform/dragonos/mod.rs

@@ -0,0 +1,335 @@
+use dsc::syscall;
+
+use super::{pal::Pal, types::{c_void, c_int}};
+
+pub struct Sys;
+
+impl Sys {
+    pub unsafe fn ioctl() {
+        unimplemented!();
+    }
+}
+
+pub fn e(sys: usize) -> usize {
+    if (sys as isize) < 0 && (sys as isize) >= -256 {
+        unsafe {
+            errno = -(sys as isize) as c_int;
+        }
+        !0
+    } else {
+        sys
+    }
+}
+
+impl Pal for Sys {
+    fn access(path: &CStr, mode: c_int) -> c_int {
+        unimplemented!()
+    }
+
+    fn brk(addr: *mut c_void) -> *mut c_void {
+        unsafe { syscall!(SYS_BRK, addr) as *mut c_void }
+    }
+
+    fn chdir(path: &CStr) -> c_int {
+        e(unsafe { syscall!(SYS_CHDIR, path.as_ptr()) }) as c_int
+    }
+
+    fn chmod(path: &CStr, mode: mode_t) -> c_int {
+        return 0;
+    }
+
+    fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
+        return 0;
+    }
+
+    fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
+        return -ENOSYS;
+    }
+
+    fn close(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(SYS_CLOSE, fildes) }) as c_int
+    }
+
+    fn dup(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(SYS_DUP, fildes) }) as c_int
+    }
+
+    fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
+        e(unsafe { syscall!(SYS_DUP2, fildes, fildes2) }) as c_int
+    }
+
+    unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
+        e(syscall!(SYS_EXECVE, path.as_ptr(), argv, envp)) as c_int
+    }
+
+    fn exit(status: c_int) -> ! {
+        unsafe {
+            syscall!(SYS_EXIT, status);
+        }
+        loop {}
+    }
+
+    fn fchdir(fildes: c_int) -> c_int {
+        unimplemented!()
+    }
+
+    fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
+        return 0;
+    }
+
+    fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
+        return 0;
+    }
+
+    fn flock(fd: c_int, operation: c_int) -> c_int {
+        return 0;
+    }
+
+    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+        e(unsafe { syscall!(SYS_FSTAT, fildes, buf) }) as c_int
+    }
+
+    fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
+        unimplemented!()
+    }
+
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
+        let rc = e(unsafe { syscall!(SYS_FCNTL, fildes, cmd, arg) }) as c_int;
+        return rc;
+    }
+
+    fn fork() -> pid_t {
+        e(unsafe { syscall!(SYS_FORK) }) as pid_t
+    }
+
+    fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t {
+        unimplemented!()
+    }
+
+    fn fsync(fildes: c_int) -> c_int {
+        return 0;
+    }
+
+    fn ftruncate(fildes: c_int, length: off_t) -> c_int {
+        e(unsafe { syscall!(SYS_FTRUNCATE, fildes, length) }) as c_int
+    }
+
+    fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int {
+        unimplemented!()
+    }
+
+    fn futimens(fd: c_int, times: *const timespec) -> c_int {
+        unimplemented!()
+    }
+
+    fn utimens(path: &CStr, times: *const timespec) -> c_int {
+        unimplemented!()
+    }
+
+    fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
+        if size > 2 {
+            unsafe {
+                *buf = b'/' as c_char;
+                *buf.add(1) = b'\0' as c_char;
+            }
+        }
+
+        return buf;
+    }
+
+    fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int {
+        unsafe { syscall!(SYS_GET_DENTS, fd, dirents, bytes) as c_int }
+    }
+
+    fn getegid() -> gid_t {
+        return 0;
+    }
+
+    fn geteuid() -> uid_t {
+        return 0;
+    }
+
+    fn getgid() -> gid_t {
+        return 0;
+    }
+
+    fn getpagesize() -> usize {
+        return 4096;
+    }
+
+    fn getpgid(pid: pid_t) -> pid_t {
+        return 0;
+    }
+
+    fn getpid() -> pid_t {
+        e(unsafe { syscall!(SYS_GETPID) }) as pid_t
+    }
+
+    fn getppid() -> pid_t {
+        return 0;
+    }
+
+    fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t {
+        unimplemented!()
+    }
+
+    unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int {
+        unimplemented!()
+    }
+
+    fn getsid(pid: pid_t) -> pid_t {
+        return 0;
+    }
+
+    fn gettid() -> pid_t {
+        return Self::getpid();
+    }
+
+    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
+        e(unsafe { syscall!(SYS_GETTIMEOFDAY, tp, tzp) }) as c_int
+    }
+
+    fn getuid() -> uid_t {
+        return 0;
+    }
+
+    fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
+        return 0;
+    }
+
+    fn link(path1: &CStr, path2: &CStr) -> c_int {
+        unimplemented!()
+    }
+
+    fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
+        e(unsafe { syscall!(SYS_LSEEK, fildes, offset, whence) }) as off_t
+    }
+
+    fn mkdir(path: &CStr, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(SYS_MKDIR, path.as_ptr(), mode) }) as c_int
+    }
+
+    fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
+        unimplemented!()
+    }
+
+    unsafe fn mlock(addr: *const c_void, len: usize) -> c_int {
+        unimplemented!()
+    }
+
+    fn mlockall(flags: c_int) -> c_int {
+        unimplemented!()
+    }
+
+    unsafe fn mmap(
+        addr: *mut c_void,
+        len: usize,
+        prot: c_int,
+        flags: c_int,
+        fildes: c_int,
+        off: off_t,
+    ) -> *mut c_void {
+        e(syscall!(SYS_MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
+    }
+
+    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
+        e(syscall!(SYS_MPROTECT, addr, len, prot)) as c_int
+    }
+
+    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
+        unimplemented!()
+    }
+
+    unsafe fn munlock(addr: *const c_void, len: usize) -> c_int {
+        unimplemented!()
+    }
+
+    fn munlockall() -> c_int {
+        unimplemented!()
+    }
+
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
+        e(syscall!(SYS_MUNMAP, addr, len)) as c_int
+    }
+
+    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+        e(unsafe { syscall!(SYS_NANOSLEEP, rqtp, rmtp) }) as c_int
+    }
+
+    fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(SYS_OPEN, path.as_ptr(), oflag, mode) }) as c_int
+    }
+
+    fn pipe2(fildes: &mut [c_int], flags: c_int) -> c_int {
+        if flags == 0 {
+            e(unsafe { syscall!(SYS_PIPE, fildes.as_mut_ptr()) }) as c_int
+        } else {
+            unimplemented!()
+        }
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    unsafe fn pte_clone(stack: *mut usize) -> pid_t {
+        unimplemented!()
+    }
+
+    fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
+        e(unsafe { syscall!(SYS_READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
+    }
+
+    fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
+        unimplemented!()
+    }
+
+    fn rename(old: &CStr, new: &CStr) -> c_int {
+        unimplemented!()
+    }
+
+    fn rmdir(path: &CStr) -> c_int {
+        e(unsafe { syscall!(SYS_UNLINK_AT, 0, path.as_ptr(), AT_REMOVEDIR) }) as c_int
+    }
+
+    fn sched_yield() -> c_int {
+        unimplemented!()
+    }
+
+    fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+        unimplemented!()
+    }
+
+    fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+        unimplemented!()
+    }
+
+    fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+        unimplemented!()
+    }
+
+    fn symlink(path1: &CStr, path2: &CStr) -> c_int {
+        unimplemented!()
+    }
+
+    fn umask(mask: mode_t) -> mode_t {
+        unimplemented!()
+    }
+
+    fn uname(utsname: *mut utsname) -> c_int {
+        unimplemented!()
+    }
+
+    fn unlink(path: &CStr) -> c_int {
+        e(unsafe { syscall!(SYS_UNLINK_AT, AT_FDCWD, path.as_ptr(), 0) }) as c_int
+    }
+
+    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
+        e(unsafe { syscall!(SYS_WAIT4, pid, stat_loc, options, 0) }) as pid_t
+    }
+
+    fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
+        e(unsafe { syscall!(SYS_WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
+    }
+
+    fn verify() -> bool {
+        return true;
+    }
+}

+ 7 - 0
src/platform/mod.rs

@@ -0,0 +1,7 @@
+pub use super::header::time;
+
+pub mod allocator;
+pub mod pal;
+pub mod types;
+
+pub mod dragonos;

+ 86 - 0
src/platform/pal/mod.rs

@@ -0,0 +1,86 @@
+use core::ffi::CStr;
+use crate::header::{sys_stat::stat, sys_statvfs::statvfs, dirent::dirent, sys_resource::rlimit, sys_time::{timeval, timezone}, sys_utsname::utsname};
+
+use super::{types::*, time::timespec};
+pub trait Pal {
+    fn access(path: &CStr, mode: c_int) -> c_int;
+    fn brk(addr: *mut c_void) -> *mut c_void;
+    fn chdir(path: &CStr) -> c_int;
+    fn chmod(path: &CStr, mode: mode_t) -> c_int;
+    fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int;
+    fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int;
+    fn close(fildes: c_int) -> c_int;
+    fn dup(fildes: c_int) -> c_int;
+    fn dup2(fildes: c_int, fildes2: c_int) -> c_int;
+    unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
+    fn exit(status: c_int) -> !;
+    fn fchdir(fildes: c_int) -> c_int;
+    fn fchmod(fildes: c_int, mode: mode_t) -> c_int;
+    fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int;
+    fn flock(fd: c_int, operation: c_int) -> c_int;
+    fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+    fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int;
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int;
+    fn fork() -> pid_t;
+    fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t;
+    fn fsync(fildes: c_int) -> c_int;
+    fn ftruncate(fildes: c_int, length: off_t) -> c_int;
+    fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int;
+    fn futimens(fd: c_int, times: *const timespec) -> c_int;
+    fn utimens(path: &CStr, times: *const timespec) -> c_int;
+    fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
+    fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int;
+    fn getegid() -> gid_t;
+    fn geteuid() -> uid_t;
+    fn getgid() -> gid_t;
+    /* Note that this is distinct from the legacy POSIX function    * getpagesize(), which returns a c_int. On some Linux platforms,    * page size may be determined through a syscall ("getpagesize"). */
+    fn getpagesize() -> usize;
+    fn getpgid(pid: pid_t) -> pid_t;
+    fn getpid() -> pid_t;
+    fn getppid() -> pid_t;
+    fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t;
+    unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int;
+    fn getsid(pid: pid_t) -> pid_t;
+    fn gettid() -> pid_t;
+    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int;
+    fn getuid() -> uid_t;
+    fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int;
+    fn link(path1: &CStr, path2: &CStr) -> c_int;
+    fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t;
+    fn mkdir(path: &CStr, mode: mode_t) -> c_int;
+    fn mkfifo(path: &CStr, mode: mode_t) -> c_int;
+    unsafe fn mlock(addr: *const c_void, len: usize) -> c_int;
+    fn mlockall(flags: c_int) -> c_int;
+    unsafe fn mmap(
+        addr: *mut c_void,
+        len: usize,
+        prot: c_int,
+        flags: c_int,
+        fildes: c_int,
+        off: off_t,
+    ) -> *mut c_void;
+    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int;
+    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int;
+    unsafe fn munlock(addr: *const c_void, len: usize) -> c_int;
+    fn munlockall() -> c_int;
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int;
+    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int;
+    fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int;
+    fn pipe2(fildes: &mut [c_int], flags: c_int) -> c_int;
+    unsafe fn pte_clone(stack: *mut usize) -> pid_t;
+    fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t;
+    fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t;
+    fn rename(old: &CStr, new: &CStr) -> c_int;
+    fn rmdir(path: &CStr) -> c_int;
+    fn sched_yield() -> c_int;
+    fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
+    fn setregid(rgid: gid_t, egid: gid_t) -> c_int;
+    fn setreuid(ruid: uid_t, euid: uid_t) -> c_int;
+    fn symlink(path1: &CStr, path2: &CStr) -> c_int;
+    fn umask(mask: mode_t) -> mode_t;
+    fn uname(utsname: *mut utsname) -> c_int;
+    fn unlink(path: &CStr) -> c_int;
+    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t;
+    fn write(fildes: c_int, buf: &[u8]) -> ssize_t;
+    fn verify() -> bool;
+}

+ 78 - 0
src/platform/types.rs

@@ -0,0 +1,78 @@
+use core::i32;
+
+// Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable
+// more optimization opportunities around it recognizing things like
+// malloc/free.
+#[repr(u8)]
+pub enum c_void {
+    // Two dummy variants so the #[repr] attribute can be used.
+    #[doc(hidden)]
+     __variant1,
+     #[doc(hidden)]
+     __variant2,
+ }
+ 
+ pub type int8_t = i8;
+ pub type int16_t = i16;
+ pub type int32_t = i32;
+ pub type int64_t = i64;
+ pub type uint8_t = u8;
+ pub type uint16_t = u16;
+ pub type uint32_t = u32;
+ pub type uint64_t = u64;
+ 
+ pub type c_schar = i8;
+ pub type c_uchar = u8;
+ pub type c_short = i16;
+ pub type c_ushort = u16;
+ pub type c_int = i32;
+ pub type c_uint = u32;
+ pub type c_float = f32;
+ pub type c_double = f64;
+ pub type c_longlong = i64;
+ pub type c_ulonglong = u64;
+ pub type intmax_t = i64;
+ pub type uintmax_t = u64;
+ 
+ pub type size_t = usize;
+ pub type ptrdiff_t = isize;
+ pub type intptr_t = isize;
+ pub type uintptr_t = usize;
+ pub type ssize_t = isize;
+ 
+ pub type c_char = i8;
+ #[cfg(target_pointer_width = "32")]
+ pub type c_long = i32;
+ #[cfg(target_pointer_width = "32")]
+ pub type c_ulong = u32;
+ #[cfg(target_pointer_width = "64")]
+ pub type c_long = i64;
+ #[cfg(target_pointer_width = "64")]
+ pub type c_ulong = u64;
+ 
+ pub type wchar_t = i32;
+ pub type wint_t = u32;
+ 
+ pub type regoff_t = size_t;
+ pub type off_t = c_longlong;
+ pub type mode_t = c_int;
+ pub type time_t = c_longlong;
+ pub type pid_t = c_int;
+ pub type id_t = c_uint;
+ pub type gid_t = c_int;
+ pub type uid_t = c_int;
+ pub type dev_t = c_long;
+ pub type ino_t = c_ulong;
+ pub type nlink_t = c_ulong;
+ pub type blksize_t = c_long;
+ pub type blkcnt_t = c_ulong;
+ 
+ pub type fsblkcnt_t = c_ulong;
+ pub type fsfilcnt_t = c_ulong;
+ 
+ pub type useconds_t = c_uint;
+ pub type suseconds_t = c_int;
+ 
+ pub type clock_t = c_long;
+ pub type clockid_t = c_int;
+ pub type timer_t = *mut c_void;