LoginSignup
0
0

More than 1 year has passed since last update.

[07] C言語の独自メモリアロケータの振り返り ... ソースコード全文

Last updated at Posted at 2021-08-06
本シリーズのトップページ
https://qiita.com/robozushi10/items/ca7c25dab3c279ba4e2b

はじめに

本記事の趣旨は「01 概要」に記しているが、
要は 13年前(=2008年) に K&R をマネて実装した「自作メモリアロケータ」の振り返りである.

本項ではコード全文を記す. 

余談

1.

デバッグ用関数定義 memman_debug.c を見ると、「hoge」「piyo」といったログ表示をさせていた..
当時、ifdef が切り替わることをテストしていたのだろうか..

2.

不必要にラッパ関数が多いが、当時の開発現場のコードをマネたのだと思う.
当時のコードは printf() を呼び出すまでに、5個ほどラッパ関数が存在していた.

 

Makefile


PROGRAM=memman

SRCS=main.c \
     memman.c \
     memman_core.c \
     memman_resource.c \
     memman_debug.c 


HDRS=memman.h \
     priv_memman_core.h \
     priv_memman_debug.h \
     priv_memman_std.h

OBJS=$(SRCS:%.c=%.o)

CC = gcc
LIBPATH = 
LIBS     = -lpthread
CFLAGS = -Wall -g -O0 $(INCHEADER) 
LDFLAGS = $(LIBPATH)

$(PROGRAM):$(SRCS) $(HDRS)
    $(CC) $(CFLAGS) -o $(PROGRAM) $(SRCS) $(LDFLAGS) $(LIBS)

clean:
    \rm -f $(PROGRAM) $(OBJS)

 

main.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>


#include "memman.h"
#ifdef DEBUG
#include "priv_memman_debug.h"
#endif
#ifdef DEBUG_CHK_MEMLEAK
#include "priv_memman_debug.h"
#endif

sem_t  Sem;

int
main()
{
    mem_inst_t     * instance = NULL;
    char           * buf[1000];
    int              i        = 0;
    int              j        = 0;
    req_mem_inst_t   req;

    /* セマフォについても管理モジュールを作成し,内部で資源情報を
     * 保持すると良いが,ここでは作成していない  */
    sem_init /* セマフォの初期化 */
    (
        &Sem, /* セマフォ変数の初期化 */
        0,    /* 0:スレッドでセマフォ共有, 非0:プロセスで共有 */
        1     /* 並列処理数 */
    );

    req.functor_alloc = &malloc,
    req.functor_free  = &free,
    req.pool_size     = 4096,
    req.key           = "main",
    req.sem           = &Sem;
    req.pshared       = 0;
    req.value         = 0;

#if 1
    instance = Mman_new_inst(&req);
    for(j = 0; j < 500; j++)
    {
        for(i = 0; i < 1000; i++)
        {
            buf[i] = instance->alloc(0,i);
        }

        for(i = 0; i < 1000; i++) /* alloc よりも小さい値にするとメモリリークが確認出来る */
        {
            instance->free(0, buf[i]);
        }
    }

#ifdef DEBUG_CHK_MEMLEAK
    //Mmc_debug_dump_buf();
#endif /* DEBUG_CHK_MEMLEAK */

    /* robozushi10 セマフォ破棄についても管理モジュールを作成すると良い */
    Mman_delete_inst(instance->id);

    Mman_close();   /* フリーリスト破棄 + フリーノード破棄 */
#else
    for(j = 0; j < 500; j++)
    {
        for(i = 0; i < 1000; i++)
        {
            buf[i] = malloc(i);
        }

        for(i = 0; i < 1000; i++)
        {
            free(buf[i]);
        }
    }
#endif

    return 0;
}

 

memman.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

extern mman_t memrtbl[];

/* key からメモリリソース情報の ID を取得する */
static int
mman_key2id(const char * key)
{
    int       id         =  0;
    const int invalid_id = -1;

    for(id = 0; id < Mman_get_rsrc_num(); id++)
    {
        if(MMAN_STRCMP(key, ==, memrtbl[id].key))
        {
            return id;
        }
    }
    /* even if id is not exist, you don't need error message */
    return invalid_id;
}

