summaryrefslogtreecommitdiff
path: root/src/common/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/malloc.c')
-rw-r--r--src/common/malloc.c162
1 files changed, 95 insertions, 67 deletions
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 9976a28d5..77eef2508 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#include "../common/malloc.h"
#include "../common/core.h"
@@ -129,49 +130,49 @@ void aFree_(void *p, const char *file, int line, const char *func)
/* USE_MEMMGR */
/*
- * メモリマネージャ
- * malloc , free の処理を効率的に出来るようにしたもの。
- * 複雑な処理を行っているので、若干重くなるかもしれません。
- *
- * データ構造など(説明下手ですいません^^; )
- * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」
- * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分
- * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ
- * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって
- * 出来ていたりします。(padding,unit_head を除く)
- *
- * ・ブロック同士はリンクリスト(block_prev,block_next) でつながり、同じサイ
- * ズを持つブロック同士もリンクリスト(hash_prev,hash_nect) でつな
- * がっています。それにより、不要となったメモリの再利用が効率的に行えます。
- */
-
-/* ブロックのアライメント */
+* Memory manager
+* able to handle malloc and free efficiently
+* Since the complex processing, I might be slightly heavier.
+*
+* (I'm sorry for the poor description ^ ^;) such as data structures
+* Divided into "blocks" of a plurality of memory, "unit" of a plurality of blocks further
+* I have to divide. Size of the unit, a plurality of distribution equal to the capacity of one block
+* That's what you have. For example, if one unit of 32KB, one block 1 Yu 32Byte
+* Knit, or are able to gather 1024, gathered 512 units 64Byte
+* I can be or have. (Excluding padding, the unit_head)
+*
+* Lead-linked list (block_prev, block_next) in each other is the same size block
+* Linked list (hash_prev, hash_nect) even among such one in the block with the figure
+* I like to have. Thus, reuse of memory no longer needed can be performed efficiently.
+*/
+
+/* Alignment of the block */
#define BLOCK_ALIGNMENT1 16
#define BLOCK_ALIGNMENT2 64
-/* ブロックに入るデータ量 */
+/* Amount of data entering a block */
#define BLOCK_DATA_COUNT1 128
#define BLOCK_DATA_COUNT2 608
-/* ブロックの大きさ: 16*128 + 64*576 = 40KB */
+/* The size of the block: 16*128 + 64*576 = 40KB */
#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 )
#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 )
#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 )
-/* 一度に確保するブロックの数。 */
+/* The number of blocks to be allocated at a time. */
#define BLOCK_ALLOC 104
-/* ブロック */
+/* block */
struct block {
- struct block* block_next; /* 次に確保した領域 */
- struct block* unfill_prev; /* 次の埋まっていない領域 */
- struct block* unfill_next; /* 次の埋まっていない領域 */
- unsigned short unit_size; /* ユニットの大きさ */
- unsigned short unit_hash; /* ユニットのハッシュ */
- unsigned short unit_count; /* ユニットの個数 */
- unsigned short unit_used; /* 使用ユニット数 */
- unsigned short unit_unfill; /* 未使用ユニットの場所 */
- unsigned short unit_maxused; /* 使用ユニットの最大値 */
+ struct block* block_next; /* Then the allocated area */
+ struct block* unfill_prev; /* The previous area not filled */
+ struct block* unfill_next; /* The next area not filled */
+ unsigned short unit_size; /* The size of the unit */
+ unsigned short unit_hash; /* The hash of the unit */
+ unsigned short unit_count; /* The number of units */
+ unsigned short unit_used; /* The number of used units */
+ unsigned short unit_unfill; /* The number of unused units */
+ unsigned short unit_maxused; /* The maximum value of units used */
char data[ BLOCK_DATA_SIZE ];
};
@@ -186,7 +187,7 @@ struct unit_head {
static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1];
static struct block* block_first, *block_last, block_head;
-/* メモリを使い回せない領域用のデータ */
+/* Data for areas that do not use the memory be turned */
struct unit_head_large {
size_t size;
struct unit_head_large* prev;
@@ -209,9 +210,9 @@ static unsigned short size2hash( size_t size )
return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1;
} else if( size <= BLOCK_DATA_SIZE ){
return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2
- + BLOCK_DATA_COUNT1;
+ + BLOCK_DATA_COUNT1;
} else {
- return 0xffff; // ブロック長を超える場合は hash にしない
+ return 0xffff; // If it exceeds the block length hash I do not
}
}
@@ -234,14 +235,14 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
ShowError("_mmalloc: %d\n", size);
return NULL;
}
-
+
if(size == 0) {
return NULL;
}
memmgr_usage_bytes += size;
- /* ブロック長を超える領域の確保には、malloc() を用いる */
- /* その際、unit_head.block に NULL を代入して区別する */
+ /* To ensure the area that exceeds the length of the block, using malloc () to */
+ /* At that time, the distinction by assigning NULL to unit_head.block */
if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
if(p != NULL) {
@@ -266,7 +267,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
}
}
- /* 同一サイズのブロックが確保されていない時、新たに確保する */
+ /* When a block of the same size is not ensured, to ensure a new */
if(hash_unfill[size_hash]) {
block = hash_unfill[size_hash];
} else {
@@ -274,7 +275,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
}
if( block->unit_unfill == 0xFFFF ) {
- // free済み領域が残っていない
+ // there are no more free space that
memmgr_assert(block->unit_used < block->unit_count);
memmgr_assert(block->unit_used == block->unit_maxused);
head = block2unit(block, block->unit_maxused);
@@ -287,7 +288,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
}
if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) {
- // ユニットを使い果たしたので、unfillリストから削除
+ // Since I ran out of the unit, removed from the list unfill
if( block->unfill_prev == &block_head) {
hash_unfill[ size_hash ] = block->unfill_next;
} else {
@@ -331,7 +332,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func )
{
- void *p = _mmalloc(num * size,file,line,func);
+ void *p = malloclib->malloc(num * size,file,line,func);
memset(p,0,num * size);
return p;
}
@@ -340,7 +341,7 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
{
size_t old_size;
if(memblock == NULL) {
- return _mmalloc(size,file,line,func);
+ return malloclib->malloc(size,file,line,func);
}
old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
@@ -348,15 +349,15 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size;
}
if(old_size > size) {
- // サイズ縮小 -> そのまま返す(手抜き)
+ // Size reduction - return> as it is (negligence)
return memblock;
} else {
- // サイズ拡大
- void *p = _mmalloc(size,file,line,func);
+ // Size Large
+ void *p = malloclib->malloc(size,file,line,func);
if(p != NULL) {
memcpy(p,memblock,old_size);
}
- _mfree(memblock,file,line,func);
+ malloclib->free(memblock,file,line,func);
return p;
}
}
@@ -367,7 +368,7 @@ char* _mstrdup(const char *p, const char *file, int line, const char *func )
return NULL;
} else {
size_t len = strlen(p);
- char *string = (char *)_mmalloc(len + 1,file,line,func);
+ char *string = (char *)malloclib->malloc(len + 1,file,line,func);
memcpy(string,p,len+1);
return string;
}
@@ -382,7 +383,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long));
if(head->size == 0) {
- /* malloc() で直に確保された領域 */
+ /* area that is directly secured by malloc () */
struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long));
if(
*(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size)
@@ -407,7 +408,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
FREE(head_large,file,line,func);
}
} else {
- /* ユニット解放 */
+ /* Release unit */
struct block *block = head->block;
if( (char*)head - (char*)block > sizeof(struct block) ) {
ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line);
@@ -425,11 +426,11 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
#endif
memmgr_assert( block->unit_used > 0 );
if(--block->unit_used == 0) {
- /* ブロックの解放 */
+ /* Release of the block */
block_free(block);
} else {
if( block->unfill_prev == NULL) {
- // unfill リストに追加
+ // add to unfill list
if( hash_unfill[ block->unit_hash ] ) {
hash_unfill[ block->unit_hash ]->unfill_prev = block;
}
@@ -444,17 +445,17 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
}
}
-/* ブロックを確保する */
+/* Allocating blocks */
static struct block* block_malloc(unsigned short hash)
{
int i;
struct block *p;
if(hash_unfill[0] != NULL) {
- /* ブロック用の領域は確保済み */
+ /* Space for the block has already been secured */
p = hash_unfill[0];
hash_unfill[0] = hash_unfill[0]->unfill_next;
} else {
- /* ブロック用の領域を新たに確保する */
+ /* Newly allocated space for the block */
p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
if(p == NULL) {
ShowFatalError("Memory manager::block_alloc failed.\n");
@@ -462,17 +463,17 @@ static struct block* block_malloc(unsigned short hash)
}
if(block_first == NULL) {
- /* 初回確保 */
+ /* First ensure */
block_first = p;
} else {
block_last->block_next = p;
}
block_last = &p[BLOCK_ALLOC - 1];
block_last->block_next = NULL;
- /* ブロックを連結させる */
+ /* Linking the block */
for(i=0;i<BLOCK_ALLOC;i++) {
if(i != 0) {
- // p[0] はこれから使うのでリンクには加えない
+ // I do not add the link p [0], so we will use
p[i].unfill_next = hash_unfill[0];
hash_unfill[0] = &p[i];
p[i].unfill_prev = NULL;
@@ -484,7 +485,7 @@ static struct block* block_malloc(unsigned short hash)
}
}
- // unfill に追加
+ // Add to unfill
memmgr_assert(hash_unfill[ hash ] == NULL);
hash_unfill[ hash ] = p;
p->unfill_prev = &block_head;
@@ -530,18 +531,20 @@ static FILE *log_fp;
static void memmgr_log (char *buf)
{
- if( !log_fp )
- {
+ if( !log_fp ) {
time_t raw;
struct tm* t;
+ const char* svn = get_svn_revision();
+ const char* git = get_git_hash();
log_fp = fopen(memmer_logfile,"at");
if (!log_fp) log_fp = stdout;
time(&raw);
t = localtime(&raw);
- fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n",
- (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision());
+ fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (rev %s).\n",
+ (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
+ git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown");
}
fprintf(log_fp, "%s", buf);
return;
@@ -618,7 +621,7 @@ static void memmgr_final (void)
memmgr_log (buf);
#endif /* LOG_MEMMGR */
// get block pointer and free it [celest]
- _mfree(ptr, ALC_MARK);
+ malloclib->free(ptr, ALC_MARK);
}
}
}
@@ -660,9 +663,9 @@ static void memmgr_init (void)
/*======================================
- * Initialise
- *--------------------------------------
- */
+* Initialise
+*--------------------------------------
+*/
/// Tests the memory for errors and memory leaks.
@@ -716,3 +719,28 @@ void malloc_init (void)
memmgr_init ();
#endif
}
+
+void malloc_defaults()
+{
+ malloclib = &malloclib_s;
+ malloclib->init = malloc_init;
+ malloclib->final = malloc_final;
+ malloclib->memory_check = malloc_memory_check;
+ malloclib->usage = malloc_usage;
+ malloclib->verify_ptr = malloc_verify_ptr;
+
+// Athena's built-in Memory Manager
+#ifdef USE_MEMMGR
+ malloclib->malloc = _mmalloc;
+ malloclib->calloc = _mcalloc;
+ malloclib->realloc = _mrealloc;
+ malloclib->strdup = _mstrdup;
+ malloclib->free = _mfree;
+#else
+ malloclib->malloc = aMalloc_;
+ malloclib->calloc = aCalloc_;
+ malloclib->realloc = aRealloc_;
+ malloclib->strdup = aStrdup_;
+ malloclib->free = aFree_;
+#endif
+}