diff --git a/kernel/inc/mm/region.h b/kernel/inc/mm/region.h index abb4653..89f621f 100644 --- a/kernel/inc/mm/region.h +++ b/kernel/inc/mm/region.h @@ -29,13 +29,17 @@ #define KERNEL_START_ADDRESS (uint64_t)&_kernel_start #define KERNEL_END_ADDRESS (uint64_t)&_kernel_end +#define MEM_REGION_THREAD_OFFSET 0x100000000 + #define MEM_REGION_PROCESS 0x0000000000000000 #define MEM_REGION_PROCESS_EXEC 0x0000010000000000 -#define MEM_REGION_PROCESS_THREAD_DATA 0x0000010100000000 +#define MEM_REGION_PROCESS_THREAD_BASE 0x0000010100000000 #define MEM_REGION_KERNEL 0xFFFF800000000000 +#define MEM_REGION_KERNEL_STACK_DUMMY 0xFFFFF00000000000 // size 0x4000 +#define MEM_REGION_KERNEL_HEAP 0xFFFFF80000000000 +#define MEM_REGION_KERNEL_THREAD_BASE 0xFFFFFF0000000000 #define MEM_REGION_KERNEL_EXEC 0xFFFFFFFF80000000 -#define MEM_REGION_KERNEL_HEAP 0xFFFFFFFFF0000000 extern uint64_t _kernel_start; extern uint64_t _kernel_end; diff --git a/kernel/inc/proc/process.h b/kernel/inc/proc/process.h index c1b0943..6f253ee 100644 --- a/kernel/inc/proc/process.h +++ b/kernel/inc/proc/process.h @@ -26,9 +26,13 @@ #include "utils/stdtypes.h" #include "utils/string.h" +#include "utils/bitmap.h" #include "mm/page_map.h" #include "drivers/elf/elf.h" +#define MAX_THREADS_PER_PROCESS 64 +#define THREAD_ID_INVALID (-1) + typedef uint32_t pid_t; typedef enum { @@ -48,6 +52,7 @@ struct process_T { uint32_t num_threads; void* threads; + bitmap_T thread_ids; process_T* parent; process_T* childs; @@ -55,9 +60,11 @@ struct process_T { process_T* next; }; -void process_kernel_spawn (elf_executable_T* executable); -pid_t process_spawn (pid_t parent, string_t name, elf_executable_T* executable, void* buffer); -void process_kill_pid (pid_t pid); -void process_kill (process_T* process); +void process_kernel_spawn (elf_executable_T* executable); +pid_t process_spawn (pid_t parent, string_t name, elf_executable_T* executable, void* buffer); +int32_t process_get_thread_id (process_T* process); +void process_clear_thread_id (process_T* process, uint32_t id); +void process_kill_pid (pid_t pid); +void process_kill (process_T* process); #endif //NOX_PROCESS_H diff --git a/kernel/inc/proc/thread.h b/kernel/inc/proc/thread.h index dc91cf3..fc2ae6e 100644 --- a/kernel/inc/proc/thread.h +++ b/kernel/inc/proc/thread.h @@ -42,6 +42,7 @@ struct thread_T{ thread_T* local_prev; thread_T* local_next; + uint32_t local_id; }; diff --git a/kernel/src/proc/process.c b/kernel/src/proc/process.c index bb5d5ca..b8430fa 100644 --- a/kernel/src/proc/process.c +++ b/kernel/src/proc/process.c @@ -47,6 +47,7 @@ pid_t process_spawn(pid_t parent, string_t name, elf_executable_T* executable, v process_T* process = memory_allocate(sizeof(process_T)); process->num_threads = 0; process->threads = NULL; + process->thread_ids = bitmap_init(MAX_THREADS_PER_PROCESS); process->parent = scheduler_get_process(parent); process->executable = executable; @@ -60,6 +61,20 @@ pid_t process_spawn(pid_t parent, string_t name, elf_executable_T* executable, v return scheduler_register_process(process); } +int32_t process_get_thread_id(process_T* process) { + for (int i = 0; i < MAX_THREADS_PER_PROCESS; i++) { + if (!bitmap_get(&process->thread_ids, i)) { + bitmap_set(&process->thread_ids, i, true); + return i; + } + } + return THREAD_ID_INVALID; +} + +void process_clear_thread_id(process_T* process, uint32_t id) { + bitmap_set(&process->thread_ids, id, false); +} + void process_kill_pid(pid_t pid) { process_kill(scheduler_get_process(pid)); } @@ -69,6 +84,7 @@ void process_kill(process_T* process) { elf_executable_destruct(process->executable); page_map_destruct(process->page_map); + bitmap_destruct(&process->thread_ids); memory_free(process); } \ No newline at end of file diff --git a/kernel/src/proc/scheduler.c b/kernel/src/proc/scheduler.c index 1992702..f9dd957 100644 --- a/kernel/src/proc/scheduler.c +++ b/kernel/src/proc/scheduler.c @@ -324,7 +324,7 @@ cpu_state_T* scheduler_switch_context(cpu_state_T* state) { } // dirty map 0x0000010000000000 <--> 0x0000020000000000 - for (int i = 1; i < 4; i++) { + for (int i = 2; i < 5; i++) { g_kernel_page_map->entries[i] = new_thread->process->page_map->entries[i]; } diff --git a/kernel/src/proc/thread.c b/kernel/src/proc/thread.c index b403f6e..6417193 100644 --- a/kernel/src/proc/thread.c +++ b/kernel/src/proc/thread.c @@ -35,18 +35,31 @@ thread_T* thread_spawn(pid_t process, void* function) { thread->process = scheduler_get_process(process); if (thread->process == NULL) { + memory_free(thread); log(LOG_WARNING, " failed to spawn thread for process %d (invalid pid)", process); return NULL; } + int32_t id = process_get_thread_id(thread->process); + if (id == THREAD_ID_INVALID) { + memory_free(thread); + log(LOG_WARNING, " failed to spawn thread for process %d (no free thread id)", process); + return NULL; + } + thread->local_id = (uint32_t)id; + + uint8_t* base = (uint8_t*)((process == PROCESS_KERNEL ? MEM_REGION_KERNEL_THREAD_BASE : MEM_REGION_PROCESS_THREAD_BASE) + (MEM_REGION_THREAD_OFFSET * thread->local_id)); + + log(LOG_DEBUG, "spawning thread with base address: 0x%x", base); + thread->cpu_time = 0; thread->stack_size = PFRAME_SIZE * 4; - thread->stack = MEM_REGION_PROCESS_THREAD_DATA; + thread->stack = base; for (int i = 0; i < 4; i++) { void* physical_address = pframe_request(); - page_map_map_memory(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (i * PFRAME_SIZE), physical_address, PM_FLAG_READ_WRITE); - page_map_map_memory(g_kernel_page_map, MEM_REGION_PROCESS_THREAD_DATA + (i * PFRAME_SIZE), physical_address, PM_FLAG_READ_WRITE); + page_map_map_memory(thread->process->page_map, &base[i * PFRAME_SIZE], physical_address, PM_FLAG_READ_WRITE); + page_map_map_memory(g_kernel_page_map, MEM_REGION_KERNEL_STACK_DUMMY + i * PFRAME_SIZE, physical_address, PM_FLAG_READ_WRITE); } cpu_state_T state = { @@ -67,16 +80,14 @@ thread_T* thread_spawn(pid_t process, void* function) { .ss = GDT_SELECTOR_KERNEL_DATA }; - memory_copy(&state, thread->stack + (thread->stack_size - sizeof(cpu_state_T)), sizeof(cpu_state_T)); + memory_copy(&state, MEM_REGION_KERNEL_STACK_DUMMY + (thread->stack_size - sizeof(cpu_state_T)), sizeof(cpu_state_T)); thread->state = thread->stack + (thread->stack_size - sizeof(cpu_state_T)); for (int i = 0; i < 4; i++) { - page_map_unmap_memory(g_kernel_page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + page_map_unmap_memory(g_kernel_page_map, MEM_REGION_KERNEL_STACK_DUMMY + i * PFRAME_SIZE); } - page_map_dump_info(thread->process->page_map); - return scheduler_register_thread(thread); } @@ -85,6 +96,7 @@ thread_T* thread_spawn_from_state(pid_t process, cpu_state_T* state) { thread->process = scheduler_get_process(process); if (thread->process == NULL) { + memory_free(thread); log(LOG_WARNING, " failed to spawn thread for process %d (invalid pid)", process); return NULL; } @@ -109,11 +121,15 @@ void thread_pause(thread_T* thread) { void thread_kill(thread_T* thread) { scheduler_kill_thread(thread); + process_clear_thread_id(thread->process, thread->local_id); + + uint8_t* base = (uint8_t*)((thread->process->id == PROCESS_KERNEL ? MEM_REGION_KERNEL_THREAD_BASE : MEM_REGION_PROCESS_THREAD_BASE) + (MEM_REGION_THREAD_OFFSET * thread->local_id)); + if (thread->stack != NULL) { for (int i = 0; i < 4; i++) { - void* pframe = page_map_get_physical_address(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + void* pframe = page_map_get_physical_address(thread->process->page_map, &base[PFRAME_SIZE * i]); pframe_free(pframe); - page_map_unmap_memory(thread->process->page_map, MEM_REGION_PROCESS_THREAD_DATA + (PFRAME_SIZE * i)); + page_map_unmap_memory(thread->process->page_map, &base[PFRAME_SIZE * i]); } }