Use a global spinlock to lock the alloc/free functions

This commit is contained in:
Maschell 2021-09-28 17:58:20 +02:00
parent 01a2396b83
commit d36d3610ca
4 changed files with 29 additions and 36 deletions

View File

@ -101,7 +101,7 @@ public:
} }
//! Shutdown thread //! Shutdown thread
virtual void shutdownThread() { void shutdownThread() {
//! wait for thread to finish //! wait for thread to finish
if (pThread && !(iAttributes & eAttributeDetach)) { if (pThread && !(iAttributes & eAttributeDetach)) {
while (isThreadSuspended()) { while (isThreadSuspended()) {

View File

@ -68,13 +68,13 @@ void *MemoryMappingAlloc(uint32_t size) {
return res; return res;
} }
void *MemoryMappingAllocEx(uint32_t size, uint32_t align) { void *MemoryMappingAllocEx(uint32_t size, int32_t align) {
void *res = MemoryMapping_alloc(size, align); void *res = MemoryMapping_alloc(size, align);
//DEBUG_FUNCTION_LINE("[res %08X] allocEX %d %d ", res, size, align); //DEBUG_FUNCTION_LINE("[res %08X] allocEX %d %d ", res, size, align);
return res; return res;
} }
void *MemoryMappingAllocForGX2Ex(uint32_t size, uint32_t align) { void *MemoryMappingAllocForGX2Ex(uint32_t size, int32_t align) {
void *res = MemoryMapping_allocVideoMemory(size, align); void *res = MemoryMapping_allocVideoMemory(size, align);
//DEBUG_FUNCTION_LINE("[res %08X] allocEX %d %d ", res, size, align); //DEBUG_FUNCTION_LINE("[res %08X] allocEX %d %d ", res, size, align);
return res; return res;

View File

@ -13,6 +13,8 @@
#include <coreinit/debug.h> #include <coreinit/debug.h>
#include <cstdio> #include <cstdio>
OSSpinLock allocFreeSpinlock;
// #define DEBUG_FUNCTION_LINE(x,...) // #define DEBUG_FUNCTION_LINE(x,...)
void runOnAllCores(CThread::Callback callback, void *callbackArg, int32_t iAttr = 0, int32_t iPriority = 16, int32_t iStackSize = 0x8000) { void runOnAllCores(CThread::Callback callback, void *callbackArg, int32_t iAttr = 0, int32_t iPriority = 16, int32_t iStackSize = 0x8000) {
@ -382,17 +384,22 @@ void MemoryMapping_setupMemoryMapping() {
//runOnAllCores(writeSegmentRegister,&srTableCpy); //runOnAllCores(writeSegmentRegister,&srTableCpy);
} }
void *MemoryMapping_alloc(uint32_t size, uint32_t align) { void *MemoryMapping_allocEx(uint32_t size, int32_t align, bool videoOnly) {
OSUninterruptibleSpinLock_Acquire(&allocFreeSpinlock);
void *res = nullptr; void *res = nullptr;
for (int32_t i = 0; /* waiting for a break */; i++) { for (int32_t i = 0; /* waiting for a break */; i++) {
if (mem_mapping[i].physical_addresses == nullptr) { if (mem_mapping[i].physical_addresses == nullptr) {
break; break;
} }
auto heapHandle = (MEMHeapHandle) mem_mapping[i].effective_start_address; uint32_t effectiveAddress = mem_mapping[i].effective_start_address;
auto heapHandle = (MEMHeapHandle) effectiveAddress;
auto *heap = (MEMExpHeap *) heapHandle; auto *heap = (MEMExpHeap *) heapHandle;
auto header = (MEMHeapHeader *) heap;
OSUninterruptibleSpinLock_Acquire(&header->lock); // Skip non-video memory
if (videoOnly && ((effectiveAddress < MEMORY_START_VIDEO) || (effectiveAddress > MEMORY_END_VIDEO))) {
continue;
}
res = MEMAllocFromExpHeapEx(heapHandle, size, align); res = MEMAllocFromExpHeapEx(heapHandle, size, align);
auto cur = heap->usedList.head; auto cur = heap->usedList.head;
while (cur != nullptr) { while (cur != nullptr) {
@ -404,39 +411,27 @@ void *MemoryMapping_alloc(uint32_t size, uint32_t align) {
DCFlushRange(cur, sizeof(MEMExpHeapBlock)); DCFlushRange(cur, sizeof(MEMExpHeapBlock));
cur = cur->next; cur = cur->next;
} }
OSUninterruptibleSpinLock_Release(&header->lock);
if (res != nullptr) { if (res != nullptr) {
break; break;
} }
} }
OSUninterruptibleSpinLock_Release(&allocFreeSpinlock);
return res; return res;
} }
void *MemoryMapping_allocVideoMemory(uint32_t size, uint32_t align) { void *MemoryMapping_alloc(uint32_t size, int32_t align) {
void *res = nullptr; return MemoryMapping_allocEx(size, align, false);
for (int32_t i = 0; /* waiting for a break */; i++) {
if (mem_mapping[i].physical_addresses == nullptr) {
break;
}
uint32_t effectiveAddress = mem_mapping[i].effective_start_address;
// Skip non-video memory
if (effectiveAddress < MEMORY_START_VIDEO || effectiveAddress > MEMORY_END_VIDEO) {
continue;
}
res = MEMAllocFromExpHeapEx((MEMHeapHandle) mem_mapping[i].effective_start_address, size, align);
if (res != nullptr) {
break;
}
}
return res;
} }
void *MemoryMapping_allocVideoMemory(uint32_t size, int32_t align) {
return MemoryMapping_allocEx(size, align, true);
}
void MemoryMapping_free(void *ptr) { void MemoryMapping_free(void *ptr) {
if (ptr == nullptr) { if (ptr == nullptr) {
return; return;
} }
OSUninterruptibleSpinLock_Acquire(&allocFreeSpinlock);
auto ptr_val = (uint32_t) ptr; auto ptr_val = (uint32_t) ptr;
for (int32_t i = 0; /* waiting for a break */; i++) { for (int32_t i = 0; /* waiting for a break */; i++) {
if (mem_mapping[i].physical_addresses == nullptr) { if (mem_mapping[i].physical_addresses == nullptr) {
@ -445,9 +440,7 @@ void MemoryMapping_free(void *ptr) {
if (ptr_val > mem_mapping[i].effective_start_address && ptr_val < mem_mapping[i].effective_end_address) { if (ptr_val > mem_mapping[i].effective_start_address && ptr_val < mem_mapping[i].effective_end_address) {
auto heapHandle = (MEMHeapHandle) mem_mapping[i].effective_start_address; auto heapHandle = (MEMHeapHandle) mem_mapping[i].effective_start_address;
auto *heap = (MEMExpHeap *) heapHandle; auto *heap = (MEMExpHeap *) heapHandle;
auto *header = (MEMHeapHeader *) heapHandle;
OSUninterruptibleSpinLock_Acquire(&header->lock);
MEMFreeToExpHeap((MEMHeapHandle) mem_mapping[i].effective_start_address, ptr); MEMFreeToExpHeap((MEMHeapHandle) mem_mapping[i].effective_start_address, ptr);
auto cur = heap->usedList.head; auto cur = heap->usedList.head;
while (cur != nullptr) { while (cur != nullptr) {
@ -459,10 +452,10 @@ void MemoryMapping_free(void *ptr) {
DCFlushRange(cur, sizeof(MEMExpHeapBlock)); DCFlushRange(cur, sizeof(MEMExpHeapBlock));
cur = cur->next; cur = cur->next;
} }
OSUninterruptibleSpinLock_Release(&header->lock);
break; break;
} }
} }
OSUninterruptibleSpinLock_Release(&allocFreeSpinlock);
} }
uint32_t MemoryMapping_MEMGetAllocatableSize() { uint32_t MemoryMapping_MEMGetAllocatableSize() {

View File

@ -52,7 +52,7 @@ const memory_values_t mem_vals_heap_2[] = {
}; };
#define MEMORY_HEAP1_SIZE 0xE20000 #define MEMORY_HEAP1_SIZE 0xE20000
#define MEMORY_HEAP1 MEMORY_HEAP0 + MEMORY_HEAP0_SIZE #define MEMORY_HEAP1 (MEMORY_HEAP0 + MEMORY_HEAP0_SIZE)
const memory_values_t mem_vals_heap_3[] = { const memory_values_t mem_vals_heap_3[] = {
{0x28000000 + 0x058E0000, 0x28000000 + 0x06000000}, // size: 7296 kB {0x28000000 + 0x058E0000, 0x28000000 + 0x06000000}, // size: 7296 kB
@ -60,7 +60,7 @@ const memory_values_t mem_vals_heap_3[] = {
}; };
#define MEMORY_HEAP2_SIZE 0x720000 #define MEMORY_HEAP2_SIZE 0x720000
#define MEMORY_HEAP2 MEMORY_HEAP1 + MEMORY_HEAP1_SIZE #define MEMORY_HEAP2 (MEMORY_HEAP1 + MEMORY_HEAP1_SIZE)
const memory_values_t mem_vals_heap_4[] = { const memory_values_t mem_vals_heap_4[] = {
{0x28000000 + 0x053C0000, 0x28000000 + 0x05880000}, // size: 4864 kB {0x28000000 + 0x053C0000, 0x28000000 + 0x05880000}, // size: 4864 kB
@ -68,9 +68,9 @@ const memory_values_t mem_vals_heap_4[] = {
}; };
#define MEMORY_HEAP3_SIZE 0x4C0000 #define MEMORY_HEAP3_SIZE 0x4C0000
#define MEMORY_HEAP3 MEMORY_HEAP2 + MEMORY_HEAP2_SIZE #define MEMORY_HEAP3 (MEMORY_HEAP2 + MEMORY_HEAP2_SIZE)
#define MEMORY_HEAP4 MEMORY_HEAP3 + MEMORY_HEAP3_SIZE #define MEMORY_HEAP4 (MEMORY_HEAP3 + MEMORY_HEAP3_SIZE)
const memory_values_t mem_vals_video[] = { const memory_values_t mem_vals_video[] = {
// The GPU doesn't have access to the 0x28000000 - 0x32000000 area, so we need memory from somewhere else. // The GPU doesn't have access to the 0x28000000 - 0x32000000 area, so we need memory from somewhere else.
@ -107,7 +107,7 @@ const memory_values_t mem_vals_video[] = {
}; };
#define MEMORY_START_VIDEO MEMORY_START_VIDEO_BASE #define MEMORY_START_VIDEO MEMORY_START_VIDEO_BASE
#define MEMORY_END_VIDEO MEMORY_START_VIDEO + 0xE60000 #define MEMORY_END_VIDEO (MEMORY_START_VIDEO + 0xE60000)
const memory_mapping_t mem_mapping[] = { const memory_mapping_t mem_mapping[] = {
{MEMORY_HEAP0, MEMORY_HEAP1, mem_vals_heap_1}, {MEMORY_HEAP0, MEMORY_HEAP1, mem_vals_heap_1},
@ -186,9 +186,9 @@ void MemoryMapping_readTestValuesFromMemory();
void MemoryMapping_searchEmptyMemoryRegions(); void MemoryMapping_searchEmptyMemoryRegions();
void *MemoryMapping_alloc(uint32_t size, uint32_t align); void *MemoryMapping_alloc(uint32_t size, int32_t align);
void *MemoryMapping_allocVideoMemory(uint32_t size, uint32_t align); void *MemoryMapping_allocVideoMemory(uint32_t size, int32_t align);
void MemoryMapping_free(void *ptr); void MemoryMapping_free(void *ptr);