diff --git a/src/libCom/dbmf.c b/src/libCom/dbmf.c index b10b6b49a..11b37a125 100644 --- a/src/libCom/dbmf.c +++ b/src/libCom/dbmf.c @@ -1,214 +1,222 @@ - /* - * $Id$ - * $Log$ - * Revision 1.1 1997/04/07 20:16:41 jbk - * Added a simple library for doing malloc/free from a buffer pool - * - * - * Author: Jim Kowalkowski + * Author: Jim Kowalkowski and Marty Kraimer * Date: 4/97 * - * Intended for applications that create small strings over and over again - * - * I use a 1 byte indentifier in the front of the allocated chunk to tell - * if it is managed by me or not. This limited the applications that can - * use this library to just strings because the block I return will not - * be aligned on a 4 or 8 byte boundary. Increasing it to 4 or 8 bytes - * seems wasteful. I really need to identify the chunks as mine or malloced. + * Intended for applications that create and free requently * */ #include +#include +#include +#include "ellLib.h" #ifdef vxWorks +#include #include #else #define SEM_ID int -#define semGive(x) ; -#define semTake(x,y) ; +#define semGive(x) +#define semTake(x,y) #define semBCreate(x,y) 0 +#define SEM_Q_PRIORITY 0 +#define SEM_FULL 0 #endif #include "dbmf.h" -#define MAKE_TEST_PROGRAM 0 -#define DBMF_OWNED 0x01 -#define DBMF_SIZE 55 -#define DBMF_ALIGN 1 -#define DBMF_POOL 4 +/*Default values for dblfInit */ +#define DBMF_SIZE 64 +#define DBMF_INITIAL_ITEMS 10 -struct _chunk +typedef struct chunkNode {/*control block for each set of chunkItems*/ + ELLNODE node; + void *pchunk; + int nNotFree; +}chunkNode; + +typedef struct itemHeader{ + void *pnextFree; + chunkNode *pchunkNode; +}itemHeader; + +typedef struct dbmfPrivate { + ELLLIST chunkList; + SEM_ID sem; + size_t size; + size_t allocSize; + int chunkItems; + size_t chunkSize; + int nAlloc; + int nFree; + int nGtSize; + void *freeList; +} dbmfPrivate; +dbmfPrivate dbmfPvt; +static dbmfPrivate *pdbmfPvt = NULL; +int dbmfDebug=0; + +int dbmfInit(size_t size, int chunkItems) { - size_t chunk_size; /* size of my chunk */ - size_t user_size; /* size the user wants managed (this or less) */ - size_t group_size; /* bytes in group */ - size_t total; /* allocate chunks in groups of this number */ - size_t align; - char* free_list; - SEM_ID sem; -}; -typedef struct _chunk chunk; - -static chunk* def=NULL; /* default buffer pool - when handle to malloc() NULL */ - -/* returns handle to user */ -void* epicsShareAPI dbmfInit(size_t size, size_t alignment, int init_num_free_list_items) + if(pdbmfPvt) { + printf("dbmfInit: Already initialized\n"); + return(-1); + } + pdbmfPvt = &dbmfPvt; + ellInit(&pdbmfPvt->chunkList); + pdbmfPvt->sem = semBCreate(SEM_Q_PRIORITY,SEM_FULL); + /*allign to at least a double*/ + pdbmfPvt->size = size + size%sizeof(double); + pdbmfPvt->allocSize = pdbmfPvt->size + sizeof(itemHeader); + pdbmfPvt->chunkItems = chunkItems; + pdbmfPvt->chunkSize = pdbmfPvt->allocSize * pdbmfPvt->chunkItems; + pdbmfPvt->nAlloc = 0; + pdbmfPvt->nFree = 0; + pdbmfPvt->nGtSize = 0; + pdbmfPvt->freeList = NULL; + return(0); +} + +void* dbmfMalloc(size_t size) { - chunk* c = (chunk*)malloc(sizeof(chunk)); + void **pnextFree; + void **pfreeList; + char *pmem = NULL; + chunkNode *pchunkNode; + itemHeader *pitemHeader; - if(c) - { - c->user_size=size; - c->chunk_size=((c->user_size/alignment)*alignment)+alignment; - c->total=init_num_free_list_items; - c->group_size=c->chunk_size*c->total; - c->align=alignment; - c->free_list=NULL; - c->sem=semBCreate(SEM_Q_PRIORITY,SEM_FULL); + if(!pdbmfPvt) dbmfInit(DBMF_SIZE,DBMF_INITIAL_ITEMS); + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pfreeList = &pdbmfPvt->freeList; + if(*pfreeList == NULL) { + int i; + size_t nbytesTotal; + + if(dbmfDebug) printf("dbmfMalloc allocating new storage\n"); + nbytesTotal = pdbmfPvt->chunkSize + sizeof(chunkNode); + pmem = (char *)malloc(nbytesTotal); + if(!pmem) { + semGive(pdbmfPvt->sem); + printf("dbmfMalloc malloc failed\n"); + return(NULL); } + pchunkNode = (chunkNode *)(pmem + pdbmfPvt->chunkSize); + pchunkNode->pchunk = pmem; + pchunkNode->nNotFree=0; + ellAdd(&pdbmfPvt->chunkList,&pchunkNode->node); + for(i=0; ichunkItems; i++) { + pitemHeader = (itemHeader *)pmem; + pitemHeader->pchunkNode = pchunkNode; + pnextFree = &pitemHeader->pnextFree; + *pnextFree = *pfreeList; *pfreeList = (void *)pmem; + pdbmfPvt->nFree++; + pmem += pdbmfPvt->allocSize; + } + } + if(size<=pdbmfPvt->size) { + pnextFree = *pfreeList; *pfreeList = *pnextFree; + pmem = (void *)pnextFree; + pdbmfPvt->nAlloc++; pdbmfPvt->nFree--; + pitemHeader = (itemHeader *)pnextFree; + pitemHeader->pchunkNode->nNotFree += 1; + } else { + pmem = malloc(sizeof(itemHeader) + size); pdbmfPvt->nAlloc++; + pdbmfPvt->nGtSize++; + pitemHeader = (itemHeader *)pmem; + pitemHeader->pchunkNode = NULL; + if(dbmfDebug) printf("dbmfMalloc: size %d mem %p\n",size,pmem); + } + semGive(pdbmfPvt->sem); + return((void *)(pmem + sizeof(itemHeader))); +} + +void dbmfFree(void* mem) +{ + char *pmem = (char *)mem; + chunkNode *pchunkNode; + itemHeader *pitemHeader; - return c; + if(!mem) return; + if(!pdbmfPvt) { + printf("dbmfFree called but dbmfInit never called\n"); + return; + } + pmem -= sizeof(itemHeader); + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pitemHeader = (itemHeader *)pmem; + if(!pitemHeader->pchunkNode) { + if(dbmfDebug) printf("dbmfGree: mem %p\n",pmem); + free((void *)pmem); pdbmfPvt->nAlloc--; + }else { + void **pfreeList = &pdbmfPvt->freeList; + void **pnextFree = &pitemHeader->pnextFree; + + pchunkNode = pitemHeader->pchunkNode; + pchunkNode->nNotFree--; + *pnextFree = *pfreeList; *pfreeList = pnextFree; + pdbmfPvt->nAlloc--; pdbmfPvt->nFree++; + } + semGive(pdbmfPvt->sem); +} + +int dbmfShow(int level) +{ + if(pdbmfPvt==NULL) { + printf("Never initialized\n"); + return(0); + } + printf("size %d allocSize %d chunkItems %d ", + pdbmfPvt->size,pdbmfPvt->allocSize,pdbmfPvt->chunkItems); + printf("nAlloc %d nFree %d nChunks %d nGtSize %d\n", + pdbmfPvt->nAlloc,pdbmfPvt->nFree, + ellCount(&pdbmfPvt->chunkList),pdbmfPvt->nGtSize); + if(level>0) { + chunkNode *pchunkNode; + + pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList); + while(pchunkNode) { + printf("pchunkNode %p nNotFree %d\n", + pchunkNode,pchunkNode->nNotFree); + pchunkNode = (chunkNode *)ellNext(&pchunkNode->node); + } + } + if(level>1) { + void **pnextFree;; + + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pnextFree = (void**)pdbmfPvt->freeList; + while(pnextFree) { + printf("%p\n",*pnextFree); + pnextFree = (void**)*pnextFree; + } + semGive(pdbmfPvt->sem); + } + return(0); } -void* epicsShareAPI dbmfMalloc(void* handle,size_t x) +void dbmfFreeChunks(void) { - chunk* c = (chunk*)handle; - char** addr; - char *node,*rc; - int i; + chunkNode *pchunkNode; + chunkNode *pnext;; - if(c==NULL) - { - if(def==NULL) - def=dbmfInit(DBMF_SIZE,DBMF_ALIGN,DBMF_POOL); - c=def; - } - - if(c->free_list==NULL) - { - node=(char*)malloc(c->group_size); - if(node) - { - semTake(c->sem,WAIT_FOREVER); - for(i=0;itotal;i++) - { - /* yuck */ - addr=(char**)node; - *addr=c->free_list; - c->free_list=node; - node+=c->chunk_size; - } - semGive(c->sem); - } - else - rc=NULL; - } - if(x<=c->user_size) - { - semTake(c->sem,WAIT_FOREVER); - node=c->free_list; - if(node) - { - addr=(char**)node; - c->free_list=*addr; - node[0]=DBMF_OWNED; - } - semGive(c->sem); - } - else - { - node=(char*)malloc(x+c->align); - node[0]=0x00; - } - - return (void*)(&node[c->align]); + if(!pdbmfPvt) { + printf("dbmfFreeChunks called but dbmfInit never called\n"); + return; + } + semTake(pdbmfPvt->sem,WAIT_FOREVER); + if(pdbmfPvt->nFree + != (pdbmfPvt->chunkItems * ellCount(&pdbmfPvt->chunkList))) { + printf("dbmfFinish: not all free\n"); + semGive(pdbmfPvt->sem); + return; + } + pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList); + while(pchunkNode) { + pnext = (chunkNode *)ellNext(&pchunkNode->node); + ellDelete(&pdbmfPvt->chunkList,&pchunkNode->node); + free(pchunkNode->pchunk); + pchunkNode = pnext; + } + pdbmfPvt->nFree = 0; pdbmfPvt->freeList = NULL; + semGive(pdbmfPvt->sem); } - -void epicsShareAPI dbmfFree(void* handle,void* x) -{ - chunk* c = (chunk*)handle; - char* p = (char*)x; - char** addr; - - /* kind-of goofy, bad if buffer not malloc'ed using dbmfMalloc() */ - if(c==NULL) - { - if(def==NULL) - def=dbmfInit(DBMF_SIZE,DBMF_ALIGN,DBMF_POOL); - c=def; - } - - p-=c->align; - if(*p!=DBMF_OWNED) - free(p); - else - { - addr=(char**)p; - semTake(c->sem,WAIT_FOREVER); - *addr=c->free_list; - c->free_list=p; - semGive(c->sem); - } -} - -#if MAKE_TEST_PROGRAM -#include - -int main() -{ - char* x[10]; - int i; - void* handle; - - handle=dbStrInit(20,1,5); - - printf("ALLOCATE\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - fprintf(stderr,"x[%d]=%8.8x\n",i,(int)x[i]); - } - fprintf(stderr,"FREE\n"); - for(i=0;i<10;i++) - { fprintf(stderr,"free %8.8x\n",(int)x[i]); dbStrFree(x[i]); } - - return 0; -} -#endif diff --git a/src/libCom/dbmf.h b/src/libCom/dbmf.h index 8798f13c1..997a00293 100644 --- a/src/libCom/dbmf.h +++ b/src/libCom/dbmf.h @@ -1,38 +1,26 @@ +/* + * Author: Jim Kowalkowski and Marty Kraimer + * Date: 4/97 + * + * A library to manage storage that is allocated and then freed. + */ #ifndef DBMF_H #define DBMF_H -/* - * Author: Jim Kowalkowski - * Date: 4/97 - * - * Simple library to manage reusing buffers of similar sizes using - * malloc/free type style calls. - * - * void* dbmfInit(MAX_BUFFER_SIZE,REQUIRED_BUFFER_ALIGNMENT,INITIAL_POOL_SIZE); - * - * void* dbmfMalloc(handle,byte_count); - * void* dbmfFree(handle,buffer_pointer); - * - * dbmfInit() returns a handle to a buffer pool. - * Use dbmfMalloc() and dbmfFree() to get buffers from it. The buffer pool - * will give you managed buffers for sizes of MAX_BUFFER_SIZE and less. - * Sizes requested which are larger than MAX_BUFFER_SIZE will just be - * allocated using normal malloc() call. A buffer gotten with dbmfMalloc() - * will be aligned to REQUIRED_BUFFER_ALIGNMENT. The buffer pool will - * grow by INITIAL_POOL_SIZE each time it runs out of buffers. - * - * $Id$ - * $Log$ - * Revision 1.1 1997/04/07 20:16:42 jbk - * Added a simple library for doing malloc/free from a buffer pool - * - * - */ - +int dbmfInit(size_t size, int chunkItems); +void *dbmfMalloc(size_t bytes); +void dbmfFree(void* bytes); +void dbmfFreeChunks(void); +int dbmfShow(int level); #include "shareLib.h" -void* epicsShareAPI dbmfInit(size_t size, size_t alignment, int init_num_free_list_items); -void* epicsShareAPI dbmfMalloc(void* handle,size_t bytes); -void epicsShareAPI dbmfFree(void* handle,void* bytes); +/* Rules: + * 1) Size is always made a multiple of 8. + * 2) if dbmfInit is not called before one of the other routines then it + * is automatically called with size=64 and initial_items=10 + * 3) These routines should only be used to allocate storage that will + * shortly thereafter be freed. + * 4) dbmfFreeChunks can only free chunks that contain only free items +*/ #endif diff --git a/src/libCom/dbmf/dbmf.c b/src/libCom/dbmf/dbmf.c index b10b6b49a..11b37a125 100644 --- a/src/libCom/dbmf/dbmf.c +++ b/src/libCom/dbmf/dbmf.c @@ -1,214 +1,222 @@ - /* - * $Id$ - * $Log$ - * Revision 1.1 1997/04/07 20:16:41 jbk - * Added a simple library for doing malloc/free from a buffer pool - * - * - * Author: Jim Kowalkowski + * Author: Jim Kowalkowski and Marty Kraimer * Date: 4/97 * - * Intended for applications that create small strings over and over again - * - * I use a 1 byte indentifier in the front of the allocated chunk to tell - * if it is managed by me or not. This limited the applications that can - * use this library to just strings because the block I return will not - * be aligned on a 4 or 8 byte boundary. Increasing it to 4 or 8 bytes - * seems wasteful. I really need to identify the chunks as mine or malloced. + * Intended for applications that create and free requently * */ #include +#include +#include +#include "ellLib.h" #ifdef vxWorks +#include #include #else #define SEM_ID int -#define semGive(x) ; -#define semTake(x,y) ; +#define semGive(x) +#define semTake(x,y) #define semBCreate(x,y) 0 +#define SEM_Q_PRIORITY 0 +#define SEM_FULL 0 #endif #include "dbmf.h" -#define MAKE_TEST_PROGRAM 0 -#define DBMF_OWNED 0x01 -#define DBMF_SIZE 55 -#define DBMF_ALIGN 1 -#define DBMF_POOL 4 +/*Default values for dblfInit */ +#define DBMF_SIZE 64 +#define DBMF_INITIAL_ITEMS 10 -struct _chunk +typedef struct chunkNode {/*control block for each set of chunkItems*/ + ELLNODE node; + void *pchunk; + int nNotFree; +}chunkNode; + +typedef struct itemHeader{ + void *pnextFree; + chunkNode *pchunkNode; +}itemHeader; + +typedef struct dbmfPrivate { + ELLLIST chunkList; + SEM_ID sem; + size_t size; + size_t allocSize; + int chunkItems; + size_t chunkSize; + int nAlloc; + int nFree; + int nGtSize; + void *freeList; +} dbmfPrivate; +dbmfPrivate dbmfPvt; +static dbmfPrivate *pdbmfPvt = NULL; +int dbmfDebug=0; + +int dbmfInit(size_t size, int chunkItems) { - size_t chunk_size; /* size of my chunk */ - size_t user_size; /* size the user wants managed (this or less) */ - size_t group_size; /* bytes in group */ - size_t total; /* allocate chunks in groups of this number */ - size_t align; - char* free_list; - SEM_ID sem; -}; -typedef struct _chunk chunk; - -static chunk* def=NULL; /* default buffer pool - when handle to malloc() NULL */ - -/* returns handle to user */ -void* epicsShareAPI dbmfInit(size_t size, size_t alignment, int init_num_free_list_items) + if(pdbmfPvt) { + printf("dbmfInit: Already initialized\n"); + return(-1); + } + pdbmfPvt = &dbmfPvt; + ellInit(&pdbmfPvt->chunkList); + pdbmfPvt->sem = semBCreate(SEM_Q_PRIORITY,SEM_FULL); + /*allign to at least a double*/ + pdbmfPvt->size = size + size%sizeof(double); + pdbmfPvt->allocSize = pdbmfPvt->size + sizeof(itemHeader); + pdbmfPvt->chunkItems = chunkItems; + pdbmfPvt->chunkSize = pdbmfPvt->allocSize * pdbmfPvt->chunkItems; + pdbmfPvt->nAlloc = 0; + pdbmfPvt->nFree = 0; + pdbmfPvt->nGtSize = 0; + pdbmfPvt->freeList = NULL; + return(0); +} + +void* dbmfMalloc(size_t size) { - chunk* c = (chunk*)malloc(sizeof(chunk)); + void **pnextFree; + void **pfreeList; + char *pmem = NULL; + chunkNode *pchunkNode; + itemHeader *pitemHeader; - if(c) - { - c->user_size=size; - c->chunk_size=((c->user_size/alignment)*alignment)+alignment; - c->total=init_num_free_list_items; - c->group_size=c->chunk_size*c->total; - c->align=alignment; - c->free_list=NULL; - c->sem=semBCreate(SEM_Q_PRIORITY,SEM_FULL); + if(!pdbmfPvt) dbmfInit(DBMF_SIZE,DBMF_INITIAL_ITEMS); + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pfreeList = &pdbmfPvt->freeList; + if(*pfreeList == NULL) { + int i; + size_t nbytesTotal; + + if(dbmfDebug) printf("dbmfMalloc allocating new storage\n"); + nbytesTotal = pdbmfPvt->chunkSize + sizeof(chunkNode); + pmem = (char *)malloc(nbytesTotal); + if(!pmem) { + semGive(pdbmfPvt->sem); + printf("dbmfMalloc malloc failed\n"); + return(NULL); } + pchunkNode = (chunkNode *)(pmem + pdbmfPvt->chunkSize); + pchunkNode->pchunk = pmem; + pchunkNode->nNotFree=0; + ellAdd(&pdbmfPvt->chunkList,&pchunkNode->node); + for(i=0; ichunkItems; i++) { + pitemHeader = (itemHeader *)pmem; + pitemHeader->pchunkNode = pchunkNode; + pnextFree = &pitemHeader->pnextFree; + *pnextFree = *pfreeList; *pfreeList = (void *)pmem; + pdbmfPvt->nFree++; + pmem += pdbmfPvt->allocSize; + } + } + if(size<=pdbmfPvt->size) { + pnextFree = *pfreeList; *pfreeList = *pnextFree; + pmem = (void *)pnextFree; + pdbmfPvt->nAlloc++; pdbmfPvt->nFree--; + pitemHeader = (itemHeader *)pnextFree; + pitemHeader->pchunkNode->nNotFree += 1; + } else { + pmem = malloc(sizeof(itemHeader) + size); pdbmfPvt->nAlloc++; + pdbmfPvt->nGtSize++; + pitemHeader = (itemHeader *)pmem; + pitemHeader->pchunkNode = NULL; + if(dbmfDebug) printf("dbmfMalloc: size %d mem %p\n",size,pmem); + } + semGive(pdbmfPvt->sem); + return((void *)(pmem + sizeof(itemHeader))); +} + +void dbmfFree(void* mem) +{ + char *pmem = (char *)mem; + chunkNode *pchunkNode; + itemHeader *pitemHeader; - return c; + if(!mem) return; + if(!pdbmfPvt) { + printf("dbmfFree called but dbmfInit never called\n"); + return; + } + pmem -= sizeof(itemHeader); + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pitemHeader = (itemHeader *)pmem; + if(!pitemHeader->pchunkNode) { + if(dbmfDebug) printf("dbmfGree: mem %p\n",pmem); + free((void *)pmem); pdbmfPvt->nAlloc--; + }else { + void **pfreeList = &pdbmfPvt->freeList; + void **pnextFree = &pitemHeader->pnextFree; + + pchunkNode = pitemHeader->pchunkNode; + pchunkNode->nNotFree--; + *pnextFree = *pfreeList; *pfreeList = pnextFree; + pdbmfPvt->nAlloc--; pdbmfPvt->nFree++; + } + semGive(pdbmfPvt->sem); +} + +int dbmfShow(int level) +{ + if(pdbmfPvt==NULL) { + printf("Never initialized\n"); + return(0); + } + printf("size %d allocSize %d chunkItems %d ", + pdbmfPvt->size,pdbmfPvt->allocSize,pdbmfPvt->chunkItems); + printf("nAlloc %d nFree %d nChunks %d nGtSize %d\n", + pdbmfPvt->nAlloc,pdbmfPvt->nFree, + ellCount(&pdbmfPvt->chunkList),pdbmfPvt->nGtSize); + if(level>0) { + chunkNode *pchunkNode; + + pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList); + while(pchunkNode) { + printf("pchunkNode %p nNotFree %d\n", + pchunkNode,pchunkNode->nNotFree); + pchunkNode = (chunkNode *)ellNext(&pchunkNode->node); + } + } + if(level>1) { + void **pnextFree;; + + semTake(pdbmfPvt->sem,WAIT_FOREVER); + pnextFree = (void**)pdbmfPvt->freeList; + while(pnextFree) { + printf("%p\n",*pnextFree); + pnextFree = (void**)*pnextFree; + } + semGive(pdbmfPvt->sem); + } + return(0); } -void* epicsShareAPI dbmfMalloc(void* handle,size_t x) +void dbmfFreeChunks(void) { - chunk* c = (chunk*)handle; - char** addr; - char *node,*rc; - int i; + chunkNode *pchunkNode; + chunkNode *pnext;; - if(c==NULL) - { - if(def==NULL) - def=dbmfInit(DBMF_SIZE,DBMF_ALIGN,DBMF_POOL); - c=def; - } - - if(c->free_list==NULL) - { - node=(char*)malloc(c->group_size); - if(node) - { - semTake(c->sem,WAIT_FOREVER); - for(i=0;itotal;i++) - { - /* yuck */ - addr=(char**)node; - *addr=c->free_list; - c->free_list=node; - node+=c->chunk_size; - } - semGive(c->sem); - } - else - rc=NULL; - } - if(x<=c->user_size) - { - semTake(c->sem,WAIT_FOREVER); - node=c->free_list; - if(node) - { - addr=(char**)node; - c->free_list=*addr; - node[0]=DBMF_OWNED; - } - semGive(c->sem); - } - else - { - node=(char*)malloc(x+c->align); - node[0]=0x00; - } - - return (void*)(&node[c->align]); + if(!pdbmfPvt) { + printf("dbmfFreeChunks called but dbmfInit never called\n"); + return; + } + semTake(pdbmfPvt->sem,WAIT_FOREVER); + if(pdbmfPvt->nFree + != (pdbmfPvt->chunkItems * ellCount(&pdbmfPvt->chunkList))) { + printf("dbmfFinish: not all free\n"); + semGive(pdbmfPvt->sem); + return; + } + pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList); + while(pchunkNode) { + pnext = (chunkNode *)ellNext(&pchunkNode->node); + ellDelete(&pdbmfPvt->chunkList,&pchunkNode->node); + free(pchunkNode->pchunk); + pchunkNode = pnext; + } + pdbmfPvt->nFree = 0; pdbmfPvt->freeList = NULL; + semGive(pdbmfPvt->sem); } - -void epicsShareAPI dbmfFree(void* handle,void* x) -{ - chunk* c = (chunk*)handle; - char* p = (char*)x; - char** addr; - - /* kind-of goofy, bad if buffer not malloc'ed using dbmfMalloc() */ - if(c==NULL) - { - if(def==NULL) - def=dbmfInit(DBMF_SIZE,DBMF_ALIGN,DBMF_POOL); - c=def; - } - - p-=c->align; - if(*p!=DBMF_OWNED) - free(p); - else - { - addr=(char**)p; - semTake(c->sem,WAIT_FOREVER); - *addr=c->free_list; - c->free_list=p; - semGive(c->sem); - } -} - -#if MAKE_TEST_PROGRAM -#include - -int main() -{ - char* x[10]; - int i; - void* handle; - - handle=dbStrInit(20,1,5); - - printf("ALLOCATE\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - printf("x[%d]=%8.8x\n",i,(int)x[i]); - } - printf("FREE\n"); - for(i=0;i<10;i++) dbStrFree(x[i]); - - printf("ALLOCATE BIGGER\n"); - for(i=0;i<10;i++) - { - x[i]=(char*)dbStrMalloc(i+15); - fprintf(stderr,"x[%d]=%8.8x\n",i,(int)x[i]); - } - fprintf(stderr,"FREE\n"); - for(i=0;i<10;i++) - { fprintf(stderr,"free %8.8x\n",(int)x[i]); dbStrFree(x[i]); } - - return 0; -} -#endif diff --git a/src/libCom/dbmf/dbmf.h b/src/libCom/dbmf/dbmf.h index 8798f13c1..997a00293 100644 --- a/src/libCom/dbmf/dbmf.h +++ b/src/libCom/dbmf/dbmf.h @@ -1,38 +1,26 @@ +/* + * Author: Jim Kowalkowski and Marty Kraimer + * Date: 4/97 + * + * A library to manage storage that is allocated and then freed. + */ #ifndef DBMF_H #define DBMF_H -/* - * Author: Jim Kowalkowski - * Date: 4/97 - * - * Simple library to manage reusing buffers of similar sizes using - * malloc/free type style calls. - * - * void* dbmfInit(MAX_BUFFER_SIZE,REQUIRED_BUFFER_ALIGNMENT,INITIAL_POOL_SIZE); - * - * void* dbmfMalloc(handle,byte_count); - * void* dbmfFree(handle,buffer_pointer); - * - * dbmfInit() returns a handle to a buffer pool. - * Use dbmfMalloc() and dbmfFree() to get buffers from it. The buffer pool - * will give you managed buffers for sizes of MAX_BUFFER_SIZE and less. - * Sizes requested which are larger than MAX_BUFFER_SIZE will just be - * allocated using normal malloc() call. A buffer gotten with dbmfMalloc() - * will be aligned to REQUIRED_BUFFER_ALIGNMENT. The buffer pool will - * grow by INITIAL_POOL_SIZE each time it runs out of buffers. - * - * $Id$ - * $Log$ - * Revision 1.1 1997/04/07 20:16:42 jbk - * Added a simple library for doing malloc/free from a buffer pool - * - * - */ - +int dbmfInit(size_t size, int chunkItems); +void *dbmfMalloc(size_t bytes); +void dbmfFree(void* bytes); +void dbmfFreeChunks(void); +int dbmfShow(int level); #include "shareLib.h" -void* epicsShareAPI dbmfInit(size_t size, size_t alignment, int init_num_free_list_items); -void* epicsShareAPI dbmfMalloc(void* handle,size_t bytes); -void epicsShareAPI dbmfFree(void* handle,void* bytes); +/* Rules: + * 1) Size is always made a multiple of 8. + * 2) if dbmfInit is not called before one of the other routines then it + * is automatically called with size=64 and initial_items=10 + * 3) These routines should only be used to allocate storage that will + * shortly thereafter be freed. + * 4) dbmfFreeChunks can only free chunks that contain only free items +*/ #endif