rpm 5.2.1

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

- File List
- Globals

rpmio/rpmmalloc.c
Go to the documentation of this file.

    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__)) */