This is Unofficial EPICS BASE Doxygen Site
freeListLib.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE Versions 3.13.7
7 * and higher are distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 /* Author: Marty Kraimer Date: 04-19-94 */
11 
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 
16 #include "valgrind/valgrind.h"
17 
18 #ifndef NVALGRIND
19 /* buffer around allocations to detect out of bounds access */
20 #define REDZONE sizeof(double)
21 #else
22 #define REDZONE 0
23 #endif
24 
25 #include "cantProceed.h"
26 #include "epicsMutex.h"
27 #include "freeList.h"
28 #include "adjustment.h"
29 
30 typedef struct allocMem {
31  struct allocMem *next;
32  void *memory;
33 }allocMem;
34 typedef struct {
35  int size;
36  int nmalloc;
37  void *head;
42 
43 LIBCOM_API void epicsStdCall
44  freeListInitPvt(void **ppvt,int size,int nmalloc)
45 {
46  FREELISTPVT *pfl;
47 
48  pfl = callocMustSucceed(1,sizeof(FREELISTPVT), "freeListInitPvt");
49  pfl->size = adjustToWorstCaseAlignment(size);
50  pfl->nmalloc = nmalloc;
51  pfl->head = NULL;
52  pfl->mallochead = NULL;
53  pfl->nBlocksAvailable = 0u;
54  pfl->lock = epicsMutexMustCreate();
55  *ppvt = (void *)pfl;
57  return;
58 }
59 
60 LIBCOM_API void * epicsStdCall freeListCalloc(void *pvt)
61 {
62  FREELISTPVT *pfl = pvt;
63 # ifdef EPICS_FREELIST_DEBUG
64  return callocMustSucceed(1,pfl->size,"freeList Debug Calloc");
65 # else
66  void *ptemp;
67 
68  ptemp = freeListMalloc(pvt);
69  if(ptemp) memset((char *)ptemp,0,pfl->size);
70  return(ptemp);
71 # endif
72 }
73 
74 LIBCOM_API void * epicsStdCall freeListMalloc(void *pvt)
75 {
76  FREELISTPVT *pfl = pvt;
77 # ifdef EPICS_FREELIST_DEBUG
78  return callocMustSucceed(1,pfl->size,"freeList Debug Malloc");
79 # else
80  void *ptemp;
81  void **ppnext;
82  allocMem *pallocmem;
83  int i;
84 
86  ptemp = pfl->head;
87  if(ptemp==0) {
88  /* layout of each block. nmalloc+1 REDZONEs for nmallocs.
89  * The first sizeof(void*) bytes are used to store a pointer
90  * to the next free block.
91  *
92  * | RED | size0 ------ | RED | size1 | ... | RED |
93  * | | next | ----- |
94  */
95  ptemp = (void *)malloc(pfl->nmalloc*(pfl->size+REDZONE)+REDZONE);
96  if(ptemp==0) {
97  epicsMutexUnlock(pfl->lock);
98  return(0);
99  }
100  pallocmem = (allocMem *)calloc(1,sizeof(allocMem));
101  if(pallocmem==0) {
102  epicsMutexUnlock(pfl->lock);
103  free(ptemp);
104  return(0);
105  }
106  pallocmem->memory = ptemp; /* real allocation */
107  ptemp = REDZONE + (char *) ptemp; /* skip first REDZONE */
108  if(pfl->mallochead)
109  pallocmem->next = pfl->mallochead;
110  pfl->mallochead = pallocmem;
111  for(i=0; i<pfl->nmalloc; i++) {
112  ppnext = ptemp;
113  VALGRIND_MEMPOOL_ALLOC(pfl, ptemp, sizeof(void*));
114  *ppnext = pfl->head;
115  pfl->head = ptemp;
116  ptemp = ((char *)ptemp) + pfl->size+REDZONE;
117  }
118  ptemp = pfl->head;
119  pfl->nBlocksAvailable += pfl->nmalloc;
120  }
121  ppnext = pfl->head;
122  pfl->head = *ppnext;
123  pfl->nBlocksAvailable--;
124  epicsMutexUnlock(pfl->lock);
125  VALGRIND_MEMPOOL_FREE(pfl, ptemp);
126  VALGRIND_MEMPOOL_ALLOC(pfl, ptemp, pfl->size);
127  return(ptemp);
128 # endif
129 }
130 
131 LIBCOM_API void epicsStdCall freeListFree(void *pvt,void*pmem)
132 {
133  FREELISTPVT *pfl = pvt;
134 # ifdef EPICS_FREELIST_DEBUG
135  memset ( pmem, 0xdd, pfl->size );
136  free(pmem);
137 # else
138  void **ppnext;
139 
140  VALGRIND_MEMPOOL_FREE(pvt, pmem);
141  VALGRIND_MEMPOOL_ALLOC(pvt, pmem, sizeof(void*));
142 
143  epicsMutexMustLock(pfl->lock);
144  ppnext = pmem;
145  *ppnext = pfl->head;
146  pfl->head = pmem;
147  pfl->nBlocksAvailable++;
148  epicsMutexUnlock(pfl->lock);
149 # endif
150 }
151 
152 LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)
153 {
154  FREELISTPVT *pfl = pvt;
155  allocMem *phead;
156  allocMem *pnext;
157 
159 
160  phead = pfl->mallochead;
161  while(phead) {
162  pnext = phead->next;
163  free(phead->memory);
164  free(phead);
165  phead = pnext;
166  }
167  epicsMutexDestroy(pfl->lock);
168  free(pvt);
169 }
170 
171 LIBCOM_API size_t epicsStdCall freeListItemsAvail(void *pvt)
172 {
173  FREELISTPVT *pfl = pvt;
174  size_t nBlocksAvailable;
175  epicsMutexMustLock(pfl->lock);
176  nBlocksAvailable = pfl->nBlocksAvailable;
177  epicsMutexUnlock(pfl->lock);
178  return nBlocksAvailable;
179 }
180 
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
Definition: epicsMutex.cpp:127
int i
Definition: scan.c:967
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
Definition: freeListLib.c:60
void * memory
Definition: freeListLib.c:32
LIBCOM_API size_t adjustToWorstCaseAlignment(size_t size)
Definition: adjustment.c:25
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
#define NULL
Definition: catime.c:38
#define REDZONE
Definition: freeListLib.c:20
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
LIBCOM_API void *epicsStdCall freeListMalloc(void *pvt)
Definition: freeListLib.c:74
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)
Definition: valgrind.h:6470
epicsMutexId lock
Definition: freeListLib.c:40
#define VALGRIND_DESTROY_MEMPOOL(pool)
Definition: valgrind.h:6475
APIs for the epicsMutex mutual exclusion semaphore.
struct allocMem allocMem
Declare function adjustToWorstCaseAlignment
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)
Definition: valgrind.h:6480
struct allocMem * next
Definition: freeListLib.c:31
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
Definition: cantProceed.c:22
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
Definition: freeListLib.c:44
LIBCOM_API size_t epicsStdCall freeListItemsAvail(void *pvt)
Definition: freeListLib.c:171
LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)
Definition: freeListLib.c:152
void * head
Definition: freeListLib.c:37
Routines for code that can&#39;t continue or return after an error.
#define VALGRIND_MEMPOOL_FREE(pool, addr)
Definition: valgrind.h:6485
size_t nBlocksAvailable
Definition: freeListLib.c:39
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
allocMem * mallochead
Definition: freeListLib.c:38
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
Definition: freeListLib.c:131