xaizek / tos (License: GPLv3 only) (since 2018-12-07)
This is an alternative version of sources presented as part of Write Your Own OS video tutorial by Viktor Engelmann.
Commit f55d8cc4b95639cfd359b90d3830da0c89a06536

Drop tasks from manager when they are done
Need to handle situation when last task ends.
Author: xaizek
Author date (UTC): 2018-04-12 14:29
Committer name: xaizek
Committer date (UTC): 2018-04-12 14:30
Parent(s): 9c0cf63fb1e8371c0afe58ea9152684cfd89ac3e
Signing key: 99DC5E4DB05F6BE2
Tree: eab5b5a697312635d5616f5d6dc6d352cd3c5f06
File Lines added Lines deleted
src/kernel.cpp 7 10
src/multitasking.cpp 16 7
src/multitasking.hpp 11 5
File src/kernel.cpp changed (mode: 100644) (index 34516d3..e9b80b5)
... ... extern "C" void stop();
116 116
117 117 static void heapDemo(MemoryManager &mm); static void heapDemo(MemoryManager &mm);
118 118 static void ataDemo(); static void ataDemo();
119 static std::unique_ptr<NetworkStack> netDemo(GlobalDescriptorTable &gdt,
120 TaskManager &taskManager,
119 static std::unique_ptr<NetworkStack> netDemo(TaskManager &taskManager,
121 120 drv::DriverManager &drvManager); drv::DriverManager &drvManager);
122 121 static bool strEqual(const char s[], const char t[]); static bool strEqual(const char s[], const char t[]);
123 122
 
... ... kernelEntry(multiboot_info *multibootInfo, unsigned int /*multibootMagic*/)
180 179
181 180 ataDemo(); ataDemo();
182 181
183 TaskManager taskManager;
182 TaskManager taskManager(gdt);
184 183
185 184 kprint("Initializing Hardware, Stage 3\n"); kprint("Initializing Hardware, Stage 3\n");
186 185 interrupts.activate(); interrupts.activate();
187 186
188 std::unique_ptr<NetworkStack> networkStack = netDemo(gdt, taskManager,
187 std::unique_ptr<NetworkStack> networkStack = netDemo(taskManager,
189 188 drvManager); drvManager);
190 189
191 taskManager.addTask(std::unique_ptr<Task>(new Task(gdt, []() {
190 taskManager.addTask(std::unique_ptr<Task>(new Task([]() {
192 191 demo.run(); demo.run();
193 stop();
194 192 }))); })));
195 193
196 194 stop(); stop();
 
