summaryrefslogtreecommitdiff
path: root/src/kernel/proc/proc.cc
blob: 469b7eb5dbed6ecf65a4a027b88da9647c57df19 (plain)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "kernel/proc.h"
#include "kernel/pmm.h"
#include "drivers/uart.h"

#define NPROC 10

void str_copy(char *dst, const char *src)
{
    while (*src)
        *dst++ = *src++;
    *dst = 0;
}

extern "C" void swtch(struct Context *old_ctx, struct Context *new_ctx);

struct Proc procs[NPROC];
struct Context main_context;

namespace ProcManager
{
    void init()
    {
        for (int i = 0; i < NPROC; i++)
        {
            procs[i].state = UNUSED;
        }
    }

    void create_kernel_thread(void (*func)(), const char *name)
    {
        struct Proc *p = nullptr;
        for(int i = 0; i < NPROC; i++)
        {
            if(procs[i].state == UNUSED)
            {
                p = &procs[i];
                p->pid = i + 1;
                break;
            }
        }

        if (!p)
        {
            Drivers::uart_puts("Error: No free process slots!\n");
            return;
        }

        p->kstack = PMM::alloc_page();
        if (!p->kstack)
        {
            Drivers::uart_puts("Error: Alloc kstack failed!\n");
            return;
        }

        p->context.ra = (uint64)func;

        p->context.sp = (uint64)p->kstack + 4096;

        p->state = RUNNABLE;
        str_copy(p->name, name);

        Drivers::uart_puts("[Proc] Created thread: ");
        Drivers::uart_puts(name);
        Drivers::uart_puts("\n");
    }

    void yield()
    {
        struct Proc *p = nullptr;
        for(int i = 0; i < NPROC; i++)
        {
            if (procs[i].state == RUNNING)
            {
                p = &procs[i];
                break;
            }
        }
        if(p)
        {
            p->state = RUNNABLE;
            swtch(&p->context, &main_context);
        }
    }

    void scheduler()
    {
        struct Proc *p = nullptr;
        Drivers::uart_puts("[Proc] Scheduler started.\n");

        for (;;)
        {
            // int nothing_to_run = 1;

            intr_off();

            for (p = procs; p < &procs[NPROC]; p++)
            {
                if (p->state == RUNNABLE)
                {
                    // nothing_to_run = 0;

                    p->state = RUNNING;

                    intr_on();

                    swtch(&main_context, &p->context);

                    intr_off();
                }
            }
        }
    }
}