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.c548
1 files changed, 0 insertions, 548 deletions
diff --git a/src/common/malloc.c b/src/common/malloc.c
deleted file mode 100644
index b81c25ed5..000000000
--- a/src/common/malloc.c
+++ /dev/null
@@ -1,548 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "malloc.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-// 独自メモリマネージャを使用する場合、次のコメントを外してください。
-//#define USE_MEMMGR
-
-#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR)
-
-void* aMalloc_( size_t size, const char *file, int line, const char *func )
-{
- void *ret;
-
-// printf("%s:%d: in func %s: malloc %d\n",file,line,func,size);
-#ifdef MEMWATCH
- ret=mwMalloc(size,file,line);
-#else
- ret=malloc(size);
-#endif
- if(ret==NULL){
- printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
- exit(1);
-
- }
- return ret;
-}
-void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func )
-{
- void *ret;
-
-// printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
-#ifdef MEMWATCH
- ret=mwCalloc(num,size,file,line);
-#else
- ret=calloc(num,size);
-#endif
- if(ret==NULL){
- printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func);
- exit(1);
-
- }
- return ret;
-}
-
-void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func )
-{
- void *ret;
-
-// printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size);
-#ifdef MEMWATCH
- ret=mwRealloc(p,size,file,line);
-#else
- ret=realloc(p,size);
-#endif
- if(ret==NULL){
- printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func);
- exit(1);
-
- }
- return ret;
-}
-
-char* aStrdup_( const void *p, const char *file, int line, const char *func )
-{
- char *ret;
-
- // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p);
-#ifdef MEMWATCH
- ret=mwStrdup(p,file,line);
-#else
- ret= strdup((char *) p);
-#endif
- if(ret==NULL){
- printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func);
- exit(1);
-
- }
- return ret;
-}
-
-void aFree_( void *p, const char *file, int line, const char *func )
-{
- // printf("%s:%d: in func %s: free %p\n",file,line,func,p);
-#ifdef MEMWATCH
- mwFree(p,file,line);
-#else
- free(p);
-#endif
-}
-
-#elif defined(GCOLLECT)
-
-void * _bcallocA(size_t size, size_t cnt) {
- void *ret = aMallocA(size * cnt);
- memset(ret, 0, size * cnt);
- return ret;
-}
-
-void * _bcalloc(size_t size, size_t cnt) {
- void *ret = aMalloc(size * cnt);
- memset(ret, 0, size * cnt);
- return ret;
-}
-
-char * _bstrdup(const char *chr) {
- int len = strlen(chr);
- char *ret = (char*)aMalloc(len + 1);
- strcpy(ret, chr);
- return ret;
-}
-
-#elif defined(USE_MEMMGR)
-
-/* USE_MEMMGR */
-
-/*
- * メモリマネージャ
- * malloc , free の処理を効率的に出来るようにしたもの。
- * 複雑な処理を行っているので、若干重くなるかもしれません。
- *
- * データ構造など(説明下手ですいません^^; )
- * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」
- * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分
- * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ
- * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって
- * 出来ていたりします。(padding,unit_head を除く)
- *
- * ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ
- * ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな
- * がっています。それにより、不要となったメモリの再利用が効率的に行えます。
- */
-
-/* ブロックに入るデータ量 */
-#define BLOCK_DATA_SIZE 80*1024
-
-/* 一度に確保するブロックの数。 */
-#define BLOCK_ALLOC 32
-
-/* ブロックのアライメント */
-#define BLOCK_ALIGNMENT 64
-
-/* ブロック */
-struct block {
- int block_no; /* ブロック番号 */
- struct block* block_prev; /* 前に確保した領域 */
- struct block* block_next; /* 次に確保した領域 */
- int samesize_no; /* 同じサイズの番号 */
- struct block* samesize_prev; /* 同じサイズの前の領域 */
- struct block* samesize_next; /* 同じサイズの次の領域 */
- int unit_size; /* ユニットのバイト数 0=未使用 */
- int unit_hash; /* ユニットのハッシュ */
- int unit_count; /* ユニットの数 */
- int unit_used; /* 使用済みユニット */
- char data[BLOCK_DATA_SIZE];
-};
-
-struct unit_head {
- struct block* block;
- int size;
- const char* file;
- int line;
-};
-
-static struct block* block_first = NULL;
-static struct block* block_last = NULL;
-static struct block* block_unused = NULL;
-
-/* ユニットへのハッシュ。80KB/64Byte = 1280個 */
-static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最初 */
-static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 埋まってない */
-static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最後 */
-
-/* メモリを使い回せない領域用のデータ */
-struct unit_head_large {
- struct unit_head_large* prev;
- struct unit_head_large* next;
- struct unit_head unit_head;
-};
-static struct unit_head_large *unit_head_large_first = NULL;
-
-static struct block* block_malloc(void);
-static void block_free(struct block* p);
-static void memmgr_info(void);
-
-void* aMalloc_(size_t size, const char *file, int line, const char *func ) {
- int i;
- struct block *block;
- int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
- size = size_hash * BLOCK_ALIGNMENT; /* アライメントの倍数に切り上げ */
-
- if(size == 0) {
- return NULL;
- }
-
- /* ブロック長を超える領域の確保には、malloc() を用いる */
- /* その際、unit_head.block に NULL を代入して区別する */
- if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
-#ifdef MEMWATCH
- struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line);
-#else
- struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size);
-#endif
- if(p != NULL) {
- p->unit_head.block = NULL;
- p->unit_head.size = size;
- p->unit_head.file = file;
- p->unit_head.line = line;
- if(unit_head_large_first == NULL) {
- unit_head_large_first = p;
- p->next = NULL;
- p->prev = NULL;
- } else {
- unit_head_large_first->prev = p;
- p->prev = NULL;
- p->next = unit_head_large_first;
- unit_head_large_first = p;
- }
- return (char *)p + sizeof(struct unit_head_large);
- } else {
- printf("MEMMGR::memmgr_alloc failed.\n");
- exit(1);
- }
- }
-
- /* 同一サイズのブロックが確保されていない時、新たに確保する */
- if(unit_unfill[size_hash] == NULL) {
- block = block_malloc();
- if(unit_first[size_hash] == NULL) {
- /* 初回確保 */
- unit_first[size_hash] = block;
- unit_last[size_hash] = block;
- block->samesize_no = 0;
- block->samesize_prev = NULL;
- block->samesize_next = NULL;
- } else {
- /* 連結作業 */
- unit_last[size_hash]->samesize_next = block;
- block->samesize_no = unit_last[size_hash]->samesize_no + 1;
- block->samesize_prev = unit_last[size_hash];
- block->samesize_next = NULL;
- unit_last[size_hash] = block;
- }
- unit_unfill[size_hash] = block;
- block->unit_size = size + sizeof(struct unit_head);
- block->unit_count = BLOCK_DATA_SIZE / block->unit_size;
- block->unit_used = 0;
- block->unit_hash = size_hash;
- /* 未使用Flagを立てる */
- for(i=0;i<block->unit_count;i++) {
- ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL;
- }
- }
- /* ユニット使用個数加算 */
- block = unit_unfill[size_hash];
- block->unit_used++;
-
- /* ユニット内を全て使い果たした */
- if(block->unit_count == block->unit_used) {
- do {
- unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next;
- } while(
- unit_unfill[size_hash] != NULL &&
- unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used
- );
- }
-
- /* ブロックの中の空きユニット捜索 */
- for(i=0;i<block->unit_count;i++) {
- struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
- if(head->block == NULL) {
- head->block = block;
- head->size = size;
- head->line = line;
- head->file = file;
- return (char *)head + sizeof(struct unit_head);
- }
- }
- // ここに来てはいけない。
- printf("MEMMGR::memmgr_malloc() serious error.\n");
- memmgr_info();
- exit(1);
- return NULL;
-};
-
-void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) {
- void *p = aMalloc_(num * size,file,line,func);
- memset(p,0,num * size);
- return p;
-}
-
-void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) {
- size_t old_size;
- if(memblock == NULL) {
- return aMalloc_(size,file,line,func);
- }
-
- old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size;
- if(old_size > size) {
- // サイズ縮小 -> そのまま返す(手抜き)
- return memblock;
- } else {
- // サイズ拡大
- void *p = aMalloc_(size,file,line,func);
- if(p != NULL) {
- memcpy(p,memblock,old_size);
- }
- aFree_(memblock,file,line,func);
- return p;
- }
-}
-
-char* aStrdup_(const void *p, const char *file, int line, const char *func ) {
- if(p == NULL) {
- return NULL;
- } else {
- int len = strlen(p);
- char *string = (char *)aMalloc_(len + 1,file,line,func);
- memcpy(string,p,len+1);
- return string;
- }
-}
-
-void aFree_(void *ptr, const char *file, int line, const char *func ) {
- struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head));
- if(ptr == NULL) {
- return;
- } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
- /* malloc() で直に確保された領域 */
- struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large));
- if(head_large->prev) {
- head_large->prev->next = head_large->next;
- } else {
- unit_head_large_first = head_large->next;
- }
- if(head_large->next) {
- head_large->next->prev = head_large->prev;
- }
- free(head_large);
- return;
- } else {
- /* ユニット解放 */
- struct block *block = head->block;
- if(head->block == NULL) {
- printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line);
- } else {
- head->block = NULL;
- if(--block->unit_used == 0) {
- /* ブロックの解放 */
- if(unit_unfill[block->unit_hash] == block) {
- /* 空きユニットに指定されている */
- do {
- unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next;
- } while(
- unit_unfill[block->unit_hash] != NULL &&
- unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used
- );
- }
- if(block->samesize_prev == NULL && block->samesize_next == NULL) {
- /* 独立ブロックの解放 */
- unit_first[block->unit_hash] = NULL;
- unit_last[block->unit_hash] = NULL;
- unit_unfill[block->unit_hash] = NULL;
- } else if(block->samesize_prev == NULL) {
- /* 先頭ブロックの解放 */
- unit_first[block->unit_hash] = block->samesize_next;
- (block->samesize_next)->samesize_prev = NULL;
- } else if(block->samesize_next == NULL) {
- /* 末端ブロックの解放 */
- unit_last[block->unit_hash] = block->samesize_prev;
- (block->samesize_prev)->samesize_next = NULL;
- } else {
- /* 中間ブロックの解放 */
- (block->samesize_next)->samesize_prev = block->samesize_prev;
- (block->samesize_prev)->samesize_next = block->samesize_next;
- }
- block_free(block);
- } else {
- /* 空きユニットの再設定 */
- if(
- unit_unfill[block->unit_hash] == NULL ||
- unit_unfill[block->unit_hash]->samesize_no > block->samesize_no
- ) {
- unit_unfill[block->unit_hash] = block;
- }
- }
- }
- }
-}
-
-/* 現在の状況を表示する */
-static void memmgr_info(void) {
- int i;
- struct block *p;
- printf("** Memory Maneger Information **\n");
- if(block_first == NULL) {
- printf("Uninitialized.\n");
- return;
- }
- printf(
- "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n",
- block_last->block_no+1,sizeof(struct block),
- (block_last->block_no+1) * sizeof(struct block) / 1024
- );
- p = block_first;
- for(i=0;i<=block_last->block_no;i++) {
- printf(" Block #%04u : ",p->block_no);
- if(p->unit_size == 0) {
- printf("unused.\n");
- } else {
- printf(
- "size: %05u byte. used: %04u/%04u prev:",
- p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count
- );
- if(p->samesize_prev == NULL) {
- printf("NULL");
- } else {
- printf("%04u",(p->samesize_prev)->block_no);
- }
- printf(" next:");
- if(p->samesize_next == NULL) {
- printf("NULL");
- } else {
- printf("%04u",(p->samesize_next)->block_no);
- }
- printf("\n");
- }
- p = p->block_next;
- }
-}
-
-/* ブロックを確保する */
-static struct block* block_malloc(void) {
- if(block_unused != NULL) {
- /* ブロック用の領域は確保済み */
- struct block* ret = block_unused;
- do {
- block_unused = block_unused->block_next;
- } while(block_unused != NULL && block_unused->unit_size != 0);
- return ret;
- } else {
- /* ブロック用の領域を新たに確保する */
- int i;
- int block_no;
- struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC);
- if(p == NULL) {
- printf("MEMMGR::block_alloc failed.\n");
- exit(1);
- }
- if(block_first == NULL) {
- /* 初回確保 */
- block_no = 0;
- block_first = p;
- } else {
- block_no = block_last->block_no + 1;
- block_last->block_next = p;
- p->block_prev = block_last;
- }
- block_last = &p[BLOCK_ALLOC - 1];
- /* ブロックを連結させる */
- for(i=0;i<BLOCK_ALLOC;i++) {
- if(i != 0) {
- p[i].block_prev = &p[i-1];
- }
- if(i != BLOCK_ALLOC -1) {
- p[i].block_next = &p[i+1];
- }
- p[i].block_no = block_no + i;
- }
-
- /* 未使用ブロックへのポインタを更新 */
- block_unused = &p[1];
- p->unit_size = 1;
- return p;
- }
-}
-
-static void block_free(struct block* p) {
- /* free() せずに、未使用フラグを付けるだけ */
- p->unit_size = 0;
- /* 未使用ポインターを更新する */
- if(block_unused == NULL) {
- block_unused = p;
- } else if(block_unused->block_no > p->block_no) {
- block_unused = p;
- }
-}
-
-static char memmer_logfile[128];
-
-static FILE* memmgr_log(void) {
- FILE *fp = fopen(memmer_logfile,"w");
- if(!fp) { fp = stdout; }
- fprintf(fp,"memmgr: memory leaks found\n");
- return fp;
-}
-
-static void memmer_exit(void) {
- FILE *fp = NULL;
- int i;
- int count = 0;
- struct block *block = block_first;
- struct unit_head_large *large = unit_head_large_first;
- while(block) {
- if(block->unit_size) {
- if(!fp) { fp = memmgr_log(); }
- for(i=0;i<block->unit_count;i++) {
- struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
- if(head->block != NULL) {
- fprintf(
- fp,"%04d : %s line %d size %d\n",++count,
- head->file,head->line,head->size
- );
- }
- }
- }
- block = block->block_next;
- }
- while(large) {
- if(!fp) { fp = memmgr_log(); }
- fprintf(
- fp,"%04d : %s line %d size %d\n",++count,
- large->unit_head.file,
- large->unit_head.line,large->unit_head.size
- );
- large = large->next;
- }
- if(!fp) {
- printf("memmgr: no memory leaks found.\n");
- } else {
- printf("memmgr: memory leaks found.\n");
- fclose(fp);
- }
-}
-#endif
-
-int do_init_memmgr(const char* file) {
- #ifdef USE_MEMMGR
- sprintf(memmer_logfile,"%s.log",file);
- atexit(memmer_exit);
- printf("memmgr: initialised: %s\n",memmer_logfile);
- #endif
- return 0;
-}