Add sys_exit() and fix problem with %rax getting clobbered

This commit is contained in:
Mark
2019-10-29 11:29:08 +02:00
parent 5a3b8621bc
commit b846ee2ad4
10 changed files with 115 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "sys/thread.h"
void sched_add(struct thread *t);
void sched_init(void);
+3
View File
@@ -3,6 +3,7 @@
#include "sys/fs/vfs.h"
#define THREAD_KERNEL (1 << 31)
#define THREAD_STOPPED (1 << 2)
#if defined(ARCH_AMD64)
typedef uint64_t *mm_space_t;
@@ -22,6 +23,8 @@ struct thread {
mm_space_t space;
// TODO: maybe __sched_thread
int cpu;
struct thread *prev;
struct thread *next;
};
+1 -1
View File
@@ -17,6 +17,7 @@
#include "sys/fs/vfs.h"
#include "sys/blk/ram.h"
#include "sys/fs/tar.h"
#include "sys/sched.h"
#include "sys/tty.h"
static multiboot_info_t *multiboot_info;
@@ -37,7 +38,6 @@ void kernel_main(struct amd64_loader_data *data) {
amd64_mm_init(data);
amd64_acpi_init();
extern void sched_init(void);
sched_init();
amd64_apic_init();
rtc_init();
+55 -1
View File
@@ -126,6 +126,12 @@ void init_func(void *arg) {
}
}
static uint32_t sched_alloc_pid(void) {
// The first pid allocation will be 1 (init process)
static uint32_t last_pid = 1;
return last_pid++;
}
void sched_add_to(int cpu, struct thread *t) {
t->next = NULL;
@@ -135,6 +141,14 @@ void sched_add_to(int cpu, struct thread *t) {
} else {
sched_queue_heads[cpu] = t;
}
t->prev = sched_queue_tails[cpu];
t->cpu = cpu;
if (!(t->flags & THREAD_KERNEL)) {
t->pid = sched_alloc_pid();
} else {
t->pid = 0;
}
sched_queue_tails[cpu] = t;
++sched_queue_sizes[cpu];
spin_release(&sched_lock);
@@ -187,12 +201,52 @@ void sched_init(void) {
int sched(void) {
struct thread *from = get_cpu()->thread;
struct thread *to;
int cpu = get_cpu()->processor_id;
spin_lock(&sched_lock);
// Cleanup stopped tasks
// TODO: this won't be needed if I call sched_remove directly
to = sched_queue_heads[cpu];
while (to) {
if (to->flags & THREAD_STOPPED) {
// So we don't remove [idle]
_assert(to != sched_queue_heads[cpu]);
kdebug("(cpu%d) Removing %u from queue\n", cpu, to->pid);
if (to->pid == 1) {
panic("init process was killed\n");
}
struct thread *prev, *next;
prev = to->prev;
next = to->next;
_assert(prev);
prev->next = next;
if (next) {
next->prev = prev;
} else {
sched_queue_tails[cpu] = prev;
}
// TODO: free the task?
if (to == from) {
// Removing current thread
from = NULL;
}
if (!next) {
break;
}
}
to = to->next;
}
if (from && from->next) {
to = from->next;
} else {
to = sched_queue_heads[get_cpu()->processor_id];
to = sched_queue_heads[cpu];
}
spin_release(&sched_lock);
+17
View File
@@ -7,6 +7,7 @@
static ssize_t sys_read(int fd, void *buf, size_t lim);
static ssize_t sys_write(int fd, const void *buf, size_t lim);
static void sys_exit(int status);
uint8_t irq1_key = 0;
@@ -16,7 +17,16 @@ intptr_t amd64_syscall(uintptr_t rdi, uintptr_t rsi, uintptr_t rdx, uintptr_t rc
return sys_read((int) rdi, (void *) rsi, (size_t) rdx);
case 1:
return sys_write((int) rdi, (const void *) rsi, (size_t) rdx);
case 60:
sys_exit((int) rdi);
// TODO: call sched_remove and reschedule a new task so that
// this one does not return
asm volatile ("sti; hlt");
panic("This should not happen\n");
// WTF?
return -1;
default:
kdebug("unknown syscall: %u\n", rax);
return -1;
}
return 0;
@@ -38,6 +48,13 @@ static ssize_t sys_read(int fd, void *buf, size_t lim) {
return vfs_read(&thr->ioctx, of, buf, lim);
}
static void sys_exit(int status) {
struct thread *thr = get_cpu()->thread;
_assert(thr);
kdebug("%u exited with code %d\n", thr->pid, status);
thr->flags |= THREAD_STOPPED;
}
static ssize_t sys_write(int fd, const void *buf, size_t lim) {
if (fd >= 4 || fd < 0) {
return -EBADF;
+1
View File
@@ -12,6 +12,7 @@ usr_CFLAGS=-ffreestanding \
-mno-sse \
-mno-sse2 \
-Ilibc/include \
-O0 \
-I$(S)/include
usr_LDFLAGS=-nostdlib \
-lgcc \
+7
View File
@@ -8,10 +8,17 @@ int main(int argc, char **argv) {
ssize_t sz = read(STDIN_FILENO, &c, 1);
if (sz >= 0) {
if (c == '\n') {
break;
}
write(STDOUT_FILENO, "Char: ", 6);
write(STDOUT_FILENO, &c, 1);
c = '\n';
write(STDOUT_FILENO, &c, 1);
}
}
write(STDOUT_FILENO, "Enter\n", 6);
return 0;
}
+3 -4
View File
@@ -16,9 +16,8 @@ _start:
// Ignore %rdi/%rsi for now
xorq %rdi, %rdi
// exit(main(argc, argv))
call main
// I haven't implemented exit() yet
xorq %rdi, %rdi
jmp *%rdi
movq %rax, %rdi
call exit
.size _start, . - _start
+1
View File
@@ -3,3 +3,4 @@
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
__attribute__((noreturn)) void exit(int code);
+22 -2
View File
@@ -3,12 +3,27 @@
#define ASM_REGISTER(name) \
register uint64_t name asm (#name)
#define ASM_SYSCALL3(r0, r1, r2, r3) ({ \
#define ASM_SYSCALL1(r0, r1) ({ \
ASM_REGISTER(rdi) = (uint64_t) (r1); \
/*
* Should be the last one because memory accesses for arguments
* fuck up %rax
*/ \
ASM_REGISTER(rax) = (uint64_t) (r0); \
asm volatile ("syscall":::"memory"); \
rax; \
})
#define ASM_SYSCALL3(r0, r1, r2, r3) ({ \
ASM_REGISTER(rdi) = (uint64_t) (r1); \
ASM_REGISTER(rsi) = (uint64_t) (r2); \
ASM_REGISTER(rdx) = (uint64_t) (r3); \
asm volatile ("syscall":::"memory"); \
/*
* Should be the last one because memory accesses for arguments
* fuck up %rax
*/ \
ASM_REGISTER(rax) = (uint64_t) (r0); \
asm volatile ("syscall":::"memory", "rax", "rdi", "rsi", "rdx"); \
rax; \
})
@@ -19,3 +34,8 @@ ssize_t write(int fd, const void *buf, size_t count) {
ssize_t read(int fd, void *buf, size_t count) {
return (ssize_t) ASM_SYSCALL3(0, fd, buf, count);
}
__attribute__((noreturn)) void exit(int code) {
(void) ASM_SYSCALL1(60, code);
while (1);
}