-
Notifications
You must be signed in to change notification settings - Fork 0
/
process.cpp
100 lines (83 loc) · 2.59 KB
/
process.cpp
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
//
// Created by per on 2016-04-27.
//
#include "process.h"
#include "ProcessTable.h"
#include "core.h"
extern "C" void contextSwitch(uintptr_t*, uintptr_t*);
using Func = void(*)(void);
static uintptr_t createStack(Func func, uintptr_t stack, uintptr_t retAddr) {
static constexpr uint8_t CONTEXT_WORDS = 15;
uint32_t* sAddr = reinterpret_cast<uint32_t*>(stack);
sAddr -= CONTEXT_WORDS;
for(int i = 0; i < CONTEXT_WORDS - 3; ++i) {
//Insert args here
sAddr[i] = 0;
}
sAddr[CONTEXT_WORDS - 3] = CPSR_MODE_SYS | CPSR_FIQ;
sAddr[CONTEXT_WORDS - 2] = static_cast<uint32_t>(retAddr);
sAddr[CONTEXT_WORDS - 1] = reinterpret_cast<uint32_t>(func);
return reinterpret_cast<uintptr_t>(sAddr);
}
namespace Scheduler {
ProcessTable<Process> processTable;
ProcessTable<Process>::List* ready;
//ProcessTable<Process>::List* running;
ProcessTable<Process>::List* suspended;
size_t currentPid;
bool needsReschedule() {
if(processTable.listFront(ready)->mPrio > processTable.get(currentPid).mPrio) {
return true;
} else {
return false;
}
}
void schedule() {
Process& oldProc = processTable.get(currentPid);
Process* newProc = processTable.listPopFront(ready);
processTable.moveToListBack(currentPid, &ready);
oldProc.mState = State::READY;
newProc->mState = State::RUNNING;
currentPid = newProc->mPID;
contextSwitch(&oldProc.mStack, &newProc->mStack);
}
void suspend(size_t pid) {
auto& p = processTable.get(pid);
p.mState = State::SUSPENDED;
if(pid == currentPid) {
schedule();
}
}
void resume(size_t pid) {
auto& p = processTable.get(pid);
p.mState = State::READY;
if(needsReschedule()) {
schedule();
}
}
size_t create(Func func, uintptr_t stack) {
for(size_t i = 0; i < processTable.size(); ++i) {
auto& p = processTable.get(i);
if(p.mState == State::FREE) {
p.mPID = i;
p.mNext = i;
p.mPrev = i;
p.mStack = createStack(func, stack, 0);
p.mState = State::SUSPENDED;
processTable.moveToListBack(i, &suspended);
return i;
}
}
return 0;
}
void createNullProc() {
auto& p = processTable.get(0);
p.mPID = 0;
p.mPrev = 0;
p.mNext = 0;
p.mPrio = 0;
p.mStack = 0;
p.mState = State::RUNNING;
currentPid = 0;
}
};