mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp
synced 2026-07-01 12:19:12 -04:00
More WIP linux work, upgraded libultra to include changes from BT recomp
This commit is contained in:
+29
-35
@@ -7,10 +7,8 @@
|
||||
#include "multilibultra.hpp"
|
||||
|
||||
// Native APIs only used to set thread names for easier debugging
|
||||
#if defined(_WIN32)
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#elif defined(__linux__)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
extern "C" void bootproc();
|
||||
@@ -127,7 +125,6 @@ static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entry
|
||||
Multilibultra::set_native_thread_priority(Multilibultra::ThreadPriority::High);
|
||||
|
||||
// Set initialized to false to indicate that this thread can be started.
|
||||
Multilibultra::set_self_paused(PASS_RDRAM1);
|
||||
self->context->initialized.store(true);
|
||||
self->context->initialized.notify_all();
|
||||
|
||||
@@ -153,7 +150,7 @@ extern "C" void osStartThread(RDRAM_ARG PTR(OSThread) t_) {
|
||||
OSThread* t = TO_PTR(OSThread, t_);
|
||||
debug_printf("[os] Start Thread %d\n", t->id);
|
||||
|
||||
// Wait until the thread is initialized to indicate that it's action_queued to be started.
|
||||
// Wait until the thread is initialized to indicate that it's queued to be started.
|
||||
t->context->initialized.wait(false);
|
||||
|
||||
debug_printf("[os] Thread %d is ready to be started\n", t->id);
|
||||
@@ -178,20 +175,33 @@ extern "C" void osCreateThread(RDRAM_ARG PTR(OSThread) t_, OSId id, PTR(thread_f
|
||||
t->next = NULLPTR;
|
||||
t->priority = pri;
|
||||
t->id = id;
|
||||
t->state = OSThreadState::PAUSED;
|
||||
t->state = OSThreadState::STOPPED;
|
||||
t->sp = sp - 0x10; // Set up the first stack frame
|
||||
t->destroyed = false;
|
||||
|
||||
// Spawn a new thread, which will immediately pause itself and wait until it's been started.
|
||||
t->context = new UltraThreadContext{};
|
||||
t->context->initialized.store(false);
|
||||
t->context->running.store(false);
|
||||
t->context->scheduled.store(false);
|
||||
t->context->descheduled.store(true);
|
||||
|
||||
t->context->host_thread = std::thread{_thread_func, PASS_RDRAM t_, entrypoint, arg};
|
||||
}
|
||||
|
||||
extern "C" void osStopThread(RDRAM_ARG PTR(OSThread) t_) {
|
||||
assert(false);
|
||||
// If null is passed in as the thread then the calling thread is stopping itself.
|
||||
if (t_ == NULLPTR) {
|
||||
t_ = Multilibultra::this_thread();
|
||||
}
|
||||
|
||||
// Remove the thread in question from the scheduler so it doesn't get scheduled again.
|
||||
OSThread* t = TO_PTR(OSThread, t_);
|
||||
Multilibultra::stop_thread(t);
|
||||
|
||||
// If a thread is stopping itself, tell the scheduler that it has yielded.
|
||||
if (t_ == Multilibultra::this_thread()) {
|
||||
Multilibultra::yield_self(PASS_RDRAM1);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void osDestroyThread(RDRAM_ARG PTR(OSThread) t_) {
|
||||
@@ -207,6 +217,12 @@ extern "C" void osDestroyThread(RDRAM_ARG PTR(OSThread) t_) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO make the thread queue stable to ensure correct yielding behavior
|
||||
extern "C" void osYieldThread(RDRAM_ARG1) {
|
||||
Multilibultra::yield_self(PASS_RDRAM1);
|
||||
Multilibultra::wait_for_resumed(PASS_RDRAM1);
|
||||
}
|
||||
|
||||
extern "C" void osSetThreadPri(RDRAM_ARG PTR(OSThread) t, OSPri pri) {
|
||||
if (t == NULLPTR) {
|
||||
t = thread_self;
|
||||
@@ -214,13 +230,12 @@ extern "C" void osSetThreadPri(RDRAM_ARG PTR(OSThread) t, OSPri pri) {
|
||||
bool pause_self = false;
|
||||
if (pri > TO_PTR(OSThread, thread_self)->priority) {
|
||||
pause_self = true;
|
||||
Multilibultra::set_self_paused(PASS_RDRAM1);
|
||||
} else if (t == thread_self && pri < TO_PTR(OSThread, thread_self)->priority) {
|
||||
pause_self = true;
|
||||
Multilibultra::set_self_paused(PASS_RDRAM1);
|
||||
}
|
||||
Multilibultra::reprioritize_thread(TO_PTR(OSThread, t), pri);
|
||||
if (pause_self) {
|
||||
Multilibultra::yield_self(PASS_RDRAM1);
|
||||
Multilibultra::wait_for_resumed(PASS_RDRAM1);
|
||||
}
|
||||
}
|
||||
@@ -239,15 +254,6 @@ extern "C" OSId osGetThreadId(RDRAM_ARG PTR(OSThread) t) {
|
||||
return TO_PTR(OSThread, t)->id;
|
||||
}
|
||||
|
||||
// TODO yield thread, need a stable priority queue in the scheduler
|
||||
|
||||
void Multilibultra::set_self_paused(RDRAM_ARG1) {
|
||||
debug_printf("[Thread] Thread pausing itself: %d\n", TO_PTR(OSThread, thread_self)->id);
|
||||
TO_PTR(OSThread, thread_self)->state = OSThreadState::PAUSED;
|
||||
TO_PTR(OSThread, thread_self)->context->running.store(false);
|
||||
TO_PTR(OSThread, thread_self)->context->running.notify_all();
|
||||
}
|
||||
|
||||
void check_destroyed(OSThread* t) {
|
||||
if (t->destroyed) {
|
||||
throw thread_terminated{};
|
||||
@@ -256,25 +262,13 @@ void check_destroyed(OSThread* t) {
|
||||
|
||||
void Multilibultra::wait_for_resumed(RDRAM_ARG1) {
|
||||
check_destroyed(TO_PTR(OSThread, thread_self));
|
||||
TO_PTR(OSThread, thread_self)->context->running.wait(false);
|
||||
//TO_PTR(OSThread, thread_self)->context->descheduled.wait(false);
|
||||
//TO_PTR(OSThread, thread_self)->context->descheduled.store(false);
|
||||
TO_PTR(OSThread, thread_self)->context->scheduled.wait(false);
|
||||
TO_PTR(OSThread, thread_self)->context->scheduled.store(false);
|
||||
check_destroyed(TO_PTR(OSThread, thread_self));
|
||||
}
|
||||
|
||||
void Multilibultra::pause_thread_impl(OSThread* t) {
|
||||
t->state = OSThreadState::PREEMPTED;
|
||||
t->context->running.store(false);
|
||||
t->context->running.notify_all();
|
||||
}
|
||||
|
||||
void Multilibultra::resume_thread_impl(OSThread *t) {
|
||||
if (t->state == OSThreadState::PREEMPTED) {
|
||||
// Nothing to do here
|
||||
}
|
||||
t->state = OSThreadState::RUNNING;
|
||||
t->context->running.store(true);
|
||||
t->context->running.notify_all();
|
||||
}
|
||||
|
||||
PTR(OSThread) Multilibultra::this_thread() {
|
||||
return thread_self;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user