summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/thread.c
blob: da20067c700ec1f25d5a1980e1d3da7b9368a0fa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "tsk/tasking.h"
#include "mem/memory.h"
#include "io/log.h"
#include "lib/hashtable.h"
#include "lib/string.h"
#include "paging.h"
#include "cpu.h"

struct ThreadBody {
    struct Thread base;
    struct PageDirectory pd;
    struct Registers state;
};

struct Thread *thread_current;
uintptr_t _kernel_thread_bp = 0;

//static struct SLinkedList s_threads;
static struct HashTable s_threads;

static struct SlabCache s_thread_cache;
static struct SlabCache s_kbp_cache;

static tid_t s_thread_id_next = 1;

static size_t
s_thread_hash_func(const void* tid, size_t _)
{
    return (tid_t)tid;
}

void
tasking_setup(void)
{
    hashtable_new(&s_threads, struct ThreadBody*, tid_t);
    s_threads.hash_function = s_thread_hash_func;
 
    mem_slabcache_new(&s_thread_cache, "threads", sizeof(struct ThreadBody));
    mem_slabcache_new(&s_kbp_cache, "kernel stacks", 4096);

    struct ThreadBody *kthread = mem_slab_alloc(&s_thread_cache);
    *kthread = (struct ThreadBody){
        .base.id = s_thread_id_next++,
        .base.kbp = ((uintptr_t)mem_slab_alloc(&s_kbp_cache)) + 0xFFF,
        .base.perm = (size_t)-1,
        .pd = *mem_current_pd
    };
    hashtable_insert(&s_threads, 0, kthread);

    thread_current = (struct Thread*)kthread;
    _kernel_thread_bp = thread_current->kbp;
}

struct Thread*
thread_new(struct Thread *parent)
{
    struct ThreadBody *new = mem_slab_alloc(&s_thread_cache);
    memcpy(new, parent, sizeof(struct ThreadBody));
    new->base.id = s_thread_id_next++;
    
    uintptr_t ksp_base = (uintptr_t)mem_slab_alloc(&s_kbp_cache);
    new->base.kbp = ksp_base + 0xFFF;
    new->base.perm = parent->perm;

    hashtable_insert(&s_threads, (void*)new->base.id, new);
    return (struct Thread*)new;
}

struct Thread*
thread_get(tid_t id)
{
    struct Thread **thread = hashtable_get(&s_threads, (void*)id, struct Thread*);
    if(thread == NULL) return NULL;
    return *thread;
}

void
thread_free(struct Thread *thread)
{
    struct ThreadBody *body = (struct ThreadBody*)thread;
    body->pd.references--;
    thread->kbp -= 0xFFF;
    mem_slab_free(&s_kbp_cache, (void*)(thread->kbp));
    klogf("Need impl for thread_free\n");
}