/* メモリリソーステーブルに登録 */
static void
mman_register_memrtbl(req_mem_inst_t * req, mem_inst_t * inst)
{
    int id = mman_key2id(req->key);

    memrtbl[id].id            = id;
    strcpy(memrtbl[id].key, req->key);
    memrtbl[id].instance      = inst;
    memrtbl[id].functor_alloc = req->functor_alloc;
    memrtbl[id].functor_free  = req->functor_free; 
    memrtbl[id].pool_size     = req->pool_size;
    memrtbl[id].rest_size     = req->pool_size;
    memrtbl[id].position      = 0;
    memrtbl[id].sem           = req->sem;
}

/* ID からメモリリソース情報へのポインタ取得 */
inline
static mman_t *
mman_get_rsrc(int id)
{
    return &memrtbl[id];
}

/* key からメモリリソース情報へのポインタ取得 */
static mman_t *
mman_get_rsrc_by_key(char * key)
{
    int id = mman_key2id(key);
    if(-1 == id)
    {
        FATAL("mman_key2id error at mman_get_rsrc_by_key(%s)\n", key);
    }

    return &memrtbl[id];
}

/* インスタンスのセットアップ */
static mem_inst_t *
mman_create_instance(req_mem_inst_t * req)
{
    mman_t     * p    = NULL;
    mem_inst_t * inst = NULL;

    inst = malloc(sizeof(mem_inst_t));
    if(NULL == inst)
    {
        FATAL("malloc error at mman_create_instance\n");
    }

    /* メモリリソーステーブルに登録 */
    mman_register_memrtbl(req, inst);

    /* メモリリソース情報へのポインタ取得 */
    p                   = mman_get_rsrc_by_key(req->key);
    inst->id            = p->id;
    inst->alloc         = &Mman_alloc;
    inst->free          = &Mman_free;
    inst->get_used_size = NULL;
    inst->get_rest_size = NULL;

    return inst;
}

/* ID をキーにして,インスタンスを返す(内部用) */
inline
static mem_inst_t *
mman_get_inst(int id)
{
    if((id < 0) || (Mman_get_rsrc_num() < id))
    {
        err_mesg("invalid id(%d)\n", id);
    }
    return memrtbl[id].instance;
}

/* key をキーにして,インスタンスを返す(内部用) */
inline
static mem_inst_t *
mman_get_inst_by_key(char * key)
{
    int      id = mman_key2id(key);

    /* even if id is not exist, you don't need error message */
    return memrtbl[id].instance;
}

/* すでにインスタンスが存在しているかどうか */
static int
mman_is_inst_already_exist(char * key)
{
    mem_inst_t * p = NULL;
    enum { not_exist, exist };

    p = mman_get_inst_by_key(key);

    return (NULL != p) ? exist : not_exist;
}

/* インスタンス作成I/F */
mem_inst_t *
Mman_new_inst(req_mem_inst_t * req)
{
    mem_inst_t  * inst     = NULL;
    int           exist    = 0; 
    static  int   is_flist = 0;

    if(!is_flist)
    {
        Mmc_initialize(Mman_get_rsrc_num());
        is_flist = 1;
    }
    /* 既にインスタンスが存在しているか */
    exist = mman_is_inst_already_exist(req->key);
    if(exist)
    {
        err_mesg("instance is already exist\n");
        return NULL; /* すでにインスタンスが存在している */
    }

    /* インスタンス作成 */
    inst = mman_create_instance(req);
    if(NULL == inst)
    {
        err_mesg("could not create instance\n");
        return NULL;
    }

    return inst;
}

inline
static void
mman_erase_instance(mem_inst_t * inst)
{
    free(inst);
}

void
Mman_delete_inst(int id)
{
    mman_t     * p    = mman_get_rsrc(id);
    mem_inst_t * inst = p->instance;

    mman_erase_instance(inst);
    p->instance = NULL;
}

void
Mman_close(void)
{
    Mmc_shutdown(Mman_get_rsrc_num());
}

mem_inst_t *
Mman_get_inst(int id)
{
    return mman_get_inst(id);
}

void *
Mman_alloc(int id, size_t size)
{
    mman_t  * p = mman_get_rsrc(id);

    /* robozushi10: verify request size */

    return Mmc_alloc(id, size, p->functor_alloc);
}

void
Mman_free(int id, void * ptr) 
{
    mman_t  * p = mman_get_rsrc(id);

    Mmc_free(id, ptr, p->functor_free);
}

 

memman.h


/* 外部公開ヘッダ */
#ifndef   __MEMMAN_H__
#define   __MEMMAN_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>

#if 0
#define  DEBUG                      /* デバッグログ表示                   */
#define  DEBUG_CHK_MEMLEAK          /* メモリリークチェック               */
#endif
#define  DBG_BUFSIZ        (128)    /* メモリリークチェック用バッファ行数 */

