00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "autoconf.h"
00007 #include "config.h"
00008 #include "externs.h"
00009
00010
00011
00012
00013
00014
00015 typedef struct pool_header_unaligned
00016 {
00017 unsigned int magicnum;
00018 size_t pool_size;
00019 struct pool_header *next;
00020 struct pool_header *nxtfree;
00021 char *buf_tag;
00022 } POOLHDR_UNALIGNED;
00023
00024
00025
00026
00027
00028 typedef struct pool_header
00029 {
00030 unsigned int magicnum;
00031 size_t pool_size;
00032 struct pool_header *next;
00033 struct pool_header *nxtfree;
00034 char *buf_tag;
00035 char PaddingTo64bits[7 - ((sizeof(POOLHDR_UNALIGNED)-1) & 7)];
00036 } POOLHDR;
00037
00038 typedef struct pool_footer
00039 {
00040 unsigned int magicnum;
00041 } POOLFTR;
00042
00043 typedef struct pooldata
00044 {
00045 size_t pool_size;
00046 unsigned int poolmagic;
00047 POOLHDR *free_head;
00048 POOLHDR *chain_head;
00049 UINT64 tot_alloc;
00050 UINT64 num_alloc;
00051 UINT64 max_alloc;
00052 UINT64 num_lost;
00053 } POOL;
00054
00055 static POOL pools[NUM_POOLS];
00056 static const char *poolnames[] =
00057 {
00058 "Lbufs", "Sbufs", "Mbufs", "Bools", "Descs", "Qentries", "Pcaches"
00059 };
00060
00061 void pool_init(int poolnum, int poolsize)
00062 {
00063 pools[poolnum].pool_size = poolsize;
00064 pools[poolnum].poolmagic = CRC32_ProcessInteger2(poolnum, poolsize);
00065 pools[poolnum].free_head = NULL;
00066 pools[poolnum].chain_head = NULL;
00067 pools[poolnum].tot_alloc = 0;
00068 pools[poolnum].num_alloc = 0;
00069 pools[poolnum].max_alloc = 0;
00070 pools[poolnum].num_lost = 0;
00071 }
00072
00073 static void pool_err
00074 (
00075 const char *logsys,
00076 int logflag,
00077 int poolnum,
00078 const char *tag,
00079 POOLHDR *ph,
00080 const char *action,
00081 const char *reason,
00082 const char *file,
00083 const int line
00084 )
00085 {
00086 if (mudstate.logging == 0)
00087 {
00088 STARTLOG(logflag, logsys, "ALLOC");
00089 Log.tinyprintf("%s[%d] (tag %s) %s in %s line %d at %lx. (%s)", action,
00090 pools[poolnum].pool_size, tag, reason, file, line, (long)ph,
00091 mudstate.debug_cmd);
00092 ENDLOG;
00093 }
00094 else if (logflag != LOG_ALLOCATE)
00095 {
00096 Log.tinyprintf(ENDLINE "***< %s[%d] (tag %s) %s in %s line %d at %lx. >***",
00097 action, pools[poolnum].pool_size, tag, reason, file, line, (long)ph);
00098 }
00099 }
00100
00101 static void pool_vfy(int poolnum, const char *tag, const char *file, const int line)
00102 {
00103 POOLHDR *ph, *lastph;
00104 POOLFTR *pf;
00105 char *h;
00106
00107 lastph = NULL;
00108 size_t psize = pools[poolnum].pool_size;
00109 for (ph = pools[poolnum].chain_head; ph; lastph = ph, ph = ph->next)
00110 {
00111 h = (char *)ph;
00112 h += sizeof(POOLHDR);
00113 h += pools[poolnum].pool_size;
00114 pf = (POOLFTR *) h;
00115
00116 if (ph->magicnum != pools[poolnum].poolmagic)
00117 {
00118 pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph, "Verify",
00119 "header corrupted (clearing freelist)", file, line);
00120
00121
00122
00123
00124
00125
00126 if (lastph)
00127 {
00128 lastph->next = NULL;
00129 }
00130 else
00131 {
00132 pools[poolnum].chain_head = NULL;
00133 }
00134
00135
00136
00137 return;
00138 }
00139 if (pf->magicnum != pools[poolnum].poolmagic)
00140 {
00141 pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph, "Verify",
00142 "footer corrupted", file, line);
00143 pf->magicnum = pools[poolnum].poolmagic;
00144 }
00145 if (ph->pool_size != psize)
00146 {
00147 pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph,
00148 "Verify", "header has incorrect size", file, line);
00149 }
00150 }
00151 }
00152
00153 static void pool_check(const char *tag, const char *file, const int line)
00154 {
00155 int i;
00156 for (i = 0; i < NUM_POOLS; i++)
00157 {
00158 pool_vfy(i, tag, file, line);
00159 }
00160 }
00161
00162 char *pool_alloc(int poolnum, const char *tag, const char *file, const int line)
00163 {
00164 if (mudconf.paranoid_alloc)
00165 {
00166 pool_check(tag, file, line);
00167 }
00168
00169 char *p;
00170 POOLFTR *pf;
00171 POOLHDR *ph = (POOLHDR *)pools[poolnum].free_head;
00172 if ( ph
00173 && ph->magicnum == pools[poolnum].poolmagic)
00174 {
00175 p = (char *)(ph + 1);
00176 pf = (POOLFTR *)(p + pools[poolnum].pool_size);
00177 pools[poolnum].free_head = ph->nxtfree;
00178
00179
00180
00181 if (pf->magicnum != pools[poolnum].poolmagic)
00182 {
00183 pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph, "Alloc",
00184 "corrupted buffer footer", file, line);
00185 pf->magicnum = pools[poolnum].poolmagic;
00186 }
00187 }
00188 else
00189 {
00190 if (ph)
00191 {
00192
00193
00194 pool_err("BUG", LOG_ALWAYS, poolnum, tag, ph, "Alloc",
00195 "corrupted buffer header", file, line);
00196
00197
00198
00199 pools[poolnum].free_head = NULL;
00200 pools[poolnum].num_lost += (pools[poolnum].tot_alloc
00201 - pools[poolnum].num_alloc);
00202 pools[poolnum].tot_alloc = pools[poolnum].num_alloc;
00203 }
00204
00205 ph = (POOLHDR *)MEMALLOC(pools[poolnum].pool_size + sizeof(POOLHDR)
00206 + sizeof(POOLFTR));
00207 ISOUTOFMEMORY(ph);
00208 p = (char *)(ph + 1);
00209 pf = (POOLFTR *)(p + pools[poolnum].pool_size);
00210
00211
00212
00213 ph->next = pools[poolnum].chain_head;
00214 ph->nxtfree = NULL;
00215 ph->magicnum = pools[poolnum].poolmagic;
00216 ph->pool_size = pools[poolnum].pool_size;
00217 pf->magicnum = pools[poolnum].poolmagic;
00218 *((unsigned int *)p) = pools[poolnum].poolmagic;
00219 pools[poolnum].chain_head = ph;
00220 pools[poolnum].max_alloc++;
00221 }
00222
00223 ph->buf_tag = (char *)tag;
00224 pools[poolnum].tot_alloc++;
00225 pools[poolnum].num_alloc++;
00226
00227 if ( (LOG_ALLOCATE & mudconf.log_options)
00228 && mudstate.logging == 0
00229 && start_log("DBG", "ALLOC"))
00230 {
00231 Log.tinyprintf("Alloc[%d] (tag %s) in %s line %d buffer at %lx. (%s)",
00232 pools[poolnum].pool_size, tag, file, line, (long)ph, mudstate.debug_cmd);
00233 end_log();
00234 }
00235
00236
00237
00238 unsigned int *pui = (unsigned int *)p;
00239 if (*pui != pools[poolnum].poolmagic)
00240 {
00241 pool_err("BUG", LOG_PROBLEMS, poolnum, tag, ph, "Alloc",
00242 "buffer modified after free", file, line);
00243 }
00244 *pui = 0;
00245 return p;
00246 }
00247
00248 char *pool_alloc_lbuf(const char *tag, const char *file, const int line)
00249 {
00250 if (mudconf.paranoid_alloc)
00251 {
00252 pool_check(tag, file, line);
00253 }
00254
00255 char *p;
00256 POOLFTR *pf;
00257 POOLHDR *ph = (POOLHDR *)pools[POOL_LBUF].free_head;
00258 if ( ph
00259 && ph->magicnum == pools[POOL_LBUF].poolmagic)
00260 {
00261 p = (char *)(ph + 1);
00262 pf = (POOLFTR *)(p + LBUF_SIZE);
00263 pools[POOL_LBUF].free_head = ph->nxtfree;
00264
00265
00266
00267 if (pf->magicnum != pools[POOL_LBUF].poolmagic)
00268 {
00269 pool_err("BUG", LOG_ALWAYS, POOL_LBUF, tag, ph, "Alloc",
00270 "corrupted buffer footer", file, line);
00271 pf->magicnum = pools[POOL_LBUF].poolmagic;
00272 }
00273 }
00274 else
00275 {
00276 if (ph)
00277 {
00278
00279
00280 pool_err("BUG", LOG_ALWAYS, POOL_LBUF, tag, ph, "Alloc",
00281 "corrupted buffer header", file, line);
00282
00283
00284
00285 pools[POOL_LBUF].free_head = NULL;
00286 pools[POOL_LBUF].num_lost += (pools[POOL_LBUF].tot_alloc
00287 - pools[POOL_LBUF].num_alloc);
00288 pools[POOL_LBUF].tot_alloc = pools[POOL_LBUF].num_alloc;
00289 }
00290
00291 ph = (POOLHDR *)MEMALLOC(LBUF_SIZE + sizeof(POOLHDR)
00292 + sizeof(POOLFTR));
00293 ISOUTOFMEMORY(ph);
00294 p = (char *)(ph + 1);
00295 pf = (POOLFTR *)(p + LBUF_SIZE);
00296
00297
00298
00299 ph->next = pools[POOL_LBUF].chain_head;
00300 ph->nxtfree = NULL;
00301 ph->magicnum = pools[POOL_LBUF].poolmagic;
00302 ph->pool_size = LBUF_SIZE;
00303 pf->magicnum = pools[POOL_LBUF].poolmagic;
00304 *((unsigned int *)p) = pools[POOL_LBUF].poolmagic;
00305 pools[POOL_LBUF].chain_head = ph;
00306 pools[POOL_LBUF].max_alloc++;
00307 }
00308
00309 ph->buf_tag = (char *)tag;
00310 pools[POOL_LBUF].tot_alloc++;
00311 pools[POOL_LBUF].num_alloc++;
00312
00313 if ( (LOG_ALLOCATE & mudconf.log_options)
00314 && mudstate.logging == 0
00315 && start_log("DBG", "ALLOC"))
00316 {
00317 Log.tinyprintf("Alloc[%d] (tag %s) in %s line %d buffer at %lx. (%s)",
00318 LBUF_SIZE, tag, file, line, (long)ph, mudstate.debug_cmd);
00319 end_log();
00320 }
00321
00322
00323
00324 unsigned int *pui = (unsigned int *)p;
00325 if (*pui != pools[POOL_LBUF].poolmagic)
00326 {
00327 pool_err("BUG", LOG_PROBLEMS, POOL_LBUF, tag, ph, "Alloc",
00328 "buffer modified after free", file, line);
00329 }
00330 *pui = 0;
00331 return p;
00332 }
00333
00334 void pool_free(int poolnum, char *buf, const char *file, const int line)
00335 {
00336 if (buf == NULL)
00337 {
00338 STARTLOG(LOG_PROBLEMS, "BUG", "ALLOC")
00339 log_text(tprintf("Attempt to free null pointer in %s line %d.", file, line));
00340 ENDLOG
00341 return;
00342 }
00343 POOLHDR *ph = ((POOLHDR *)(buf)) - 1;
00344 POOLFTR *pf = (POOLFTR *)(buf + pools[poolnum].pool_size);
00345 unsigned int *pui = (unsigned int *)buf;
00346
00347 if (mudconf.paranoid_alloc)
00348 {
00349 pool_check(ph->buf_tag, file, line);
00350 }
00351
00352
00353
00354
00355 if (ph->magicnum != pools[poolnum].poolmagic)
00356 {
00357 pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
00358 "corrupted buffer header", file, line);
00359 pools[poolnum].num_lost++;
00360 pools[poolnum].num_alloc--;
00361 pools[poolnum].tot_alloc--;
00362 return;
00363 }
00364
00365
00366
00367 if (pf->magicnum != pools[poolnum].poolmagic)
00368 {
00369 pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
00370 "corrupted buffer footer", file, line);
00371 pf->magicnum = pools[poolnum].poolmagic;
00372 }
00373
00374
00375
00376 if (ph->pool_size != pools[poolnum].pool_size)
00377 {
00378 pool_err("BUG", LOG_ALWAYS, poolnum, ph->buf_tag, ph, "Free",
00379 "Attempt to free into a different pool.", file, line);
00380 return;
00381 }
00382
00383 if ( (LOG_ALLOCATE & mudconf.log_options)
00384 && mudstate.logging == 0
00385 && start_log("DBG", "ALLOC"))
00386 {
00387 Log.tinyprintf("Free[%d] (tag %s) in %s line %d buffer at %lx. (%s)",
00388 pools[poolnum].pool_size, ph->buf_tag, file, line, (long)ph,
00389 mudstate.debug_cmd);
00390 end_log();
00391 }
00392
00393
00394
00395
00396 if (*pui == pools[poolnum].poolmagic)
00397 {
00398 pool_err("BUG", LOG_BUGS, poolnum, ph->buf_tag, ph, "Free",
00399 "buffer already freed", file, line);
00400 }
00401 else
00402 {
00403 *pui = pools[poolnum].poolmagic;
00404 ph->nxtfree = pools[poolnum].free_head;
00405 pools[poolnum].free_head = ph;
00406 pools[poolnum].num_alloc--;
00407 }
00408 }
00409
00410 void pool_free_lbuf(char *buf, const char *file, const int line)
00411 {
00412 if (buf == NULL)
00413 {
00414 STARTLOG(LOG_PROBLEMS, "BUG", "ALLOC")
00415 log_text(tprintf("Attempt to free_lbuf null pointer in %s line %d.", file, line));
00416 ENDLOG
00417 return;
00418 }
00419 POOLHDR *ph = ((POOLHDR *)(buf)) - 1;
00420 POOLFTR *pf = (POOLFTR *)(buf + LBUF_SIZE);
00421 unsigned int *pui = (unsigned int *)buf;
00422
00423 if (mudconf.paranoid_alloc)
00424 {
00425 pool_check(ph->buf_tag, file, line);
00426 }
00427
00428 if ( ph->magicnum != pools[POOL_LBUF].poolmagic
00429 || pf->magicnum != pools[POOL_LBUF].poolmagic
00430 || ph->pool_size != LBUF_SIZE
00431 || *pui == pools[POOL_LBUF].poolmagic)
00432 {
00433 if (ph->magicnum != pools[POOL_LBUF].poolmagic)
00434 {
00435
00436
00437
00438 pool_err("BUG", LOG_ALWAYS, POOL_LBUF, ph->buf_tag, ph, "Free",
00439 "corrupted buffer header", file, line);
00440 pools[POOL_LBUF].num_lost++;
00441 pools[POOL_LBUF].num_alloc--;
00442 pools[POOL_LBUF].tot_alloc--;
00443 return;
00444 }
00445 else if (pf->magicnum != pools[POOL_LBUF].poolmagic)
00446 {
00447
00448
00449 pool_err("BUG", LOG_ALWAYS, POOL_LBUF, ph->buf_tag, ph, "Free",
00450 "corrupted buffer footer", file, line);
00451 pf->magicnum = pools[POOL_LBUF].poolmagic;
00452 }
00453 else if (ph->pool_size != LBUF_SIZE)
00454 {
00455
00456
00457 pool_err("BUG", LOG_ALWAYS, POOL_LBUF, ph->buf_tag, ph, "Free",
00458 "Attempt to free into a different pool.", file, line);
00459 return;
00460 }
00461
00462
00463
00464 if (*pui == pools[POOL_LBUF].poolmagic)
00465 {
00466 pool_err("BUG", LOG_BUGS, POOL_LBUF, ph->buf_tag, ph, "Free",
00467 "buffer already freed", file, line);
00468 return;
00469 }
00470 }
00471
00472 if ( (LOG_ALLOCATE & mudconf.log_options)
00473 && mudstate.logging == 0
00474 && start_log("DBG", "ALLOC"))
00475 {
00476 Log.tinyprintf("Free[%d] (tag %s) in %s line %d buffer at %lx. (%s)",
00477 LBUF_SIZE, ph->buf_tag, file, line, (long)ph, mudstate.debug_cmd);
00478 end_log();
00479 }
00480
00481
00482
00483 *pui = pools[POOL_LBUF].poolmagic;
00484 ph->nxtfree = pools[POOL_LBUF].free_head;
00485 pools[POOL_LBUF].free_head = ph;
00486 pools[POOL_LBUF].num_alloc--;
00487 }
00488
00489 static void pool_trace(dbref player, int poolnum, const char *text)
00490 {
00491 POOLHDR *ph;
00492 int numfree = 0;
00493 notify(player, tprintf("----- %s -----", text));
00494 for (ph = pools[poolnum].chain_head; ph != NULL; ph = ph->next)
00495 {
00496 if (ph->magicnum != pools[poolnum].poolmagic)
00497 {
00498 notify(player, "*** CORRUPTED BUFFER HEADER, ABORTING SCAN ***");
00499 notify(player, tprintf("%d free %s (before corruption)",
00500 numfree, text));
00501 return;
00502 }
00503 char *h = (char *)ph;
00504 h += sizeof(POOLHDR);
00505 unsigned int *ibuf = (unsigned int *)h;
00506 if (*ibuf != pools[poolnum].poolmagic)
00507 {
00508 notify(player, ph->buf_tag);
00509 }
00510 else
00511 {
00512 numfree++;
00513 }
00514 }
00515 notify(player, tprintf("%d free %s", numfree, text));
00516 }
00517
00518 void list_bufstats(dbref player)
00519 {
00520 char buff[MBUF_SIZE];
00521
00522 notify(player, "Buffer Stats Size InUse Total Allocs Lost");
00523
00524 int i;
00525 for (i = 0; i < NUM_POOLS; i++)
00526 {
00527 char szNumAlloc[22];
00528 char szMaxAlloc[22];
00529 char szTotAlloc[22];
00530 char szNumLost[22];
00531
00532 mux_i64toa(pools[i].num_alloc, szNumAlloc);
00533 mux_i64toa(pools[i].max_alloc, szMaxAlloc);
00534 mux_i64toa(pools[i].tot_alloc, szTotAlloc);
00535 mux_i64toa(pools[i].num_lost, szNumLost);
00536
00537 sprintf(buff, "%-12s %5d%10s%10s%14s%7s",
00538 poolnames[i], (int)pools[i].pool_size,
00539 szNumAlloc, szMaxAlloc, szTotAlloc, szNumLost);
00540 notify(player, buff);
00541 }
00542 }
00543
00544 void list_buftrace(dbref player)
00545 {
00546 int i;
00547 for (i = 0; i < NUM_POOLS; i++)
00548 {
00549 pool_trace(player, i, poolnames[i]);
00550 }
00551 }
00552
00553 void pool_reset(void)
00554 {
00555 int i;
00556 for (i = 0; i < NUM_POOLS; i++)
00557 {
00558 POOLHDR *newchain = NULL;
00559 POOLHDR *phnext;
00560 POOLHDR *ph;
00561 for (ph = pools[i].chain_head; ph != NULL; ph = phnext)
00562 {
00563 char *h = (char *)ph;
00564 phnext = ph->next;
00565 h += sizeof(POOLHDR);
00566 unsigned int *ibuf = (unsigned int *)h;
00567 if (*ibuf == pools[i].poolmagic)
00568 {
00569 MEMFREE(ph);
00570 ph = NULL;
00571 }
00572 else
00573 {
00574 ph->next = newchain;
00575 newchain = ph;
00576 ph->nxtfree = NULL;
00577 }
00578 }
00579 pools[i].chain_head = newchain;
00580 pools[i].free_head = NULL;
00581 pools[i].max_alloc = pools[i].num_alloc;
00582 }
00583 }
00584