rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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 #if defined(WITH_DMALLOC)
13 #undef xmalloc
14 #undef xcalloc
15 #undef xrealloc
16 #undef xstrdup
17 #endif
18
19 #if !defined(EXIT_FAILURE)
20 #define EXIT_FAILURE 1
21 #endif
22
23 /*@-modfilesys@*/
24 /*@only@*/ void *vmefail(size_t size)
25 {
26 fprintf(stderr, _("memory alloc (%u bytes) returned NULL.\n"), (unsigned)size);
27 exit(EXIT_FAILURE);
28 /*@notreached@*/
29 /*@-nullret@*/
30 return NULL;
31 /*@=nullret@*/
32 }
33 /*@=modfilesys@*/
34
37 struct rpmioPool_s {
38 yarnLock have;
39 /*@relnull@*/
40 void *pool;
41 /*@relnull@*/
42 rpmioItem head;
43 /*@dependent@*/
44 rpmioItem * tail;
45 size_t size;
46 int limit;
47 int flags;
48 /*@null@*/
49 const char * (*dbg) (void *item)
50 /*@*/;
51 /*@null@*/
52 void (*init) (void *item)
53 /*@modifies *item @*/;
54 /*@null@*/
55 void (*fini) (void *item)
56 /*@modifies *item @*/;
57 int reused;
58 int made;
59 /*@observer@*/
60 const char *name;
61 /*@null@*/
62 void * zlog;
63 };
64
65 /*@unchecked@*/ /*@only@*/ /*@null@*/
66 static rpmioPool _rpmioPool;
67
68 rpmioPool rpmioFreePool(rpmioPool pool)
69 /*@globals _rpmioPool @*/
70 /*@modifies _rpmioPool @*/
71 {
72 if (pool == NULL) {
73 pool = _rpmioPool;
74 _rpmioPool = NULL;
75 }
76 if (pool != NULL) {
77 rpmioItem item;
78 int count = 0;
79 yarnPossess(pool->have);
80 while ((item = pool->head) != NULL) {
81 pool->head = item->pool; /* XXX pool == next */
82 if (item->use != NULL)
83 item->use = yarnFreeLock(item->use);
84 item = _free(item);
85 count++;
86 }
87 yarnRelease(pool->have);
88 pool->have = yarnFreeLock(pool->have);
89 rpmlog(RPMLOG_DEBUG, D_("pool %s:\treused %d, alloc'd %d, free'd %d items.\n"), pool->name, pool->reused, pool->made, count);
90 #ifdef NOTYET
91 assert(pool->made == count);
92 #else
93 if (pool->made != count)
94 rpmlog(RPMLOG_DEBUG, 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);
95 #endif
96 pool = _free(pool);
97 }
98 return NULL;
99 }
100
101 /*@-internalglobs@*/
102 rpmioPool rpmioNewPool(const char * name, size_t size, int limit, int flags,
103 const char * (*dbg) (void *item),
104 void (*init) (void *item),
105 void (*fini) (void *item))
106 /*@*/
107 {
108 rpmioPool pool = xcalloc(1, sizeof(*pool));
109 pool->have = yarnNewLock(0);
110 pool->pool = NULL;
111 pool->head = NULL;
112 pool->tail = &pool->head;
113 pool->size = size;
114 pool->limit = limit;
115 pool->flags = flags;
116 pool->dbg = dbg;
117 pool->init = init;
118 pool->fini = fini;
119 pool->reused = 0;
120 pool->made = 0;
121 pool->name = name;
122 pool->zlog = NULL;
123 rpmlog(RPMLOG_DEBUG, D_("pool %s:\tcreated size %u limit %d flags %d\n"), pool->name, (unsigned)pool->size, pool->limit, pool->flags);
124 return pool;
125 }
126 /*@=internalglobs@*/
127
128 /*@-internalglobs@*/
129 rpmioItem rpmioUnlinkPoolItem(rpmioItem item, const char * msg,
130 const char * fn, unsigned ln)
131 {
132 rpmioPool pool;
133 if (item == NULL) return NULL;
134 yarnPossess(item->use);
135 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) {
136 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
137 /*@-modfilesys@*/
138 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
139 item, yarnPeekLock(item->use), msg, fn, ln, imsg);
140 /*@=modfilesys@*/
141 }
142 yarnTwist(item->use, BY, -1);
143 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */
144 return item;
145 /*@=retalias@*/
146 }
147 /*@=internalglobs@*/
148
149 /*@-internalglobs@*/
150 rpmioItem rpmioLinkPoolItem(rpmioItem item, const char * msg,
151 const char * fn, unsigned ln)
152 {
153 rpmioPool pool;
154 if (item == NULL) return NULL;
155 yarnPossess(item->use);
156 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) {
157 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
158 /*@-modfilesys@*/
159 fprintf(stderr, "--> %s %p ++ %ld %s at %s:%u%s\n", pool->name,
160 item, yarnPeekLock(item->use)+1, msg, fn, ln, imsg);
161 /*@=modfilesys@*/
162 }
163 yarnTwist(item->use, BY, 1);
164 return item;
165 }
166 /*@=internalglobs@*/
167
168 /*@-internalglobs@*/
169 /*@null@*/
170 void * rpmioFreePoolItem(/*@killref@*/ /*@null@*/ rpmioItem item,
171 const char * msg, const char * fn, unsigned ln)
172 /*@modifies item @*/
173 {
174 rpmioPool pool;
175 if (item == NULL) return NULL;
176
177 #ifdef NOTYET
178 assert(item->pool != NULL); /* XXX (*pool->fini) is likely necessary */
179 #endif
180 yarnPossess(item->use);
181 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) {
182 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : "");
183 /*@-modfilesys@*/
184 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
185 item, yarnPeekLock(item->use), msg, fn, ln, imsg);
186 /*@=modfilesys@*/
187 }
188 if (yarnPeekLock(item->use) <= 1L) {
189 if (pool != NULL && pool->fini != NULL)
190 (*pool->fini) ((void *)item);
191 item = rpmioPutPool(item);
192 } else
193 yarnTwist(item->use, BY, -1);
194 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */
195 return (void *) item;
196 /*@=retalias@*/
197 }
198 /*@=internalglobs@*/
199
200 /*@-internalglobs@*/
201 rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
202 {
203 rpmioItem item;
204
205 if (pool != NULL) {
206 /* if can't create any more, wait for a space to show up */
207 yarnPossess(pool->have);
208 if (pool->limit == 0)
209 yarnWaitFor(pool->have, NOT_TO_BE, 0);
210
211 /* if a space is available, pull it from the list and return it */
212 if (pool->head != NULL) {
213 item = pool->head;
214 pool->head = item->pool; /* XXX pool == next */
215 if (pool->head == NULL)
216 pool->tail = &pool->head;
217 pool->reused++;
218 item->pool = pool; /* remember the pool this belongs to */
219 yarnTwist(pool->have, BY, -1); /* one less in pool */
220 return item;
221 }
222
223 /* nothing available, don't want to wait, make a new item */
224 assert(pool->limit != 0);
225 if (pool->limit > 0)
226 pool->limit--;
227 pool->made++;
228 yarnRelease(pool->have);
229 }
230
231 item = xcalloc(1, size);
232 item->use = yarnNewLock(0); /* XXX newref? */
233 item->pool = pool;
234 return item;
235 }
236 /*@=internalglobs@*/
237
238 /*@-internalglobs@*/
239 rpmioItem rpmioPutPool(rpmioItem item)
240 {
241 rpmioPool pool;
242
243 if ((pool = item->pool) != NULL) {
244 yarnPossess(pool->have);
245 item->pool = NULL; /* XXX pool == next */
246 *pool->tail = item;
247 pool->tail = (rpmioItem *)&item->pool;/* XXX pool == next */
248 yarnTwist(pool->have, BY, 1);
249 if (item->use != NULL)
250 yarnTwist(item->use, TO, 0);
251 return NULL;
252 }
253
254 if (item->use != NULL) {
255 yarnTwist(item->use, TO, 0);
256 item->use = yarnFreeLock(item->use);
257 }
258 item = _free(item);
259 return NULL;
260 }
261 /*@=internalglobs@*/
262
263 #if !(HAVE_MCHECK_H && defined(__GNUC__)) && !defined(__LCLINT__)
264
265 /*@out@*/ /*@only@*/ void * xmalloc (size_t size)
266 {
267 register void *value;
268 if (size == 0) size++;
269 value = malloc (size);
270 if (value == 0)
271 value = vmefail(size);
272 return value;
273 }
274
275 /*@only@*/ void * xcalloc (size_t nmemb, size_t size)
276 {
277 register void *value;
278 if (size == 0) size++;
279 if (nmemb == 0) nmemb++;
280 value = calloc (nmemb, size);
281 if (value == 0)
282 value = vmefail(size);
283 return value;
284 }
285
286 /*@only@*/ void * xrealloc (/*@only@*/ void *ptr, size_t size)
287 {
288 register void *value;
289 if (size == 0) size++;
290 value = realloc (ptr, size);
291 if (value == 0)
292 value = vmefail(size);
293 return value;
294 }
295
296 /*@only@*/ char * xstrdup (const char *str)
297 {
298 size_t size = strlen(str) + 1;
299 char *newstr = (char *) malloc (size);
300 if (newstr == 0)
301 newstr = (char *) vmefail(size);
302 strcpy (newstr, str);
303 return newstr;
304 }
305
306 #endif /* !(HAVE_MCHECK_H && defined(__GNUC__)) */