11#![ no_std]
22#![ no_main]
33
4+ extern crate alloc;
5+
46use core:: panic:: PanicInfo ;
57use graphics:: { draw_memory_map, fill_screen_blue} ;
68use hal:: serial_println;
79use limine:: request:: { FramebufferRequest , MemoryMapRequest } ;
810use limine:: BaseRevision ;
911use memory:: heap:: { init_heap, StaticBootFrameAllocator } ;
10- use task:: { SchedClass , TaskCB , TaskManager } ;
12+ use task:: { SchedClass , Scheduler , TaskCB , TaskManager } ;
1113use util:: panic:: halt_loop;
1214use x86_64:: structures:: paging:: PhysFrame ;
1315use x86_64:: { PhysAddr , VirtAddr } ;
@@ -17,16 +19,31 @@ static FRAMEBUFFER_REQ: FramebufferRequest = FramebufferRequest::new();
1719static MMAP_REQ : MemoryMapRequest = MemoryMapRequest :: new ( ) ;
1820static SCHEDULER : TaskManager = TaskManager :: new ( ) ;
1921
20- fn idle_task ( ) -> ! {
21- serial_println ! ( "Idle task running" ) ;
22+ /*unsafe extern "C" {
23+ fn context_switch(old: *mut CPUContext, new: *const CPUContext) -> !;
24+ }*/
25+
26+ unsafe extern "C" fn idle_task ( ) -> ! {
27+ serial_println ! ( "Idle task started!" ) ;
2228 loop {
23- hal:: cpu:: halt ( ) ;
29+ serial_println ! ( "Idle task running" ) ;
30+ for _ in 0 ..10000000 {
31+ core:: hint:: spin_loop ( ) ;
32+ }
33+ serial_println ! ( "Idle task calling yield" ) ;
34+ task:: task_yield ( ) ;
35+ serial_println ! ( "Idle task returned from yield" ) ;
2436 }
2537}
26- fn user_task_one ( ) -> ! {
27- serial_println ! ( "User task one running" ) ;
38+
39+ unsafe extern "C" fn task1 ( ) -> ! {
40+ serial_println ! ( "Task 1 started!" ) ;
2841 loop {
29- hal:: cpu:: halt ( ) ;
42+ serial_println ! ( "Task 1 running" ) ;
43+ for _ in 0 ..10000000 {
44+ core:: hint:: spin_loop ( ) ;
45+ }
46+ task:: task_yield ( ) ;
3047 }
3148}
3249
@@ -58,22 +75,6 @@ pub extern "C" fn _start() -> ! {
5875 apic:: timer:: init_hardware ( ) ; // Initialize timer hardware
5976 }
6077
61- let idle = TaskCB :: new (
62- "idle" ,
63- VirtAddr :: new ( idle_task as * const ( ) as u64 ) ,
64- VirtAddr :: new ( 0xFFFF_FF80_0000_1000 ) ,
65- SchedClass :: Fair ( 120 ) ,
66- ) ;
67- let task1 = TaskCB :: new (
68- "idle" ,
69- VirtAddr :: new ( user_task_one as * const ( ) as u64 ) ,
70- VirtAddr :: new ( 0xFFFF_FF80_0000_2000 ) ,
71- SchedClass :: Fair ( 110 ) ,
72- ) ;
73-
74- //SCHEDULER.add_task(idle);
75- //SCHEDULER.add_task(task1);
76-
7778 //Access framebuffer info
7879 let fb_response = FRAMEBUFFER_REQ
7980 . get_response ( )
@@ -115,24 +116,43 @@ pub extern "C" fn _start() -> ! {
115116 fill_screen_blue ( & fb) ;
116117 draw_memory_map ( & fb, mmap_response. entries ( ) ) ;
117118 }
118-
119- loop {
120- if let Some ( task) = SCHEDULER . schedule ( ) {
121- serial_println ! ( "Running task: {}" , task. name) ;
122- //simply call entr fn
123- let task_fn: extern "C" fn ( ) -> ! = unsafe { core:: mem:: transmute ( task. context . rip ) } ;
124- task_fn ( ) ;
125- } else {
126- // Print timer ticks every so often to show timer is working
127- static mut LAST_TICK : u64 = 0 ;
128- let current_tick = apic:: timer:: ticks ( ) ;
129- unsafe {
130- if current_tick > LAST_TICK + 1000 {
131- serial_println ! ( "Timer ticks: {}" , current_tick) ;
132- LAST_TICK = current_tick;
133- }
134- }
135- hal:: cpu:: halt ( ) ;
136- }
137- }
119+
120+ // Initialize global scheduler
121+ Scheduler :: init_global ( ) ;
122+ {
123+ let mut scheduler = Scheduler :: global ( ) . lock ( ) ;
124+
125+ // Allocate proper stacks for tasks (8KB each)
126+ const STACK_SIZE : usize = 8192 ;
127+
128+ // Create kernel boot task - this represents the current execution context
129+ let kernel_stack_mem = alloc:: vec![ 0u8 ; STACK_SIZE ] ;
130+ let kernel_stack = VirtAddr :: from_ptr ( kernel_stack_mem. as_ptr ( ) ) + STACK_SIZE as u64 ;
131+ core:: mem:: forget ( kernel_stack_mem) ;
132+
133+ let idle_stack_mem = alloc:: vec![ 0u8 ; STACK_SIZE ] ;
134+ let task1_stack_mem = alloc:: vec![ 0u8 ; STACK_SIZE ] ;
135+
136+ // Get stack top addresses (stacks grow downward)
137+ let idle_stack = VirtAddr :: from_ptr ( idle_stack_mem. as_ptr ( ) ) + STACK_SIZE as u64 ;
138+ let task1_stack = VirtAddr :: from_ptr ( task1_stack_mem. as_ptr ( ) ) + STACK_SIZE as u64 ;
139+
140+ // Prevent stack memory from being deallocated
141+ core:: mem:: forget ( idle_stack_mem) ;
142+ core:: mem:: forget ( task1_stack_mem) ;
143+
144+ // Add kernel boot task as first task (will never actually run, just holds boot context)
145+ let kernel_task = TaskCB :: new ( "kernel_boot" , idle_task, kernel_stack, SchedClass :: Fair ( 0 ) ) ;
146+ scheduler. add_task ( kernel_task) ;
147+
148+ let idle = TaskCB :: new ( "idle" , idle_task, idle_stack, SchedClass :: Fair ( 120 ) ) ;
149+ let task1 = TaskCB :: new ( "task1" , task1, task1_stack, SchedClass :: Fair ( 110 ) ) ;
150+ scheduler. add_task ( idle) ;
151+ scheduler. add_task ( task1) ;
152+
153+ serial_println ! ( "Starting scheduler with {} tasks" , scheduler. task_count( ) ) ;
154+ } // Lock is dropped here
155+
156+ // Jump into scheduler - this never returns
157+ unsafe { Scheduler :: start ( ) ; }
138158}
0 commit comments