Initial kthread implementation
This commit is contained in:
parent
5141044c06
commit
2c0f54926d
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ CPPFLAGS += $(foreach dir, $(SUBDIRS), -I$(dir))
|
||||
asmsrc=$(wildcard *.asm)
|
||||
asmobj=$(asmsrc:%.asm=%.o)
|
||||
csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c)
|
||||
cobj=$(csrc:%.c=%.o) core/cpu_context_switch.o
|
||||
cobj=$(csrc:%.c=%.o) core/cpu_context_switch.o core/irq_pit.o
|
||||
deps = $(csrc:%.c=%.d)
|
||||
|
||||
kernel:$(asmobj) $(cobj) linker.ld
|
||||
|
@ -12,8 +12,8 @@ cpu_context_switch:
|
||||
pushf // (eflags) esp+56
|
||||
pushl %cs // (cs) esp+52
|
||||
pushl $resume_pc // (ip) esp+48
|
||||
pushl $0 // (error code) esp+44
|
||||
pushal // (general reg) esp+12+8*4
|
||||
pushl $0 // (error code) esp+12+8x4
|
||||
pushal // (general reg) esp+12
|
||||
subl $2, %esp // (alignment) esp+10
|
||||
pushw %ss // esp+8
|
||||
pushw %ds // esp+6
|
||||
|
@ -16,6 +16,7 @@ void print_handler(struct interrupt_frame *frame, ulong error_code);
|
||||
void pagefault_handler(struct interrupt_frame *frame, ulong error_code);
|
||||
|
||||
// IRQ
|
||||
void pit_handler(struct interrupt_frame *frame);
|
||||
void keyboard_handler(struct interrupt_frame *frame);
|
||||
void timer_handler(struct interrupt_frame *frame);
|
||||
void serial_handler(struct interrupt_frame *frame);
|
||||
|
38
core/irq_pit.S
Normal file
38
core/irq_pit.S
Normal file
@ -0,0 +1,38 @@
|
||||
.file "irq_pit.S"
|
||||
|
||||
.text
|
||||
|
||||
.extern selectNextThread
|
||||
|
||||
.globl pit_handler
|
||||
.type pit_handler, @function
|
||||
pit_handler: // already got eflags, cs and eip on stack thanks to CPU
|
||||
pushl $0 // err_code esp+12+8*4=44
|
||||
pushal // (general reg) esp+12
|
||||
subl $2, %esp // (alignment) esp+10
|
||||
pushw %ss // esp+8
|
||||
pushw %ds // esp+6
|
||||
pushw %es // esp+4
|
||||
pushw %fs // esp+2
|
||||
pushw %gs // esp
|
||||
|
||||
/* Send EOI to PIC */
|
||||
movb $0x20, %al
|
||||
outb %al, $0x20
|
||||
|
||||
pushl %esp
|
||||
call selectNextThread
|
||||
movl %eax,%esp
|
||||
|
||||
/* Restore the CPU context */
|
||||
popw %gs
|
||||
popw %fs
|
||||
popw %es
|
||||
popw %ds
|
||||
popw %ss
|
||||
addl $2,%esp
|
||||
popal
|
||||
addl $4, %esp /* Ignore "error code" */
|
||||
|
||||
/* This restores the eflags, the cs and the eip registers */
|
||||
iret /* equivalent to: popfl ; ret */
|
34
core/klibc.c
34
core/klibc.c
@ -80,7 +80,7 @@ void reverse(char s[])
|
||||
}
|
||||
|
||||
/* K&R */
|
||||
int strlen(char s[])
|
||||
int strlen(const char s[])
|
||||
{
|
||||
int i = 0;
|
||||
while (s[i] != '\0')
|
||||
@ -90,7 +90,7 @@ int strlen(char s[])
|
||||
|
||||
/* K&R
|
||||
* Returns <0 if s1<s2, 0 if s1==s2, >0 if s1>s2 */
|
||||
int strcmp(char s1[], char s2[])
|
||||
int strcmp(const char s1[], const char s2[])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; s1[i] == s2[i]; i++) {
|
||||
@ -100,6 +100,33 @@ int strcmp(char s1[], char s2[])
|
||||
return s1[i] - s2[i];
|
||||
}
|
||||
|
||||
unsigned int strnlen(const char *s, size_t count)
|
||||
{
|
||||
const char *sc;
|
||||
|
||||
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||
/* nothing */ continue;
|
||||
|
||||
return sc - s;
|
||||
}
|
||||
|
||||
char *strzcpy(register char *dst, register const char *src, register int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len <= 0)
|
||||
return dst;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
dst[i] = src[i];
|
||||
if (src[i] == '\0')
|
||||
return dst;
|
||||
}
|
||||
|
||||
dst[len - 1] = '\0';
|
||||
return dst;
|
||||
}
|
||||
|
||||
void printf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -115,7 +142,8 @@ void puts(const char *str)
|
||||
}
|
||||
}
|
||||
|
||||
void putc(const char str){
|
||||
void putc(const char str)
|
||||
{
|
||||
VGAputc(str);
|
||||
serialPutc(str);
|
||||
}
|
||||
|
@ -14,8 +14,10 @@ void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
char *itoa(int value, char *str, int base);
|
||||
void reverse(char s[]);
|
||||
int strlen(char s[]);
|
||||
int strcmp(char s1[], char s2[]);
|
||||
int strlen(const char s[]);
|
||||
unsigned int strnlen(const char * s, size_t count);
|
||||
int strcmp(const char s1[], const char s2[]);
|
||||
char *strzcpy(char *dst, const char *src, int len);
|
||||
void puts(const char *str);
|
||||
void putc(const char str);
|
||||
void printInt(int integer);
|
||||
|
67
core/kthread.c
Normal file
67
core/kthread.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "kthread.h"
|
||||
#include "list.h"
|
||||
#include "alloc.h"
|
||||
#include "klibc.h"
|
||||
|
||||
static struct kthread *currentThread;
|
||||
|
||||
void _kthread_exit(){
|
||||
//TODO
|
||||
return;
|
||||
}
|
||||
|
||||
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize){
|
||||
struct kthread * current = (struct kthread *)malloc(sizeof(struct kthread));
|
||||
strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH);
|
||||
current->stackAddr = mainStack;
|
||||
current->stackSize = mainStackSize;
|
||||
|
||||
list_singleton(currentThread, current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct kthread *createKthread(const char *name, cpu_kstate_function_arg1_t func,
|
||||
void *args)
|
||||
{
|
||||
struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread));
|
||||
if (!thread)
|
||||
return NULL;
|
||||
|
||||
thread->stackAddr = (vaddr_t) malloc(KTHREAD_DEFAULT_STACK_SIZE);
|
||||
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
|
||||
|
||||
if(!thread->stackAddr)
|
||||
goto free_mem;
|
||||
|
||||
if(name)
|
||||
strzcpy(thread->name, name, KTHREAD_NAME_MAX_LENGTH);
|
||||
else
|
||||
strzcpy(thread->name, "[UNKNOW]", KTHREAD_NAME_MAX_LENGTH);
|
||||
|
||||
if(cpu_kstate_init(&thread->cpuState, (cpu_kstate_function_arg1_t *)func, (vaddr_t)args,
|
||||
thread->stackAddr, thread->stackSize,
|
||||
(cpu_kstate_function_arg1_t *)_kthread_exit, 0))
|
||||
goto free_mem;
|
||||
|
||||
list_add_tail(currentThread, thread);
|
||||
return thread;
|
||||
free_mem:
|
||||
free((void *)thread->stackAddr);
|
||||
free((void *)thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void deleteKthread(struct kthread *thread){
|
||||
list_delete(currentThread, thread);
|
||||
|
||||
free((void *)thread->stackAddr);
|
||||
free((void *)thread);
|
||||
}
|
||||
|
||||
struct cpu_state *selectNextThread(struct cpu_state *prevCpu){
|
||||
currentThread->cpuState = prevCpu;
|
||||
struct kthread *nextThread = currentThread->next;
|
||||
currentThread = nextThread;
|
||||
return nextThread->cpuState;
|
||||
}
|
26
core/kthread.h
Normal file
26
core/kthread.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "cpu_context.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define KTHREAD_NAME_MAX_LENGTH 32
|
||||
#define KTHREAD_DEFAULT_STACK_SIZE PAGE_SIZE
|
||||
|
||||
struct kthread {
|
||||
char name[KTHREAD_NAME_MAX_LENGTH];
|
||||
struct cpu_state *cpuState;
|
||||
vaddr_t stackAddr;
|
||||
size_t stackSize;
|
||||
struct kthread *next;
|
||||
struct kthread *prev;
|
||||
};
|
||||
|
||||
|
||||
int kthreadSetup(vaddr_t mainStack, size_t mainStackSize);
|
||||
|
||||
struct kthread *createKthread(const char *name, cpu_kstate_function_arg1_t func,
|
||||
void *args);
|
||||
|
||||
void deleteKthread(struct kthread *thread);
|
||||
|
||||
struct cpu_state *selectNextThread(struct cpu_state *prev_cpu);
|
19
core/main.c
19
core/main.c
@ -6,11 +6,13 @@
|
||||
#include "io.h"
|
||||
#include "irq.h"
|
||||
#include "klibc.h"
|
||||
#include "kthread.h"
|
||||
#include "mem.h"
|
||||
#include "multiboot.h"
|
||||
#include "paging.h"
|
||||
#include "pit.h"
|
||||
#include "serial.h"
|
||||
#include "stack.h"
|
||||
#include "stdarg.h"
|
||||
#ifdef RUN_TEST
|
||||
#include "test.h"
|
||||
@ -24,6 +26,18 @@ void cpuid(int code, uint32_t *a, uint32_t *d)
|
||||
asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx");
|
||||
}
|
||||
|
||||
void idleThread(void *arg){
|
||||
(void)arg;
|
||||
while(1)
|
||||
printf(".");
|
||||
}
|
||||
|
||||
void dashThread(void *arg){
|
||||
(void)arg;
|
||||
while(1)
|
||||
printf("-");
|
||||
}
|
||||
|
||||
// Multiboot information available here :
|
||||
// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec
|
||||
// https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format
|
||||
@ -99,7 +113,6 @@ void kmain(unsigned long magic, unsigned long addr)
|
||||
|
||||
printf("Setting up IRQ handlers\n");
|
||||
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
||||
irqSetRoutine(IRQ_TIMER, timer_handler);
|
||||
|
||||
printf("Enabling HW interrupts\n");
|
||||
exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, print_handler);
|
||||
@ -110,6 +123,10 @@ void kmain(unsigned long magic, unsigned long addr)
|
||||
printf("Setting up Serial link (115200)\n");
|
||||
serialSetup(115200);
|
||||
allocInit();
|
||||
kthreadSetup(_stack_bottom, (_stack_top - _stack_bottom + 1));
|
||||
createKthread("idle", idleThread, NULL);
|
||||
createKthread("dash", dashThread, NULL);
|
||||
irqSetRoutine(IRQ_TIMER, pit_handler);
|
||||
#ifdef RUN_TEST
|
||||
run_test();
|
||||
#endif
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include "types.h"
|
||||
#include "klibc.h"
|
||||
|
||||
extern vaddr_t _stack_bottom;
|
||||
extern vaddr_t _stack_top;
|
||||
void printStackTrace(unsigned int maxFrames)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -1,3 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
extern vaddr_t _stack_bottom;
|
||||
extern vaddr_t _stack_top;
|
||||
void printStackTrace(unsigned int maxFrame);
|
||||
|
Loading…
Reference in New Issue
Block a user