Scheduler and multiple threads
This commit is contained in:
parent
9a68961a64
commit
576a32d92f
38
src/kernel/boot/TEMP-test_scheduler.c
Normal file
38
src/kernel/boot/TEMP-test_scheduler.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <framebuffer.h>
|
||||||
|
#include <proc.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
extern gfx_context *term_fb;
|
||||||
|
void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void thread1()
|
||||||
|
{
|
||||||
|
int a = 0;
|
||||||
|
while(1) {
|
||||||
|
drawCharacter(term_fb, 0, 0, RGB(255,0,0), RGB(0,0,0), '0'+(a++%10));
|
||||||
|
flip(term_fb);
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread2()
|
||||||
|
{
|
||||||
|
int a = 0;
|
||||||
|
while(1) {
|
||||||
|
drawCharacter(term_fb, 10, 10, RGB(0,0,255), RGB(0,0,0), 'A'+(a++%10));
|
||||||
|
flip(term_fb);
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TEMP_test_scheduler()
|
||||||
|
{
|
||||||
|
struct thread *th1 = new_thread(thread1);
|
||||||
|
scheduler_insert(th1);
|
||||||
|
|
||||||
|
struct thread *th2 = new_thread(thread2);
|
||||||
|
scheduler_insert(th2);
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <proc.h>
|
#include <proc.h>
|
||||||
|
|
||||||
|
void TEMP_test_scheduler();
|
||||||
|
|
||||||
struct kernel_boot_data_st kernel_boot_data;
|
struct kernel_boot_data_st kernel_boot_data;
|
||||||
|
|
||||||
@ -30,6 +31,10 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data)
|
|||||||
|
|
||||||
debug_info("Boot complete\n");
|
debug_info("Boot complete\n");
|
||||||
|
|
||||||
|
|
||||||
|
TEMP_test_scheduler();
|
||||||
|
|
||||||
|
|
||||||
start_scheduler();
|
start_scheduler();
|
||||||
|
|
||||||
PANIC("End of kernel function!");
|
PANIC("End of kernel function!");
|
||||||
|
@ -105,7 +105,7 @@ char font[95][16] = {
|
|||||||
gfx_context *term_fb;
|
gfx_context *term_fb;
|
||||||
static int setup = 0;
|
static int setup = 0;
|
||||||
|
|
||||||
static void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c)
|
void drawCharacter(gfx_context *ctx, uint64_t x, uint64_t y, uint32_t clr_fg, uint32_t clr_bg, char c)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *chr = c ? font[(int)c-0x20]: font[0];
|
char *chr = c ? font[(int)c-0x20]: font[0];
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#define SYSCALL_BRK 12
|
#define SYSCALL_BRK 12
|
||||||
#define SYSCALL_IOCTL 16
|
#define SYSCALL_IOCTL 16
|
||||||
#define SYSCALL_WRITEV 20
|
#define SYSCALL_WRITEV 20
|
||||||
|
#define SYSCALL_SCHED_YIELD 24
|
||||||
|
|
||||||
typedef long (*syscall_handler)(long, long, long, long, long, long);
|
typedef long (*syscall_handler)(long, long, long, long, long, long);
|
||||||
|
|
||||||
@ -15,3 +16,6 @@ long k_writev(long fd, long iov, long iovcnt, long, long, long);
|
|||||||
|
|
||||||
// memory/kbrk.c
|
// memory/kbrk.c
|
||||||
long k_brk(long brk, long, long, long, long, long);
|
long k_brk(long brk, long, long, long, long, long);
|
||||||
|
|
||||||
|
// proc/scheduler.c
|
||||||
|
long k_sched_yield(long, long, long, long, long, long);
|
@ -5,12 +5,21 @@ struct thread
|
|||||||
{
|
{
|
||||||
struct thread *q_next;
|
struct thread *q_next;
|
||||||
uint64_t tid;
|
uint64_t tid;
|
||||||
void *stack;
|
void *stack_ptr;
|
||||||
uint64_t state;
|
uint64_t state;
|
||||||
|
uint8_t stack[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// proc/thread.c
|
||||||
|
extern struct thread *current_thread;
|
||||||
|
|
||||||
// proc/swtch.S
|
// proc/swtch.S
|
||||||
void *switch_stack(void *out, void *in);
|
void *switch_stack(void *out, void *in);
|
||||||
|
|
||||||
// proc/thread.c
|
// proc/thread.c
|
||||||
|
struct thread *new_thread(void (*function)(void));
|
||||||
|
struct thread *thread();
|
||||||
|
|
||||||
|
// proc/scheduler.c
|
||||||
|
void scheduler_insert(struct thread *new);
|
||||||
void start_scheduler();
|
void start_scheduler();
|
@ -2,9 +2,10 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
syscall_handler syscall_handlers[440] = {
|
syscall_handler syscall_handlers[440] = {
|
||||||
[SYSCALL_BRK] = &k_brk,
|
[SYSCALL_BRK] = k_brk,
|
||||||
[SYSCALL_IOCTL] = &k_ioctl,
|
[SYSCALL_IOCTL] = k_ioctl,
|
||||||
[SYSCALL_WRITEV] = &k_writev,
|
[SYSCALL_WRITEV] = k_writev,
|
||||||
|
[SYSCALL_SCHED_YIELD] = k_sched_yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
syscall_handler set_syscall_handler(long num, syscall_handler handler)
|
syscall_handler set_syscall_handler(long num, syscall_handler handler)
|
||||||
|
57
src/kernel/proc/scheduler.c
Normal file
57
src/kernel/proc/scheduler.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <proc.h>
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct thread *first;
|
||||||
|
struct thread *last;
|
||||||
|
} run_q = {0,0};
|
||||||
|
|
||||||
|
static struct thread *scheduler_thread;
|
||||||
|
|
||||||
|
static struct thread *scheduler_next()
|
||||||
|
{
|
||||||
|
struct thread *ret = run_q.first;
|
||||||
|
if(run_q.first && !(run_q.first = run_q.first->q_next))
|
||||||
|
run_q.last = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler_insert(struct thread *new)
|
||||||
|
{
|
||||||
|
if(run_q.last) {
|
||||||
|
run_q.last->q_next = new;
|
||||||
|
run_q.last = new;
|
||||||
|
} else {
|
||||||
|
run_q.first = run_q.last = new;
|
||||||
|
}
|
||||||
|
new->q_next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler()
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
struct thread *new = 0;
|
||||||
|
while(!(new = scheduler_next()));
|
||||||
|
|
||||||
|
current_thread = new;
|
||||||
|
switch_stack(&scheduler_thread->stack_ptr, &new->stack_ptr);
|
||||||
|
|
||||||
|
scheduler_insert(current_thread);
|
||||||
|
current_thread = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long k_sched_yield(long, long, long, long, long, long)
|
||||||
|
{
|
||||||
|
switch_stack(¤t_thread->stack_ptr, &scheduler_thread->stack_ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_scheduler()
|
||||||
|
{
|
||||||
|
scheduler_thread = new_thread(scheduler);
|
||||||
|
scheduler_thread->tid = (uint64_t)-1;
|
||||||
|
|
||||||
|
uint64_t stack;
|
||||||
|
switch_stack(&stack, &scheduler_thread->stack_ptr);
|
||||||
|
}
|
@ -16,18 +16,16 @@ struct swtch_stack
|
|||||||
|
|
||||||
static uint64_t next_tid = 1;
|
static uint64_t next_tid = 1;
|
||||||
|
|
||||||
static struct thread *run_queue = 0;
|
struct thread *current_thread;
|
||||||
static struct thread *current_thread;
|
|
||||||
static struct thread *scheduler_thread;
|
|
||||||
|
|
||||||
struct thread *new_thread(void (*function)(void))
|
struct thread *new_thread(void (*function)(void))
|
||||||
{
|
{
|
||||||
struct thread *th = P2V(pmm_calloc());
|
struct thread *th = P2V(pmm_calloc());
|
||||||
th->tid = next_tid++;
|
th->tid = next_tid++;
|
||||||
th->stack = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack));
|
th->stack_ptr = incptr(th, PAGE_SIZE - sizeof(struct swtch_stack));
|
||||||
th->q_next = 0;
|
th->q_next = 0;
|
||||||
|
|
||||||
struct swtch_stack *stck = th->stack;
|
struct swtch_stack *stck = th->stack_ptr;
|
||||||
stck->RBP = (uint64_t)&stck->RBP2;
|
stck->RBP = (uint64_t)&stck->RBP2;
|
||||||
stck->ret = (uint64_t)function;
|
stck->ret = (uint64_t)function;
|
||||||
|
|
||||||
@ -38,37 +36,3 @@ struct thread *thread()
|
|||||||
{
|
{
|
||||||
return current_thread;
|
return current_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void k_yield()
|
|
||||||
{
|
|
||||||
switch_stack(¤t_thread->stack, &scheduler_thread->stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct thread *scheduler_next()
|
|
||||||
{
|
|
||||||
if(!current_thread) return run_queue;
|
|
||||||
return current_thread->q_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheduler()
|
|
||||||
{
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
struct thread *new = 0;
|
|
||||||
while(!(new = scheduler_next()));
|
|
||||||
|
|
||||||
current_thread = new;
|
|
||||||
switch_stack(&scheduler_thread->stack, &new->stack);
|
|
||||||
|
|
||||||
current_thread = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_scheduler()
|
|
||||||
{
|
|
||||||
scheduler_thread = new_thread(scheduler);
|
|
||||||
scheduler_thread->tid = (uint64_t)-1;
|
|
||||||
|
|
||||||
uint64_t stack;
|
|
||||||
switch_stack(&stack, &scheduler_thread->stack);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user