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

The global scheduler that manages all processes and threads across all cores. More...

#include <scheduler.h>

Inheritance diagram for MaxOS::processes::GlobalScheduler:
MaxOS::hardwarecommunication::InterruptHandler

Public Member Functions

 GlobalScheduler (system::Multiboot &multiboot)
 Constructs a new Global Scheduler object. Registers as the interrupt handler for interrupt 0x20 and setups the shared resource registries. Loads any ELF files from the multiboot structure.
 
 ~GlobalScheduler ()
 Destroys the global scheduler and frees the per core schedulers.
 
system::cpu_status_thandle_interrupt (system::cpu_status_t *status) final
 Handles the interrupt 0x20.
 
void balance ()
 Moves processes and threads between cores to balance the load so that each core has a similar amount of threads and processes.
 
uint64_t add_process (Process *process)
 Adds a process to the least busy core.
 
uint64_t add_thread (Thread *thread)
 Adds a thread to the least busy core.
 
- Public Member Functions inherited from MaxOS::hardwarecommunication::InterruptHandler
virtual void handle_interrupt ()
 Handles an interrupt.
 

Static Public Member Functions

static GlobalSchedulersystem_scheduler ()
 Gets the system scheduler.
 
static Schedulercore_scheduler ()
 Gets the scheduler for the currently executing core.
 
static system::cpu_status_tyield (system::cpu_status_t *current)
 Pass execution to the next thread.
 
static void activate ()
 Activates each core's scheduler.
 
static void deactivate ()
 Deactivates each core's scheduler.
 
static bool is_active ()
 Checks if the global scheduler is active.
 
static void load_multiboot_elfs (system::Multiboot *multiboot)
 Loads any valid ELF files from the multiboot structure.
 
static void print_running_header ()
 Print the header for the running processes in the form ({name}:t{tid}c{core})
 
static 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)
 
static system::cpu_status_tforce_remove_process (Process *process)
 Removes a process from the scheduler and deletes all threads, begins running the next process.
 
static Processcurrent_process ()
 Gets the process on the currently executing core.
 
static Processget_process (uint64_t pid)
 Gets a process on the currently executing core by its PID.
 
static uint64_t next_pid ()
 Gets the next usable global PID.
 
static Threadcurrent_thread ()
 Gets the thread on the currently executing core.
 
static Threadget_thread (uint64_t tid)
 Gets a thread on the currently executing core by its TID.
 
static uint64_t next_tid ()
 Gets the next usable global TID.
 

Additional Inherited Members

- Protected Member Functions inherited from MaxOS::hardwarecommunication::InterruptHandler
 InterruptHandler (uint8_t interrupt_number, int64_t redirect=-1, uint64_t redirect_index=0)
 Creates a new interrupt handler and registers it with the interrupt manager.
 
 ~InterruptHandler ()
 Destroys the interrupt handler and unregisters it from the interrupt manager.
 
- Protected Attributes inherited from MaxOS::hardwarecommunication::InterruptHandler
uint8_t m_interrupt_number
 The interrupt number this handler handles.
 

Detailed Description

The global scheduler that manages all processes and threads across all cores.

Definition at line 26 of file scheduler.h.

Constructor & Destructor Documentation

◆ GlobalScheduler()

GlobalScheduler::GlobalScheduler ( system::Multiboot multiboot)
explicit

Constructs a new Global Scheduler object. Registers as the interrupt handler for interrupt 0x20 and setups the shared resource registries. Loads any ELF files from the multiboot structure.

Parameters
multibootThe multiboot structure that may contain ELF files to load

Definition at line 24 of file scheduler.cpp.

25: InterruptHandler(0x20),
26 m_shared_memory_registry(resource_type_t::SHARED_MEMORY),
27 m_shared_messages_registry(resource_type_t::MESSAGE_ENDPOINT),
28 m_next_pid(-1),
29 m_next_tid(-1)
30{
31
32 // Set up the global scheduler
33 Logger::INFO() << "Setting up global Scheduler\n";
34 s_instance = this;
35
36 // Set up the per core scheduler
37 for(const auto& core : CPU::cores)
38 core -> scheduler = new Scheduler();
39
40 // Load the elfs
41 load_multiboot_elfs(&multiboot);
42
43}
static Logger INFO()
Gets active logger set to info level.
Definition logger.cpp:171
Handles a certain interrupt number.
Definition interrupts.h:30
static void load_multiboot_elfs(system::Multiboot *multiboot)
Loads any valid ELF files from the multiboot structure.
Schedules processes to run on the core via their threads.
Definition scheduler.h:85
Manages the CPU and its cores.
Definition cpu.h:253

References MaxOS::system::CPU::cores, MaxOS::Logger::INFO(), and load_multiboot_elfs().

