|
|
@ -35,18 +35,22 @@ |
|
|
|
#include <exec/memory.h> |
|
|
|
#include <exec/semaphores.h> |
|
|
|
#include <clib/exec_protos.h> |
|
|
|
#define ALLOC_MEM(x) AllocVec(x, MEMF_ANY | MEMF_CLEAR) |
|
|
|
#define FREE_MEM(x) FreeVec(x) |
|
|
|
#define Debug(x,y,z) |
|
|
|
#define ALLOC_LIST(x) AllocVec(x, MEMF_ANY | MEMF_CLEAR) |
|
|
|
#define FREE_LIST(x) FreeVec(x) |
|
|
|
#define ALLOC_MEM(x, y) AllocPooledZero(x, y) |
|
|
|
#define FREE_MEM(x, y, z) FreePooled(x, y, z) |
|
|
|
#define Debug(x, y, z) |
|
|
|
#else |
|
|
|
#include <stdlib.h> |
|
|
|
#define ALLOC_MEM(x) calloc(1L,x) |
|
|
|
#define FREE_MEM(x) free(x) |
|
|
|
#define Debug(x,y,z) |
|
|
|
#define ALLOC_LIST(x) calloc(1L, x) |
|
|
|
#define FREE_LIST(x) free(x) |
|
|
|
#define ALLOC_MEM(x, y) calloc(1L, y) |
|
|
|
#define FREE_MEM(x, y, z) free(y) |
|
|
|
#define Debug(x, y, z) |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(__x86_64__) || defined(__aarch64__) || \ |
|
|
|
defined(_M_AMD64) || defined(_M_ARM64) || \ |
|
|
|
defined(_M_AMD64) || defined(_M_ARM64) || \ |
|
|
|
defined(__powerpc64__) |
|
|
|
#define P64BIT |
|
|
|
#endif |
|
|
@ -56,9 +60,9 @@ |
|
|
|
*/ |
|
|
|
struct MemoryBlock |
|
|
|
{ |
|
|
|
struct MemoryBlock* next; |
|
|
|
struct MemoryBlock *next; |
|
|
|
size_t size; |
|
|
|
void* address; |
|
|
|
void *address; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
@ -66,7 +70,8 @@ struct MemoryBlock |
|
|
|
*/ |
|
|
|
struct MemoryList |
|
|
|
{ |
|
|
|
struct MemoryBlock* first; |
|
|
|
struct MemoryBlock *first; |
|
|
|
void *pool; |
|
|
|
size_t peak; |
|
|
|
size_t size; |
|
|
|
long count; |
|
|
@ -75,28 +80,56 @@ struct MemoryList |
|
|
|
/** |
|
|
|
* @brief Global list of allocated memory. |
|
|
|
*/ |
|
|
|
struct MemoryList* list = nullptr; |
|
|
|
struct MemoryList *list = nullptr; |
|
|
|
|
|
|
|
void alloc_error(char*, size_t); |
|
|
|
void dealloc_error(char*, void*); |
|
|
|
void alloc_error(char *, size_t); |
|
|
|
void dealloc_error(char *, void *); |
|
|
|
|
|
|
|
#if defined(AMIGA) |
|
|
|
|
|
|
|
static void MemZero(void *address, ULONG size) |
|
|
|
{ |
|
|
|
char *c = (char *)address; |
|
|
|
int n = size; |
|
|
|
do |
|
|
|
{ |
|
|
|
*c++ = '\0'; |
|
|
|
} while (--n); |
|
|
|
} |
|
|
|
|
|
|
|
static void *AllocPooledZero(void *pool, size_t size) |
|
|
|
{ |
|
|
|
ULONG memSize = (ULONG)size; |
|
|
|
void *memory = AllocPooled(pool, memSize); |
|
|
|
if (memory != NULL) |
|
|
|
{ |
|
|
|
MemZero(memory, memSize); |
|
|
|
} |
|
|
|
return memory; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief Allocate memory and add it to the global memory list. |
|
|
|
*/ |
|
|
|
void* AllocMemSafe(size_t size) |
|
|
|
void *AllocMemSafe(size_t size) |
|
|
|
{ |
|
|
|
struct MemoryBlock* newblock; |
|
|
|
struct MemoryBlock *newblock; |
|
|
|
size_t allocsize; |
|
|
|
|
|
|
|
if (list == nullptr) |
|
|
|
{ |
|
|
|
list = (struct MemoryList*)ALLOC_MEM(sizeof(struct MemoryList)); |
|
|
|
list = (struct MemoryList *)ALLOC_LIST(sizeof(struct MemoryList)); |
|
|
|
if (!list) |
|
|
|
{ |
|
|
|
alloc_error("list", sizeof(struct MemoryList)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#if defined(AMIGA) |
|
|
|
list->pool = CreatePool(MEMF_ANY, 4096, 512); |
|
|
|
#endif |
|
|
|
list->first = nullptr; |
|
|
|
list->peak = 0; |
|
|
|
list->size = 0; |
|
|
@ -104,24 +137,24 @@ void* AllocMemSafe(size_t size) |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef P64BIT |
|
|
|
// Align to bytes of 8 |
|
|
|
allocsize = (size + 7) & ~0x07; |
|
|
|
// Align to bytes of 8, remove 0 bytes allocations |
|
|
|
allocsize = (size + 8) & ~0x07; |
|
|
|
#else |
|
|
|
// Align to bytes of 4 |
|
|
|
allocsize = (size + 3) & ~0x03; |
|
|
|
// Align to bytes of 4, remove 0 bytes allocations |
|
|
|
allocsize = (size + 4) & ~0x03; |
|
|
|
#endif |
|
|
|
|
|
|
|
newblock = (struct MemoryBlock*)ALLOC_MEM(sizeof(struct MemoryBlock)); |
|
|
|
if (!newblock) |
|
|
|
newblock = (struct MemoryBlock *)ALLOC_MEM(list->pool, sizeof(struct MemoryBlock)); |
|
|
|
if (newblock == NULL) |
|
|
|
{ |
|
|
|
alloc_error("block", sizeof(struct MemoryBlock)); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
newblock->address = (struct MemoryBlock*)ALLOC_MEM(allocsize); |
|
|
|
if (!newblock->address) |
|
|
|
newblock->address = (struct MemoryBlock *)ALLOC_MEM(list->pool, allocsize); |
|
|
|
if (newblock->address == NULL) |
|
|
|
{ |
|
|
|
FREE_MEM(newblock); |
|
|
|
FREE_MEM(list->pool, newblock, sizeof(struct MemoryBlock)); |
|
|
|
alloc_error("memory", allocsize); |
|
|
|
return 0; |
|
|
|
} |
|
|
@ -141,7 +174,7 @@ void* AllocMemSafe(size_t size) |
|
|
|
return newblock->address; |
|
|
|
} |
|
|
|
|
|
|
|
void RemoveMemSafe(void* block, bool deallocate) |
|
|
|
void RemoveMemSafe(void *block, bool deallocate) |
|
|
|
{ |
|
|
|
struct MemoryBlock *current, *previous; |
|
|
|
|
|
|
@ -185,19 +218,19 @@ void RemoveMemSafe(void* block, bool deallocate) |
|
|
|
|
|
|
|
if (deallocate) |
|
|
|
{ |
|
|
|
FREE_MEM(current->address); |
|
|
|
FREE_MEM(list->pool, current->address, current->size); |
|
|
|
} |
|
|
|
|
|
|
|
current->address = nullptr; |
|
|
|
current->next = nullptr; |
|
|
|
current->size = 0; |
|
|
|
FREE_MEM(current); |
|
|
|
FREE_MEM(list->pool, current, sizeof(struct MemoryBlock)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief Deallocate memory from the global memory list. |
|
|
|
*/ |
|
|
|
void FreeMemSafe(void* block) |
|
|
|
void FreeMemSafe(void *block) |
|
|
|
{ |
|
|
|
RemoveMemSafe(block, true); |
|
|
|
} |
|
|
@ -206,7 +239,7 @@ void FreeMemSafe(void* block) |
|
|
|
* @brief Detach an allocated memory from the global memory list. |
|
|
|
* @details The memory block is only detached, not deallocated. |
|
|
|
*/ |
|
|
|
void DetachMemSafe(void* block) |
|
|
|
void DetachMemSafe(void *block) |
|
|
|
{ |
|
|
|
RemoveMemSafe(block, false); |
|
|
|
} |
|
|
@ -227,29 +260,34 @@ void FreeAllSafe() |
|
|
|
while (current != nullptr) |
|
|
|
{ |
|
|
|
next = current->next; |
|
|
|
FREE_MEM(current->address); |
|
|
|
FREE_MEM(current); |
|
|
|
FREE_MEM(list->pool, current->address, current->size); |
|
|
|
FREE_MEM(list->pool, current, sizeof(struct MemoryBlock)); |
|
|
|
current = next; |
|
|
|
} |
|
|
|
|
|
|
|
FREE_MEM(list); |
|
|
|
#if defined(AMIGA) |
|
|
|
DeletePool(list->pool); |
|
|
|
#endif |
|
|
|
|
|
|
|
FREE_LIST(list); |
|
|
|
list = nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief Get memory usage in the global memory list. |
|
|
|
*/ |
|
|
|
void MemUsage(long* blocks, long* size, long* peak) |
|
|
|
void MemUsage(long *blocks, long *size, long *peak) |
|
|
|
{ |
|
|
|
*blocks = list->count; |
|
|
|
*size = (long)list->size; |
|
|
|
*peak = (long)list->peak;; |
|
|
|
*peak = (long)list->peak; |
|
|
|
; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief Log a memory allocation error |
|
|
|
*/ |
|
|
|
void alloc_error(char* descr, size_t size) |
|
|
|
void alloc_error(char *descr, size_t size) |
|
|
|
{ |
|
|
|
Debug("Memory allocation error (%s) with size (%d)\n", descr, size); |
|
|
|
//if (size == 0) |
|
|
@ -259,7 +297,7 @@ void alloc_error(char* descr, size_t size) |
|
|
|
/** |
|
|
|
* @brief Log a memory deallocation error |
|
|
|
*/ |
|
|
|
void dealloc_error(char* descr, void* p) |
|
|
|
void dealloc_error(char *descr, void *p) |
|
|
|
{ |
|
|
|
Debug("Memory deallocation error (%s) address (%x)\n", descr, p); |
|
|
|
} |