This is Unofficial EPICS BASE Doxygen Site
dbmf.c File Reference
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "valgrind/valgrind.h"
#include "cantProceed.h"
#include "epicsMutex.h"
#include "ellLib.h"
#include "dbmf.h"
+ Include dependency graph for dbmf.c:

Go to the source code of this file.

Classes

struct  chunkNode
 
struct  itemHeader
 
struct  dbmfPrivate
 

Macros

#define REDZONE   sizeof(double)
 
#define DBMF_SIZE   64
 
#define DBMF_INITIAL_ITEMS   10
 

Typedefs

typedef struct chunkNode chunkNode
 
typedef struct itemHeader itemHeader
 
typedef struct dbmfPrivate dbmfPrivate
 

Functions

int dbmfInit (size_t size, int chunkItems)
 Initialize the facility. More...
 
void * dbmfMalloc (size_t size)
 Allocate memory. More...
 
char * dbmfStrdup (const char *str)
 Duplicate a string. More...
 
char * dbmfStrndup (const char *str, size_t len)
 Duplicate a string (up to len bytes). More...
 
void dbmfFree (void *mem)
 Free the memory allocated by dbmfMalloc. More...
 
int dbmfShow (int level)
 Show the status of the dbmf memory pool. More...
 
void dbmfFreeChunks (void)
 Free all chunks that contain only free items. More...
 
char * dbmfStrcat3 (const char *lhs, const char *mid, const char *rhs)
 Concatenate three strings. More...
 

Variables

dbmfPrivate dbmfPvt
 
int dbmfDebug =0
 

Macro Definition Documentation

#define DBMF_INITIAL_ITEMS   10

Definition at line 42 of file dbmf.c.

#define DBMF_SIZE   64

Definition at line 41 of file dbmf.c.

#define REDZONE   sizeof(double)

Definition at line 26 of file dbmf.c.

Typedef Documentation

typedef struct chunkNode chunkNode
typedef struct dbmfPrivate dbmfPrivate
typedef struct itemHeader itemHeader

Function Documentation

void dbmfFree ( void *  bytes)

Free the memory allocated by dbmfMalloc.

Parameters
bytesPointer to memory obtained from dbmfMalloc(), dbmfStrdup(), dbmfStrndup() or dbmfStrcat3().

Definition at line 175 of file dbmf.c.

176 {
177  char *pmem = (char *)mem;
178  chunkNode *pchunkNode;
179  itemHeader *pitemHeader;
180 
181  if(!mem) return;
182  if(!pdbmfPvt) {
183  printf("dbmfFree called but dbmfInit never called\n");
184  return;
185  }
186  VALGRIND_MEMPOOL_FREE(pdbmfPvt, mem);
187  pmem -= sizeof(itemHeader) + REDZONE;
188  epicsMutexMustLock(pdbmfPvt->lock);
189  pitemHeader = (itemHeader *)pmem;
190  if(!pitemHeader->pchunkNode) {
191  if(dbmfDebug) printf("dbmfGree: mem %p\n",pmem);
192  free((void *)pmem); pdbmfPvt->nAlloc--;
193  }else {
194  void **pfreeList = &pdbmfPvt->freeList;
195  void **pnextFree = &pitemHeader->pnextFree;
196 
197  pchunkNode = pitemHeader->pchunkNode;
198  pchunkNode->nNotFree--;
199  *pnextFree = *pfreeList; *pfreeList = pnextFree;
200  pdbmfPvt->nAlloc--; pdbmfPvt->nFree++;
201  }
202  epicsMutexUnlock(pdbmfPvt->lock);
203 }
int nAlloc
Definition: dbmf.c:62
struct itemHeader itemHeader
#define printf
Definition: epicsStdio.h:41
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
void * pnextFree
Definition: dbmf.c:51
int nNotFree
Definition: dbmf.c:47
int nFree
Definition: dbmf.c:63
int dbmfDebug
Definition: dbmf.c:69
Definition: dbmf.c:44
void * freeList
Definition: dbmf.c:65
#define REDZONE
Definition: dbmf.c:26
epicsMutexId lock
Definition: dbmf.c:57
#define VALGRIND_MEMPOOL_FREE(pool, addr)
Definition: valgrind.h:6485
chunkNode * pchunkNode
Definition: dbmf.c:52
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
void dbmfFreeChunks ( void  )

Free all chunks that contain only free items.

Definition at line 241 of file dbmf.c.

