rpm 5.3.7
|
00001 00005 #include "system.h" 00006 #include <rpmiotypes.h> 00007 #include <rpmio.h> 00008 #include <rpmlog.h> 00009 #include <yarn.h> 00010 #include "debug.h" 00011 00012 #if defined(WITH_DMALLOC) 00013 #undef xmalloc 00014 #undef xcalloc 00015 #undef xrealloc 00016 #undef xstrdup 00017 #endif 00018 00019 #if !defined(EXIT_FAILURE) 00020 #define EXIT_FAILURE 1 00021 #endif 00022 00023 /*@-modfilesys@*/ 00024 /*@only@*/ void *vmefail(size_t size) 00025 { 00026 fprintf(stderr, _("memory alloc (%u bytes) returned NULL.\n"), (unsigned)size); 00027 exit(EXIT_FAILURE); 00028 /*@notreached@*/ 00029 /*@-nullret@*/ 00030 return NULL; 00031 /*@=nullret@*/ 00032 } 00033 /*@=modfilesys@*/ 00034 00037 struct rpmioPool_s { 00038 yarnLock have; 00039 /*@relnull@*/ 00040 void *pool; 00041 /*@relnull@*/ 00042 rpmioItem head; 00043 /*@dependent@*/ 00044 rpmioItem * tail; 00045 size_t size; 00046 int limit; 00047 int flags; 00048 /*@null@*/ 00049 const char * (*dbg) (void *item) 00050 /*@*/; 00051 /*@null@*/ 00052 void (*init) (void *item) 00053 /*@modifies *item @*/; 00054 /*@null@*/ 00055 void (*fini) (void *item) 00056 /*@modifies *item @*/; 00057 int reused; 00058 int made; 00059 /*@observer@*/ 00060 const char *name; 00061 /*@null@*/ 00062 void * zlog; 00063 }; 00064 00065 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00066 static rpmioPool _rpmioPool; 00067 00068 rpmioPool rpmioFreePool(rpmioPool pool) 00069 /*@globals _rpmioPool @*/ 00070 /*@modifies _rpmioPool @*/ 00071 { 00072 if (pool == NULL) { 00073 pool = _rpmioPool; 00074 _rpmioPool = NULL; 00075 } 00076 if (pool != NULL) { 00077 rpmioItem item; 00078 int count = 0; 00079 yarnPossess(pool->have); 00080 while ((item = pool->head) != NULL) { 00081 pool->head = item->pool; /* XXX pool == next */ 00082 if (item->use != NULL) 00083 item->use = yarnFreeLock(item->use); 00084 item = _free(item); 00085 count++; 00086 } 00087 yarnRelease(pool->have); 00088 pool->have = yarnFreeLock(pool->have); 00089 rpmlog(RPMLOG_DEBUG, D_("pool %s:\treused %d, alloc'd %d, free'd %d items.\n"), pool->name, pool->reused, pool->made, count); 00090 #ifdef NOTYET 00091 assert(pool->made == count); 00092 #else 00093 if (pool->made != count) 00094 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); 00095 #endif 00096 (void) _free(pool); 00097 VALGRIND_DESTROY_MEMPOOL(pool); 00098 } 00099 return NULL; 00100 } 00101 00102 /*@-internalglobs@*/ 00103 rpmioPool rpmioNewPool(const char * name, size_t size, int limit, int flags, 00104 char * (*dbg) (void *item), 00105 void (*init) (void *item), 00106 void (*fini) (void *item)) 00107 /*@*/ 00108 { 00109 rpmioPool pool = xcalloc(1, sizeof(*pool)); 00110 #if defined(WITH_VALGRIND) 00111 static int rzB = 0; /* size of red-zones (if any) */ 00112 static int is_zeroed = 0; /* does pool return zero'd allocations? */ 00113 rzB = rzB; /* XXX CentOS5 valgrind doesn't use. */ 00114 is_zeroed = is_zeroed; /* XXX CentOS5 valgrind doesn't use. */ 00115 #endif 00116 VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed); 00117 pool->have = yarnNewLock(0); 00118 pool->pool = NULL; 00119 pool->head = NULL; 00120 pool->tail = &pool->head; 00121 pool->size = size; 00122 pool->limit = limit; 00123 pool->flags = flags; 00124 pool->dbg = (void *) dbg; 00125 pool->init = init; 00126 pool->fini = fini; 00127 pool->reused = 0; 00128 pool->made = 0; 00129 pool->name = name; 00130 pool->zlog = NULL; 00131 rpmlog(RPMLOG_DEBUG, D_("pool %s:\tcreated size %u limit %d flags %d\n"), pool->name, (unsigned)pool->size, pool->limit, pool->flags); 00132 return pool; 00133 } 00134 /*@=internalglobs@*/ 00135 00136 /*@-internalglobs@*/ 00137 rpmioItem rpmioUnlinkPoolItem(rpmioItem item, const char * msg, 00138 const char * fn, unsigned ln) 00139 { 00140 rpmioPool pool; 00141 if (item == NULL) return NULL; 00142 yarnPossess(item->use); 00143 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00144 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00145 /*@-modfilesys@*/ 00146 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name, 00147 item, yarnPeekLock(item->use), msg, fn, ln, imsg); 00148 /*@=modfilesys@*/ 00149 } 00150 yarnTwist(item->use, BY, -1); 00151 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */ 00152 return item; 00153 /*@=retalias@*/ 00154 } 00155 /*@=internalglobs@*/ 00156 00157 /*@-internalglobs@*/ 00158 rpmioItem rpmioLinkPoolItem(rpmioItem item, const char * msg, 00159 const char * fn, unsigned ln) 00160 { 00161 rpmioPool pool; 00162 if (item == NULL) return NULL; 00163 yarnPossess(item->use); 00164 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00165 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00166 /*@-modfilesys@*/ 00167 fprintf(stderr, "--> %s %p ++ %ld %s at %s:%u%s\n", pool->name, 00168 item, yarnPeekLock(item->use)+1, msg, fn, ln, imsg); 00169 /*@=modfilesys@*/ 00170 } 00171 yarnTwist(item->use, BY, 1); 00172 return item; 00173 } 00174 /*@=internalglobs@*/ 00175 00176 /*@-internalglobs@*/ 00177 /*@null@*/ 00178 void * rpmioFreePoolItem(/*@killref@*/ /*@null@*/ rpmioItem item, 00179 const char * msg, const char * fn, unsigned ln) 00180 /*@modifies item @*/ 00181 { 00182 rpmioPool pool; 00183 if (item == NULL) return NULL; 00184 00185 #ifdef NOTYET 00186 assert(item->pool != NULL); /* XXX (*pool->fini) is likely necessary */ 00187 #endif 00188 yarnPossess(item->use); 00189 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00190 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00191 /*@-modfilesys@*/ 00192 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name, 00193 item, yarnPeekLock(item->use), msg, fn, ln, imsg); 00194 /*@=modfilesys@*/ 00195 } 00196 if (yarnPeekLock(item->use) <= 1L) { 00197 if (pool != NULL && pool->fini != NULL) 00198 (*pool->fini) ((void *)item); 00199 VALGRIND_MEMPOOL_FREE(pool, item + 1); 00200 item = rpmioPutPool(item); 00201 } else 00202 yarnTwist(item->use, BY, -1); 00203 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */ 00204 return (void *) item; 00205 /*@=retalias@*/ 00206 } 00207 /*@=internalglobs@*/ 00208 00209 /*@-internalglobs@*/ 00210 rpmioItem rpmioGetPool(rpmioPool pool, size_t size) 00211 { 00212 rpmioItem item; 00213 00214 if (pool != NULL) { 00215 /* if can't create any more, wait for a space to show up */ 00216 yarnPossess(pool->have); 00217 if (pool->limit == 0) 00218 yarnWaitFor(pool->have, NOT_TO_BE, 0); 00219 00220 /* if a space is available, pull it from the list and return it */ 00221 if (pool->head != NULL) { 00222 item = pool->head; 00223 pool->head = item->pool; /* XXX pool == next */ 00224 if (pool->head == NULL) 00225 pool->tail = &pool->head; 00226 pool->reused++; 00227 item->pool = pool; /* remember the pool this belongs to */ 00228 yarnTwist(pool->have, BY, -1); /* one less in pool */ 00229 VALGRIND_MEMPOOL_ALLOC(pool, 00230 item + 1, 00231 size - sizeof(struct rpmioItem_s)); 00232 return item; 00233 } 00234 00235 /* nothing available, don't want to wait, make a new item */ 00236 assert(pool->limit != 0); 00237 if (pool->limit > 0) 00238 pool->limit--; 00239 pool->made++; 00240 yarnRelease(pool->have); 00241 } 00242 00243 item = xcalloc(1, size); 00244 item->use = yarnNewLock(0); /* XXX newref? */ 00245 item->pool = pool; 00246 VALGRIND_MEMPOOL_ALLOC(pool, 00247 item + 1, 00248 size - sizeof(struct rpmioItem_s)); 00249 return item; 00250 } 00251 /*@=internalglobs@*/ 00252 00253 /*@-internalglobs@*/ 00254 rpmioItem rpmioPutPool(rpmioItem item) 00255 { 00256 rpmioPool pool; 00257 00258 if ((pool = item->pool) != NULL) { 00259 yarnPossess(pool->have); 00260 item->pool = NULL; /* XXX pool == next */ 00261 *pool->tail = item; 00262 pool->tail = (void *)&item->pool;/* XXX pool == next */ 00263 yarnTwist(pool->have, BY, 1); 00264 if (item->use != NULL) 00265 yarnTwist(item->use, TO, 0); 00266 return NULL; 00267 } 00268 00269 if (item->use != NULL) { 00270 yarnTwist(item->use, TO, 0); 00271 item->use = yarnFreeLock(item->use); 00272 } 00273 (void) _free(item); 00274 return NULL; 00275 } 00276 /*@=internalglobs@*/ 00277 00278 #if !(HAVE_MCHECK_H && defined(__GNUC__)) && !defined(__LCLINT__) 00279 00280 /*@out@*/ /*@only@*/ void * xmalloc (size_t size) 00281 { 00282 register void *value; 00283 if (size == 0) size++; 00284 value = malloc (size); 00285 if (value == 0) 00286 value = vmefail(size); 00287 return value; 00288 } 00289 00290 /*@only@*/ void * xcalloc (size_t nmemb, size_t size) 00291 { 00292 register void *value; 00293 if (size == 0) size++; 00294 if (nmemb == 0) nmemb++; 00295 value = calloc (nmemb, size); 00296 if (value == 0) 00297 value = vmefail(size); 00298 return value; 00299 } 00300 00301 /*@only@*/ void * xrealloc (/*@only@*/ void *ptr, size_t size) 00302 { 00303 register void *value; 00304 if (size == 0) size++; 00305 value = realloc (ptr, size); 00306 if (value == 0) 00307 value = vmefail(size); 00308 return value; 00309 } 00310 00311 /*@only@*/ char * xstrdup (const char *str) 00312 { 00313 size_t size = strlen(str) + 1; 00314 char *newstr = (char *) malloc (size); 00315 if (newstr == 0) 00316 newstr = (char *) vmefail(size); 00317 strcpy (newstr, str); 00318 return newstr; 00319 } 00320 00321 #endif /* !(HAVE_MCHECK_H && defined(__GNUC__)) */