fix (proc): made threads working in isolated process setup
This commit is contained in:
parent
35783e6538
commit
c4d09a17ee
|
@ -29,13 +29,17 @@
|
||||||
#define KERNEL_START_ADDRESS (uint64_t)&_kernel_start
|
#define KERNEL_START_ADDRESS (uint64_t)&_kernel_start
|
||||||
#define KERNEL_END_ADDRESS (uint64_t)&_kernel_end
|
#define KERNEL_END_ADDRESS (uint64_t)&_kernel_end
|
||||||
|
|
||||||
|
#define MEM_REGION_THREAD_OFFSET 0x100000000
|
||||||
|
|
||||||
#define MEM_REGION_PROCESS 0x0000000000000000
|
#define MEM_REGION_PROCESS 0x0000000000000000
|
||||||
#define MEM_REGION_PROCESS_EXEC 0x0000010000000000
|
#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 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_EXEC 0xFFFFFFFF80000000
|
||||||
#define MEM_REGION_KERNEL_HEAP 0xFFFFFFFFF0000000
|
|
||||||
|
|
||||||
extern uint64_t _kernel_start;
|
extern uint64_t _kernel_start;
|
||||||
extern uint64_t _kernel_end;
|
extern uint64_t _kernel_end;
|
||||||
|
|
|
@ -26,9 +26,13 @@
|
||||||
|
|
||||||
#include "utils/stdtypes.h"
|
#include "utils/stdtypes.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
#include "utils/bitmap.h"
|
||||||
#include "mm/page_map.h"
|
#include "mm/page_map.h"
|
||||||
#include "drivers/elf/elf.h"
|
#include "drivers/elf/elf.h"
|
||||||
|
|
||||||
|
#define MAX_THREADS_PER_PROCESS 64
|
||||||
|
#define THREAD_ID_INVALID (-1)
|
||||||
|
|
||||||
typedef uint32_t pid_t;
|
typedef uint32_t pid_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -48,6 +52,7 @@ struct process_T {
|
||||||
|
|
||||||
uint32_t num_threads;
|
uint32_t num_threads;
|
||||||
void* threads;
|
void* threads;
|
||||||
|
bitmap_T thread_ids;
|
||||||
|
|
||||||
process_T* parent;
|
process_T* parent;
|
||||||
process_T* childs;
|
process_T* childs;
|
||||||
|
@ -55,9 +60,11 @@ struct process_T {
|
||||||
process_T* next;
|
process_T* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void process_kernel_spawn (elf_executable_T* executable);
|
void process_kernel_spawn (elf_executable_T* executable);
|
||||||
pid_t process_spawn (pid_t parent, string_t name, elf_executable_T* executable, void* buffer);
|
pid_t process_spawn (pid_t parent, string_t name, elf_executable_T* executable, void* buffer);
|
||||||
void process_kill_pid (pid_t pid);
|
int32_t process_get_thread_id (process_T* process);
|
||||||
void process_kill (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
|
#endif //NOX_PROCESS_H
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct thread_T{
|
||||||
|
|
||||||
thread_T* local_prev;
|
thread_T* local_prev;
|
||||||
thread_T* local_next;
|
thread_T* local_next;
|
||||||
|
uint32_t local_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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_T* process = memory_allocate(sizeof(process_T));
|
||||||
process->num_threads = 0;
|
process->num_threads = 0;
|
||||||
process->threads = NULL;
|
process->threads = NULL;
|
||||||
|
process->thread_ids = bitmap_init(MAX_THREADS_PER_PROCESS);
|
||||||
process->parent = scheduler_get_process(parent);
|
process->parent = scheduler_get_process(parent);
|
||||||
process->executable = executable;
|
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);
|
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) {
|
void process_kill_pid(pid_t pid) {
|
||||||
process_kill(scheduler_get_process(pid));
|
process_kill(scheduler_get_process(pid));
|
||||||
}
|
}
|
||||||
|
@ -69,6 +84,7 @@ void process_kill(process_T* process) {
|
||||||
|
|
||||||
elf_executable_destruct(process->executable);
|
elf_executable_destruct(process->executable);
|
||||||
page_map_destruct(process->page_map);
|
page_map_destruct(process->page_map);
|
||||||
|
bitmap_destruct(&process->thread_ids);
|
||||||
|
|
||||||
memory_free(process);
|
memory_free(process);
|
||||||
}
|
}
|
|
@ -324,7 +324,7 @@ cpu_state_T* scheduler_switch_context(cpu_state_T* state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// dirty map 0x0000010000000000 <--> 0x0000020000000000
|
// 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];
|
g_kernel_page_map->entries[i] = new_thread->process->page_map->entries[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,18 +35,31 @@ thread_T* thread_spawn(pid_t process, void* function) {
|
||||||
|
|
||||||
thread->process = scheduler_get_process(process);
|
thread->process = scheduler_get_process(process);
|
||||||
if (thread->process == NULL) {
|
if (thread->process == NULL) {
|
||||||
|
memory_free(thread);
|
||||||
log(LOG_WARNING, "<Thread> failed to spawn thread for process %d (invalid pid)", process);
|
log(LOG_WARNING, "<Thread> failed to spawn thread for process %d (invalid pid)", process);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t id = process_get_thread_id(thread->process);
|
||||||
|
if (id == THREAD_ID_INVALID) {
|
||||||
|
memory_free(thread);
|
||||||
|
log(LOG_WARNING, "<Thread> 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->cpu_time = 0;
|
||||||
|
|
||||||
thread->stack_size = PFRAME_SIZE * 4;
|
thread->stack_size = PFRAME_SIZE * 4;
|
||||||
thread->stack = MEM_REGION_PROCESS_THREAD_DATA;
|
thread->stack = base;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
void* physical_address = pframe_request();
|
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(thread->process->page_map, &base[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(g_kernel_page_map, MEM_REGION_KERNEL_STACK_DUMMY + i * PFRAME_SIZE, physical_address, PM_FLAG_READ_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_state_T state = {
|
cpu_state_T state = {
|
||||||
|
@ -67,16 +80,14 @@ thread_T* thread_spawn(pid_t process, void* function) {
|
||||||
.ss = GDT_SELECTOR_KERNEL_DATA
|
.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));
|
thread->state = thread->stack + (thread->stack_size - sizeof(cpu_state_T));
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
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);
|
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);
|
thread->process = scheduler_get_process(process);
|
||||||
if (thread->process == NULL) {
|
if (thread->process == NULL) {
|
||||||
|
memory_free(thread);
|
||||||
log(LOG_WARNING, "<Thread> failed to spawn thread for process %d (invalid pid)", process);
|
log(LOG_WARNING, "<Thread> failed to spawn thread for process %d (invalid pid)", process);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -109,11 +121,15 @@ void thread_pause(thread_T* thread) {
|
||||||
void thread_kill(thread_T* thread) {
|
void thread_kill(thread_T* thread) {
|
||||||
scheduler_kill_thread(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) {
|
if (thread->stack != NULL) {
|
||||||
for (int i = 0; i < 4; i++) {
|
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);
|
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue