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