◆ ~GlobalScheduler()

GlobalScheduler::~GlobalScheduler ( )

Destroys the global scheduler and frees the per core schedulers.

Definition at line 87 of file scheduler.cpp.

87 {
88
89 // No longer the global instance
90 s_instance = nullptr;
91
92 // Free the per core scheduler
93 for(const auto& core : CPU::cores)
94 delete core->scheduler;
95
96}

References MaxOS::system::CPU::cores.

Member Function Documentation

◆ activate()

void GlobalScheduler::activate ( )
static

Activates each core's scheduler.

Definition at line 101 of file scheduler.cpp.

101 {
102
103 s_instance -> m_active = true;
104 for(const auto& core : CPU::cores)
105 core->scheduler->activate();
106
107}
static void activate()
Activates each core's scheduler.

References MaxOS::system::CPU::cores.

Referenced by kernel_main().

◆ add_process()

uint64_t GlobalScheduler::add_process ( Process process)

Adds a process to the least busy core.

Parameters
processThe process to add
Returns
The pid of the new process

Definition at line 186 of file scheduler.cpp.

186 {
187
188 // No cores?
189 if(CPU::cores.empty())
190 return 0;
191
192 // Find the core with the least processes
193 uint64_t core_id = 0;
194 Scheduler* scheduler = CPU::cores[core_id]->scheduler;
195 for(const auto& core : CPU::cores){
196 auto core_scheduler = core->scheduler;
197 if(core_scheduler->process_amount() < scheduler->process_amount()){
198 core_id = core->id;
199 scheduler = core_scheduler;
200 }
201 }
202
203 // Save the pid
204 auto pid = scheduler->add_process(process);
205 m_core_pids.insert(pid,core_id);
206
207 Logger::DEBUG() << "Adding process " << pid << ": " << process->name << " to core " << core_id <<"\n";
208 return pid;
209}
static Logger DEBUG()
Gets active logger set to DEBUG level.
Definition logger.cpp:193
void insert(Key, Value)
Updates the value of an element, or adds a new element if it does not exist.
Definition map.h:253
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
string name
The name of the process.
Definition process.h:109
uint64_t add_process(Process *process)
Adds a process to the scheduler.
uint64_t process_amount()
Gets how processes are running on this scheduler.
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:270

References MaxOS::processes::Scheduler::add_process(), core_scheduler(), MaxOS::system::CPU::cores, MaxOS::Logger::DEBUG(), MaxOS::common::Map< Key, Value >::insert(), MaxOS::processes::Process::name, and MaxOS::processes::Scheduler::process_amount().

Referenced by load_multiboot_elfs().

◆ add_thread()

uint64_t GlobalScheduler::add_thread ( Thread thread)

Adds a thread to the least busy core.

Parameters
threadThe thread to add
Returns
The tid of the new thread

Definition at line 217 of file scheduler.cpp.

217 {
218
219 // No cores?
220 if(CPU::cores.empty())
221 return 0;
222
223 // Find the core with the least threads
224 uint64_t core_id = 0;
225 Scheduler* scheduler = CPU::cores[core_id]->scheduler;
226 for(const auto& core : CPU::cores){
227 auto core_scheduler = core->scheduler;
228 if(core_scheduler->thread_amount() < scheduler->thread_amount()){
229 core_id = core->id;
230 scheduler = core_scheduler;
231 }
232 }
233
234 // Save the tid
235 auto tid = scheduler->add_thread(thread);
236 m_core_tids.insert(tid,core_id);
237
238 Logger::DEBUG() << "Adding thread " << tid << " to core " << core_id <<"\n";
239 return tid;
240}
uint64_t thread_amount()
Gets how many threads are running on this scheduler.
uint64_t add_thread(Thread *thread)
Adds a thread to the scheduler.

References MaxOS::processes::Scheduler::add_thread(), core_scheduler(), MaxOS::system::CPU::cores, MaxOS::Logger::DEBUG(), MaxOS::common::Map< Key, Value >::insert(), and MaxOS::processes::Scheduler::thread_amount().

◆ balance()

void GlobalScheduler::balance ( )

Moves processes and threads between cores to balance the load so that each core has a similar amount of threads and processes.

Todo:
Implement

Definition at line 126 of file scheduler.cpp.

126 {
127
128}

◆ core_scheduler()

Scheduler * GlobalScheduler::core_scheduler ( )
static

Gets the scheduler for the currently executing core.

Returns
The scheduler for this core

Definition at line 349 of file scheduler.cpp.

349 {
351}
static Core * executing_core()
Gets the core that is currently executing.
Definition cpu.cpp:623
processes::Scheduler * scheduler
The scheduler for this core.
Definition cpu.h:246

References MaxOS::system::CPU::executing_core(), and MaxOS::system::Core::scheduler.

