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
00024 void *vmefail(size_t size)
00025 {
00026 fprintf(stderr, _("memory alloc (%u bytes) returned NULL.\n"), (unsigned)size);
00027 exit(EXIT_FAILURE);
00028
00029
00030 return NULL;
00031
00032 }
00033
00034
00037 struct rpmioPool_s {
00038 yarnLock have;
00039
00040 void *pool;
00041
00042 rpmioItem head;
00043
00044 rpmioItem * tail;
00045 size_t size;
00046 int limit;
00047 int flags;
00048
00049 const char * (*dbg) (void *item)
00050 ;
00051
00052 void (*init) (void *item)
00053 ;
00054
00055 void (*fini) (void *item)
00056 ;
00057 int reused;
00058 int made;
00059
00060 const char *name;
00061
00062 void * zlog;
00063 };
00064
00065
00066 static rpmioPool _rpmioPool;
00067
00068 rpmioPool rpmioFreePool(rpmioPool pool)
00069
00070
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;
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
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
00127
00128
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
00138 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
00139 item, yarnPeekLock(item->use), msg, fn, ln, imsg);
00140
00141 }
00142 yarnTwist(item->use, BY, -1);
00143
00144 return item;
00145
00146 }
00147
00148
00149
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
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
00162 }
00163 yarnTwist(item->use, BY, 1);
00164 return item;
00165 }
00166
00167
00168
00169
00170 void * rpmioFreePoolItem( rpmioItem item,
00171 const char * msg, const char * fn, unsigned ln)
00172
00173 {
00174 rpmioPool pool;
00175 if (item == NULL) return NULL;
00176
00177 #ifdef NOTYET
00178 assert(item->pool != NULL);
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
00184 fprintf(stderr, "--> %s %p -- %ld %s at %s:%u%s\n", pool->name,
00185 item, yarnPeekLock(item->use), msg, fn, ln, imsg);
00186
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
00195 return (void *) item;
00196
00197 }
00198
00199
00200
00201 rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
00202 {
00203 rpmioItem item;
00204
00205 if (pool != NULL) {
00206
00207 yarnPossess(pool->have);
00208 if (pool->limit == 0)
00209 yarnWaitFor(pool->have, NOT_TO_BE, 0);
00210
00211
00212 if (pool->head != NULL) {
00213 item = pool->head;
00214 pool->head = item->pool;
00215 if (pool->head == NULL)
00216 pool->tail = &pool->head;
00217 pool->reused++;
00218 item->pool = pool;
00219 yarnTwist(pool->have, BY, -1);
00220 return item;
00221 }
00222
00223
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);
00233 item->pool = pool;
00234 return item;
00235 }
00236
00237
00238
00239 rpmioItem rpmioPutPool(rpmioItem item)
00240 {
00241 rpmioPool pool;
00242
00243 if ((pool = item->pool) != NULL) {
00244 yarnPossess(pool->have);
00245 item->pool = NULL;
00246 *pool->tail = item;
00247 pool->tail = (rpmioItem *)&item->pool;
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
00262
00263 #if !(HAVE_MCHECK_H && defined(__GNUC__)) && !defined(__LCLINT__)
00264
00265 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 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 void * xrealloc ( 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 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