Add sys_exit() and fix problem with %rax getting clobbered
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "sys/thread.h"
|
||||
|
||||
void sched_add(struct thread *t);
|
||||
void sched_init(void);
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -12,6 +12,7 @@ usr_CFLAGS=-ffreestanding \
|
||||
-mno-sse \
|
||||
-mno-sse2 \
|
||||
-Ilibc/include \
|
||||
-O0 \
|
||||
-I$(S)/include
|
||||
usr_LDFLAGS=-nostdlib \
|
||||
-lgcc \
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user