fn next_thread_state(&self, old_stack: VirtAddr) -> NextThreadState {
        // Cleanup old thread.
        // Relaxed ordering is fine because this is only for this core.
        let garbage = self.garbage.load(Ordering::Relaxed);
        if unlikely(garbage != ThreadId::zero()) {
            tcb_dealloc(garbage);
            self.garbage.store(ThreadId::zero(), Ordering::Relaxed);
        }

        let mut queues = self.queues.lock();

        let old_thread_id = self.current_thread_id.load(Ordering::Acquire);

        let (old_mapping, old_thread_status) = with_thread(old_thread_id, |old_thread| {
            let old_thread_status = old_thread.status();

            if likely(!matches!(old_thread_status, ThreadStatus::Exit(_))) {
                old_thread.save_simd();
                old_thread.stack.set_current_location(old_stack);
            }

            (old_thread.domain().cpu_page_mapping(), old_thread_status)
        });

        match old_thread_status {
            ThreadStatus::Runnable => {
                if likely(old_thread_id != self.idle_thread_id) {
                    queues.run_queue.push_back(old_thread_id);
                }
            }

            ThreadStatus::Blocked => {}

            ThreadStatus::Exit(_) => {
                debug_assert_eq!(self.garbage.load(Ordering::Relaxed), ThreadId::zero());
                // Safety: We call this from an uninterrupted place and we are not referencing thread memory here.
                unsafe {
                    with_thread(old_thread_id, |old_thread| {
                        old_thread.unmap_memory();
                    });
                }
                self.garbage.store(old_thread_id, Ordering::Relaxed);
            }
        };

        /*print!("runqueue: ");
        for x in &queues.run_queue {
            print!("{:?} ", x.id);
        }
        println!();
        print!("blocked: ");
        for x in &queues.blocked_threads {
            print!("{:?} ", x.id);
        }
        println!();*/

        let next_thread_id = self.next_thread(&mut queues);
        debug_assert_eq!(
            { with_thread(next_thread_id, |next_thread| next_thread.status(),) },
            ThreadStatus::Runnable
        );

        self.current_thread_id
            .store(next_thread_id, Ordering::Release);

        self.with_current_thread(|current_thread| {
            current_thread.restore_simd();
            let domain = current_thread.domain();
            domain.assign_asid_if_necessary();
            NextThreadState(current_thread.stack.get_current_location(), {
                let new_mapping = domain.cpu_page_mapping();
                if old_mapping == new_mapping {
                    CpuPageMapping::sentinel()
                } else {
                    new_mapping
                }
            })
        })
    }
/// Sets the scheduler up for switching to the next thread and gets the next thread stack address.
Sets the scheduler up for switching to the next thread and gets the next thread stack address.
Sets the scheduler up for switching to the next thread and gets the next thread stack address .
fn next_thread_state(&self, old_stack: VirtAddr) -> NextThreadState {
        // Cleanup old thread.
        // Relaxed ordering is fine because this is only for this core.
        let garbage = self.garbage.load(Ordering::Relaxed);
        if unlikely(garbage != ThreadId::zero()) {
            tcb_dealloc(garbage);
            self.garbage.store(ThreadId::zero(), Ordering::Relaxed);
        }
        let mut queues = self.queues.lock();
        let old_thread_id = self.current_thread_id.load(Ordering::Acquire);
        let (old_mapping, old_thread_status) = with_thread(old_thread_id, |old_thread| {
            let old_thread_status = old_thread.status();
            if likely(!matches!(old_thread_status, ThreadStatus::Exit(_))) {
                old_thread.save_simd();
                old_thread.stack.set_current_location(old_stack);
            }
            (old_thread.domain().cpu_page_mapping(), old_thread_status)
        });
        match old_thread_status {
            ThreadStatus::Runnable => {
                if likely(old_thread_id != self.idle_thread_id) {
                    queues.run_queue.push_back(old_thread_id);
                }
            }
            ThreadStatus::Blocked => {}
            ThreadStatus::Exit(_) => {
                debug_assert_eq!(self.garbage.load(Ordering::Relaxed), ThreadId::zero());
                // Safety: We call this from an uninterrupted place and we are not referencing thread memory here.
                unsafe {
                    with_thread(old_thread_id, |old_thread| {
                        old_thread.unmap_memory();
                    });
                }
                self.garbage.store(old_thread_id, Ordering::Relaxed);
            }
        };
        /*print!("runqueue: ");
        for x in &queues.run_queue {
            print!("{:?} ", x.id);
        }
        println!();
        print!("blocked: ");
        for x in &queues.blocked_threads {
            print!("{:?} ", x.id);
        }
        println!();*/
        let next_thread_id = self.next_thread(&mut queues);
        debug_assert_eq!(
            { with_thread(next_thread_id, |next_thread| next_thread.status(),) },
            ThreadStatus::Runnable
        );
        self.current_thread_id
            .store(next_thread_id, Ordering::Release);
        self.with_current_thread(|current_thread| {
            current_thread.restore_simd();
            let domain = current_thread.domain();
            domain.assign_asid_if_necessary();
            NextThreadState(current_thread.stack.get_current_location(), {
                let new_mapping = domain.cpu_page_mapping();
                if old_mapping == new_mapping {
                    CpuPageMapping::sentinel()
                } else {
                    new_mapping
                }
            })
        })
    }