/* インスタンス要求時に用いる */
typedef
struct _req_mem_inst_t
{
    void         * (* functor_alloc)(size_t  size); /* メモリ獲得ファンクター */
    void           (* functor_free) (void  * ptr);  /* メモリ解放ファンクター */
    size_t         pool_size; /* メモリサイズ        */
    char         * key;       /* 識別キー(7文字まで) */
    sem_t        * sem;       /* セマフォID          */
    int            pshared;   /* 0: プロセスでセマフォを共有する */
    unsigned int   value;     /* 同時実行可能な数    */
}
    req_mem_inst_t;

/* ユーザが使用するアクセッサ */
typedef
struct _mem_inst_t
{
    void   * (* alloc)        (int id, size_t  size); /* メモリ獲得I/F */
    void     (* free)         (int id, void  * ptr);  /* メモリ解放I/F */
    void     (* get_used_size)(void);                 /* 使用量取得I/F */
    void     (* get_rest_size)(void);                 /* 残量取得関I/F */
    int      id;
}
    mem_inst_t;

/* インスタンス作成I/F */
mem_inst_t * Mman_new_inst   (req_mem_inst_t * req);
mem_inst_t * Mman_get_inst   (int id);
void         Mman_delete_inst(int id);

/* メモリ操作I/F */
void       * Mman_alloc(int id, size_t size);
void         Mman_free (int id, void * p) ;
void         Mman_close(void);

#endif /* __MEMMAN_H__ */

 

memman_core.c


/* [プログラミング言語C] p225 を流用 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#ifdef DEBUG 
#include "priv_memman_debug.h" /* for debug */
#endif /* DEBUG */
#ifdef DEBUG_CHK_MEMLEAK
#include "priv_memman_debug.h" /* for debug */
#endif /* DEBUG */

#define    NALLOC      5120  /* x86 では,sbrk(NALLOC * 8) が最小単位になる */
                            /* 極端に小さくする(2など)とデバッグ出来る */
typedef
struct _mmc_flist_t
{
    Header   base;
    Header * freep;
}
    mmc_flist_t;

static mmc_flist_t ** flist_tbl = NULL;

static void        * mmc_alloc    (int id, unsigned   nbytes, void * functor);
static void          mmc_free     (int id, void     * p,      void * functor);
static void        * add_freelist (int id, void     * ap);
static Header      * morecore     (int id, unsigned   nu, void * functor);
inline
static mmc_flist_t * mmc_get_flist(int id);


/* フリーリストテーブルの構築 */
void
Mmc_initialize(int resource_num)
{
    int    i = 0;

    flist_tbl = malloc(sizeof(mmc_flist_t **) * resource_num);

    for(i = 0; i < resource_num; i++)
    {
        flist_tbl[i] = malloc(sizeof(mmc_flist_t));
    }
}


/* フリーノードをシステムに返却する */
static void
mmc_walk_flist_for_free(void)
{
    ;
}

/* フリーリストテーブルの破棄 */
void
Mmc_shutdown(int resource_num)
{
    int    i = 0;

    for(i = 0; i < resource_num; i++)
    {
        free(flist_tbl[i]);
    }
    free(flist_tbl);

    mmc_walk_flist_for_free(); /* フリーノードをシステムに返却する */
}

void
Mmc_free
(
    int    id,
    void * p,
    void * functor
)
{
    (void) id;
    mmc_free(id, p, functor);
}

/* メモリ解放関数。実際には free せずにフリーリストにつなぐだけ */
static void
mmc_free(int id, void * p, void * functor)
{
    Header * bp = (Header *)p;
    Header * hp = ((Header *)p)-1;

    (void) functor;
/* robozushi10: need sem look */
    MMAN_DBP("[id:%d]mmc_free(): mmc_free(%p)\n", id, p);

    hp->s.ptr = NULL;

#ifdef DEBUG_CHK_MEMLEAK
    Mmc_debug_rm_addr((unsigned)p);
#endif /* DEBUG_CHK_MEMLEAK */
    MMAN_DBP("[id:%d]mmc_free(): call add_freelist(%p)\n", id, bp);
    add_freelist(id, (void *)bp);
/* robozushi10: need sem unlook */
}


void *
Mmc_alloc
(
    int      id,
    size_t   size,
    void   * functor
)
{
    return mmc_alloc(id, size, functor);
}

static void *
mmc_alloc(int id, unsigned nbytes, void * functor)
{
    mmc_flist_t  * flist  = NULL;
    Header       * freep  = NULL;
    Header       * prevp  = NULL;
    Header       * base   = NULL;
    Header       * p      = NULL;
    unsigned int   nunits = ((nbytes + sizeof(Header)-1) / sizeof(Header)) + 1;

/* robozushi10: need sem look */
    flist  = mmc_get_flist(id);
    freep  = flist->freep;
    prevp  = freep;
    base   = &(flist->base);

    if(prevp == NULL) /* 初回のアロケートの場合 */
    {
        base->s.ptr = base;
        freep       = base;
        prevp       = base;
        base->s.size = 0;
    }
    /* 2回目以降は、前回 freep で記憶させておいたアドレスを辿ってフリーノードを探す */

    /* フリーリストを辿って使用可能なフリーノードを探す */
    MMAN_DBP("[id=%d]mmc_alloc(): mmc_alloc(%d bytes)\n", id, nbytes);
    for(p = prevp->s.ptr;  ; prevp=p, p=p->s.ptr)
    {
        MMAN_DBP
        (
            "[id:%d]mmc_alloc(): (p, p->s.ptr, p->s.size) = (%p, %p, %dblk)\n",
            id, p, p->s.ptr, p->s.size
        );
        /* 見つかったフリーノードには要求分以上のブロックがあるか? */
        if(p->s.size >= nunits)
        {
            if(p->s.size == nunits) /* 丁度、要求分だけフリーノードがあった */
            {
                MMAN_DBP("[id:%d]mmc_alloc(): found free-node just fit size(%d blk)\n", id, p->s.size);
                /* フリーノードを全部使い切ったので,フリーリストから削除する */
                prevp->s.ptr = p->s.ptr;
            }
            else /* フリーノードから nunitsブロック分拝借する */
            {
                /* フリーノードの末尾から使用する */
                p->s.size -= nunits;
                p         += p->s.size;
                p->s.size = nunits;
                MMAN_DBP("[id:%d]mmc_alloc(): found free-node(%p, %dblk)\n", id, p, p->s.size);
            }
            /* p が現在ポイントしているよりも1つ前のフリーノードのアドレスを freep に *
             * 記憶させておく. これにより,次に mmc_alloc() が呼ばれたときは freep で記憶 *
             * させておいたフリーノードから探索を開始する                             *
             * (フリーリストは循環構造になっているので全てのノード探索は可能)         */
            flist->freep = freep = prevp;    
            MMAN_DBP("[id:%d]mmc_alloc(): Remember freep=prevp=%p\n", id, freep);
            MMAN_DBP("[id:%d]mmc_alloc(): return %p\n", id, (void *)(p+1));
#ifdef  DEBUG_CHK_MEMLEAK
            Mmc_debug_cp_addr((unsigned)(void *)(p+1));
#endif /* DEBUG_CHK_MEMLEAK */
/* robozushi10: need sem unlook */
            return (void *)(p+1); /* ヘッダ部分を除いた先頭領域のアドレスを返す */ 
        }

        /* 初期状態では p は base をポイントしている => base.s.ptr=freep=prevp=&base */
        if(p == freep)
        {   /* フリーリストを一周した */
            MMAN_DBP("[id:%d]mmc_alloc(): not found free-node\n", id);
            MMAN_DBP("[id:%d]mmc_alloc(): call morecore(%d blk)\n", id, nunits);
            flist->freep = freep;
#if 1
            p = morecore(id, nunits, functor); /* フリーノードが無いのでシステムにメモリ要求 */
#else
#endif
            if(p == NULL)
            {
/* robozushi10: need sem unlook */
                return NULL; /* メモリリーク!! 割り当て可能なメモリが無い */
            }
        }
    } /* for loop end */
/* robozushi10: need sem unlook */
}


