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