#include <atomic>
#include <chrono>
#include <cstdint>
#include <mutex>
extern "C" {
#include <libultra/exception.h>
}
namespace {
std::recursive_mutex gAudioLock;
thread_local int gAudioMaskDepth = 0;
}
namespace {
constexpr int64_t kCushionMs = 100;
std::atomic<int64_t> sAllowedUntilMs{ 0 };
int64_t NowMs() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
.count();
}
}
extern "C" void port_noteMainLoopAlive(void) {
sAllowedUntilMs.store(NowMs() + kCushionMs, std::memory_order_relaxed);
}
extern "C" int port_audioStallHold(void) {
const int64_t allowedUntil = sAllowedUntilMs.load(std::memory_order_relaxed);
return allowedUntil != 0 && NowMs() > allowedUntil;
}
extern "C" void port_lockAudio(void) {
gAudioLock.lock();
}
extern "C" void port_unlockAudio(void) {
gAudioLock.unlock();
}
extern "C" void port_audioIntMaskEnter(void) {
gAudioLock.lock();
gAudioMaskDepth++;
}
extern "C" void port_audioIntMaskExit(void) {
if (gAudioMaskDepth > 0) {
gAudioMaskDepth--;
gAudioLock.unlock();
}
}
extern "C" OSIntMask osSetIntMask(OSIntMask mask) {
if (mask == OS_IM_NONE) {
port_audioIntMaskEnter();
} else {
port_audioIntMaskExit();
}
return 0;
}