/* システム依存のメモリ要求関数(void * functor)を呼び出す */
static Header *
morecore(int id, unsigned nu, void * functor)
{
    mmc_flist_t  * flist              = mmc_get_flist(id);
    Header       * freep              = flist->freep;
    char         * cp                 = NULL;
    Header       * up                 = NULL;
    void         * (* p_func)(size_t) = functor;

    /* 最低 NALLOC からブロックサイズを要求する */
    nu = (nu < NALLOC) ? NALLOC : nu;

    MMAN_DBP("[id:%d]morecore(): require %dblk,  %dByte\n", id, nu, nu * sizeof(Header));
#if 0  /* sbrk() を使った場合 */
    cp = (void *)sbrk(nu * sizeof(Header)); /* ヒープ領域を広げる */
    if(cp == (char *)-1)
    {
        return NULL;
    }
#else  /* malloc で動作確認済み */
    cp = (*p_func)(nu * sizeof(Header));
    if(cp == NULL)
    {
/* robozushi10: need sem unlook */
        FATAL
        (
            "[id:%d]morecore(): alloc(func=%p)(size=%d)\n",
            id,
            p_func,
            nu * sizeof(Header)
        );
    }
#endif

    up         = (Header *)cp; /* sbrk()の返り値 */
    up->s.size = nu;           /* 使用可能なブロックサイズ値 */
    MMAN_DBP("[id:%d]morecore(): allocated new node (addr=%p, blk size=%d)\n", id, up, up->s.size);
    MMAN_DBP("[id:%d]morecore(): call add_freelist(%p)\n", id, (void *)(up+1));
    freep =  add_freelist(id, (void *)(up+1)); /* ヘッダを除いたブロック領域の先頭アドレス */
    return freep;
}


static void *
add_freelist(int id, void * ap)
{
    mmc_flist_t  * flist  = mmc_get_flist(id);
    Header       * freep  = flist->freep;
    Header       * bp     = ((Header *)ap)-1;
    Header       * p      = NULL;

    /* ブレークポイントがフリーノード間に無ければループを継続 */
    for(p = freep; !((p < bp) && (bp < p->s.ptr)); p = p->s.ptr)
    {    
        if((p >= p->s.ptr) && (bp > p || bp < p->s.ptr))
        {
        /* リストを一周し,かつ,ブレークポイントがフリーノード間にある場合   */
        /* なお、if(p >= p->s.ptr) だけではフリーリストの終端が見つけられない */
#ifdef  DEBUG
            if(bp > p)
            {
                MMAN_DBP("[id:%d]add_freelist(): bp(%p) > p(%p)\n", id, bp, p);
            }
            else if(bp < p->s.ptr)
            {
                MMAN_DBP("[id:%d]add_freelist(): bp(%p) < p->s.ptr(%p)\n", id, bp, p->s.ptr);
            }
#endif
            break;
        }
    }

    if((bp + bp->s.size) == p->s.ptr)
    { /* 新たにノードを登録すると丁度既にあるノードと連結する場合,*
       * 2つのノードを合併させる                                   */
        MMAN_DBP
        (
            "[id:%d]add_freelist(): bp->s.size(%d) + p->s.ptr->s.size(%d) = %d\n",
            id,
            bp->s.size,
            p->s.ptr->s.size,
            bp->s.size + p->s.ptr->s.size
        );
        bp->s.size += p->s.ptr->s.size;
        bp->s.ptr   = p->s.ptr->s.ptr;    
    } 
    else
    {
        bp->s.ptr = p->s.ptr;
        MMAN_DBP("[id:%d]add_freelist(): link [new node(%p)] => [next node(%p)]\n", id, bp, bp->s.ptr);
    }

    if(p + p->s.size == bp)
    { /* 現在のフリーノードにブロック分(s.size)だけアドレスを進めると *
       * sbrk()で確保した領域の先頭アドレスと同じになる場合, 現在のフ *
       * リーリスト領域と bp 領域を併せてしまう                       */
        p->s.size += bp->s.size;    
        p->s.ptr   = bp->s.ptr;
    }
    else
    {
        p->s.ptr = bp;
        MMAN_DBP("[id:%d]add_freelist(): link(2) [new node(%p)]\n", id, p->s.ptr);
    }                
    flist->freep = freep = p;

    return freep;
}

/* フリーリスト情報構造体を返す */
inline
static mmc_flist_t *
mmc_get_flist(int id)
{
    return flist_tbl[id];
}

 

memman_debug.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

static unsigned buf[DBG_BUFSIZ];

void
Mmc_debug_cp_addr(unsigned addr)
{
    static int i = 0;
printf("hogepiyo\n");
    i &= (DBG_BUFSIZ - 1); /* DBG_BUFSIZ を超えると上書きする */
    buf[i++] = addr;
}

void
Mmc_debug_rm_addr(unsigned addr)
{
    int i = 0;

//printf("hogepiyo2\n");
    for(i = 0; i < DBG_BUFSIZ; i++)
    {
        if(buf[i] == addr)
        {
            buf[i] = 0;
        }
    }
}

