Max OS 0.3
Loading...
Searching...
No Matches
MaxOS::processes::Scheduler Class Reference

Schedules processes to run on the core via their threads. More...

#include <scheduler.h>

Public Member Functions

 Scheduler (uint64_t core_id)
 Constructs a new Scheduler object and creates the idle process.
 
system::cpu_status_t * schedule (system::cpu_status_t *cpu_state)
 Schedules the next thread to run.
 
system::cpu_status_t * schedule_next (system::cpu_status_t *status)
 Schedules the next thread to run.
 
uint64_t add_process (Process *process)
 Adds a process to the scheduler.
 
uint64_t remove_process (Process *process)
 Removes a process from the scheduler if the process has no threads, if it does then the threads are stopped but the process is not removed (this will be done automatically when all threads are stopped)
 
system::cpu_status_t * force_remove_process (Process *process)
 Removes a process from the scheduler and deletes all threads, begins running the next process.
 
uint64_t add_thread (Thread *thread)
 Adds a thread to the scheduler.
 
Process * current_process ()
 Gets the current process.
 
Process * get_process (uint64_t pid)
 Gets a process by its PID.
 
uint64_t process_amount ()
 Gets how processes are running on this scheduler.
 
Thread * current_thread ()
 Gets the currently executing thread.
 
Thread * get_thread (uint64_t tid)
 Gets a thread by its TID.
 
uint64_t thread_amount ()
 Gets how many threads are running on this scheduler.
 
uint64_t ticks () const
 Gets how long the system has been running for.
 
uint64_t core_id () const
 Gets the core that this scheduler handles processes for.
 
void activate ()
 Activates the scheduler.
 
void deactivate ()
 Deactivates the scheduler.
 

Detailed Description

Schedules processes to run on the core via their threads.

Definition at line 90 of file scheduler.h.

Constructor & Destructor Documentation

◆ Scheduler()

Scheduler::Scheduler ( uint64_t  core_id)

Constructs a new Scheduler object and creates the idle process.

Definition at line 417 of file scheduler.cpp.