Referenced by MaxOS::common::BlockingLock::acquire(), add_process(), add_thread(), current_process(), current_thread(), handle_interrupt(), MaxOS::system::CPU::PANIC(), MaxOS::system::SyscallManager::syscall_close_process(), MaxOS::system::SyscallManager::syscall_thread_close(), and yield().

◆ current_process()

◆ current_thread()

Thread * GlobalScheduler::current_thread ( )
static

Gets the thread on the currently executing core.

Returns
The currently executing thread

Definition at line 316 of file scheduler.cpp.

316 {
317 return core_scheduler()->current_thread();
318}
Thread * current_thread()
Gets the currently executing thread.

References core_scheduler(), and MaxOS::processes::Scheduler::current_thread().

Referenced by MaxOS::common::BlockingLock::acquire(), print_running_header(), MaxOS::system::SyscallManager::syscall_thread_close(), MaxOS::system::SyscallManager::syscall_thread_sleep(), and yield().

◆ deactivate()

void GlobalScheduler::deactivate ( )
static

Deactivates each core's scheduler.

Definition at line 112 of file scheduler.cpp.

112 {
113
114 s_instance -> m_active = false;
115 for(const auto& core : CPU::cores)
116 core->scheduler->deactivate();
117
118}
static void deactivate()
Deactivates each core's scheduler.

References MaxOS::system::CPU::cores.

◆ force_remove_process()

system::cpu_status_t * GlobalScheduler::force_remove_process ( Process process)
static

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 264 of file scheduler.cpp.

264 {
265
266 // Get the core running the process
267 if(!s_instance)
268 return nullptr;
269
270 auto core = s_instance -> m_core_pids[process->pid()];
271 return CPU::cores[core]->scheduler->force_remove_process(process);
272
273}
uint64_t pid() const
Gets the pid of the process.
Definition process.cpp:326

References MaxOS::system::CPU::cores, and MaxOS::processes::Process::pid().

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

◆ get_process()

Process * GlobalScheduler::get_process ( uint64_t  pid)
static

Gets a process on the currently executing core by its PID.

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

Definition at line 293 of file scheduler.cpp.

293 {
294
295 // Get the core running the pid
296 if(!s_instance)
297 return nullptr;
298
299 auto core = s_instance -> m_core_pids[pid];
300 return CPU::cores[core]->scheduler->get_process(pid);
301}

References MaxOS::system::CPU::cores.

Referenced by MaxOS::system::SyscallManager::syscall_close_process().

◆ get_thread()

Thread * GlobalScheduler::get_thread ( uint64_t  tid)
static

Gets a thread on the currently executing core by its TID.

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

Definition at line 326 of file scheduler.cpp.

326 {
327
328 // Get the core running the tid
329 if(!s_instance)
330 return nullptr;
331
332 auto core = s_instance -> m_core_tids[tid];
333 return CPU::cores[core]->scheduler->get_thread(tid);
334}

References MaxOS::system::CPU::cores.

Referenced by MaxOS::common::BlockingLock::release(), and MaxOS::system::SyscallManager::syscall_thread_close().

◆ handle_interrupt()

system::cpu_status_t * GlobalScheduler::handle_interrupt ( system::cpu_status_t status)
finalvirtual

Handles the interrupt 0x20.

Parameters
statusThe current CPU status
Returns
The new CPU status

Reimplemented from MaxOS::hardwarecommunication::InterruptHandler.

Definition at line 62 of file scheduler.cpp.

62 {
63
64 // Scheduler not active
65 if(!s_instance || !s_instance->m_active)
66 return status;
67
68 auto s = core_scheduler()->schedule(status);
69 ASSERT(s->rip != 0, "Cant run a empty state\n");
70 return s;
71}
system::cpu_status_t * schedule(system::cpu_status_t *cpu_state)
Schedules the next thread to run.
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100

References ASSERT, core_scheduler(), and MaxOS::processes::Scheduler::schedule().

◆ is_active()

bool GlobalScheduler::is_active ( )
static

Checks if the global scheduler is active.

Returns
True if the scheduler is active, false otherwise

Definition at line 358 of file scheduler.cpp.

358 {
359 return s_instance->m_active;
360}

◆ load_multiboot_elfs()

void GlobalScheduler::load_multiboot_elfs ( system::Multiboot multiboot)
static

Loads any valid ELF files from the multiboot structure.

Parameters
multibootThe multiboot structure
Todo:
Handle passing multiple args to the process

Definition at line 138 of file scheduler.cpp.

