wip: thread and processes handle
This commit is contained in:
11
headers/assert.h
Normal file
11
headers/assert.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "kpanic.h"
|
||||||
|
|
||||||
|
#define assert(X) \
|
||||||
|
do { \
|
||||||
|
if (!(X)) { \
|
||||||
|
kpanic("ASSERT_FAIL %s:%u %s\n", __FILE__, __LINE__, \
|
||||||
|
#X); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
@ -9,13 +9,6 @@
|
|||||||
#define PRINT_STR(X) kprintf("%s:%u %s: %s\n", __FILE__, __LINE__, #X, X)
|
#define PRINT_STR(X) kprintf("%s:%u %s: %s\n", __FILE__, __LINE__, #X, X)
|
||||||
#define PRINT_UINT(X) kprintf("%s:%u %s: %u\n", __FILE__, __LINE__, #X, X)
|
#define PRINT_UINT(X) kprintf("%s:%u %s: %u\n", __FILE__, __LINE__, #X, X)
|
||||||
#define PRINT_INT(X) kprintf("%s:%u %s: %d\n", __FILE__, __LINE__, #X, X)
|
#define PRINT_INT(X) kprintf("%s:%u %s: %d\n", __FILE__, __LINE__, #X, X)
|
||||||
#define assert(X) \
|
|
||||||
do { \
|
|
||||||
if (!(X)) { \
|
|
||||||
kpanic("ASSERT_FAIL %s:%u %s\n", __FILE__, __LINE__, \
|
|
||||||
#X); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
struct function_entry {
|
struct function_entry {
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
|
|||||||
25
headers/process.h
Normal file
25
headers/process.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern struct pcb *current_pcb;
|
||||||
|
|
||||||
|
enum owner { OWNER_KERNEL, OWNER_USER };
|
||||||
|
|
||||||
|
struct pcb {
|
||||||
|
void *cr3;
|
||||||
|
uint32_t *heap;
|
||||||
|
uint16_t pid;
|
||||||
|
uint8_t uid;
|
||||||
|
struct signal_data signals;
|
||||||
|
struct pcb *next;
|
||||||
|
struct pcb *prev;
|
||||||
|
struct tcb *thread_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
void switch_process(struct pcb *next_pcb);
|
||||||
|
struct pcb *create_process(uint8_t uid);
|
||||||
|
int8_t create_kernel_process(void);
|
||||||
|
void remove_process(struct pcb *pcb);
|
||||||
3
headers/scheduler.h
Normal file
3
headers/scheduler.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void scheduler(void);
|
||||||
@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "list.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "signal.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern struct task *current_task;
|
|
||||||
|
|
||||||
enum status { ZOMBIE, THREAD, RUN, WAIT, SLEEP, STOPPED, FORKED };
|
|
||||||
enum owner { OWNER_KERNEL, OWNER_USER };
|
|
||||||
|
|
||||||
#define STACK_SIZE PAGE_SIZE * 4
|
|
||||||
|
|
||||||
struct task {
|
|
||||||
uint8_t *esp;
|
|
||||||
uint8_t *esp0;
|
|
||||||
uint32_t *cr3; // physical
|
|
||||||
uint32_t *heap; // virtual
|
|
||||||
uint32_t *eip;
|
|
||||||
uint16_t pid;
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t uid;
|
|
||||||
struct task *daddy;
|
|
||||||
struct task *child;
|
|
||||||
struct signal_data signals;
|
|
||||||
struct task *next;
|
|
||||||
struct task *prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
void scheduler(void);
|
|
||||||
void switch_to_task(struct task *next_task);
|
|
||||||
struct task *create_task(uint8_t uid);
|
|
||||||
int8_t create_kernel_task(void);
|
|
||||||
void remove_task(struct task *task);
|
|
||||||
struct task *copy_task(const struct task *task);
|
|
||||||
void kfork(struct task *daddy);
|
|
||||||
void zombify_task(struct task *task);
|
|
||||||
|
|
||||||
// utils
|
|
||||||
void exec_fn(void (*fn)(void));
|
|
||||||
uint16_t fork(void);
|
|
||||||
uint16_t wait(void);
|
|
||||||
27
headers/thread.h
Normal file
27
headers/thread.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "process.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define STACK_SIZE PAGE_SIZE * 4
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NEW,
|
||||||
|
RUNNING,
|
||||||
|
WAITING,
|
||||||
|
STOPPED,
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
struct tcb {
|
||||||
|
uint8_t *esp;
|
||||||
|
uint8_t *esp0;
|
||||||
|
uint16_t tid;
|
||||||
|
state_t state;
|
||||||
|
struct pcb *process;
|
||||||
|
struct tcb *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tcb *create_thread(struct pcb *process, void (*routine)(void));
|
||||||
|
void delete_thread(struct tcb *thread);
|
||||||
|
void switch_thread(struct tcb *thread_to_switch);
|
||||||
@ -5,8 +5,9 @@
|
|||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "scheduler.h"
|
||||||
#include "sys/io.h"
|
#include "sys/io.h"
|
||||||
#include "task.h"
|
|
||||||
|
|
||||||
#define PIT_CHANNEL0 0x40
|
#define PIT_CHANNEL0 0x40
|
||||||
#define PIT_FREQUENCY 1193182
|
#define PIT_FREQUENCY 1193182
|
||||||
|
|||||||
@ -38,7 +38,6 @@ irq_common_stub:
|
|||||||
iret
|
iret
|
||||||
|
|
||||||
irq0:
|
irq0:
|
||||||
mov [esp_backup], esp
|
|
||||||
push 0
|
push 0
|
||||||
push 32
|
push 32
|
||||||
jmp irq_common_stub
|
jmp irq_common_stub
|
||||||
|
|||||||
@ -8,9 +8,9 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
#include "process.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "task.h"
|
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "vbe.h"
|
#include "vbe.h"
|
||||||
@ -43,9 +43,9 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic)
|
|||||||
init_memory(mbd, magic);
|
init_memory(mbd, magic);
|
||||||
load_drivers();
|
load_drivers();
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
create_kernel_task();
|
create_kernel_process();
|
||||||
signal(4, bozo);
|
signal(4, bozo);
|
||||||
kill(0, 4);
|
kill(0, 4);
|
||||||
create_task(42);
|
// create_process(42);
|
||||||
shell_init();
|
shell_init();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|||||||
@ -2,11 +2,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "task.h"
|
#include "process.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
|
static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
void init_page_table(uint32_t page_table[1024], uint16_t start)
|
void init_page_table(uint32_t page_table[1024], uint16_t start)
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kpanic.h"
|
#include "kpanic.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "task.h"
|
#include "process.h"
|
||||||
|
|
||||||
Zone *kzones[3];
|
Zone *kzones[3];
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kpanic.h"
|
#include "kpanic.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "task.h"
|
#include "process.h"
|
||||||
|
|
||||||
Zone *vzones[3];
|
Zone *vzones[3];
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "debug.h"
|
#include "assert.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
#include "interrupts.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "task.h"
|
|
||||||
|
|
||||||
uint16_t fork(void)
|
|
||||||
{
|
|
||||||
current_task->status = FORKED;
|
|
||||||
scheduler();
|
|
||||||
return current_task->child ? current_task->child->pid : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kfork(struct task *daddy)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
struct task *child = copy_task(daddy);
|
|
||||||
if (!child) {
|
|
||||||
kprintf(KERN_ALERT "Fork failed ! retry at the next loop");
|
|
||||||
toris();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
child->daddy = daddy;
|
|
||||||
daddy->child = child;
|
|
||||||
daddy->status = RUN;
|
|
||||||
child->status = RUN;
|
|
||||||
toris();
|
|
||||||
}
|
|
||||||
57
src/multitasking/process.c
Normal file
57
src/multitasking/process.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "process.h"
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
int8_t create_kernel_process(void)
|
||||||
|
{
|
||||||
|
struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
|
||||||
|
if (!new_pcb)
|
||||||
|
return -1;
|
||||||
|
new_pcb->pid = 0;
|
||||||
|
new_pcb->uid = 0;
|
||||||
|
new_pcb->heap = kernel_pd;
|
||||||
|
new_pcb->cr3 = (uint32_t *)((uint32_t)kernel_pd - HEAP_END);
|
||||||
|
new_pcb->next = new_pcb;
|
||||||
|
new_pcb->prev = new_pcb;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pcb *create_process(uint8_t uid)
|
||||||
|
{
|
||||||
|
static uint32_t pid = 1;
|
||||||
|
struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
|
||||||
|
if (!new_pcb)
|
||||||
|
return NULL;
|
||||||
|
new_pcb->uid = uid;
|
||||||
|
new_pcb->pid = pid++;
|
||||||
|
|
||||||
|
new_pcb->heap = alloc_pages(4096, &new_pcb->cr3);
|
||||||
|
if (!new_pcb->heap) {
|
||||||
|
vfree(new_pcb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(new_pcb->heap, current_pcb->heap, 4096);
|
||||||
|
new_pcb->next = current_pcb->next;
|
||||||
|
new_pcb->prev = current_pcb;
|
||||||
|
current_pcb->next = new_pcb;
|
||||||
|
if (current_pcb->prev == current_pcb)
|
||||||
|
current_pcb->prev = new_pcb;
|
||||||
|
|
||||||
|
new_pcb->signals.pending = SIG_IGN;
|
||||||
|
|
||||||
|
return new_pcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_pcb(struct pcb *pcb)
|
||||||
|
{
|
||||||
|
struct pcb *left = pcb->prev;
|
||||||
|
struct pcb *right = pcb->next;
|
||||||
|
if (pcb->heap)
|
||||||
|
free_pages(pcb->heap, 4096);
|
||||||
|
left->next = right;
|
||||||
|
right->prev = left;
|
||||||
|
vfree(pcb);
|
||||||
|
}
|
||||||
@ -2,34 +2,28 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "task.h"
|
#include "process.h"
|
||||||
|
#include "thread.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct task *current_task;
|
struct pcb *current_pcb;
|
||||||
|
struct tcb *current_tcb;
|
||||||
|
|
||||||
void scheduler(void)
|
void scheduler(void)
|
||||||
{
|
{
|
||||||
// ZOMBIE, THREAD, RUN, WAIT, SLEEP, STOPPED, FORKED
|
struct tcb *thread_to_switch;
|
||||||
void (*func[])(struct task *) = {
|
if (!current_tcb) {
|
||||||
zombify_task, NULL, NULL, NULL, NULL, remove_task, kfork,
|
thread_to_switch = current_pcb->thread_list;
|
||||||
};
|
} else {
|
||||||
|
if (!current_tcb->next) {
|
||||||
if (!current_task) // || current_task->next == current_task)
|
current_pcb = current_pcb->next;
|
||||||
return;
|
// TODO switch context
|
||||||
cli();
|
thread_to_switch = current_pcb->thread_list;
|
||||||
switch_pd(kernel_pd, (uint32_t *)((uint32_t)kernel_pd - HEAP_END));
|
} else {
|
||||||
struct task *it = current_task->next;
|
thread_to_switch = current_tcb->next;
|
||||||
while (it && it->status != RUN) {
|
|
||||||
if (it != current_task && func[it->status]) {
|
|
||||||
struct task *new_it = it->prev;
|
|
||||||
func[it->status](it);
|
|
||||||
it = new_it;
|
|
||||||
}
|
}
|
||||||
it = it->next;
|
|
||||||
}
|
}
|
||||||
switch_to_task(it);
|
switch_thread(thread_to_switch);
|
||||||
exec_signal_pending();
|
|
||||||
toris();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,58 +0,0 @@
|
|||||||
.intel_syntax noprefix
|
|
||||||
|
|
||||||
.section .text
|
|
||||||
.global switch_to_task
|
|
||||||
|
|
||||||
switch_to_task:
|
|
||||||
push ebx
|
|
||||||
push ebp
|
|
||||||
push edi
|
|
||||||
push esi
|
|
||||||
|
|
||||||
mov eax, [current_task]
|
|
||||||
|
|
||||||
// save the current stack pointer to the old stack
|
|
||||||
mov [eax+0], esp
|
|
||||||
|
|
||||||
// stack pointer + the 4 regs pushed
|
|
||||||
// and + 1 to get the argument (next task)
|
|
||||||
mov esi, [esp+(4+1)*4]
|
|
||||||
mov [current_task], esi
|
|
||||||
|
|
||||||
mov eax, [current_task]
|
|
||||||
|
|
||||||
mov esp, [eax+0] // get esp
|
|
||||||
|
|
||||||
mov ecx, [eax+12] // get task's pd
|
|
||||||
mov [current_pd], ecx
|
|
||||||
mov ecx, [eax+8]
|
|
||||||
mov cr3, ecx
|
|
||||||
|
|
||||||
pop esi
|
|
||||||
pop edi
|
|
||||||
pop ebp
|
|
||||||
pop ebx
|
|
||||||
|
|
||||||
|
|
||||||
mov ecx, 0
|
|
||||||
|
|
||||||
cmp [eax+16], ecx
|
|
||||||
je .END
|
|
||||||
|
|
||||||
sti
|
|
||||||
|
|
||||||
push [eax+16] // store func_ptr
|
|
||||||
|
|
||||||
mov [eax+16], ecx // clear eip in current_task
|
|
||||||
|
|
||||||
push 0
|
|
||||||
call pic_send_eoi
|
|
||||||
pop edx // remove pic_send_eoi argument
|
|
||||||
|
|
||||||
pop edx // get func_ptr
|
|
||||||
call edx
|
|
||||||
|
|
||||||
call exit_task
|
|
||||||
|
|
||||||
.END:
|
|
||||||
ret
|
|
||||||
31
src/multitasking/switch_to_thread.s
Normal file
31
src/multitasking/switch_to_thread.s
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global switch_thread
|
||||||
|
|
||||||
|
switch_thread:
|
||||||
|
push ebx
|
||||||
|
push ebp
|
||||||
|
push edi
|
||||||
|
push esi
|
||||||
|
|
||||||
|
mov eax, [current_tcb]
|
||||||
|
|
||||||
|
// save the current stack pointer to the old stack
|
||||||
|
mov [eax+0], esp
|
||||||
|
|
||||||
|
// stack pointer + the 4 regs pushed
|
||||||
|
// and + 1 to get the argument (next thread)
|
||||||
|
mov esi, [esp+(4+1)*4]
|
||||||
|
mov [current_tcb], esi
|
||||||
|
|
||||||
|
mov eax, [current_tcb]
|
||||||
|
|
||||||
|
mov esp, [eax+0] // get esp
|
||||||
|
|
||||||
|
pop esi
|
||||||
|
pop edi
|
||||||
|
pop ebp
|
||||||
|
pop ebx
|
||||||
|
|
||||||
|
iret
|
||||||
@ -1,140 +0,0 @@
|
|||||||
#include "task.h"
|
|
||||||
#include "alloc.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "interrupts.h"
|
|
||||||
#include "kpanic.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint32_t esp_backup;
|
|
||||||
|
|
||||||
struct task *create_task(uint8_t uid)
|
|
||||||
{
|
|
||||||
static uint32_t pid = 1;
|
|
||||||
switch_pd(kernel_pd, (uint32_t *)((uint32_t)kernel_pd - HEAP_END));
|
|
||||||
struct task *new_task = vmalloc(sizeof(struct task));
|
|
||||||
if (!new_task) {
|
|
||||||
switch_pd(current_task->heap, current_task->cr3);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
switch_pd(current_task->heap, current_task->cr3);
|
|
||||||
new_task->status = RUN;
|
|
||||||
new_task->uid = uid;
|
|
||||||
new_task->esp = new_task->esp0 + STACK_SIZE;
|
|
||||||
new_task->pid = pid++;
|
|
||||||
|
|
||||||
// Allocate new pd
|
|
||||||
new_task->heap = alloc_pages(4096, (void **)&new_task->cr3);
|
|
||||||
if (!new_task->heap) {
|
|
||||||
vfree(new_task);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
new_task->heap[768] = ((uint32_t)boot_page_table1 - HEAP_END) | 0x03;
|
|
||||||
// memcpy(new_task->heap, current_task->heap, 4096);
|
|
||||||
current_pd = new_task->heap;
|
|
||||||
// switch_pd(new_task->heap, new_task->cr3);
|
|
||||||
|
|
||||||
// Allocate new stack on the newly allocated pd
|
|
||||||
new_task->esp0 = alloc_pages(STACK_SIZE, NULL);
|
|
||||||
current_pd = kernel_pd;
|
|
||||||
// switch_pd(current_task->heap, current_task->cr3);
|
|
||||||
if (!new_task->esp0) {
|
|
||||||
vfree(new_task);
|
|
||||||
free_pages(new_task->heap, 4096);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_task->next = current_task->next;
|
|
||||||
new_task->prev = current_task;
|
|
||||||
current_task->next = new_task;
|
|
||||||
if (current_task->prev == current_task)
|
|
||||||
current_task->prev = new_task;
|
|
||||||
|
|
||||||
new_task->signals.pending = SIG_IGN;
|
|
||||||
|
|
||||||
return new_task;
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t create_kernel_task(void)
|
|
||||||
{
|
|
||||||
struct task *new_task = vmalloc(sizeof(struct task));
|
|
||||||
if (!new_task)
|
|
||||||
return -1;
|
|
||||||
new_task->status = RUN;
|
|
||||||
new_task->uid = 0;
|
|
||||||
new_task->pid = 0;
|
|
||||||
new_task->heap = kernel_pd;
|
|
||||||
new_task->cr3 = (uint32_t *)((uint32_t)kernel_pd - HEAP_END);
|
|
||||||
new_task->prev = new_task;
|
|
||||||
new_task->next = new_task;
|
|
||||||
new_task->signals.pending = SIG_IGN;
|
|
||||||
current_task = new_task;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec_fn(void (*fn)(void))
|
|
||||||
{
|
|
||||||
struct task *new_task = create_task(OWNER_KERNEL);
|
|
||||||
if (!new_task)
|
|
||||||
kpanic("failed to create new task");
|
|
||||||
new_task->eip = (uint32_t *)fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zombify_task(struct task *task)
|
|
||||||
{
|
|
||||||
cli(); // Technically useless
|
|
||||||
free_pages(task->heap, 4096);
|
|
||||||
free_pages(task->esp0, STACK_SIZE);
|
|
||||||
task->esp0 = NULL;
|
|
||||||
task->heap = NULL;
|
|
||||||
toris();
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_task(struct task *task)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
struct task *left = task->prev;
|
|
||||||
struct task *right = task->next;
|
|
||||||
|
|
||||||
if (task->child) {
|
|
||||||
remove_task(task->child);
|
|
||||||
task->child = NULL;
|
|
||||||
}
|
|
||||||
if (task->heap)
|
|
||||||
free_pages(task->heap, 4096);
|
|
||||||
if (task->esp0)
|
|
||||||
free_pages(task->esp0, STACK_SIZE);
|
|
||||||
left->next = right;
|
|
||||||
right->prev = left;
|
|
||||||
vfree(task);
|
|
||||||
toris();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct task *copy_task(const struct task *task)
|
|
||||||
{
|
|
||||||
struct task *new_task = create_task(task->uid);
|
|
||||||
if (!new_task)
|
|
||||||
return NULL;
|
|
||||||
memcpy(new_task->esp0, task->esp0, STACK_SIZE);
|
|
||||||
new_task->esp = new_task->esp0 + (task->esp - task->esp0);
|
|
||||||
new_task->status = task->status;
|
|
||||||
return new_task;
|
|
||||||
}
|
|
||||||
|
|
||||||
void exit_task(void)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
if (current_task->daddy && current_task->daddy->status != WAIT)
|
|
||||||
current_task->status = ZOMBIE;
|
|
||||||
else {
|
|
||||||
if (current_task->daddy->status == WAIT)
|
|
||||||
current_task->daddy->status = RUN;
|
|
||||||
current_task->status = STOPPED;
|
|
||||||
}
|
|
||||||
toris();
|
|
||||||
scheduler();
|
|
||||||
}
|
|
||||||
47
src/multitasking/thread.c
Normal file
47
src/multitasking/thread.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "thread.h"
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
struct tcb *create_thread(struct pcb *process, void (*routine)(void))
|
||||||
|
{
|
||||||
|
static uint32_t tid = 1;
|
||||||
|
struct tcb *new_tcb = vmalloc(sizeof(struct tcb));
|
||||||
|
if (!new_tcb)
|
||||||
|
return NULL;
|
||||||
|
new_tcb->tid = tid++;
|
||||||
|
|
||||||
|
new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL);
|
||||||
|
if (!new_tcb->esp0) {
|
||||||
|
vfree(new_tcb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// set esp to "skip" the 4 GPRs and eip later to be used as the context
|
||||||
|
// of the thread
|
||||||
|
new_tcb->esp = new_tcb->esp0 + STACK_SIZE - 5 * 4;
|
||||||
|
memcpy(new_tcb->esp + 4, routine, 4);
|
||||||
|
new_tcb->process = process;
|
||||||
|
new_tcb->next = NULL;
|
||||||
|
new_tcb->state = NEW;
|
||||||
|
|
||||||
|
struct tcb *it = process->thread_list;
|
||||||
|
while (it)
|
||||||
|
it = it->next;
|
||||||
|
it = new_tcb;
|
||||||
|
|
||||||
|
return new_tcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_thread(struct tcb *thread)
|
||||||
|
{
|
||||||
|
vfree(thread->esp0);
|
||||||
|
struct tcb *it = thread->process->thread_list;
|
||||||
|
assert(it);
|
||||||
|
while (it->next != thread)
|
||||||
|
it = it->next;
|
||||||
|
it->next = it->next->next;
|
||||||
|
vfree(thread);
|
||||||
|
}
|
||||||
@ -1,17 +0,0 @@
|
|||||||
#include "interrupts.h"
|
|
||||||
#include "task.h"
|
|
||||||
|
|
||||||
uint16_t wait(void)
|
|
||||||
{
|
|
||||||
if (current_task->child == NULL)
|
|
||||||
return -1;
|
|
||||||
cli();
|
|
||||||
if (current_task->child->status == ZOMBIE)
|
|
||||||
current_task->child->status = STOPPED;
|
|
||||||
else
|
|
||||||
current_task->status = WAIT;
|
|
||||||
uint16_t child_pid = current_task->child->pid;
|
|
||||||
toris();
|
|
||||||
scheduler();
|
|
||||||
return child_pid;
|
|
||||||
}
|
|
||||||
@ -1,21 +1,21 @@
|
|||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "kprintf.h"
|
#include "kprintf.h"
|
||||||
#include "task.h"
|
#include "process.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void signal(SIGNAL_CODE sig_num, void *handler)
|
void signal(SIGNAL_CODE sig_num, void *handler)
|
||||||
{
|
{
|
||||||
current_task->signals.handlers[sig_num] = handler;
|
current_pcb->signals.handlers[sig_num] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kill(int pid, SIGNAL_CODE sig_num)
|
void kill(int pid, SIGNAL_CODE sig_num)
|
||||||
{
|
{
|
||||||
struct task *task = current_task;
|
struct pcb *pcb = current_pcb;
|
||||||
|
|
||||||
while (task->pid != pid)
|
while (pcb->pid != pid)
|
||||||
task = task->next;
|
pcb = pcb->next;
|
||||||
|
|
||||||
task->signals.pending = sig_num;
|
pcb->signals.pending = sig_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_signal(SIGNAL_CODE sig_num)
|
static void display_signal(SIGNAL_CODE sig_num)
|
||||||
@ -25,12 +25,12 @@ static void display_signal(SIGNAL_CODE sig_num)
|
|||||||
|
|
||||||
static void exec_signal(SIGNAL_CODE sig_num)
|
static void exec_signal(SIGNAL_CODE sig_num)
|
||||||
{
|
{
|
||||||
void *handler = current_task->signals.handlers[sig_num];
|
void *handler = current_pcb->signals.handlers[sig_num];
|
||||||
|
|
||||||
if (handler == SIG_IGN)
|
if ((int32_t)handler == SIG_IGN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (handler == SIG_DFL) {
|
if ((int32_t)handler == SIG_DFL) {
|
||||||
display_signal(sig_num);
|
display_signal(sig_num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -41,9 +41,9 @@ static void exec_signal(SIGNAL_CODE sig_num)
|
|||||||
|
|
||||||
void exec_signal_pending(void)
|
void exec_signal_pending(void)
|
||||||
{
|
{
|
||||||
uint32_t signal_code = current_task->signals.pending;
|
int32_t signal_code = current_pcb->signals.pending;
|
||||||
if (signal_code != SIG_IGN) {
|
if (signal_code != SIG_IGN) {
|
||||||
exec_signal(signal_code);
|
exec_signal(signal_code);
|
||||||
current_task->signals.pending = SIG_IGN;
|
current_pcb->signals.pending = SIG_IGN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user