Browse Source

begin scheduler

master
Mathieu Serandour 1 year ago
parent
commit
2e532e1de7
  1. 73
      kernel/sched/process.c
  2. 51
      kernel/sched/process.h
  3. 45
      kernel/sched/restore_context.s
  4. 31
      kernel/sched/sched.c
  5. 23
      kernel/sched/sched.h
  6. 30
      kernel/sched/thread.c
  7. 68
      kernel/sched/thread.h

73
kernel/sched/process.c

@ -0,0 +1,73 @@
#include "../lib/assert.h"
#include "../memory/heap.h"
#include "../memory/vmap.h"
#include "../memory/paging.h"
#include "sched.h"
#define FIRST_TID 1
#define STACK_SIZE 256*1024
// return stack base
// we suppose that the process is already mapped
// we find a stack address by polling user top memory
static void* alloc_stack(process_t* process) {
// @todo this doesnt work with more than 1 thread
void* base = (void*)USER_END + 1 - STACK_SIZE;
(void) process;
alloc_pages(
base,
STACK_SIZE >> 12,
PRESENT_ENTRY | PL_XD
);
return base;
}
int create_process(process_t* process, const void* elffile, size_t elffile_sz) {
elf_program_t* program = elf_load(elffile, elffile_sz);
if(!program)
return 0;
thread_t* threads = malloc(sizeof(thread_t));
pid_t pid = alloc_pid();
assert(process);
create_thread(
&threads[0],
pid,
alloc_stack(process),
STACK_SIZE,
FIRST_TID
);
threads[0].regs.rip = program->entry;
*process = (process_t) {
.files = NULL,
.n_files = 0,
.n_threads = 1,
.threads = threads,
.page_dir_paddr = 0,
.pid = pid,
.ppid = KERNEL_PID,
.program = program,
};
return 1;
}
void free_process(process_t* process) {
assert(process);
}

51
kernel/sched/process.h

@ -0,0 +1,51 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "../lib/elf/elf.h"
#include "../fs/vfs.h"
// this file describes what are processes
typedef int pid_t;
typedef struct process {
pid_t pid;
pid_t ppid;
uint64_t page_dir_paddr;
size_t n_threads;
struct thread* threads;
elf_program_t* program;
size_t n_files;
file_handle_t** files;
} process_t;
/**
* @brief create a process with a given elf file
* the elf file is not borrowed. The caller must
* free it afterwards.
*
* this functions initializes a process with:
* - no opened file
* - single thread executing the elf entry
*
*
* @param process output process structure
* @param elf_file input file
* @return int 0 if failure, non-0 otherwise
*/
int create_process(process_t* process, const void* elffile, size_t elffile_sz);
void free_process(process_t* process);

45
kernel/sched/restore_context.s

@ -0,0 +1,45 @@
[global _restore_context]
; [[noreturn]] restore_context(struct gp_regs*)
;typedef struct gp_regs {
; uint64_t rip;
; uint64_t rbp;
; uint64_t rsp;
; uint64_t rax;
; uint64_t rcx;
; uint64_t rdx;
; uint64_t rbx;
; uint64_t rsi;
; uint64_t rdi;
; uint64_t rflags;
;
;// r8 -> r15
; uint64_t ext[8];
;
;} __attribute__((packed)) gp_regs_t;
_restore_context:
mov rsp, rdi
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbx
pop rdx
pop rcx
pop rax
pop rbp
iretq

31
kernel/sched/sched.c

@ -0,0 +1,31 @@
#include "sched.h"
#include "process.h"
// pid
static pid_t current_pid = KERNEL_PID;
// alloc pids in a circular way
static pid_t last_pid = KERNEL_PID;
gp_regs_t saved;
// defined in restore_context.s
void __attribute__((noreturn)) _restore_context(struct gp_regs*);
void sched_save(gp_regs_t* context) {
saved = *context;
}
void schedule(void) {
//_restore_context(&saved);
}
pid_t alloc_pid(void) {
return ++last_pid;
}

23
kernel/sched/sched.h

@ -0,0 +1,23 @@
#pragma once
#include "thread.h"
#include "process.h"
#define KERNEL_PID ((pid_t)0)
void sched_save(gp_regs_t* context);
// if this function returns, then a fast context restore
// can happen: no need to unmap/map user space memory
void schedule(void);
/**
* return a fresh new pid that
* doesn't overlap with an existing process
* or with a process that just exited
*/
pid_t alloc_pid(void);

30
kernel/sched/thread.c

@ -0,0 +1,30 @@
#include "thread.h"
#include "../lib/registers.h"
#include "../memory/vmap.h"
int create_thread(
thread_t* thread,
pid_t pid,
void* stack_base,
size_t stack_size,
tid_t tid
) {
*thread = (thread_t) {
.pid = pid,
.stack = {
.base = stack_base,
.size = stack_size,
},
.tid = tid,
};
thread->regs.cs = USER_CS;
thread->regs.ss = USER_DS;
thread->regs.rflags = get_rflags();
thread->regs.rbp = 0;
thread[0].regs.rsp = stack_base + stack_size;
return 0;
}

68
kernel/sched/thread.h

@ -0,0 +1,68 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "../lib/assert.h"
#include "process.h"
// this file describes what a thread is
typedef struct stack {
void* base;
size_t size;
} stack_t;
typedef int32_t tid_t;
typedef struct gp_regs {
// r15 -> r8
uint64_t ext[8];
uint64_t rdi;
uint64_t rsi;
uint64_t rbx;
uint64_t rdx;
uint64_t rcx;
uint64_t rbp;
uint64_t rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((packed)) gp_regs_t;
static_assert_equals(sizeof(gp_regs_t), 160);
struct kernel_task {
gp_regs_t* regs;
stack_t stack;
};
typedef
struct thread {
pid_t pid;
tid_t tid;
stack_t stack;
gp_regs_t regs;
} thread_t;
// 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);
Loading…
Cancel
Save