wip: fork()

This commit is contained in:
0x35c
2025-11-12 15:07:36 +01:00
parent 02d196fab5
commit 34aa0f0eb4
9 changed files with 115 additions and 28 deletions

View File

@ -1,25 +1,32 @@
#pragma once
#include "list.h"
#include "signal.h"
#include "thread.h"
#include <stdint.h>
extern struct pcb *current_pcb;
enum owner { OWNER_KERNEL, OWNER_USER };
typedef uint16_t pid_t;
typedef uint8_t uid_t;
struct pcb {
void *cr3;
uint32_t *heap;
uint16_t pid;
uint8_t uid;
pid_t pid;
uid_t uid;
tid_t tid;
struct signal_data signals;
struct pcb *next;
struct pcb *prev;
struct tcb *thread_list;
struct pcb *daddy;
struct list *children;
struct list *thread_list;
};
void switch_process(struct pcb *next_pcb);
struct pcb *create_process(uint8_t uid);
struct pcb *create_process(uid_t uid);
// int8_t create_kernel_process(void);
void remove_process(struct pcb *pcb);

View File

@ -1,10 +1,11 @@
#pragma once
#include "process.h"
#include <stdint.h>
#define STACK_SIZE PAGE_SIZE * 4
#define STACK_SIZE PAGE_SIZE * 4
#define CURRENT_TCB ((struct tcb *)current_tcb->content)
typedef uint16_t tid_t;
typedef enum {
NEW,
@ -16,10 +17,9 @@ typedef enum {
struct tcb {
uint32_t *esp;
uint32_t *esp0;
uint16_t tid;
tid_t tid;
state_t state;
struct pcb *process;
struct tcb *next;
};
struct tcb *create_thread(struct pcb *process, void (*entry)(void));

View File

@ -4,3 +4,6 @@ struct list {
void *content;
struct list *next;
};
struct list *lst_last(struct list *head);
void lst_add_back(struct list **head, struct list *e);

View File

@ -0,0 +1,10 @@
#include "list.h"
void lst_add_back(struct list **head, struct list *e)
{
struct list *last = lst_last(*head);
if (!last)
*head = e;
else
last->next = e;
}

View File

@ -0,0 +1,12 @@
#include "list.h"
#include <stddef.h>
struct list *lst_last(struct list *head)
{
if (!head)
return NULL;
struct list *it = head;
while (it->next)
it = it->next;
return it;
}

40
src/multitasking/fork.c Normal file
View File

@ -0,0 +1,40 @@
#include "alloc.h"
#include "memory.h"
#include "process.h"
#include "string.h"
#include "thread.h"
static struct tcb *thread_clone(struct tcb *thread)
{
struct tcb *new_tcb = vmalloc(sizeof(struct tcb));
if (!new_tcb)
return NULL;
new_tcb->tid = thread->tid;
new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL);
if (!new_tcb->esp0) {
delete_thread(new_tcb);
return NULL;
}
memcpy(new_tcb->esp0, thread->esp0, STACK_SIZE);
return new_tcb;
}
pid_t fork(void)
{
struct pcb *new_pcb = create_process(current_pcb->uid);
if (!new_pcb)
return -1;
struct list *new_node = vmalloc(sizeof(struct list));
if (!new_node) {
remove_process(new_pcb);
return -1;
}
new_pcb->daddy = current_pcb;
lst_add_back(&new_pcb->children, new_node);
current_pd = new_pcb->cr3;
// loop on threads clone
thread_clone(current_pcb->thread_list->content);
current_pd = current_pcb->cr3;
return new_pcb->pid;
}

View File

@ -6,14 +6,15 @@
#include "string.h"
struct pcb *create_process(uint8_t uid)
struct pcb *create_process(uid_t uid)
{
static uint32_t pid = 1;
static pid_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->tid = 1;
new_pcb->heap = alloc_pages(4096, &new_pcb->cr3);
if (!new_pcb->heap) {
@ -22,6 +23,8 @@ struct pcb *create_process(uint8_t uid)
}
memcpy(new_pcb->heap, current_pd, 4096);
new_pcb->daddy = NULL;
new_pcb->children = NULL;
new_pcb->next = new_pcb;
new_pcb->prev = new_pcb;
@ -40,7 +43,7 @@ struct pcb *create_process(uint8_t uid)
return new_pcb;
}
void remove_pcb(struct pcb *pcb)
void remove_process(struct pcb *pcb)
{
struct pcb *left = pcb->prev;
struct pcb *right = pcb->next;

View File

@ -9,18 +9,18 @@
#include <stddef.h>
struct pcb *current_pcb;
struct tcb *current_tcb;
struct list *current_tcb;
static struct tcb *get_thread_to_switch(void)
static struct list *get_thread_to_switch(void)
{
struct pcb *it_p;
struct tcb *it_t;
struct list *it_t;
it_p = current_pcb;
it_t = current_tcb == NULL ? NULL : current_tcb->next;
while (it_p) {
while (it_t != NULL) {
if (it_t != NULL && it_t->state != WAITING)
if (it_t != NULL && CURRENT_TCB->state != WAITING)
return it_t;
it_t = it_t->next;
}
@ -32,13 +32,14 @@ static struct tcb *get_thread_to_switch(void)
void scheduler(uint32_t *esp)
{
struct tcb *thread_to_switch = get_thread_to_switch();
if (!thread_to_switch)
struct list *list_node = get_thread_to_switch();
if (!list_node)
kpanic("No existing threads \n");
struct tcb *thread_to_switch = (struct tcb *)list_node->content;
if (current_tcb)
current_tcb->esp = esp;
CURRENT_TCB->esp = esp;
if (thread_to_switch->process != current_pcb)
switch_process(thread_to_switch->process);
current_tcb = thread_to_switch;
current_tcb = list_node;
switch_thread(thread_to_switch->esp);
}

View File

@ -2,17 +2,18 @@
#include "alloc.h"
#include "assert.h"
#include "interrupts.h"
#include "list.h"
#include "memory.h"
#include "process.h"
#include "string.h"
#include "thread.h"
struct tcb *create_thread(struct pcb *process, void (*entry)(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->tid = process->tid++;
new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL);
if (!new_tcb->esp0) {
@ -40,18 +41,26 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
*(--stack) = 0; // ESI
*(--stack) = 0; // EDI
*(--stack) = 0x10; // kernel DS
new_tcb->esp = stack;
new_tcb->process = process;
new_tcb->next = NULL;
new_tcb->state = NEW;
struct list *new_node = vmalloc(sizeof(struct list));
if (!new_node) {
free_pages(new_tcb->esp0, STACK_SIZE);
vfree(new_tcb);
return NULL;
}
new_node->content = new_tcb;
new_node->next = NULL;
if (process->thread_list == NULL) {
process->thread_list = new_tcb;
process->thread_list = new_node;
} else {
struct tcb *it = process->thread_list;
struct list *it = process->thread_list;
while (it->next)
it = it->next;
it->next = new_tcb;
it->next = new_node;
}
return new_tcb;
@ -60,10 +69,12 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
void delete_thread(struct tcb *thread)
{
vfree(thread->esp0);
struct tcb *it = thread->process->thread_list;
struct list *it = thread->process->thread_list;
assert(it);
while (it->next != thread)
while (it->next && it->next->content != thread)
it = it->next;
struct list *to_free = it;
it->next = it->next->next;
vfree(to_free);
vfree(thread);
}