138 {
139
140 for (multiboot_tag* tag = multiboot->start_tag(); tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct multiboot_tag*) ((multiboot_uint8_t*) tag + ((tag->size + 7) & ~7))) {
141
142 // Tag is not an ELF
143 if (tag->type != MULTIBOOT_TAG_TYPE_MODULE)
144 continue;
145
146 // Try to create the elf from the module
147 auto* module = (struct multiboot_tag_module*) tag;
148 ELF64 elf((uintptr_t) PhysicalMemoryManager::to_dm_region(module->mod_start));
149 if (!elf.is_valid())
150 continue;
151
152 Logger::DEBUG() << "Creating process from multiboot module for " << module->cmdline << " (at 0x" << (uint64_t) module->mod_start << ")\n";
153
154 // Create an array of args for the process
155 char* args[1] = {module->cmdline};
156
157 // Create the process
158 auto* process = new Process(module->cmdline, args, 1, &elf);
160
161 Logger::DEBUG() << "ELF loaded to pid " << process->pid() << "\n";
162 }
163}
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
static void * to_dm_region(uintptr_t physical_address)
Converts a physical address to a direct map region address if it is in the lower region using the hig...
Definition physical.cpp:930
Handles the loading and parsing of 64-bit ELF files.
Definition elf.h:217
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:50
uint64_t add_process(Process *process)
Adds a process to the least busy core.
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:85
multiboot_tag * start_tag() const
Common header for all multiboot info tags.
Definition multiboot.h:234

References add_process(), MaxOS::Logger::DEBUG(), MaxOS::processes::ELF64::is_valid(), MaxOS::system::Multiboot::start_tag(), system_scheduler(), and MaxOS::memory::PhysicalMemoryManager::to_dm_region().

Referenced by GlobalScheduler().

◆ next_pid()

uint64_t GlobalScheduler::next_pid ( )
static

Gets the next usable global PID.

Returns

Definition at line 307 of file scheduler.cpp.

307 {
308 return s_instance -> m_next_pid++;
309}

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

◆ next_tid()

uint64_t GlobalScheduler::next_tid ( )
static

Gets the next usable global TID.

Returns

Definition at line 340 of file scheduler.cpp.

340 {
341 return s_instance->m_next_tid++;
342}

Referenced by MaxOS::processes::Scheduler::add_thread().

◆ print_running_header()

void GlobalScheduler::print_running_header ( )
static

Print the header for the running processes in the form ({name}:t{tid}c{core})

Definition at line 168 of file scheduler.cpp.

168 {
169
170 // No threads or processes to get
171 if(!s_instance || !s_instance->m_active)
172 return;
173
174 auto process = current_process();
175 auto thread = current_thread();
176
177 Logger::Out() << "(" << process->name << ":t" << thread->tid << "c" << CPU::executing_core()->id << ") ";
178}
static Logger & Out()
Gets the active logger.
Definition logger.cpp:149
static Process * current_process()
Gets the process on the currently executing core.
static Thread * current_thread()
Gets the thread on the currently executing core.
uint8_t id
The ID of this core.
Definition cpu.h:240

References current_process(), current_thread(), MaxOS::system::CPU::executing_core(), MaxOS::system::Core::id, and MaxOS::Logger::Out().

Referenced by MaxOS::Logger::set_log_level().

◆ remove_process()

uint64_t GlobalScheduler::remove_process ( Process process)
static

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 248 of file scheduler.cpp.

248 {
249
250 // Get the core running the process
251 if(!s_instance)
252 return 0;
253
254 auto core = s_instance -> m_core_pids[process->pid()];
255 return CPU::cores[core]->scheduler->remove_process(process);
256}

References MaxOS::system::CPU::cores, and MaxOS::processes::Process::pid().

◆ system_scheduler()

GlobalScheduler * GlobalScheduler::system_scheduler ( )
static

Gets the system scheduler.

Returns
The system scheduler or nullptr if not found

Definition at line 50 of file scheduler.cpp.

50 {
51
52 return s_instance;
53}

Referenced by load_multiboot_elfs(), MaxOS::system::CPU::prepare_for_panic(), and MaxOS::system::SyscallManager::syscall_close_process().

◆ yield()

system::cpu_status_t * GlobalScheduler::yield ( system::cpu_status_t current)
static

Pass execution to the next thread.

Parameters
currentwhere to resume this thread to
Returns
The cpu state of the next thread to run

Definition at line 79 of file scheduler.cpp.

79 {
80 current_thread()->execution_state = *current;
81 return core_scheduler()->yield();
82}
system::cpu_status_t * yield()
Pass execution to the next thread.
system::cpu_status_t execution_state
The CPU state of the thread.
Definition process.h:67

References core_scheduler(), current_thread(), MaxOS::processes::Thread::execution_state, and MaxOS::processes::Scheduler::yield().

Referenced by MaxOS::system::SyscallManager::syscall_thread_sleep(), and MaxOS::system::SyscallManager::syscall_thread_yield().


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