Browse Source

sched wip

master
Mathieu Serandour 6 months ago
parent
commit
00fcbde75f
  1. 125
      kernel/sched/process.c
  2. 56
      kernel/sched/process.h
  3. 22
      kernel/sched/sched.c
  4. 3
      kernel/sched/sched.h
  5. 20
      kernel/sched/thread.c
  6. 7
      kernel/sched/thread.h

125
kernel/sched/process.c

@ -4,6 +4,7 @@
#include "../memory/paging.h"
#include "../lib/logging.h"
#include "../lib/string.h"
#include "../int/apic.h"
#include "sched.h"
@ -28,6 +29,40 @@ static void* alloc_stack(process_t* process) {
}
void dup_fd(file_descriptor_t* fd, file_descriptor_t* new_fd) {
new_fd->type = fd->type;
switch(fd->type) {
case FD_FILE:
new_fd->file = vfs_handle_dup(fd->file);
break;
case FD_DIR:
new_fd->dir = vfs_dir_dup(fd->dir);
new_fd->dir_boff = fd->dir_boff;
break;
default:
assert(0);
}
}
void close_fd(file_descriptor_t* fd) {
switch(fd->type) {
case FD_FILE:
vfs_close_file(fd->file);
break;
case FD_DIR:
vfs_closedir(fd->dir);
break;
default:
assert(0);
}
fd->type = FD_NONE;
}
int create_process(process_t* process, process_t* pparent, const void* elffile, size_t elffile_sz) {
// assert that no userspace is mapped
@ -46,9 +81,9 @@ int create_process(process_t* process, process_t* pparent, const void* elffile,
pid_t ppid = KERNEL_PID;
file_handle_t** files = NULL;
file_descriptor_t* fds = NULL;
files = malloc(sizeof(file_handle_t*) * MAX_FDS);
fds = malloc(sizeof(file_descriptor_t*) * MAX_FDS);
if(pparent) {
// inherit parent file handlers
@ -56,12 +91,23 @@ int create_process(process_t* process, process_t* pparent, const void* elffile,
for(unsigned i = 0; i < MAX_FDS; i++) {
if(pparent->files[i])
files[i] = vfs_clone_handle(pparent->files[i]);
dup_fd(pparent->fds + i, fds + i);
}
// inherit parent directory
process->cwd = strdup(pparent->cwd);
}
else {
// empty file handlers
for(unsigned i = 0; i < MAX_FDS; i++) {
fds[i].type = FD_NONE;
fds[i].file = NULL;
}
//memset(fds, 0, sizeof(file_descriptor_t*) * MAX_FDS);
// root directory
process->cwd = strdup("/");
}
else
memset(files, 0, sizeof(file_handle_t*) * MAX_FDS);
thread_t* threads = malloc(sizeof(thread_t));
@ -93,23 +139,23 @@ int create_process(process_t* process, process_t* pparent, const void* elffile,
elf_end = segment_end;
}
// empty heap
process->brk = process->unaligned_brk = process->heap_begin =
(void *)(((uint64_t)elf_end+0xfff) & ~0x0fffllu);
*process = (process_t) {
.files = files,
.fds = fds,
.n_threads = 1,
.threads = threads,
.page_dir_paddr = user_page_map,
.pid = pid,
.ppid = ppid,
.program = program,
.clock_begin = clock_ns()
};
// empty heap
process->brk = process->unaligned_brk = process->heap_begin =
(void *)(((uint64_t)elf_end+0xfff) & ~0x0fffllu);
return 1;
}
@ -120,11 +166,10 @@ void free_process(process_t* process) {
assert(!process->n_threads);
for(unsigned i = 0; i < MAX_FDS; i++) {
if(process->files)
vfs_close_file(process->files[i]);
close_fd(process->fds + i);
}
free(process->files);
free(process->fds);
if(process->threads)
@ -136,3 +181,51 @@ void free_process(process_t* process) {
free(process);
}
int replace_process(process_t* process, void* elffile, size_t elffile_sz) {
// assert that the process is already mapped
assert(get_user_page_map() == process->page_dir_paddr);
unmap_user();
free_user_page_map(process->page_dir_paddr);
// only one thread
process->threads = realloc(process->threads, sizeof(thread_t));
int r = create_thread(
&process->threads[0],
process->pid,
alloc_stack(process),
STACK_SIZE,
FIRST_TID
);
assert(!r);
// load program
elf_program_t* program = elf_load(elffile, elffile_sz);
// choose an emplacement for heap base
// choose it above the highest elf
// segment's end
void* elf_end = NULL;
for(unsigned i = 0; i < program->n_segs; i++) {
void* segment_end = program->segs[i].base + program->segs[i].length;
if((uint64_t)elf_end < (uint64_t)segment_end)
elf_end = segment_end;
}
// empty heap
process->brk = process->unaligned_brk = process->heap_begin =
(void *)(((uint64_t)elf_end+0xfff) & ~0x0fffllu);
process->threads[0].rsp->rip = (uint64_t)program->entry;
return 0;
}

56
kernel/sched/process.h

@ -15,7 +15,31 @@ typedef unsigned fd_t;
#define MAX_FDS 32
#define FD_NONE 0
#define FD_FILE 1
#define FD_DIR 2
typedef struct file_descriptor {
/*
either one of these
- FD_NONE
- FD_FILE
- FD_DIR
*/
int type;
union {
file_handle_t* file;
struct {
struct DIR* dir;
/**
* current byte offset of the directory stream
*/
size_t dir_boff;
};
};
} file_descriptor_t;
typedef struct process {
pid_t pid;
@ -30,6 +54,10 @@ typedef struct process {
elf_program_t* program;
// the instant of the creation of the
// process
uint64_t clock_begin;
void* heap_begin;
void* brk;
@ -37,8 +65,12 @@ typedef struct process {
// brk as seen by processes
void* unaligned_brk;
char* cwd;
// size [MAX_FDS]
file_handle_t** files;
file_descriptor_t* fds;
} process_t;
@ -72,4 +104,24 @@ int create_process(process_t* process, process_t* pparent, const void* elffile,
void free_process(process_t* process);
int replace_process(process_t* process, void* elffile, size_t elffile_sz);
/**
* closes the fd
* replaces its type with FD_NONE
* and calls the right close
* function
*
* @param fd
*/
void close_fd(file_descriptor_t* fd);
/**
* duplicates fd to new_fd
*
* sets new_fd's fields
*
*/
void dup_fd(file_descriptor_t* fd, file_descriptor_t* new_fd);

22
kernel/sched/sched.c

@ -1,6 +1,7 @@
#include "sched.h"
#include "process.h"
#include "../int/idt.h"
#include "../int/apic.h"
#include "../lib/logging.h"
#include "../memory/vmap.h"
#include "../memory/heap.h"
@ -46,6 +47,20 @@ static size_t n_threads = 0;
static process_t* processes;
/**
* when invoking a syscall,
* syscall_stacks[lapic_id] should contain
* the stack pointer of the current thread
* executing on the CPU with the given lapic_id
*/
void** syscall_stacks;
void sched_init(void) {
// init syscall stacks
syscall_stacks = malloc(sizeof(void*) * get_smp_count());
}
/**
* @brief alloc a process in the processes list
@ -81,10 +96,12 @@ static
thread_t* get_thread_by_tid(process_t* process, tid_t tid) {
// sequencial research
for(unsigned i = 0; i < process->n_threads; i++)
for(unsigned i = 0; i < process->n_threads; i++) {
if(process->threads[i].tid == tid)
return &process->threads[i];
}
return NULL;
}
@ -148,6 +165,7 @@ void sched_save(gp_regs_t* rsp) {
process_t* p = sched_get_process(current_pid);
assert(p);
thread_t* t = get_thread_by_tid(p, current_tid);
assert(t);
t->rsp = rsp;
}
@ -183,6 +201,8 @@ void schedule(void) {
current_pid = p->pid;
current_tid = t->tid;
syscall_stacks[get_lapic_id()] = (void*) t->kernel_stack.base + t->kernel_stack.size;
_restore_context(t->rsp);
}

3
kernel/sched/sched.h

@ -9,6 +9,9 @@
void sched_save(gp_regs_t* context);
void sched_init(void);
// if this function returns, then a fast context restore
// can happen: no need to unmap/map user space memory
void schedule(void);

20
kernel/sched/thread.c

@ -1,6 +1,7 @@
#include "thread.h"
#include "../lib/registers.h"
#include "../memory/vmap.h"
#include "../memory/heap.h"
int create_thread(
thread_t* thread,
@ -18,17 +19,32 @@ int create_thread(
.tid = tid,
};
thread->rsp = stack_base + stack_size - sizeof(gp_regs_t);
// set the stack frame
*(uint64_t*)stack_base = 0;
*((uint64_t*)stack_base + 1) = 0;
thread->rsp = stack_base + stack_size - sizeof(gp_regs_t) - 16;
thread->rsp->cs = USER_CS;
thread->rsp->ss = USER_DS;
thread->rsp->rflags = get_rflags();
thread->rsp->rbp = 0;
thread->rsp->rbp = (uint64_t)(stack_base - 8);
thread->rsp->rsp = (uint64_t)stack_base + stack_size;
thread->kernel_stack = (stack_t) {
.base = malloc(THREAD_KERNEL_STACK_SIZE),
.size = THREAD_KERNEL_STACK_SIZE,
};
thread->type = READY;
return 0;
}
void free_thread(thread_t* thread) {
free(thread->kernel_stack.base);
}

7
kernel/sched/thread.h

@ -64,6 +64,8 @@ struct thread {
tid_t tid;
stack_t kernel_stack;
stack_t stack;
gp_regs_t* rsp;
@ -71,7 +73,12 @@ struct thread {
} thread_t;
#define THREAD_KERNEL_STACK_SIZE (1024 * 16)
// 0 if the thread cannot be created
int create_thread(thread_t* thread, pid_t pid, void* stack_base, size_t stacs_size, tid_t);
void free_thread(thread_t* thread);

Loading…
Cancel
Save