242 {
243  chunkNode *pchunkNode;
244  chunkNode *pnext;;
245 
246  if(!pdbmfPvt) {
247  printf("dbmfFreeChunks called but dbmfInit never called\n");
248  return;
249  }
250  epicsMutexMustLock(pdbmfPvt->lock);
251  if(pdbmfPvt->nFree
252  != (pdbmfPvt->chunkItems * ellCount(&pdbmfPvt->chunkList))) {
253  printf("dbmfFinish: not all free\n");
254  epicsMutexUnlock(pdbmfPvt->lock);
255  return;
256  }
257  pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList);
258  while(pchunkNode) {
259  pnext = (chunkNode *)ellNext(&pchunkNode->node);
260  ellDelete(&pdbmfPvt->chunkList,&pchunkNode->node);
261  free(pchunkNode->pchunk);
262  pchunkNode = pnext;
263  }
264  pdbmfPvt->nFree = 0; pdbmfPvt->freeList = NULL;
265  epicsMutexUnlock(pdbmfPvt->lock);
266 }
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
ELLLIST chunkList
Definition: dbmf.c:56
#define printf
Definition: epicsStdio.h:41
#define NULL
Definition: catime.c:38
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
int chunkItems
Definition: dbmf.c:60
int nFree
Definition: dbmf.c:63
void * pchunk
Definition: dbmf.c:46
Definition: dbmf.c:44
void * freeList
Definition: dbmf.c:65
epicsMutexId lock
Definition: dbmf.c:57
ELLNODE node
Definition: dbmf.c:45
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
int dbmfInit ( size_t  size,
int  chunkItems 
)

Initialize the facility.

Parameters
sizeThe maximum size request from dbmfMalloc() that will be allocated from the dbmf pool (Size is always made a multiple of 8).
chunkItemsEach time malloc() must be called size*chunkItems bytes are allocated.
Returns
0 on success, -1 if already initialized
Note
If dbmfInit() is not called before one of the other routines then it is automatically called with size=64 and chunkItems=10

Definition at line 71 of file dbmf.c.

72 {
73  if(pdbmfPvt) {
74  printf("dbmfInit: Already initialized\n");
75  return(-1);
76  }
77  pdbmfPvt = &dbmfPvt;
78  ellInit(&pdbmfPvt->chunkList);
79  pdbmfPvt->lock = epicsMutexMustCreate();
80  /*allign to at least a double*/
81  pdbmfPvt->size = size + size%sizeof(double);
82  /* layout is
83  * | itemHeader | REDZONE | size | REDZONE |
84  */
85  pdbmfPvt->allocSize = pdbmfPvt->size + sizeof(itemHeader) + 2*REDZONE;
86  pdbmfPvt->chunkItems = chunkItems;
87  pdbmfPvt->chunkSize = pdbmfPvt->allocSize * pdbmfPvt->chunkItems;
88  pdbmfPvt->nAlloc = 0;
89  pdbmfPvt->nFree = 0;
90  pdbmfPvt->nGtSize = 0;
91  pdbmfPvt->freeList = NULL;
92  VALGRIND_CREATE_MEMPOOL(pdbmfPvt, REDZONE, 0);
93  return(0);
94 }
int nAlloc
Definition: dbmf.c:62
struct itemHeader itemHeader
dbmfPrivate dbmfPvt
Definition: dbmf.c:67
ELLLIST chunkList
Definition: dbmf.c:56
#define printf
Definition: epicsStdio.h:41
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
#define NULL
Definition: catime.c:38
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)
Definition: valgrind.h:6470
size_t size
Definition: dbmf.c:58
int chunkItems
Definition: dbmf.c:60
int nFree
Definition: dbmf.c:63
void * freeList
Definition: dbmf.c:65
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
#define REDZONE
Definition: dbmf.c:26
epicsMutexId lock
Definition: dbmf.c:57
size_t chunkSize
Definition: dbmf.c:61
int nGtSize
Definition: dbmf.c:64
size_t allocSize
Definition: dbmf.c:59
void* dbmfMalloc ( size_t  bytes)

Allocate memory.

Parameters
bytesIf bytes > size then malloc() is used to allocate the memory.
Returns
Pointer to the newly-allocated memory, or NULL on failure.

Definition at line 97 of file dbmf.c.

98 {
99  void **pnextFree;
100  void **pfreeList;
101  char *pmem = NULL;
102  chunkNode *pchunkNode;
103  itemHeader *pitemHeader;
104 
105  if(!pdbmfPvt) dbmfInit(DBMF_SIZE,DBMF_INITIAL_ITEMS);
106  epicsMutexMustLock(pdbmfPvt->lock);
107  pfreeList = &pdbmfPvt->freeList;
108  if(*pfreeList == NULL) {
109  int i;
110  size_t nbytesTotal;
111 
112  if(dbmfDebug) printf("dbmfMalloc allocating new storage\n");
113  nbytesTotal = pdbmfPvt->chunkSize + sizeof(chunkNode);
114  pmem = (char *)malloc(nbytesTotal);
115  if(!pmem) {
116  epicsMutexUnlock(pdbmfPvt->lock);
117  cantProceed("dbmfMalloc malloc failed\n");
118  return(NULL);
119  }
120  pchunkNode = (chunkNode *)(pmem + pdbmfPvt->chunkSize);
121  pchunkNode->pchunk = pmem;
122  pchunkNode->nNotFree=0;
123  ellAdd(&pdbmfPvt->chunkList,&pchunkNode->node);
124  for(i=0; i<pdbmfPvt->chunkItems; i++) {
125  pitemHeader = (itemHeader *)pmem;
126  pitemHeader->pchunkNode = pchunkNode;
127  pnextFree = &pitemHeader->pnextFree;
128  *pnextFree = *pfreeList; *pfreeList = (void *)pmem;
129  pdbmfPvt->nFree++;
130  pmem += pdbmfPvt->allocSize;
131  }
132  }
133  if(size<=pdbmfPvt->size) {
134  pnextFree = *pfreeList; *pfreeList = *pnextFree;
135  pmem = (void *)pnextFree;
136  pdbmfPvt->nAlloc++; pdbmfPvt->nFree--;
137  pitemHeader = (itemHeader *)pnextFree;
138  pitemHeader->pchunkNode->nNotFree += 1;
139  } else {
140  pmem = malloc(sizeof(itemHeader) + 2*REDZONE + size);
141  if(!pmem) {
142  epicsMutexUnlock(pdbmfPvt->lock);
143  cantProceed("dbmfMalloc malloc failed\n");
144  return(NULL);
145  }
146  pdbmfPvt->nAlloc++;
147  pdbmfPvt->nGtSize++;
148  pitemHeader = (itemHeader *)pmem;
149  pitemHeader->pchunkNode = NULL; /* not part of free list */
150  if(dbmfDebug) printf("dbmfMalloc: size %lu mem %p\n",
151  (unsigned long)size,pmem);
152  }
153  epicsMutexUnlock(pdbmfPvt->lock);
154  pmem += sizeof(itemHeader) + REDZONE;
155  VALGRIND_MEMPOOL_ALLOC(pdbmfPvt, pmem, size);
156  return((void *)pmem);
157 }
struct chunkNode chunkNode
int nAlloc
Definition: dbmf.c:62
struct itemHeader itemHeader
int i
Definition: scan.c:967
ELLLIST chunkList
Definition: dbmf.c:56
#define printf
Definition: epicsStdio.h:41
#define NULL
Definition: catime.c:38
#define DBMF_INITIAL_ITEMS
Definition: dbmf.c:42
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
void * pnextFree
Definition: dbmf.c:51
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)
Definition: valgrind.h:6480
int nNotFree
Definition: dbmf.c:47
int dbmfInit(size_t size, int chunkItems)
Initialize the facility.
Definition: dbmf.c:71
int chunkItems
Definition: dbmf.c:60
int nFree
Definition: dbmf.c:63
int dbmfDebug
Definition: dbmf.c:69
void * pchunk
Definition: dbmf.c:46
Definition: dbmf.c:44
void * freeList
Definition: dbmf.c:65
#define REDZONE
Definition: dbmf.c:26
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
epicsMutexId lock
Definition: dbmf.c:57
size_t chunkSize
Definition: dbmf.c:61
ELLNODE node
Definition: dbmf.c:45
chunkNode * pchunkNode
Definition: dbmf.c:52
int nGtSize
Definition: dbmf.c:64
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
#define DBMF_SIZE
Definition: dbmf.c:41
size_t allocSize
Definition: dbmf.c:59
int dbmfShow ( int  level)

Show the status of the dbmf memory pool.

Parameters
levelDetail level.
Returns
0.

Definition at line 205 of file dbmf.c.

206 {
207  if(pdbmfPvt==NULL) {
208  printf("Never initialized\n");
209  return(0);
210  }
211  printf("size %lu allocSize %lu chunkItems %d ",
212  (unsigned long)pdbmfPvt->size,
213  (unsigned long)pdbmfPvt->allocSize,pdbmfPvt->chunkItems);
214  printf("nAlloc %d nFree %d nChunks %d nGtSize %d\n",
215  pdbmfPvt->nAlloc,pdbmfPvt->nFree,
216  ellCount(&pdbmfPvt->chunkList),pdbmfPvt->nGtSize);
217  if(level>0) {
218  chunkNode *pchunkNode;
219 
220  pchunkNode = (chunkNode *)ellFirst(&pdbmfPvt->chunkList);
221  while(pchunkNode) {
222  printf("pchunkNode %p nNotFree %d\n",
223  (void*)pchunkNode,pchunkNode->nNotFree);
224  pchunkNode = (chunkNode *)ellNext(&pchunkNode->node);
225  }
226  }
227  if(level>1) {
228  void **pnextFree;;
229 
230  epicsMutexMustLock(pdbmfPvt->lock);
231  pnextFree = (void**)pdbmfPvt->freeList;
232  while(pnextFree) {
233  printf("%p\n",*pnextFree);
234  pnextFree = (void**)*pnextFree;
235  }
236  epicsMutexUnlock(pdbmfPvt->lock);
237  }
238  return(0);
239 }
int nAlloc
Definition: dbmf.c:62
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
ELLLIST chunkList
Definition: dbmf.c:56
#define printf
Definition: epicsStdio.h:41
#define NULL
Definition: catime.c:38
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
int nNotFree
Definition: dbmf.c:47
size_t size
Definition: dbmf.c:58
int chunkItems
Definition: dbmf.c:60
int nFree
Definition: dbmf.c:63
Definition: dbmf.c:44
void * freeList
Definition: dbmf.c:65
epicsMutexId lock
Definition: dbmf.c:57
ELLNODE node
Definition: dbmf.c:45
int nGtSize
Definition: dbmf.c:64
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
size_t allocSize
Definition: dbmf.c:59
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89
char* dbmfStrcat3 ( const char *  lhs,
const char *  mid,
const char *  rhs 
)

Concatenate three strings.

Returns a pointer to a null-terminated string made by concatenating the three input strings.

Parameters
lhsStart string to which the others get concatenated to (left part).
midNext string to be concatenated to the lhs (mid part).
rhsLast string to be concatenated to the lhs+mid (right part).
Returns
A pointer to the new string, or NULL on failure.

Definition at line 289 of file dbmf.c.

290 {
291  size_t len = strlen(lhs) + strlen(mid) + strlen(rhs) + 1;
292  char *buf = dbmfMalloc(len);
293  strcpy(buf, lhs);
294  strcat(buf, mid);
295  strcat(buf, rhs);
296  return buf;
297 }
void * dbmfMalloc(size_t size)
Allocate memory.
Definition: dbmf.c:97
char* dbmfStrdup ( const char *  str)

Duplicate a string.

Create a copy of the input string.

Parameters
strPointer to the null-terminated string to be copied.
Returns
A pointer to the new copy, or NULL on failure.

Definition at line 159 of file dbmf.c.

160 {
161  size_t len = strlen(str);
162  char *buf = dbmfMalloc(len + 1); /* FIXME Can return NULL */
163 
164  return strcpy(buf, str);
165 }
#define str(v)
void * dbmfMalloc(size_t size)
Allocate memory.
Definition: dbmf.c:97
char* dbmfStrndup ( const char *  str,
size_t  len 
)

Duplicate a string (up to len bytes).

Copy at most len bytes of the input string into a new buffer. If no nil terminator is seen in the first len bytes a nil terminator is added.

Parameters
strPointer to the null-terminated string to be copied.
lenMax number of bytes to copy.
Returns
A pointer to the new string, or NULL on failure.

Definition at line 167 of file dbmf.c.

168 {
169  char *buf = dbmfMalloc(len + 1); /* FIXME Can return NULL */
170 
171  buf[len] = '\0';
172  return strncpy(buf, str, len);
173 }
#define str(v)
void * dbmfMalloc(size_t size)
Allocate memory.
Definition: dbmf.c:97

Variable Documentation

int dbmfDebug =0

Definition at line 69 of file dbmf.c.

dbmfPrivate dbmfPvt

Definition at line 67 of file dbmf.c.