Max OS 0.3
Loading...
Searching...
No Matches
process.cpp
Go to the documentation of this file.
1
9#include <processes/process.h>
10#include <common/logger.h>
11#include <processes/scheduler.h> //@todo infinite recursion
12
13using namespace MaxOS;
14using namespace MaxOS::system;
15using namespace MaxOS::memory;
16using namespace MaxOS::processes;
17using namespace MaxOS::common;
18using namespace MaxOS::hardwarecommunication;
19
32Thread::Thread(void (* _entry_point)(void*), void* args, int arg_amount, Process* parent)
33{
34
35 // Basic setup
36 thread_state = ThreadState::NEW;
37 wakeup_time = 0;
38 ticks = 0;
39
40 // Create the stack ()
41 m_stack_pointer = (uintptr_t) parent->memory_manager->allocate(STACK_SIZE) + STACK_SIZE;
42
43 // Use the kernel stack
44 m_tss_stack_pointer = parent->is_kernel ? CPU::executing_core() -> tss.rsp0 : (uintptr_t) parent->memory_manager->kmalloc(STACK_SIZE) + STACK_SIZE;
45
46 // Mak sure there is a stack
47 ASSERT(m_stack_pointer != 0 && m_tss_stack_pointer != 0, "Failed to allocate stack for thread");
48
49 // Set up the execution state
50 execution_state = {};
51 execution_state.rip = (uint64_t) _entry_point;
52 execution_state.ss = parent->is_kernel ? 0x10 : 0x23;
53 execution_state.cs = parent->is_kernel ? 0x8 : 0x1B;
54 execution_state.rflags = 0x202;
55 execution_state.interrupt_number = 0;
56 execution_state.error_code = 0;
57 execution_state.rsp = m_stack_pointer;
58 execution_state.rbp = 0;
59
60 // Copy the args into userspace
61 uint64_t argc = arg_amount;
62 size_t arg_size = argc * sizeof(void*);
63 void* argv = parent->memory_manager->allocate(arg_size);
64 for (int i = 0; i < argc; i++) {
65
66 // Copy each argument
67 size_t len = strlen(((char**)args)[i]) + 1;
68 ((char**)argv)[i] = (char*) parent->memory_manager->allocate(len);
69 memcpy(((char**)argv)[i], ((char**)args)[i], len);
70 }
71
72 execution_state.rdi = argc;
73 execution_state.rsi = (uint64_t) argv;
74 //execution_state->rdx = (uint64_t)env_args;
75
76 // All ports denied by default
77 memset(m_io_bitmap, 0xFF, sizeof(m_io_bitmap));
78
79 parent_pid = parent->pid();
80}
81
85Thread::~Thread() = default;
86
92void Thread::sleep(size_t milliseconds) {
93
94 // Update the state
95 thread_state = ThreadState::SLEEPING;
96 wakeup_time = milliseconds;
97 yield();
98}
99
104
105 // Only update the state if the caller hasn't specified the resume condition state
106 if (thread_state == ThreadState::RUNNING)
107 thread_state = ThreadState::READY;
108
109 // Save a checkpoint (resumed state is ret of the below function: execution after yield will be there)
111
112 // Schedule the replacement thread, but guard against infinite loops where thread continusly pass execution to the
113 // next thread after scheduler resumes it post yield)
114 if(thread_state != ThreadState::RUNNING){
115
116 // Yield to the next thread
119 }
120}
121
126
127 // Ensure the state saving is enabled
128 if (!CPU::executing_core()->xsave_enabled)
129 return;
130
131 // Save the state
132 asm volatile("fxsave %0" : "=m" (m_sse_save_region));
133}
134
139
140 // Ensure the state saving is enabled
141 if (!CPU::executing_core()->xsave_enabled)
142 return;
143
144 // Restore the state
145 asm volatile("fxrstor %0" : : "m" (m_sse_save_region));
146}
147
152extern "C" void save_cpu_state_naked(volatile void* location) __attribute__((naked));
153extern "C" void save_cpu_state_naked(volatile void* location) {
154 asm volatile(
155
156 // Save registers
157 "pushq %rax\n"
158 "pushq %rbx\n"
159 "pushq %rcx\n"
160 "pushq %rdx\n"
161 "pushq %rbp\n"
162 "pushq %rsi\n"
163 "pushq %rdi\n"
164 "pushq %r8\n"
165 "pushq %r9\n"
166 "pushq %r10\n"
167 "pushq %r11\n"
168 "pushq %r12\n"
169 "pushq %r13\n"
170 "pushq %r14\n"
171 "pushq %r15\n"
172
173 // Store the save location
174 "movq %rdi, %rsi\n"
175
176 // Save general registers
177 "movq 0(%rsp), %rax\n" "movq %rax, 0x00(%rsi)\n"
178 "movq 8(%rsp), %rax\n" "movq %rax, 0x08(%rsi)\n"
179 "movq 16(%rsp), %rax\n" "movq %rax, 0x10(%rsi)\n"
180 "movq 24(%rsp), %rax\n" "movq %rax, 0x18(%rsi)\n"
181 "movq 32(%rsp), %rax\n" "movq %rax, 0x20(%rsi)\n"
182 "movq 40(%rsp), %rax\n" "movq %rax, 0x28(%rsi)\n"
183 "movq 48(%rsp), %rax\n" "movq %rax, 0x30(%rsi)\n"
184 "movq 56(%rsp), %rax\n" "movq %rax, 0x38(%rsi)\n"
185 "movq 64(%rsp), %rax\n" "movq %rax, 0x40(%rsi)\n"
186 "movq 72(%rsp), %rax\n" "movq %rax, 0x48(%rsi)\n"
187 "movq 80(%rsp), %rax\n" "movq %rax, 0x50(%rsi)\n"
188 "movq 88(%rsp), %rax\n" "movq %rax, 0x58(%rsi)\n"
189 "movq 96(%rsp), %rax\n" "movq %rax, 0x60(%rsi)\n"
190 "movq 104(%rsp), %rax\n" "movq %rax, 0x68(%rsi)\n"
191 "movq 112(%rsp), %rax\n" "movq %rax, 0x70(%rsi)\n"
192
193 // Save the return address as the instruction pointer
194 "movq 120(%rsp), %rax\n"
195 "movq %rax, 0x88(%rsi)\n"
196
197 // CS
198 "xorq %rax, %rax\n"
199 "movw %cs, %ax\n"
200 "movq %rax, 0x90(%rsi)\n"
201
202 // RFLAGS
203 "pushfq\n"
204 "popq %rax\n"
205 "movq %rax, 0x98(%rsi)\n"
206
207 // RSP
208 "leaq 120(%rsp), %rax\n"
209 "movq %rax, 0xA0(%rsi)\n"
210
211 // SS
212 "xorq %rax, %rax\n"
213 "movw %ss, %ax\n"
214 "movq %rax, 0xA8(%rsi)\n"
215
216 // Restore registers
217 "popq %r15\n"
218 "popq %r14\n"
219 "popq %r13\n"
220 "popq %r12\n"
221 "popq %r11\n"
222 "popq %r10\n"
223 "popq %r9\n"
224 "popq %r8\n"
225 "popq %rdi\n"
226 "popq %rsi\n"
227 "popq %rbp\n"
228 "popq %rdx\n"
229 "popq %rcx\n"
230 "popq %rbx\n"
231 "popq %rax\n"
232 "ret\n"
233 );
234}
235
236
243
247void Thread::enable_port(uint64_t port) {
248
249 // Enable the port
250 m_io_bitmap[port / 8] &= ~(1U << (port % 8));
252
253}
254
258void Thread::disable_port(uint64_t port) {
259
260 // Disable the port
261 m_io_bitmap[port / 8] |= (1U << (port % 8));
263}
264
269
270 memcpy(CPU::executing_core()->tss.io_bitmap, &m_io_bitmap, sizeof(m_io_bitmap));
271
272}
273
280Process::Process(const string& p_name, bool is_kernel)
281: is_kernel(is_kernel),
282 name(p_name)
283{
284 // If it is a kernel process then don't need a new memory manager
286}
287
297Process::Process(const string& p_name, void (* _entry_point)(void*), void* args, int arg_amount, bool is_kernel)
298: Process(p_name, is_kernel)
299{
300
301 // Create the main thread
302 auto* main_thread = new Thread(_entry_point, args, arg_amount, this);
303
304 // Add the thread
305 add_thread(main_thread);
306}
307
321Process::Process(const string& p_name, void* args, int arg_amount, ELF64* elf, bool is_kernel)
322: Process(p_name, is_kernel)
323{
324
325 // Get the entry point
327 auto* entry_point = (void (*)(void*)) elf->header()->entry;
328
329 // Create the main thread
330 auto* main_thread = new Thread(entry_point, args, arg_amount, this);
331 add_thread(main_thread);
332}
333
334
339
341
342 // Free the threads
343 for (auto thread: m_threads)
344 delete thread;
345
346 // Free the memory manager (only if it was created)
347 if (!is_kernel)
348 delete memory_manager;
349
350 // Log the cleanup
351 Logger::DEBUG() << "Process " << name.c_str() << " cleaned up, memory before: " << (int)pages << " bytes, after cleanup: " << (int)PhysicalMemoryManager::s_current_manager->memory_used() << " bytes\n";
352}
353
360
361 m_lock.lock();
362
363 // Store the thread
364 m_threads.push_back(thread);
365 thread->parent_pid = m_pid;
366
367 m_lock.unlock();
368}
369
375void Process::remove_thread(uint64_t tid) {
376
377 // Find the thread
378 for (uint32_t i = 0; i < m_threads.size(); i++) {
379
380 // Thread is not what is being removed
381 if (m_threads[i]->tid != tid)
382 continue;
383
384 // Delete the thread
385 Thread* thread = m_threads[i];
386 delete thread;
387
388 // Remove the thread from the list
389 m_threads.erase(m_threads.begin() + i);
390 return;
391 }
392}
393
399void Process::set_pid(uint64_t pid) {
400
401 // Check if the pid is already set
402 if (m_pid != 0)
403 return;
404
405 // Set the pid
406 m_pid = pid;
407
408 // Assign the pid to the threads
409 for (auto thread: m_threads)
410 thread->parent_pid = pid;
411
412}
413
419Vector<Thread*> Process::threads() {
420
421 return m_threads;
422}
423
429uint64_t Process::pid() const {
430
431 return m_pid;
432}
433
440
441 uint64_t total_ticks = 0;
442 for (auto thread: m_threads)
443 total_ticks += thread->ticks;
444
445 return total_ticks;
446}
static LogRecord DEBUG()
Gets the active logger for debug logs.
Definition logger.cpp:204
static void ForceInterruptReturn(system::cpu_status_t *state)
Force the CPU to return from an interrupt (see interrupts.s)
Handles memory allocation and deallocation.
static MemoryManager * s_kernel_memory_manager
The memory manager for any kernel processes and all kernel allocations.
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:183
uint64_t memory_used() const
Gets the memory currently used.
Definition physical.cpp:753
void * allocate(size_t size) final
Allocates a block of memory.
Definition bump.cpp:144
Handles the loading and parsing of 64-bit ELF files.
Definition elf.h:217
elf_64_header_t * header() const
Gets the header of the elf file.
Definition elf.cpp:54
void load_into_memory(memory::VirtualMemoryManager *vmm) const
Loads the elf program into memory if a valid elf file.
Definition elf.cpp:42
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:94
uint64_t pid() const
Gets the pid of the process.
Definition process.cpp:429
uint64_t total_ticks()
Gets the total ticks of the threads in the process (not this does not include any past killed threads...
Definition process.cpp:439
string name
The name of the process.
Definition process.h:118
common::Vector< Thread * > threads()
Gets the threads of the process.
Definition process.cpp:419
void add_thread(Thread *thread)
Adds a thread to the process.
Definition process.cpp:359
~Process()
Destructor for the Process class.
Definition process.cpp:338
Process(const string &name, bool is_kernel=false)
Base Constructor for the Process.
Definition process.cpp:280
bool is_kernel
Whether this process is a kernel process.
Definition process.h:116
void set_pid(uint64_t pid)
Sets the pid of the process once added to the queue.
Definition process.cpp:399
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
memory::MemoryManager * memory_manager
The manager for memory used by this process.
Definition process.h:121
system::cpu_status_t * schedule_next(system::cpu_status_t *status)
Schedules the next thread to run.
The execution context of a sub-process thread.
Definition process.h:50
void enable_port(uint64_t port)
Sets bits in the threads TSS to allow a port for I/O.
Definition process.cpp:247
Thread(void(*_entry_point)(void *), void *args, int arg_amount, Process *parent)
Constructor for the Thread class.
Definition process.cpp:32
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
~Thread()
Destructor for the Thread class.
void yield()
Pass execution to the next ready thread.
Definition process.cpp:103
volatile size_t ticks
The number of ticks the thread has run for.
Definition process.h:74
void save_cpu_state()
Saves the CPU state into the thread's execution_state structure.
Definition process.cpp:240
void disable_port(uint64_t port)
Sets bits in the threads TSS to disallow a port for I/O.
Definition process.cpp:258
volatile thread_state_t thread_state
The current state of the thread.
Definition process.h:72
void restore_sse_state()
Restores the SSE, x87 FPU, and MMX states from the thread to memory.
Definition process.cpp:138
volatile size_t wakeup_time
The time at which the thread should wake up (if sleeping)
Definition process.h:75
void sleep(size_t milliseconds)
Sleeps the thread for a certain amount of time.
Definition process.cpp:92
void load_port_bitmap()
Copy this ports.
Definition process.cpp:268
static Core * executing_core()
Gets the core that is currently executing.
Definition cpu.cpp:660
struct PACKED MaxOS::system::CPUStatus cpu_status_t
Alias for CPUStatus struct.
Defines a Logger class for logging messages with different severity levels to multiple output streams...
void save_cpu_state_naked(volatile void *location) __attribute__((naked))
Save the state of the CPU at the exit of this function.
Definition process.cpp:153
Defines Process and Thread classes for managing processes and their execution contexts.
constexpr size_t STACK_SIZE
The size of the stack for each thread (4KB)
Definition process.h:42
Defines a GlobalScheduler and Scheduler for managing processes and threads.
uint64_t entry
The starting RIP address where the program begins execution.
Definition elf.h:116