mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
fix task node leaks
This commit is contained in:
@@ -60,17 +60,17 @@ void freeprinter() {
|
||||
char buf[69];
|
||||
while (1) {
|
||||
all_tty_putstr("=====\n");
|
||||
itoa(get_free(), buf, 10);
|
||||
itoa(get_free() * 1024, buf, 10);
|
||||
all_tty_putstr("Free mem: ");
|
||||
all_tty_putstr(buf);
|
||||
write_serial('\n');
|
||||
|
||||
itoa(get_heap_allocated() / 1024, buf, 10);
|
||||
itoa(get_heap_allocated(), buf, 10);
|
||||
all_tty_putstr("Heap allocated: ");
|
||||
all_tty_putstr(buf);
|
||||
write_serial('\n');
|
||||
|
||||
itoa(get_heap_used() / 1024, buf, 10);
|
||||
itoa(get_heap_used(), buf, 10);
|
||||
all_tty_putstr("Heap used: ");
|
||||
all_tty_putstr(buf);
|
||||
write_serial('\n');
|
||||
|
||||
@@ -34,11 +34,11 @@ List<Task *> NextTasks;
|
||||
|
||||
// Task freer
|
||||
Spinlock TasksToFree_lock;
|
||||
List<Task *> TasksToFree;
|
||||
List<List<Task *>::Node *> TasksToFree;
|
||||
|
||||
// Waiting
|
||||
Spinlock WaitingTasks_lock;
|
||||
SkipList<uint64_t, Task *> WaitingTasks;
|
||||
SkipList<uint64_t, List<Task *>::Node *> WaitingTasks;
|
||||
|
||||
static std::atomic<bool> initialized = false;
|
||||
|
||||
@@ -55,9 +55,10 @@ static void task_freer() {
|
||||
{
|
||||
LockGuard l(TasksToFree_lock);
|
||||
while (!TasksToFree.empty()) {
|
||||
auto t = TasksToFree.back();
|
||||
List<Task *>::Node *t = TasksToFree.back();
|
||||
TasksToFree.pop_back();
|
||||
free_task(t);
|
||||
free_task(t->val);
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +101,8 @@ struct Task *new_ktask(void (*fn)(), const char *name) {
|
||||
void remove_self() {
|
||||
{
|
||||
LockGuard l(TasksToFree_lock);
|
||||
TasksToFree.emplace_front(cur_task());
|
||||
assert(RunningTask != nullptr);
|
||||
TasksToFree.emplace_front(RunningTask);
|
||||
NextTasks_lock.lock();
|
||||
RunningTask->val->state = TS_BLOCKED;
|
||||
}
|
||||
@@ -117,12 +119,13 @@ void sleep_self(uint64_t diff) {
|
||||
|
||||
// TODO this is all ugly
|
||||
uint64_t l1 = 0;
|
||||
for(auto cur = &*WaitingTasks.begin(); !cur->end; cur=cur->next[0])l1++;
|
||||
for (auto cur = &*WaitingTasks.begin(); !cur->end; cur = cur->next[0]) l1++;
|
||||
|
||||
assert(WaitingTasks.add(wake_time, cur_task()) != nullptr);
|
||||
assert(RunningTask != nullptr);
|
||||
assert(WaitingTasks.add(wake_time, RunningTask) != nullptr);
|
||||
|
||||
uint64_t l2 = 0;
|
||||
for(auto cur = &*WaitingTasks.begin(); !cur->end; cur=cur->next[0])l2++;
|
||||
for (auto cur = &*WaitingTasks.begin(); !cur->end; cur = cur->next[0]) l2++;
|
||||
|
||||
assert(l2 - l1 == 1);
|
||||
NextTasks_lock.lock();
|
||||
@@ -146,27 +149,26 @@ static void task_waker() {
|
||||
{
|
||||
LockGuard l(WaitingTasks_lock);
|
||||
|
||||
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->key <= micros && WaitingTasks.begin()->data->state != TS_RUNNING) {
|
||||
while (WaitingTasks.begin() != WaitingTasks.end() && WaitingTasks.begin()->key <= micros && WaitingTasks.begin()->data->val->state != TS_RUNNING) {
|
||||
auto *node = &*WaitingTasks.begin();
|
||||
auto task = WaitingTasks.begin()->data;
|
||||
|
||||
// TODO this is all ugly
|
||||
uint64_t l1 = 0;
|
||||
for(auto cur = node; !cur->end; cur=cur->next[0])l1++;
|
||||
for (auto cur = node; !cur->end; cur = cur->next[0]) l1++;
|
||||
|
||||
WaitingTasks.erase(node, node->next[0], false);
|
||||
|
||||
uint64_t l2 = 0;
|
||||
for(auto *cur = &*WaitingTasks.begin(); !cur->end; cur=cur->next[0])l2++;
|
||||
for (auto *cur = &*WaitingTasks.begin(); !cur->end; cur = cur->next[0]) l2++;
|
||||
|
||||
assert(l1 - l2 == 1);
|
||||
task->sleep_until = 0;
|
||||
task->state = TS_RUNNING;
|
||||
task->val->sleep_until = 0;
|
||||
task->val->state = TS_RUNNING;
|
||||
|
||||
auto new_node = NextTasks.create_node(task);
|
||||
{
|
||||
LockGuard l(NextTasks_lock);
|
||||
NextTasks.emplace_front(new_node);
|
||||
NextTasks.emplace_front(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +239,20 @@ void unblock(Task *what) {
|
||||
}
|
||||
};
|
||||
|
||||
void unblock(List<Task *>::Node *what) {
|
||||
what->val->state = TS_RUNNING;
|
||||
{
|
||||
LockGuard l(NextTasks_lock);
|
||||
NextTasks.emplace_front(what);
|
||||
}
|
||||
};
|
||||
|
||||
struct Task *cur_task() {
|
||||
if (!RunningTask) return NULL;
|
||||
return RunningTask->val;
|
||||
}
|
||||
|
||||
List<Task *>::Node *extract_running_task_node() {
|
||||
if (!RunningTask) return nullptr;
|
||||
return RunningTask;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef OS1_TASK_H
|
||||
#define OS1_TASK_H
|
||||
|
||||
#include "List.hpp"
|
||||
#include "idt.hpp"
|
||||
|
||||
#define TASK_SS 16384
|
||||
@@ -33,18 +34,19 @@ struct Task {
|
||||
};
|
||||
|
||||
struct Task *cur_task();
|
||||
List<Task *>::Node *extract_running_task_node();
|
||||
|
||||
void init_tasks();
|
||||
struct Task *new_ktask(void (*fn)(), const char *name);
|
||||
void remove_self();
|
||||
void sleep_self(uint64_t diff);
|
||||
|
||||
|
||||
void self_block();
|
||||
|
||||
class Spinlock;
|
||||
void self_block(Spinlock &to_unlock);
|
||||
void unblock(Task *what);
|
||||
void unblock(List<Task *>::Node *what);
|
||||
|
||||
extern "C" void switch_task(struct task_frame *cur_frame);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
lock->unlock();
|
||||
}
|
||||
|
||||
LockGuard(LockGuard const &d) = delete;
|
||||
|
||||
private:
|
||||
T *lock;
|
||||
};
|
||||
|
||||
@@ -54,7 +54,7 @@ void Mutex::lock() {
|
||||
|
||||
while (!Mutex::try_lock()) {
|
||||
waiters_lock.lock();
|
||||
waiters.emplace_front(cur_task());
|
||||
waiters.emplace_front(extract_running_task_node());
|
||||
self_block(waiters_lock);
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ void Mutex::unlock() {
|
||||
bool expected = true;
|
||||
if (!locked.compare_exchange_strong(expected, false))
|
||||
writestr("Unlocking an unlocked mutex!\n");
|
||||
Task *t = nullptr;
|
||||
List<Task *>::Node *t = nullptr;
|
||||
{
|
||||
LockGuard l(waiters_lock);
|
||||
if (!waiters.empty()) {
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
private:
|
||||
std::atomic<bool> locked = false;
|
||||
|
||||
List<Task *> waiters; // leaking List<Task *>::Node
|
||||
List<List<Task *>::Node *> waiters;
|
||||
Spinlock waiters_lock;
|
||||
|
||||
Task *owner = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user