1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright (c) 2020 Alex Chi
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

//! All syscalls of core-os
//! 
//! Syscalls of core-os are defined and implemented with Rust
//! primitives (e.g. `str`, `[u8]`). This module will transmute
//! these Rust primitives into pointers and other machine-specific
//! representations before calling functions in `syscall_internal` and
//! trapping into kernel.
//!
//! Usage of syscalls is listed in their corresponding sub-page.

use crate::syscall_internal::*;
use core::ptr::null;

/// Exit current process with exit code `code`.
/// 
/// # Examples
///
/// ```
/// use user::syscall::exit;
/// exit(0);
/// ```
pub fn exit(code: i32) -> ! {
    unsafe { __exit(code) }
}

/// Fork current process. 
/// 
/// Child process will get return value of 0.
/// Parent process (the one calling `fork`) will
/// get pid of child process.
/// 
/// # Examples
///
/// ```
/// use user::syscall::fork;
/// if fork() == 0 {
///     println!("subprocess!");
/// } else {
///     println!("parent process");
/// }
/// ```
pub fn fork() -> i32 {
    unsafe { __fork() }
}

pub const EXEC_MAX_ARGS: usize = 10;

/// Replace current process image with the new one
/// in the filesystem.
///
/// This function will not return.
///
/// # Examples
/// ```
/// use user::syscall::exec;
/// exec("/init", &[]);
/// ```
pub fn exec(path: &str, args: &[&str]) -> ! {
    let arg_cnt = args.len();
    let mut args_sz = [0; EXEC_MAX_ARGS];
    let mut args_ptr = [null(); EXEC_MAX_ARGS];
    for i in 0..args.len() {
        args_sz[i] = args[i].len() as i32;
        args_ptr[i] = args[i].as_bytes().as_ptr() as *const u8;
    }
    unsafe {
        __exec(
            path.as_bytes().as_ptr() as *const u8,
            path.len() as i32,
            arg_cnt as i32,
            args_ptr.as_ptr(),
            args_sz.as_ptr()
        )
    }
}

/// Write `content` to file descriptor `fd`.
///
/// Returns number of characters written. A negative return value means error while writing.
///
/// # Examples
/// ```
/// use user::syscall::write;
/// use user::constant::STDOUT;
/// write(STDOUT, "Hello, World!");
/// ```
pub fn write(fd: i32, content: &[u8]) -> i32 {
    unsafe {
        __write(fd,
                content.as_ptr(),
                content.len() as i32)
    }
}

/// Read `content` from file descriptor `fd`.
///
/// You may read a maximum of `content.len()` characters from `fd`.
/// Returns number of characters read.
pub fn read(fd: i32, content: &mut [u8]) -> i32 {
    unsafe {
        __read(fd,
                content.as_mut_ptr(),
                content.len() as i32)
    }
}

/// Open file of `path` with `mode`.
///
/// This function returns file descriptor. Negative value means error.
///
/// # Examples
/// ```
/// use user::syscall::open;
/// let fd = open("/console", 0);
/// ```
pub fn open(path: &str, mode: i32) -> i32 {
    unsafe {
        __open(path.as_ptr(), path.len() as i32, mode)
    }
}

/// Close a file with file descriptor `fd`.
///
/// # Examples
/// ```
/// use user::syscall::close;
/// close(0);
/// ```
pub fn close(fd: i32) -> i32 {
    unsafe { __close(fd) }
}

/// Duplicate file descriptor `fd`.
///
/// Returns new file descriptor.
///
/// # Examples
/// ```
/// use user::syscall::dup;
/// use user::constant::STDIN;
/// let fd = dup(STDIN);
/// ```
pub fn dup(fd: i32) -> i32 {
    unsafe { __dup(fd) }
}

pub fn wait(pid: i32) -> i32 {
    unsafe { __wait(pid) }
}