mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 11:12:29 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
327
src/util/BlizzardCore.cpp
Normal file
327
src/util/BlizzardCore.cpp
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
#include "util/BlizzardCore.hpp"
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <storm/Memory.hpp>
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
#include <libkern/OSAtomic.h>
|
||||
#elif defined(WHOA_SYSTEM_LINUX)
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
bool Blizzard::System_Thread::s_initialized;
|
||||
Blizzard::System_Debug::AssertCallback Blizzard::System_Debug::s_assertCallback = nullptr;
|
||||
Blizzard::Lock::DoOnceData Blizzard::System_Lock::s_initMutexAttrOnce;
|
||||
Blizzard::System_Lock::MutexAttr Blizzard::System_Lock::s_mutexattr;
|
||||
Blizzard::Thread::ThreadRecord* Blizzard::System_Thread::s_mainThread;
|
||||
Blizzard::Lock::Mutex Blizzard::System_Thread::s_mutex;
|
||||
Blizzard::Lock::Mutex Blizzard::System_Thread::s_registryMutex;
|
||||
Blizzard::Thread::TLSSlot Blizzard::System_Thread::s_stackTraceEntryPointTLS;
|
||||
Blizzard::Thread::TLSSlot Blizzard::System_Thread::s_threadRecordTLS;
|
||||
std::map<Blizzard::Thread::ThreadRecord*, Blizzard::Thread::ThreadRecord*>* Blizzard::System_Thread::s_threadRegistry;
|
||||
Blizzard::Thread::TLSSlot* Blizzard::System_Thread::s_slotList[128];
|
||||
int32_t Blizzard::System_Thread::s_slotListUsed;
|
||||
|
||||
void Blizzard::Debug::Assert(const char* a1, const char* a2, uint32_t a3) {
|
||||
if (System_Debug::s_assertCallback) {
|
||||
System_Debug::s_assertCallback(a1, "", a2, a3);
|
||||
}
|
||||
}
|
||||
|
||||
void Blizzard::Debug::SetAssertHandler(Blizzard::System_Debug::AssertCallback callback) {
|
||||
System_Debug::s_assertCallback = callback;
|
||||
}
|
||||
|
||||
void* Blizzard::Memory::Allocate(uint32_t bytes) {
|
||||
return SMemAlloc(bytes, __FILE__, __LINE__, 0);
|
||||
}
|
||||
|
||||
void* Blizzard::Memory::Allocate(uint32_t a1, uint32_t a2, const char* a3, uint32_t a4, const char* a5) {
|
||||
// TODO
|
||||
// - what is a5?
|
||||
// - arg order?
|
||||
// - flag manipluation?
|
||||
|
||||
return SMemAlloc(a1, a3, a4, a2);
|
||||
}
|
||||
|
||||
void Blizzard::Memory::Free(void* ptr) {
|
||||
SMemFree(ptr);
|
||||
}
|
||||
|
||||
int32_t Blizzard::String::Copy(char* dst, const char* src, size_t len) {
|
||||
if (!len || !dst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
*dst = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* v3 = dst + len - 1;
|
||||
|
||||
char v4;
|
||||
const char* v5;
|
||||
char* v6;
|
||||
|
||||
int32_t result;
|
||||
|
||||
if (dst < v3 && (v4 = *src, v5 = src, v6 = dst, *src)) {
|
||||
do {
|
||||
*v6++ = v4;
|
||||
|
||||
if (v3 <= v6) {
|
||||
break;
|
||||
}
|
||||
|
||||
v4 = (v5++)[1];
|
||||
} while ( v4 );
|
||||
|
||||
result = v6 - dst;
|
||||
} else {
|
||||
v6 = dst;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
*v6 = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Blizzard::String::Length(const char* a1) {
|
||||
if (a1) {
|
||||
return strlen(a1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Blizzard::String::MemFill(void* a1, uint32_t a2, unsigned char a3) {
|
||||
memset(a1, a3, a2);
|
||||
}
|
||||
|
||||
void Blizzard::Process::Sleep(uint32_t duration) {
|
||||
struct timespec request;
|
||||
|
||||
request.tv_sec = 0;
|
||||
request.tv_nsec = duration * 1000000;
|
||||
|
||||
nanosleep(&request, nullptr);
|
||||
}
|
||||
|
||||
void Blizzard::Lock::DoOnce(DoOnceData& a1, void (*a2)(void*), void* a3) {
|
||||
if (!a1.done) {
|
||||
if (Blizzard::Lock::Atomic::Increment(&a1.atomic) == 1) {
|
||||
a2(a3);
|
||||
a1.done = true;
|
||||
} else {
|
||||
while (!a1.done) {
|
||||
Blizzard::Process::Sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Blizzard::Lock::MutexCreate(Blizzard::Lock::Mutex& a1) {
|
||||
Blizzard::Lock::DoOnce(System_Lock::s_initMutexAttrOnce, System_Lock::InitAttr, 0);
|
||||
|
||||
bool result = pthread_mutex_init(&a1, &System_Lock::s_mutexattr);
|
||||
|
||||
// Blizzard::Debug::Assert(result == 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Blizzard::Lock::MutexEnter(Blizzard::Lock::Mutex& a1) {
|
||||
bool result = pthread_mutex_lock(&a1);
|
||||
|
||||
// Blizzard::Debug::Assert(result == 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Blizzard::Lock::MutexLeave(Blizzard::Lock::Mutex& a1) {
|
||||
bool result = pthread_mutex_unlock(&a1);
|
||||
|
||||
// Blizzard::Debug::Assert(result == 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t Blizzard::Lock::Atomic::Increment(volatile int32_t* value) {
|
||||
#if defined(WHOA_SYSTEM_MAC)
|
||||
return OSAtomicAdd32(1, value);
|
||||
#elif defined(WHOA_SYSTEM_LINUX)
|
||||
volatile std::atomic<int32_t> atom(*value);
|
||||
std::atomic_fetch_add<int32_t>(&atom, 1);
|
||||
return atom;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Blizzard::System_Lock::InitAttr(void* a1) {
|
||||
pthread_mutexattr_init(&System_Lock::s_mutexattr);
|
||||
pthread_mutexattr_settype(&System_Lock::s_mutexattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
void Blizzard::Thread::AllocateLocalStorage(TLSSlot* slot) {
|
||||
System_Thread::AllocateLocalStorage(slot, 0);
|
||||
}
|
||||
|
||||
void* Blizzard::Thread::RegisterLocalStorage(TLSSlot* slot, void* (*constructor)(void*), void* userData, void (*destructor)(void*)) {
|
||||
if (!System_Thread::TLSSlotIsAllocated(slot) && !System_Thread::AllocateTLSSlot(slot, destructor)) {
|
||||
// Blizzard::Debug::Assert(!"Unable to allocate thread-local storage");
|
||||
}
|
||||
|
||||
void* value;
|
||||
|
||||
value = System_Thread::InternalGetLocalStorage(slot);
|
||||
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
value = constructor(userData);
|
||||
|
||||
System_Thread::InternalSetLocalStorage(slot, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Blizzard::Thread::SetLocalStorage(const TLSSlot* slot, const void* value) {
|
||||
BLIZZARD_ASSERT(Blizzard::Thread::TLSSlotIsAllocated(slot));
|
||||
|
||||
System_Thread::InternalSetLocalStorage(slot, value);
|
||||
}
|
||||
|
||||
bool Blizzard::Thread::TLSSlotIsAllocated(const TLSSlot* slot) {
|
||||
return System_Thread::TLSSlotIsAllocated(slot);
|
||||
}
|
||||
|
||||
void Blizzard::System_Thread::AddToRegistry(Thread::ThreadRecord* thread) {
|
||||
Blizzard::Lock::MutexEnter(System_Thread::s_registryMutex);
|
||||
|
||||
if (!System_Thread::s_threadRegistry) {
|
||||
void* v2 = Blizzard::Memory::Allocate(sizeof(std::map<Thread::ThreadRecord*, Thread::ThreadRecord*>), 0, __FILE__, __LINE__, nullptr);
|
||||
System_Thread::s_threadRegistry = new (v2) std::map<Thread::ThreadRecord*, Thread::ThreadRecord*>();
|
||||
}
|
||||
|
||||
System_Thread::s_threadRegistry->insert(std::pair<Thread::ThreadRecord*, Thread::ThreadRecord*>(thread, thread));
|
||||
|
||||
Blizzard::Lock::MutexLeave(System_Thread::s_registryMutex);
|
||||
}
|
||||
|
||||
bool Blizzard::System_Thread::AllocateLocalStorage(Thread::TLSSlot* slot, void (*destructor)(void*)) {
|
||||
System_Thread::InitThreadSystem();
|
||||
|
||||
BLIZZARD_ASSERT(!System_Thread::TLSSlotIsAllocated(slot));
|
||||
|
||||
int32_t result;
|
||||
|
||||
if (System_Thread::InternalAllocateLocalStorage(slot, destructor)) {
|
||||
slot->destructor = destructor;
|
||||
|
||||
Blizzard::Lock::MutexEnter(System_Thread::s_mutex);
|
||||
|
||||
int32_t v3 = System_Thread::s_slotListUsed;
|
||||
System_Thread::s_slotList[System_Thread::s_slotListUsed] = slot;
|
||||
System_Thread::s_slotListUsed = v3 + 1;
|
||||
|
||||
Blizzard::Lock::MutexLeave(System_Thread::s_mutex);
|
||||
|
||||
result = 1;
|
||||
} else {
|
||||
BLIZZARD_ASSERT(!"failed to allocate TLS");
|
||||
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Blizzard::System_Thread::AllocateTLSSlot(Thread::TLSSlot* slot, void (*destructor)(void*)) {
|
||||
System_Thread::InitThreadSystem();
|
||||
|
||||
Blizzard::Lock::MutexEnter(System_Thread::s_mutex);
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
if (System_Thread::TLSSlotIsAllocated(slot) || System_Thread::AllocateLocalStorage(slot, destructor)) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
Blizzard::Lock::MutexLeave(System_Thread::s_mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Blizzard::System_Thread::InitThreadSystem() {
|
||||
if (System_Thread::s_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
System_Thread::s_initialized = true;
|
||||
|
||||
Blizzard::Lock::MutexCreate(System_Thread::s_mutex);
|
||||
Blizzard::Lock::MutexCreate(System_Thread::s_registryMutex);
|
||||
|
||||
Blizzard::Thread::AllocateLocalStorage(&System_Thread::s_threadRecordTLS);
|
||||
Blizzard::Thread::AllocateLocalStorage(&System_Thread::s_stackTraceEntryPointTLS);
|
||||
|
||||
System_Thread::s_mainThread = System_Thread::NewThread(nullptr, nullptr, nullptr);
|
||||
Blizzard::Thread::SetLocalStorage(&System_Thread::s_threadRecordTLS, System_Thread::s_mainThread);
|
||||
|
||||
System_Thread::s_mainThread->unkC = 1;
|
||||
System_Thread::s_mainThread->unk10 = 1;
|
||||
}
|
||||
|
||||
bool Blizzard::System_Thread::InternalAllocateLocalStorage(Thread::TLSSlot* slot, void (*destructor)(void*)) {
|
||||
if (!pthread_key_create(&slot->key, destructor)) {
|
||||
slot->allocated = true;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* Blizzard::System_Thread::InternalGetLocalStorage(const Thread::TLSSlot* slot) {
|
||||
return pthread_getspecific(slot->key);
|
||||
}
|
||||
|
||||
void Blizzard::System_Thread::InternalSetLocalStorage(const Thread::TLSSlot* slot, const void* value) {
|
||||
int32_t err = pthread_setspecific(slot->key, value);
|
||||
|
||||
BLIZZARD_ASSERT(err == 0);
|
||||
}
|
||||
|
||||
Blizzard::Thread::ThreadRecord* Blizzard::System_Thread::NewThread(uint32_t (*a1)(void*), void* a2, const char* a3) {
|
||||
const char* v3 = a3;
|
||||
|
||||
if (!a3) {
|
||||
v3 = "";
|
||||
}
|
||||
|
||||
int32_t v4 = Blizzard::String::Length(v3);
|
||||
|
||||
Blizzard::Thread::ThreadRecord* thread = static_cast<Blizzard::Thread::ThreadRecord*>(
|
||||
Blizzard::Memory::Allocate(sizeof(Blizzard::Thread::ThreadRecord) + v4 + 1, 0, __FILE__, __LINE__, nullptr)
|
||||
);
|
||||
|
||||
Blizzard::String::MemFill(thread, sizeof(Blizzard::Thread::ThreadRecord), 0);
|
||||
|
||||
thread->unk4 = a2;
|
||||
thread->unk8 = a1;
|
||||
thread->unkC = 0;
|
||||
thread->unk10 = 2;
|
||||
|
||||
Blizzard::String::Copy(thread->unk2C, v3, v4 + 1);
|
||||
|
||||
System_Thread::AddToRegistry(thread);
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
bool Blizzard::System_Thread::TLSSlotIsAllocated(const Thread::TLSSlot* slot) {
|
||||
return slot->allocated;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue