rpm  5.4.15
rpmmalloc.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 #include <rpmiotypes.h>
7 #include <rpmio.h>
8 #include <rpmlog.h>
9 #include <yarn.h>
10 #include "debug.h"
11 
12 #ifdef __cplusplus
13 GENfree(rpmioItem)
14 #endif /* __cplusplus */
15 
16 #if defined(WITH_DMALLOC)
17 #undef xmalloc
18 #undef xcalloc
19 #undef xrealloc
20 #undef xstrdup
21 #endif
22 
23 #if !defined(EXIT_FAILURE)
24 #define EXIT_FAILURE 1
25 #endif
26 
27 /*@-modfilesys@*/
28 /*@only@*/ void *vmefail(size_t size)
29 {
30  fprintf(stderr, _("memory alloc (%u bytes) returned NULL.\n"), (unsigned)size);
31  exit(EXIT_FAILURE);
32  /*@notreached@*/
33 /*@-nullret@*/
34  return NULL;
35 /*@=nullret@*/
36 }
37 /*@=modfilesys@*/
38 
41 struct rpmioPool_s {
43 /*@relnull@*/
44  void *pool;
45 /*@relnull@*/
47 /*@dependent@*/
49  size_t size;
50  int limit;
51  int flags;
52 /*@null@*/
53  const char * (*dbg) (void *item)
54  /*@*/;
55 /*@null@*/
56  void (*init) (void *item)
57  /*@modifies *item @*/;
58 /*@null@*/
59  void (*fini) (void *item)
60  /*@modifies *item @*/;
61  int reused;
62  int made;
63 /*@observer@*/
64  const char *name;
65 /*@null@*/
66  void * zlog;
67 };
68 
69 /*@unchecked@*/ /*@only@*/ /*@null@*/
71 
73  /*@globals _rpmioPool @*/
74  /*@modifies _rpmioPool @*/
75 {
76  if (pool == NULL) {
77  pool = _rpmioPool;
78  _rpmioPool = NULL;
79  }
80  if (pool != NULL) {
81  rpmioItem item;
82  int count = 0;
83  yarnPossess(pool->have);
84 VALGRIND_HG_CLEAN_MEMORY(pool, sizeof(*pool));
85  while ((item = pool->head) != NULL) {
86 VALGRIND_HG_CLEAN_MEMORY(item, pool->size);
87  pool->head = (rpmioItem) item->pool; /* XXX pool == next */
88  if (item->use != NULL)
89  item->use = yarnFreeLock(item->use);
90  item = _free(item);
91  count++;
92  }
93  yarnRelease(pool->have);
94  pool->have = yarnFreeLock(pool->have);
95  rpmlog(RPMLOG_DEBUG, D_("pool %s:\treused %d, alloc'd %d, free'd %d items.\n"), pool->name, pool->reused, pool->made, count);
96 #ifdef NOTYET
97 assert(pool->made == count);
98 #else
99 if (pool->made != count)
100 rpmlog(RPMLOG_WARNING, D_("pool %s: FIXME: made %d, count %d\nNote: This is a harmless memory leak discovered while exiting, relax ...\n"), pool->name, pool->made, count);
101 #endif
102  (void) _free(pool);
104  }
105  return NULL;
106 }
107 
108 /*@-internalglobs@*/
109 rpmioPool rpmioNewPool(const char * name, size_t size, int limit, int flags,
110  char * (*dbg) (void *item),
111  void (*init) (void *item),
112  void (*fini) (void *item))
113  /*@*/
114 {
115  rpmioPool pool = (rpmioPool) xcalloc(1, sizeof(*pool));
116 #if defined(WITH_VALGRIND)
117  static int rzB = 0; /* size of red-zones (if any) */
118  static int is_zeroed = 0; /* does pool return zero'd allocations? */
119  rzB = rzB; /* XXX CentOS5 valgrind doesn't use. */
120  is_zeroed = is_zeroed; /* XXX CentOS5 valgrind doesn't use. */
121 #endif
122  VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed);
123  pool->have = yarnNewLock(0);
124  pool->pool = NULL;
125  pool->head = NULL;
126  pool->tail = &pool->head;
127  pool->size = size;
128  pool->limit = limit;
129  pool->flags = flags;
130  pool->dbg = (const char* (*)(void*)) dbg;
131  pool->init = init;
132  pool->fini = fini;
133  pool->reused = 0;
134  pool->made = 0;
135  pool->name = name;
136  pool->zlog = NULL;
137  rpmlog(RPMLOG_DEBUG, D_("pool %s:\tcreated size %u limit %d flags %d\n"), pool->name, (unsigned)pool->size, pool->limit, pool->flags);
138  return pool;
139 }
140 /*@=internalglobs@*/
141 
142 /*@-internalglobs@*/
143 rpmioItem rpmioUnlinkPoolItem(rpmioItem item, const char * msg,
144  const char * fn, unsigned ln)
145 {
146  rpmioPool pool;
147  if (item == NULL) return NULL;
148  yarnPossess(item->use);
150  if ((pool = (rpmioPool) item->pool) != NULL && pool->flags && msg != NULL) {
151  const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
152 /*@-modfilesys@*/
153  fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
154  item, yarnPeekLock(item->use), msg, fn, ln, imsg);
155 /*@=modfilesys@*/
156  }
157  yarnTwist(item->use, BY, -1);
158 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */
159  return item;
160 /*@=retalias@*/
161 }
162 /*@=internalglobs@*/
163 
164 /*@-internalglobs@*/
165 rpmioItem rpmioLinkPoolItem(rpmioItem item, const char * msg,
166  const char * fn, unsigned ln)
167 {
168  rpmioPool pool;
169  if (item == NULL) return NULL;
170  yarnPossess(item->use);
171  if ((pool = (rpmioPool) item->pool) != NULL && pool->flags && msg != NULL) {
172  const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
173 /*@-modfilesys@*/
174  fprintf(stderr, "--> %s %p ++ %ld %s at %s:%u%s\n", pool->name,
175  item, yarnPeekLock(item->use)+1, msg, fn, ln, imsg);
176 /*@=modfilesys@*/
177  }
179  yarnTwist(item->use, BY, 1);
180  return item;
181 }
182 /*@=internalglobs@*/
183 
184 /*@-internalglobs@*/
185 /*@null@*/
186 void * rpmioFreePoolItem(/*@killref@*/ /*@null@*/ rpmioItem item,
187  const char * msg, const char * fn, unsigned ln)
188  /*@modifies item @*/
189 {
190  rpmioPool pool;
191  if (item == NULL) return NULL;
192 
193 #ifdef NOTYET
194 assert(item->pool != NULL); /* XXX (*pool->fini) is likely necessary */
195 #endif
196  yarnPossess(item->use);
198  if ((pool = (rpmioPool) item->pool) != NULL && pool->flags && msg != NULL) {
199  const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
200 /*@-modfilesys@*/
201  fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
202  item, yarnPeekLock(item->use), msg, fn, ln, imsg);
203 /*@=modfilesys@*/
204  }
205  if (yarnPeekLock(item->use) <= 1L) {
206 VALGRIND_HG_CLEAN_MEMORY(item, pool->size);
207  if (pool != NULL && pool->fini != NULL)
208  (*pool->fini) ((void *)item);
209  VALGRIND_MEMPOOL_FREE(pool, item + 1);
210  item = rpmioPutPool(item);
211  } else
212  yarnTwist(item->use, BY, -1);
213 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */
214  return (void *) item;
215 /*@=retalias@*/
216 }
217 /*@=internalglobs@*/
218 
219 /*@-internalglobs@*/
221 {
222  rpmioItem item;
223 
224  if (pool != NULL) {
225  /* if can't create any more, wait for a space to show up */
226  yarnPossess(pool->have);
227  if (pool->limit == 0)
228  yarnWaitFor(pool->have, NOT_TO_BE, 0);
229 
230  /* if a space is available, pull it from the list and return it */
231  if (pool->head != NULL) {
232  item = pool->head;
233  pool->head = (rpmioItem) item->pool; /* XXX pool == next */
234  if (pool->head == NULL)
235  pool->tail = &pool->head;
236  pool->reused++;
237  item->pool = pool; /* remember the pool this belongs to */
238  yarnTwist(pool->have, BY, -1); /* one less in pool */
240  item + 1,
241  size - sizeof(struct rpmioItem_s));
242  return item;
243  }
244 
245  /* nothing available, don't want to wait, make a new item */
246 assert(pool->limit != 0);
247  if (pool->limit > 0)
248  pool->limit--;
249  pool->made++;
250  yarnRelease(pool->have);
251  }
252 
253  item = (rpmioItem) xcalloc(1, size);
254  item->use = yarnNewLock(0); /* XXX newref? */
255  item->pool = pool;
257  item + 1,
258  size - sizeof(struct rpmioItem_s));
259  return item;
260 }
261 /*@=internalglobs@*/
262 
263 /*@-internalglobs@*/
265 {
266  rpmioPool pool;
267 
268  if ((pool = (rpmioPool) item->pool) != NULL) {
269  yarnPossess(pool->have);
270  item->pool = NULL; /* XXX pool == next */
271  *pool->tail = item;
272  pool->tail = (rpmioItem *)&item->pool;/* XXX pool == next */
273  yarnTwist(pool->have, BY, 1);
274  if (item->use != NULL)
275  yarnTwist(item->use, TO, 0);
276  return NULL;
277  }
278 
279  if (item->use != NULL) {
280  yarnTwist(item->use, TO, 0);
281  item->use = yarnFreeLock(item->use);
282  }
283  (void) _free(item);
284  return NULL;
285 }
286 /*@=internalglobs@*/
287 
288 #if !(HAVE_MCHECK_H && defined(__GNUC__)) && !defined(__LCLINT__)
289 
290 /*@out@*/ /*@only@*/ void * xmalloc (size_t size)
291 {
292  register void *value;
293  if (size == 0) size++;
294  value = malloc (size);
295  if (value == 0)
296  value = vmefail(size);
297  return value;
298 }
299 
300 /*@only@*/ void * xcalloc (size_t nmemb, size_t size)
301 {
302  register void *value;
303  if (size == 0) size++;
304  if (nmemb == 0) nmemb++;
305  value = calloc (nmemb, size);
306  if (value == 0)
307  value = vmefail(size);
308  return value;
309 }
310 
311 /*@only@*/ void * xrealloc (/*@only@*/ void *ptr, size_t size)
312 {
313  register void *value;
314  if (size == 0) size++;
315  value = realloc (ptr, size);
316  if (value == 0)
317  value = vmefail(size);
318  return value;
319 }
320 
321 /*@only@*/ char * xstrdup (const char *str)
322 {
323  size_t size = strlen(str) + 1;
324  char *newstr = (char *) malloc (size);
325  if (newstr == 0)
326  newstr = (char *) vmefail(size);
327  strcpy (newstr, str);
328  return newstr;
329 }
330 
331 #endif /* !(HAVE_MCHECK_H && defined(__GNUC__)) */
void yarnTwist(yarnLock bolt, yarnTwistOP op, long val)
Definition: yarn.c:279
rpmioItem * tail
Definition: rpmmalloc.c:48
void * pool
Definition: rpmmalloc.c:44
void yarnPossess(yarnLock bolt)
Definition: yarn.c:262
long yarnPeekLock(yarnLock bolt)
Definition: yarn.c:325
yarnLock use
Definition: rpmiotypes.h:44
rpmioItem rpmioLinkPoolItem(rpmioItem item, const char *msg, const char *fn, unsigned ln)
Increment a pool item refcount.
Definition: rpmmalloc.c:165
Definition: yarn.h:166
static rpmioPool _rpmioPool
Definition: rpmmalloc.c:70
const char *(* dbg)(void *item)
Definition: rpmmalloc.c:53
void * pool
Definition: rpmiotypes.h:46
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
int reused
Definition: rpmmalloc.c:61
#define VALGRIND_MEMPOOL_FREE(pool, addr)
Definition: debug.h:88
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)
Definition: debug.h:85
void * xrealloc(void *ptr, size_t size)
Definition: rpmmalloc.c:311
rpmioItem head
Definition: rpmmalloc.c:46
const char * str
Definition: bson.h:593
Yet Another syslog(3) API clone.
void yarnWaitFor(yarnLock bolt, yarnWaitOP op, long val)
Definition: yarn.c:295
struct rpmioPool_s * rpmioPool
Definition: rpmiotypes.h:56
yarnLock yarnNewLock(long initial)
Definition: yarn.c:248
const char const bson const bson int limit
Definition: mongo.h:569
size_t size
Definition: rpmmalloc.c:49
yarnLock yarnFreeLock(yarnLock bolt)
Definition: yarn.c:330
#define VALGRIND_DESTROY_MEMPOOL(pool)
Definition: debug.h:86
void * rpmioFreePoolItem(rpmioItem item, const char *msg, const char *fn, unsigned ln)
Free a pool item.
Definition: rpmmalloc.c:186
yarnLock have
Definition: rpmmalloc.c:42
void * xmalloc(size_t size)
Definition: rpmmalloc.c:290
#define EXIT_FAILURE
Definition: rpmmalloc.c:24
void(* fini)(void *item)
Definition: rpmmalloc.c:59
rpmioItem rpmioUnlinkPoolItem(rpmioItem item, const char *msg, const char *fn, unsigned ln)
Decrement a pool item refcount.
Definition: rpmmalloc.c:143
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
void yarnRelease(yarnLock bolt)
Definition: yarn.c:270
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
void * zlog
Definition: rpmmalloc.c:66
rpmioItem rpmioPutPool(rpmioItem item)
Put unused item into pool (or free).
Definition: rpmmalloc.c:264
#define L(CS)
Definition: fnmatch.c:161
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
struct rpmioItem_s * rpmioItem
Definition: rpmiotypes.h:41
const char const char size_t size
Definition: bson.h:895
void(* init)(void *item)
Definition: rpmmalloc.c:56
#define ANNOTATE_HAPPENS_BEFORE(_obj)
Definition: debug.h:142
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
#define VALGRIND_HG_CLEAN_MEMORY(_qzz_start, _qzz_len)
Definition: debug.h:131
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)
Definition: debug.h:87
static const char * name
Definition: yarn.h:166
#define _(Text)
Definition: system.h:29
#define ANNOTATE_HAPPENS_AFTER(_obj)
Definition: debug.h:143
rpmioPool rpmioFreePool(rpmioPool pool)
Reclaim memory pool items.
Definition: rpmmalloc.c:72
const char * name
Definition: rpmmalloc.c:64
#define D_(Text)
Definition: system.h:526
void * vmefail(size_t size)
Definition: rpmmalloc.c:28
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321