void
Mmc_debug_dump_buf(void)
{
    fprintf(stderr, "-------------------------\n");
    fprintf(stderr, "   memory leack check    \n");
    fprintf(stderr, "-------------------------\n");

    int i = 0;

    while(i != DBG_BUFSIZ)
    {
        i &= (DBG_BUFSIZ - 1);
        if(buf[i] != 0)
        {
            printf("[%d] 0x%08x\n", i, buf[i]);
        }
        i++;
    }
}

 

memman_resource.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"
#include "priv_memman_debug.h"

/* メモリリソーステーブル *//* 型の定義は priv_memman_std.h にて */
#define  MMAN_RESOURCE_BOTTOM   \
    {   -1,     "",    NULL,        0,        0,      NULL,        NULL,       NULL,          0,          0,      NULL}

mman_t
memrtbl[] =
{   
    /* [id]   [key] [sem_id] [pshared] [sem val] [instance] [alloc func] [free func] [pool size] [rest size] [position]*/
    {    0, "main",    NULL,        0,        0,      NULL,        NULL,       NULL,          0,          0,      NULL},
    MMAN_RESOURCE_BOTTOM
};

int
Mman_get_rsrc_num(void)
{
    return MMAN_KEYNUM(memrtbl);
}

 

priv_memman_core.h


#ifndef   __PRIV_MEMMNAN_CORE_H__
#define   __PRIV_MEMMNAN_CORE_H__

#include "memman.h"
#include "priv_memman_std.h"

#define  ALIGNSIZE  4

typedef
struct header_t
{
    union    header * ptr;
    unsigned int      size;
}
    header;

union header
{
    header        s;
    unsigned char align[ALIGNSIZE];
};

typedef union header Header;

void * Mmc_alloc(int id, size_t   size, void * functor);
void   Mmc_free (int id, void   * p,    void * functor);
void   Mmc_initialize(int resource_num);
void   Mmc_shutdown  (int resource_num);
#endif /* __PRIV_MEMMNAN_CORE_H__ */

 

priv_memman_debug.h


#ifndef   __PRIV_MEMMAN_DEBUG_H__
#define   __PRIV_MEMMAN_DEBUG_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"
#include "priv_memman_std.h"
#include "priv_memman_core.h"

void Mmc_debug_cp_addr (unsigned addr);
void Mmc_debug_rm_addr (unsigned addr);
void Mmc_debug_dump_buf(void);

#endif /* __PRIV_MEMMAN_DEBUG_H__ */

 

priv_memman_std.h


#ifndef   __PRIV_MEMMNAN_STD_H__
#define   __PRIV_MEMMNAN_STD_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memman.h"

#define  MMAN_KEYNUM(a)          (sizeof(a)/sizeof(*a))
#define  MMAN_STRCMP(a, R, b)                                    \
(                                                                \
    (a) && (b) && (strlen(a) R strlen(b)) && (0 R strcmp(a, b))  \
)

#ifdef DEBUG
#define err_mesg(fmt, args...)               \
{                                            \
    fprintf                                  \
    (                                        \
        stderr,                              \
        "[%s:%-4d] ERROR: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
}

#define FATAL(fmt, args...)                  \
{                                            \
    fprintf                                  \
    (                                        \
        stderr,                              \
        "[%s:%-4d] FATAL: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
    exit(2);                                 \
}

#define MMAN_DBP(fmt, args...)               \
{                                            \
    fprintf                                  \
    (                                        \
        stdout,                              \
        "[%s:%-4d] DEBUG: " fmt,             \
        __FILE__,                            \
        __LINE__,                            \
        ## args                              \
    );                                       \
}
#else  /* DEBUG */
#define err_mesg(fmt, args...)               
#define FATAL(fmt, args...)                  
#define MMAN_DBP(fmt, args...)               
#endif /* DEBUG */

/* typedef を使った場合 */
typedef void * Fn_alloc(size_t size);
typedef void   Fn_free (void * ptr);

/* メモリ管理構造体 */
typedef
struct mman_t
{
    int             id;
    char            key[8];
    sem_t         * sem;
    int             pshared;
    unsigned  int   value;
    mem_inst_t    * instance;
#if 0  /* typedef を使った場合 */
    Fn_alloc      * alloc;
    Fn_free       * free;
#else
    void          * (* functor_alloc)(size_t   size);
    void            (* functor_free) (void   * ptr);
#endif
    size_t          pool_size;
    size_t          rest_size;
    void          * position;
}
    mman_t;

extern int Mman_get_rsrc_num(void);

#endif /* __PRIV_MEMMNAN_STD_H__ */

 

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0