... ... ataDemo()
235 233 } }
236 234
237 235 static std::unique_ptr<NetworkStack> static std::unique_ptr<NetworkStack>
238 netDemo(GlobalDescriptorTable &gdt, TaskManager &taskManager,
239 drv::DriverManager &drvManager)
236 netDemo(TaskManager &taskManager, drv::DriverManager &drvManager)
240 237 { {
241 238 auto ourIP = toNetOrder<std::uint32_t>(0x0a00020f); // 10.0.2.15 auto ourIP = toNetOrder<std::uint32_t>(0x0a00020f); // 10.0.2.15
242 239 auto gatewayIP = toNetOrder<std::uint32_t>(0x0a000202); // 10.0.2.2 auto gatewayIP = toNetOrder<std::uint32_t>(0x0a000202); // 10.0.2.2
 
... ... netDemo(GlobalDescriptorTable &gdt, TaskManager &taskManager,
252 249
253 250 auto networkStack = new NetworkStack(net, gatewayIP, subnetMask); auto networkStack = new NetworkStack(net, gatewayIP, subnetMask);
254 251
255 taskManager.addTask(std::unique_ptr<Task>(new Task(gdt, [=]() {
252 taskManager.addTask(std::unique_ptr<Task>(new Task([=]() {
256 253 net::UDPSocket &udpServer = networkStack->udp.listen(1234); net::UDPSocket &udpServer = networkStack->udp.listen(1234);
257 254 networkStack->udp.bind(udpServer, &networkStack->udpHandler); networkStack->udp.bind(udpServer, &networkStack->udpHandler);
258 255
 
... ... netDemo(GlobalDescriptorTable &gdt, TaskManager &taskManager,
263 260 udpClient.send(data); udpClient.send(data);
264 261 }))); })));
265 262
266 taskManager.addTask(std::unique_ptr<Task>(new Task(gdt, [=]() {
263 taskManager.addTask(std::unique_ptr<Task>(new Task([=]() {
267 264 net::TCPSocket &tcpServer = networkStack->tcp.listen(1234); net::TCPSocket &tcpServer = networkStack->tcp.listen(1234);
268 265 networkStack->tcp.bind(tcpServer, &networkStack->tcpHandler); networkStack->tcp.bind(tcpServer, &networkStack->tcpHandler);
269 266
File src/multitasking.cpp changed (mode: 100644) (index b0f767a..fc290e9)
... ... extern "C" void taskEntryThunk();
6 6 extern "C" void taskEntry(Task *task); extern "C" void taskEntry(Task *task);
7 7 void taskEntryCxx(Task *task); void taskEntryCxx(Task *task);
8 8
9 CPUState *
10 Task::makeCPUState(GlobalDescriptorTable &gdt)
9 void
10 Task::init(GlobalDescriptorTable &gdt)
11 11 { {
12 CPUState *cpuState = new(stack + sizeof(stack) - sizeof(CPUState)) CPUState;
12 cpuState = new(stack + sizeof(stack) - sizeof(CPUState)) CPUState;
13 13
14 14 cpuState->eax() = reinterpret_cast<std::uint32_t>(this); cpuState->eax() = reinterpret_cast<std::uint32_t>(this);
15 15 cpuState->ebx() = 0; cpuState->ebx() = 0;
 
... ... Task::makeCPUState(GlobalDescriptorTable &gdt)
30 30 cpuState->cs() = gdt.getCS(); cpuState->cs() = gdt.getCS();
31 31 // cpuState->ss() = ; // cpuState->ss() = ;
32 32 cpuState->eflags() = 0x202; cpuState->eflags() = 0x202;
33
34 return cpuState;
35 33 } }
36 34
37 35 void void
 
... ... void
50 48 Task::entry() Task::entry()
51 49 { {
52 50 (*task)(); (*task)();
51 done = true;
52 asm ("int $0x20");
53 53 } }
54 54
55 TaskManager::TaskManager()
56 : InterruptHandler(0x20), numTasks(0), currentTask(-1)
55 TaskManager::TaskManager(GlobalDescriptorTable &gdt)
56 : InterruptHandler(0x20), gdt(gdt), numTasks(0), currentTask(-1)
57 57 { {
58 58 } }
59 59
 
... ... TaskManager::addTask(std::unique_ptr<Task> task)
63 63 if (numTasks == 256) { if (numTasks == 256) {
64 64 return false; return false;
65 65 } }
66
67 task->init(gdt);
66 68 tasks[numTasks++] = std::move(task); tasks[numTasks++] = std::move(task);
67 69 return true; return true;
68 70 } }
 
... ... TaskManager::schedule(CPUState *cpuState)
83 85
84 86 if (currentTask >= 0) { if (currentTask >= 0) {
85 87 tasks[currentTask]->cpuState = cpuState; tasks[currentTask]->cpuState = cpuState;
88 if (tasks[currentTask]->done) {
89 tasks[currentTask] = std::move(tasks[numTasks - 1]);
90 --numTasks;
91 currentTask %= numTasks;
92 // XXX: this could be the last task, need to handle this.
93 return tasks[currentTask]->cpuState;
94 }
86 95 } }
87 96
88 97 if (++currentTask >= numTasks) { if (++currentTask >= numTasks) {
File src/multitasking.hpp changed (mode: 100644) (index 5dafe33..65ba31b)
... ... class Task
40 40 { {
41 41 friend class TaskManager; friend class TaskManager;
42 42 friend void taskEntryCxx(Task *task); friend void taskEntryCxx(Task *task);
43
43 44 struct TaskImplBase struct TaskImplBase
44 45 { {
45 46 virtual ~TaskImplBase() = default; virtual ~TaskImplBase() = default;
 
... ... class Task
64 65
65 66 public: public:
66 67 template <typename F> template <typename F>
67 Task(GlobalDescriptorTable &gdt, F &&f)
68 : cpuState(makeCPUState(gdt)), task(new TaskImpl<F>(std::forward<F>(f)))
68 Task(F &&f)
69 : task(new TaskImpl<F>(std::forward<F>(f))),
70 cpuState(nullptr), done(false)
69 71 { {
70 72 } }
71 73
72 74 private: private:
73 CPUState * makeCPUState(GlobalDescriptorTable &gdt);
75 void init(GlobalDescriptorTable &gdt);
74 76 void entry(); void entry();
75 77
76 78 private: private:
 
... ... private:
78 80 std::uint64_t forceAlignment; std::uint64_t forceAlignment;
79 81 std::uint8_t stack[4096]; // 4 KiB std::uint8_t stack[4096]; // 4 KiB
80 82 }; };
81 CPUState *cpuState;
82 83 std::unique_ptr<TaskImplBase> task; std::unique_ptr<TaskImplBase> task;
84 CPUState *cpuState;
85 bool done;
83 86 }; };
84 87
85 88 class TaskManager : public hwcomm::InterruptHandler class TaskManager : public hwcomm::InterruptHandler
86 89 { {
90 friend void Task::entry();
91
87 92 public: public:
88 TaskManager();
93 TaskManager(GlobalDescriptorTable &gdt);
89 94
90 95 public: public:
91 96 bool addTask(std::unique_ptr<Task> task); bool addTask(std::unique_ptr<Task> task);
 
... ... private:
97 102 CPUState * schedule(CPUState *cpuState); CPUState * schedule(CPUState *cpuState);
98 103
99 104 private: private:
105 GlobalDescriptorTable &gdt;
100 106 std::unique_ptr<Task> tasks[256]; std::unique_ptr<Task> tasks[256];
101 107 int numTasks; int numTasks;
102 108 int currentTask; int currentTask;
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master