fn next_thread_state ( & self , old_stack : VirtAddr ) -> NextThreadState { // Cleanup old thread. // Relaxed ordering is fine because this is only for this core. let garbage = self . garbage . load ( Ordering :: Relaxed ) ; if unlikely ( garbage != ThreadId :: zero ( ) ) { tcb_dealloc ( garbage ) ; self . garbage . store ( ThreadId :: zero ( ) , Ordering :: Relaxed ) ; } let mut queues = self . queues . lock ( ) ; let old_thread_id = self . current_thread_id . load ( Ordering :: Acquire ) ; let ( old_mapping , old_thread_status ) = with_thread ( old_thread_id , | old_thread | { let old_thread_status = old_thread . status ( ) ; if likely ( ! matches ! ( old_thread_status ThreadStatus Exit ( ) ) ) { old_thread . save_simd ( ) ; old_thread . stack . set_current_location ( old_stack ) ; } ( old_thread . domain ( ) . cpu_page_mapping ( ) , old_thread_status ) } ) ; match old_thread_status { ThreadStatus :: Runnable => { if likely ( old_thread_id != self . idle_thread_id ) { queues . run_queue . push_back ( old_thread_id ) ; } } ThreadStatus :: Blocked => { } ThreadStatus :: Exit ( _ ) => { debug_assert_eq ! ( self garbage load ( Ordering Relaxed ) ThreadId zero ( ) ) ; // Safety: We call this from an uninterrupted place and we are not referencing thread memory here. unsafe { with_thread ( old_thread_id , | old_thread | { old_thread . unmap_memory ( ) ; } ) ; } self . garbage . store ( old_thread_id , Ordering :: Relaxed ) ; } } ; /*print!("runqueue: ");
        for x in &queues.run_queue {
            print!("{:?} ", x.id);
        }
        println!();
        print!("blocked: ");
        for x in &queues.blocked_threads {
            print!("{:?} ", x.id);
        }
        println!();*/ let next_thread_id = self . next_thread ( & mut queues ) ; debug_assert_eq ! ( { with_thread ( next_thread_id next_thread next_thread status ( ) ) } ThreadStatus Runnable ) ; self . current_thread_id . store ( next_thread_id , Ordering :: Release ) ; self . with_current_thread ( | current_thread | { current_thread . restore_simd ( ) ; let domain = current_thread . domain ( ) ; domain . assign_asid_if_necessary ( ) ; NextThreadState ( current_thread . stack . get_current_location ( ) , { let new_mapping = domain . cpu_page_mapping ( ) ; if old_mapping == new_mapping { CpuPageMapping :: sentinel ( ) } else { new_mapping } } ) } ) }
Sets the scheduler up for switching to the next thread and gets the next thread stack address.
Sets the scheduler up for switching to the next thread and gets the next thread stack address .
&self
old_stack
VirtAddr
&self
old_stack
VirtAddr