1#![no_std]
2mod heap;
9
10extern crate alloc;
11
12use tg_console::log;
13
14pub use tg_console::{print, println};
15pub use tg_syscall::*;
16
17#[unsafe(no_mangle)]
18#[unsafe(link_section = ".text.entry")]
19pub extern "C" fn _start() -> ! {
20 tg_console::init_console(&Console);
22 tg_console::set_log_level(option_env!("LOG"));
23 heap::init();
24
25 unsafe extern "C" {
26 fn main() -> i32;
27 }
28
29 exit(unsafe { main() });
31 unreachable!()
32}
33
34#[panic_handler]
35fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
36 let err = panic_info.message();
37 if let Some(location) = panic_info.location() {
38 log::error!("Panicked at {}:{}, {err}", location.file(), location.line());
39 } else {
40 log::error!("Panicked: {err}");
41 }
42 exit(1);
43 unreachable!()
44}
45
46pub fn getchar() -> u8 {
47 let mut c = [0u8; 1];
48 read(STDIN, &mut c);
49 c[0]
50}
51
52struct Console;
53
54impl tg_console::Console for Console {
55 #[inline]
56 fn put_char(&self, c: u8) {
57 tg_syscall::write(STDOUT, &[c]);
58 }
59
60 #[inline]
61 fn put_str(&self, s: &str) {
62 tg_syscall::write(STDOUT, s.as_bytes());
63 }
64}
65
66pub fn sleep(period_ms: usize) {
67 let mut time: TimeSpec = TimeSpec::ZERO;
69 clock_gettime(ClockId::CLOCK_MONOTONIC, &mut time as *mut _ as _);
70 let time = time + TimeSpec::from_millsecond(period_ms);
71 loop {
72 let mut now: TimeSpec = TimeSpec::ZERO;
73 clock_gettime(ClockId::CLOCK_MONOTONIC, &mut now as *mut _ as _);
74 if now > time {
75 break;
76 }
77 sched_yield();
78 }
79}
80
81pub fn get_time() -> isize {
82 let mut time: TimeSpec = TimeSpec::ZERO;
83 clock_gettime(ClockId::CLOCK_MONOTONIC, &mut time as *mut _ as _);
84 (time.tv_sec * 1000 + time.tv_nsec / 1_000_000) as isize
85}
86
87pub fn trace_read(ptr: *const u8) -> Option<u8> {
88 let ret = trace(0, ptr as usize, 0);
89 if ret >= 0 && ret <= 255 {
90 Some(ret as u8)
91 } else {
92 None
93 }
94}
95
96pub fn trace_write(ptr: *const u8, value: u8) -> isize {
97 trace(1, ptr as usize, value as usize)
98}
99
100pub fn count_syscall(syscall_id: usize) -> isize {
101 trace(2, syscall_id, 0)
102}
103
104pub fn pipe_read(pipe_fd: usize, buffer: &mut [u8]) -> isize {
107 let mut total_read = 0usize;
108 let len = buffer.len();
109 loop {
110 if total_read >= len {
111 return total_read as isize;
112 }
113 let ret = read(pipe_fd, &mut buffer[total_read..]);
114 if ret == -2 {
115 sched_yield();
117 continue;
118 } else if ret == 0 {
119 return total_read as isize;
121 } else if ret < 0 {
122 return ret;
124 } else {
125 total_read += ret as usize;
126 }
127 }
128}
129
130pub fn pipe_write(pipe_fd: usize, buffer: &[u8]) -> isize {
133 let mut total_write = 0usize;
134 let len = buffer.len();
135 loop {
136 if total_write >= len {
137 return total_write as isize;
138 }
139 let ret = write(pipe_fd, &buffer[total_write..]);
140 if ret == -2 {
141 sched_yield();
143 continue;
144 } else if ret < 0 {
145 return ret;
147 } else {
148 total_write += ret as usize;
149 }
150 }
151}