418: m_next_thread_index(0),
419 m_active(false),
420 m_ticks(0),
421 m_core_id(core_id)
422{
423
424 // Name the idle
425 string name = "Idle c";
426 name += string(m_core_id);
427
428 // Create this idle process
429 auto* idle = new Process(name, nullptr, nullptr, 0, true);
431
432 // Idle must use the correct kernel memory
433 idle->memory_manager = MemoryManager::s_kernel_memory_manager;
434 idle->threads()[0]->set_tss_pointer(CPU::cores[core_id]->tss.rsp0);
435}
static MemoryManager * s_kernel_memory_manager
The memory manager for any kernel processes and all kernel allocations.
uint64_t add_process(Process *process, Scheduler *scheduler=nullptr)
Adds a process to the least busy core.
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:55
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:94
uint64_t core_id() const
Gets the core that this scheduler handles processes for.
static common::Vector< Core * > cores
The list of CPU cores in the system (populated during initialization, includes the BSP and cores that...
Definition cpu.h:273

References MaxOS::processes::GlobalScheduler::add_process(), core_id(), MaxOS::system::CPU::cores, MaxOS::memory::MemoryManager::s_kernel_memory_manager, and MaxOS::processes::GlobalScheduler::system_scheduler().

Member Function Documentation

◆ activate()

void Scheduler::activate ( )

Activates the scheduler.

Definition at line 641 of file scheduler.cpp.

641 {
642
643 m_active = true;
644}

◆ add_process()

uint64_t Scheduler::add_process ( Process *  process)

Adds a process to the scheduler.

Parameters
processThe process to add
Returns
The process ID (will be assigned during add)

Definition at line 583 of file scheduler.cpp.

583 {
584
585 // Get the next process ID
586 auto pid = GlobalScheduler::next_pid();
587 process->set_pid(pid);
588
589 // Add the process to the list
590 m_processes.push_back(process);
591
592 // Add the threads to the list
593 for(const auto& thread : process->threads())
594 thread->tid = add_thread(thread);
595
596 return pid;
597}
static uint64_t next_pid()
Gets the next usable global PID.
void set_pid(uint64_t pid)
Sets the pid of the process once added to the queue.
Definition process.cpp:399
uint64_t add_thread(Thread *thread)
Adds a thread to the scheduler.

References add_thread(), MaxOS::processes::GlobalScheduler::next_pid(), MaxOS::processes::Process::set_pid(), MaxOS::processes::Process::threads(), and MaxOS::processes::Thread::tid.

Referenced by MaxOS::processes::GlobalScheduler::add_process().

◆ add_thread()

uint64_t Scheduler::add_thread ( Thread *  thread)

Adds a thread to the scheduler.

Parameters
threadThe thread to add
Returns
The thread ID

Definition at line 605 of file scheduler.cpp.

605 {
606
607 // Get the next thread ID
608 auto tid = GlobalScheduler::next_tid();
609 thread->tid = tid;
610
611 // Add the thread to the list
612 m_threads.push_back(thread);
613
614 // Return the thread ID
615 return tid;
616}
static uint64_t next_tid()
Gets the next usable global TID.
uint64_t tid
The thread ID.
Definition process.h:68

References MaxOS::processes::GlobalScheduler::next_tid(), and MaxOS::processes::Thread::tid.

Referenced by add_process(), and MaxOS::processes::GlobalScheduler::add_thread().

◆ core_id()

uint64_t Scheduler::core_id ( ) const

Gets the core that this scheduler handles processes for.

Returns
The id of the core

Definition at line 633 of file scheduler.cpp.

633 {
634
635 return m_core_id;
636}

Referenced by MaxOS::processes::GlobalScheduler::add_process(), MaxOS::processes::GlobalScheduler::add_thread(), and Scheduler().

◆ current_process()

Process * Scheduler::current_process ( )

Gets the current process.

Returns
The current process, or nullptr if not found

Definition at line 715 of file scheduler.cpp.

715 {
716
717 Process* current_process = nullptr;
718
719 // Find the process that has the thread being executed
720 for (auto process: m_processes)
721 if (process->pid() == current_thread()->parent_pid) {
722 current_process = process;
723 break;
724 }
725
726 return current_process;
727}
Thread * current_thread()
Gets the currently executing thread.
Process * current_process()
Gets the current process.

References current_process(), current_thread(), MaxOS::processes::Thread::parent_pid, and MaxOS::processes::Process::pid().

Referenced by MaxOS::processes::GlobalScheduler::current_process(), current_process(), schedule(), and schedule_next().

◆ current_thread()

Thread * Scheduler::current_thread ( )

Gets the currently executing thread.

Returns
The currently executing thread

Definition at line 759 of file scheduler.cpp.

759 {
760
761 return m_threads[m_next_thread_index];
762}

Referenced by current_process(), MaxOS::processes::GlobalScheduler::current_thread(), force_remove_process(), schedule(), and schedule_next().

◆ deactivate()

void Scheduler::deactivate ( )

Deactivates the scheduler.

Definition at line 775 of file scheduler.cpp.

775 {
776
777 m_active = false;
778}

◆ force_remove_process()

cpu_status_t * Scheduler::force_remove_process ( Process *  process)

Removes a process from the scheduler and deletes all threads, begins running the next process.

Parameters
processThe process to remove
Returns
The status of the CPU for the next process to run or nullptr if the process was not found

Definition at line 687 of file scheduler.cpp.

687 {
688
689 // If there is no process, fail
690 if (!process)
691 return nullptr;
692
693 // Remove all the threads
694 for (auto thread: process->threads()) {
695
696 // Remove the thread from the scheduler
697 size_t index = m_threads.find(thread) - m_threads.begin();
698 m_threads.erase(m_threads.begin() + index);
699
700 // Delete the thread
701 process->remove_thread(thread->tid);
702
703 }
704
705 // Process will be dead now so run the next process (don't care about the execution state being outdated as it is being
706 // removed regardless)
707 return schedule_next(&current_thread()->execution_state);
708}
void remove_thread(uint64_t tid)
Remove a thread by its tid (NOTE: this will not remove it from the scheduler)
Definition process.cpp:375
system::cpu_status_t * schedule_next(system::cpu_status_t *status)
Schedules the next thread to run.

References current_thread(), MaxOS::processes::Process::remove_thread(), schedule_next(), MaxOS::processes::Process::threads(), and MaxOS::processes::Thread::tid.

◆ get_process()

Process * Scheduler::get_process ( uint64_t  pid)

Gets a process by its PID.

Parameters
pidThe process ID
Returns
The process or nullptr if not found

Definition at line 735 of file scheduler.cpp.

735 {
736
737 // Try to find the process
738 for (auto process: m_processes)
739 if (process->pid() == pid)
740 return process;
741
742 // Not found
743 return nullptr;
744}

References MaxOS::processes::Process::pid().

◆ get_thread()

Thread * Scheduler::get_thread ( uint64_t  tid)

Gets a thread by its TID.

Parameters
tidThe thread ID
Returns
The thread or nullptr if not found

Definition at line 786 of file scheduler.cpp.

786 {
787
788 // Try to find the thread
789 for (auto thread: m_threads)
790 if (thread->tid == tid)
791 return thread;
792
793 return nullptr;
794}

References MaxOS::processes::Thread::tid.

◆ process_amount()

uint64_t Scheduler::process_amount ( )

Gets how processes are running on this scheduler.

Returns
The amount

Definition at line 750 of file scheduler.cpp.

750 {
751 return m_processes.size();
752}

◆ remove_process()

uint64_t Scheduler::remove_process ( Process *  process)

Removes a process from the scheduler if the process has no threads, if it does then the threads are stopped but the process is not removed (this will be done automatically when all threads are stopped)

Parameters
processThe process to remove
Returns
-1 if the process has threads, 0 otherwise

Definition at line 652 of file scheduler.cpp.

652 {
653
654 // Check if the process has no threads
655 if (!process->threads().empty()) {
656
657 // Set the threads to stopped or remove them if forced
658 for (auto thread: process->threads())
659 thread->thread_state = ThreadState::STOPPED;
660
661 // Need to wait until the threads are stopped before removing the process (this will be called again when all threads are stopped)
662 return -1;
663
664 }
665
666 // Remove the process
667 for (uint32_t i = 0; i < m_processes.size(); i++) {
668 if (m_processes[i] == process) {
669 m_processes.erase(m_processes.begin() + i);
670
671 // Delete the process mem
672 delete process;
673 return 0;
674 }
675 }
676
677 // Process not found
678 return -1;
679}
common::Vector< Thread * > threads()
Gets the threads of the process.
Definition process.cpp:419
ThreadState
The different operational states a thread can be in.
Definition process.h:32

References MaxOS::processes::Thread::thread_state, and MaxOS::processes::Process::threads().

Referenced by schedule_next().

◆ schedule()

cpu_status_t * Scheduler::schedule ( system::cpu_status_t *  cpu_state)

Schedules the next thread to run.

Parameters
cpu_stateThe current CPU state
Returns
The next CPU state

Definition at line 446 of file scheduler.cpp.

446 {
447
448 // Scheduler cant schedule anything
449 if (m_threads.empty() || !m_active)
450 return cpu_state;
451
452 // Thread that we are dealing with
453 Thread* current_thread = m_threads[m_next_thread_index];
454
455 // Ticked
456 m_ticks++;
458
459 // The idle thread has no time slice to protect
460 Process* running_process = current_process();
461 if (running_process && running_process->is_kernel)
462 return schedule_next(cpu_state);
463
464 // Thread hasn't used its time slot yet
465 if(current_thread->ticks % TICKS_PER_EVENT)
466 return cpu_state;
467
468 // Schedule the next thread
469 return schedule_next(cpu_state);
470}
bool is_kernel
Whether this process is a kernel process.
Definition process.h:116
The execution context of a sub-process thread.
Definition process.h:50
volatile size_t ticks
The number of ticks the thread has run for.
Definition process.h:74

References current_process(), current_thread(), MaxOS::processes::Process::is_kernel, schedule_next(), MaxOS::processes::Thread::ticks, and MaxOS::processes::TICKS_PER_EVENT.

Referenced by MaxOS::processes::GlobalScheduler::handle_interrupt().

◆ schedule_next()

cpu_status_t * Scheduler::schedule_next ( system::cpu_status_t *  status)

Schedules the next thread to run.

Parameters
statusThe current CPU status of the thread
Returns
The next CPU status
Todo:
Remove by reference where possible

Definition at line 480 of file scheduler.cpp.

480 {
481
482 // Get the current state
483 Thread* current_thread = m_threads[m_next_thread_index];
484 Process* owner_process = current_process();
485 auto old_tid = m_next_thread_index;
486
487 // Save the executing thread state
488 current_thread->execution_state = *cpu_state;
490 if (current_thread->thread_state == ThreadState::RUNNING)
491 current_thread->thread_state = ThreadState::READY;
492
493 // Find a free thread to run
494 while ((++m_next_thread_index) != old_tid){
495 m_next_thread_index %= m_threads.size();
496
497 // Get the current thread
498 current_thread = m_threads[m_next_thread_index];
499 owner_process = current_process();
500
501 // Handle state changes
502 switch (current_thread->thread_state) {
503
504 case ThreadState::SLEEPING:
505
506 // If the wake-up time hasn't occurred yet, run the next thread
507 if (current_thread->wakeup_time > TICKS_PER_EVENT){
509 continue;
510 }
511
512 break;
513
514 case ThreadState::STOPPED:
515
516 // Find the process that has the thread and remove it
517 for (auto thread: owner_process->threads()) {
518 if (thread == current_thread) {
519 owner_process->remove_thread(thread->tid);
520 break;
521 }
522 }
523
524 // Remove the thread
525 m_threads.erase(m_threads.begin() + m_next_thread_index);
526 if(owner_process->threads().empty())
527 remove_process(owner_process);
528 continue;
529
530 case ThreadState::WAITING:
531 continue;
532
533 default:
534 break;
535 }
536 break;
537 }
538
539 int pid0 = m_processes.size() > 0 ? (int) m_processes[0]->pid() : -1;
540 int pid1 = m_processes.size() > 1 ? (int) m_processes[1]->pid() : -1;
541 int pid2 = m_processes.size() > 2 ? (int) m_processes[2]->pid() : -1;
542 ASSERT(owner_process != nullptr, "No owner process: tid %d parent_pid %d core %d index %d threads %d processes %d pids %d %d %d\n",
543 (int) current_thread->tid, (int) current_thread->parent_pid, (int) m_core_id,
544 (int) m_next_thread_index, (int) m_threads.size(), (int) m_processes.size(), pid0, pid1, pid2);
545
546
547 // Load the thread's state
548 return load_process(owner_process, current_thread);
549}
uint64_t remove_process(Process *process)
Removes a process from the scheduler if the process has no threads, if it does then the threads are s...
uint64_t parent_pid
The parent process ID.
Definition process.h:69
void save_sse_state()
Saves the SSE, x87 FPU, and MMX states from memory to the thread.
Definition process.cpp:125
volatile system::cpu_status_t execution_state
The CPU state of the thread.
Definition process.h:71
volatile thread_state_t thread_state
The current state of the thread.
Definition process.h:72
volatile size_t wakeup_time
The time at which the thread should wake up (if sleeping)
Definition process.h:75
constexpr size_t TICKS_PER_EVENT
Number of times the clock has to interrupt before switching to the next process/thread.
Definition scheduler.h:84

References current_process(), current_thread(), MaxOS::processes::Thread::execution_state, MaxOS::processes::Thread::parent_pid, remove_process(), MaxOS::processes::Process::remove_thread(), MaxOS::processes::Thread::save_sse_state(), MaxOS::processes::Thread::thread_state, MaxOS::processes::Process::threads(), MaxOS::processes::TICKS_PER_EVENT, MaxOS::processes::Thread::tid, and MaxOS::processes::Thread::wakeup_time.

Referenced by force_remove_process(), schedule(), and MaxOS::processes::Thread::yield().

◆ thread_amount()

uint64_t Scheduler::thread_amount ( )

Gets how many threads are running on this scheduler.

Returns
The amount

Definition at line 768 of file scheduler.cpp.

768 {
769 return m_threads.size();
770}

◆ ticks()

uint64_t Scheduler::ticks ( ) const

Gets how long the system has been running for.

Returns
The number of ticks

Definition at line 623 of file scheduler.cpp.

623 {
624
625 return m_ticks;
626}

Referenced by MaxOS::system::CPU::PANIC().


The documentation for this class was generated from the following files: