|
rpm
5.4.4
|
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 VALGRIND_HG_CLEAN_MEMORY(pool, sizeof(*pool)); 00081 while ((item = pool->head) != NULL) { 00082 VALGRIND_HG_CLEAN_MEMORY(item, pool->size); 00083 pool->head = item->pool; /* XXX pool == next */ 00084 if (item->use != NULL) 00085 item->use = yarnFreeLock(item->use); 00086 item = _free(item); 00087 count++; 00088 } 00089 yarnRelease(pool->have); 00090 pool->have = yarnFreeLock(pool->have); 00091 rpmlog(RPMLOG_DEBUG, D_("pool %s:\treused %d, alloc'd %d, free'd %d items.\n"), pool->name, pool->reused, pool->made, count); 00092 #ifdef NOTYET 00093 assert(pool->made == count); 00094 #else 00095 if (pool->made != count) 00096 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); 00097 #endif 00098 (void) _free(pool); 00099 VALGRIND_DESTROY_MEMPOOL(pool); 00100 } 00101 return NULL; 00102 } 00103 00104 /*@-internalglobs@*/ 00105 rpmioPool rpmioNewPool(const char * name, size_t size, int limit, int flags, 00106 char * (*dbg) (void *item), 00107 void (*init) (void *item), 00108 void (*fini) (void *item)) 00109 /*@*/ 00110 { 00111 rpmioPool pool = xcalloc(1, sizeof(*pool)); 00112 #if defined(WITH_VALGRIND) 00113 static int rzB = 0; /* size of red-zones (if any) */ 00114 static int is_zeroed = 0; /* does pool return zero'd allocations? */ 00115 rzB = rzB; /* XXX CentOS5 valgrind doesn't use. */ 00116 is_zeroed = is_zeroed; /* XXX CentOS5 valgrind doesn't use. */ 00117 #endif 00118 VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed); 00119 pool->have = yarnNewLock(0); 00120 pool->pool = NULL; 00121 pool->head = NULL; 00122 pool->tail = &pool->head; 00123 pool->size = size; 00124 pool->limit = limit; 00125 pool->flags = flags; 00126 pool->dbg = (void *) dbg; 00127 pool->init = init; 00128 pool->fini = fini; 00129 pool->reused = 0; 00130 pool->made = 0; 00131 pool->name = name; 00132 pool->zlog = NULL; 00133 rpmlog(RPMLOG_DEBUG, D_("pool %s:\tcreated size %u limit %d flags %d\n"), pool->name, (unsigned)pool->size, pool->limit, pool->flags); 00134 return pool; 00135 } 00136 /*@=internalglobs@*/ 00137 00138 /*@-internalglobs@*/ 00139 rpmioItem rpmioUnlinkPoolItem(rpmioItem item, const char * msg, 00140 const char * fn, unsigned ln) 00141 { 00142 rpmioPool pool; 00143 if (item == NULL) return NULL; 00144 yarnPossess(item->use); 00145 ANNOTATE_HAPPENS_AFTER(item); 00146 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00147 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00148 /*@-modfilesys@*/ 00149 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name, 00150 item, yarnPeekLock(item->use), msg, fn, ln, imsg); 00151 /*@=modfilesys@*/ 00152 } 00153 yarnTwist(item->use, BY, -1); 00154 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */ 00155 return item; 00156 /*@=retalias@*/ 00157 } 00158 /*@=internalglobs@*/ 00159 00160 /*@-internalglobs@*/ 00161 rpmioItem rpmioLinkPoolItem(rpmioItem item, const char * msg, 00162 const char * fn, unsigned ln) 00163 { 00164 rpmioPool pool; 00165 if (item == NULL) return NULL; 00166 yarnPossess(item->use); 00167 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00168 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00169 /*@-modfilesys@*/ 00170 fprintf(stderr, "--> %s %p ++ %ld %s at %s:%u%s\n", pool->name, 00171 item, yarnPeekLock(item->use)+1, msg, fn, ln, imsg); 00172 /*@=modfilesys@*/ 00173 } 00174 ANNOTATE_HAPPENS_BEFORE(item); 00175 yarnTwist(item->use, BY, 1); 00176 return item; 00177 } 00178 /*@=internalglobs@*/ 00179 00180 /*@-internalglobs@*/ 00181 /*@null@*/ 00182 void * rpmioFreePoolItem(/*@killref@*/ /*@null@*/ rpmioItem item, 00183 const char * msg, const char * fn, unsigned ln) 00184 /*@modifies item @*/ 00185 { 00186 rpmioPool pool; 00187 if (item == NULL) return NULL; 00188 00189 #ifdef NOTYET 00190 assert(item->pool != NULL); /* XXX (*pool->fini) is likely necessary */ 00191 #endif 00192 yarnPossess(item->use); 00193 ANNOTATE_HAPPENS_AFTER(item); 00194 if ((pool = item->pool) != NULL && pool->flags && msg != NULL) { 00195 const char * imsg = (pool->dbg ? (*pool->dbg)((void *)item) : ""); 00196 /*@-modfilesys@*/ 00197 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name, 00198 item, yarnPeekLock(item->use), msg, fn, ln, imsg); 00199 /*@=modfilesys@*/ 00200 } 00201 if (yarnPeekLock(item->use) <= 1L) { 00202 VALGRIND_HG_CLEAN_MEMORY(item, pool->size); 00203 if (pool != NULL && pool->fini != NULL) 00204 (*pool->fini) ((void *)item); 00205 VALGRIND_MEMPOOL_FREE(pool, item + 1); 00206 item = rpmioPutPool(item); 00207 } else 00208 yarnTwist(item->use, BY, -1); 00209 /*@-retalias@*/ /* XXX returning the deref'd item is used to detect nrefs = 0 */ 00210 return (void *) item; 00211 /*@=retalias@*/ 00212 } 00213 /*@=internalglobs@*/ 00214 00215 /*@-internalglobs@*/ 00216 rpmioItem rpmioGetPool(rpmioPool pool, size_t size) 00217 { 00218 rpmioItem item; 00219 00220 if (pool != NULL) { 00221 /* if can't create any more, wait for a space to show up */ 00222 yarnPossess(pool->have); 00223 if (pool->limit == 0) 00224 yarnWaitFor(pool->have, NOT_TO_BE, 0); 00225 00226 /* if a space is available, pull it from the list and return it */ 00227 if (pool->head != NULL) { 00228 item = pool->head; 00229 pool->head = item->pool; /* XXX pool == next */ 00230 if (pool->head == NULL) 00231 pool->tail = &pool->head; 00232 pool->reused++; 00233 item->pool = pool; /* remember the pool this belongs to */ 00234 yarnTwist(pool->have, BY, -1); /* one less in pool */ 00235 VALGRIND_MEMPOOL_ALLOC(pool, 00236 item + 1, 00237 size - sizeof(struct rpmioItem_s)); 00238 return item; 00239 } 00240 00241 /* nothing available, don't want to wait, make a new item */ 00242 assert(pool->limit != 0); 00243 if (pool->limit > 0) 00244 pool->limit--; 00245 pool->made++; 00246 yarnRelease(pool->have); 00247 } 00248 00249 item = xcalloc(1, size); 00250 item->use = yarnNewLock(0); /* XXX newref? */ 00251 item->pool = pool; 00252 VALGRIND_MEMPOOL_ALLOC(pool, 00253 item + 1, 00254 size - sizeof(struct rpmioItem_s)); 00255 return item; 00256 } 00257 /*@=internalglobs@*/ 00258 00259 /*@-internalglobs@*/ 00260 rpmioItem rpmioPutPool(rpmioItem item) 00261 { 00262 rpmioPool pool; 00263 00264 if ((pool = item->pool) != NULL) { 00265 yarnPossess(pool->have); 00266 item->pool = NULL; /* XXX pool == next */ 00267 *pool->tail = item; 00268 pool->tail = (void *)&item->pool;/* XXX pool == next */ 00269 yarnTwist(pool->have, BY, 1); 00270 if (item->use != NULL) 00271 yarnTwist(item->use, TO, 0); 00272 return NULL; 00273 } 00274 00275 if (item->use != NULL) { 00276 yarnTwist(item->use, TO, 0); 00277 item->use = yarnFreeLock(item->use); 00278 } 00279 (void) _free(item); 00280 return NULL; 00281 } 00282 /*@=internalglobs@*/ 00283 00284 #if !(HAVE_MCHECK_H && defined(__GNUC__)) && !defined(__LCLINT__) 00285 00286 /*@out@*/ /*@only@*/ void * xmalloc (size_t size) 00287 { 00288 register void *value; 00289 if (size == 0) size++; 00290 value = malloc (size); 00291 if (value == 0) 00292 value = vmefail(size); 00293 return value; 00294 } 00295 00296 /*@only@*/ void * xcalloc (size_t nmemb, size_t size) 00297 { 00298 register void *value; 00299 if (size == 0) size++; 00300 if (nmemb == 0) nmemb++; 00301 value = calloc (nmemb, size); 00302 if (value == 0) 00303 value = vmefail(size); 00304 return value; 00305 } 00306 00307 /*@only@*/ void * xrealloc (/*@only@*/ void *ptr, size_t size) 00308 { 00309 register void *value; 00310 if (size == 0) size++; 00311 value = realloc (ptr, size); 00312 if (value == 0) 00313 value = vmefail(size); 00314 return value; 00315 } 00316 00317 /*@only@*/ char * xstrdup (const char *str) 00318 { 00319 size_t size = strlen(str) + 1; 00320 char *newstr = (char *) malloc (size); 00321 if (newstr == 0) 00322 newstr = (char *) vmefail(size); 00323 strcpy (newstr, str); 00324 return newstr; 00325 } 00326 00327 #endif /* !(HAVE_MCHECK_H && defined(__GNUC__)) */
1.7.5.1