00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #define XM_CHECK
00026
00027
00028 #define XM_ALIGN8
00029
00030 #define XM_CONCURRENT
00031 #define XM_ESM_MUTEX
00032 #define XM_FLOPT
00033
00034 #include <eyedbconfig.h>
00035
00036 #include <assert.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039
00040 #ifdef XM_ESM_MUTEX
00041 #include <eyedbsm_p.h>
00042 #include <mutex.h>
00043 #elif defined(XM_CONCURRENT)
00044 #include <pthread.h>
00045 #endif
00046
00047 #include "xm_alloc.h"
00048 #include <eyedblib/m_mem.h>
00049 #include "lib/m_mem_p.h"
00050
00051 namespace eyedbsm {
00052
00053 #define XM_MAGIC ((unsigned int)0xEF18D467)
00054 #define XM_ZERO ((unsigned char )0xb1)
00055 #define XM_OP(MAP, OFFSET) ((XMOverhead *)XM_ADDR_(MAP, OFFSET))
00056 #define XM_OVERHEAD sizeof(XMOverhead)
00057 #define XM_NFL 12
00058
00059 #ifdef XM_ESM_MUTEX
00060 #define XM_LOCK(M) if ((M)->x) MUTEX_LOCK_VOID((M)->mp, 0)
00061 #define XM_UNLOCK(M) if ((M)->x) MUTEX_UNLOCK((M)->mp, 0)
00062 #elif defined(XM_CONCURRENT)
00063 #define XM_LOCK(M) pthread_mutex_lock(&(M)->mp)
00064 #define XM_UNLOCK(M) pthread_mutex_unlock(&(M)->mp)
00065 #else
00066 #define XM_LOCK(M)
00067 #define XM_UNLOCK(M)
00068 #endif
00069
00070 typedef struct {
00071 #ifdef XM_CHECK
00072 unsigned int magic;
00073 #endif
00074 unsigned int free:1, size:31;
00075 XMOffset prevmap, prev, next;
00076 #if defined(XM_CHECK) && defined(XM_ALIGN8)
00077 int pad;
00078 #endif
00079 } XMOverhead;
00080
00081 struct XMMap {
00082 #ifdef XM_ESM_MUTEX
00083 MutexP mp;
00084 #elif defined(XM_CONCURRENT)
00085 pthread_mutex_t mp;
00086 #endif
00087 unsigned int magic;
00088 int heapsize;
00089 int totalsize;
00090 XMOffset freelist[XM_NFL];
00091 XMOffset heap;
00092 XMOffset dataup;
00093 int used_cells, free_cells;
00094 XMOffset upmap;
00095 };
00096
00097 #define __XM_ALIGN1(N)
00098
00099 #define __XM_ALIGN4(N) \
00100 if ((N) & 0x3) \
00101 N = ((N) & ~0x3) + 0x4
00102
00103 #define __XM_ALIGN8(N) \
00104 if ((N) & 0x7) \
00105 N = ((N) & ~0x7) + 0x8
00106
00107 #ifdef XM_ALIGN8
00108 #define XM_ALIGN __XM_ALIGN8
00109 #else
00110 #define XM_ALIGN __XM_ALIGN4
00111 #endif
00112
00113
00114 static int
00115 XMCheckMap(XMHandle *xmh, int silent);
00116
00117 static void
00118 XMErrorHere(XMMap *map)
00119 {
00120 utlog("LOG_ALLOC error map=%o\n", map);
00121
00122
00123
00124
00125
00126 }
00127
00128 #ifdef XM_FLOPT
00129
00130 static char *xm_fl;
00131 static unsigned int xm_max_fl_size;
00132
00133 static void
00134 XMInitFLIdx()
00135 {
00136 static int init;
00137
00138 if (!init)
00139 {
00140 unsigned int n, idx;
00141 xm_max_fl_size = 1 << (XM_NFL+1);
00142 xm_fl = (char *)m_malloc(sizeof(char) * (xm_max_fl_size+1));
00143
00144 for (n = 0, idx = 0; n < xm_max_fl_size+1; n++)
00145 {
00146 xm_fl[n] = idx;
00147 if (n && !(n & (unsigned int)((1 << (idx+3))-1)))
00148 idx++;
00149 }
00150 init = 1;
00151 }
00152 }
00153
00154 #define XMGetFreelist(SZ) ((SZ) > xm_max_fl_size ? (XM_NFL-1) : xm_fl[SZ])
00155
00156 #else
00157
00158 #define XMInitFLIdx()
00159
00160 static int
00161 XMGetFreelist(unsigned int size)
00162 {
00163 int n, sz;
00164
00165 for (n = 0, sz = 8; n < XM_NFL; n++, sz <<= 1)
00166 if (size <= sz)
00167 return n;
00168
00169 return XM_NFL - 1;
00170 }
00171 #endif
00172
00173 static void *XMMallocRealize(XMMap *, unsigned int);
00174
00175 static int
00176 XMCheckAllZero(char *p, unsigned int size, int silent)
00177 {
00178 unsigned char *q = (unsigned char *)p;
00179 int i, errors = 0;
00180
00181 for (i = 0; i < size; i++)
00182 if (*q++ != XM_ZERO)
00183 {
00184 if (!silent)
00185 {
00186 if (!errors)
00187 utlog("LOG_ALLOC check_memory: error non zero (=0x%x) cell 0x%x, size = %d {\n", XM_ZERO, p, size);
00188 utlog("\t[%d] = %p\n", i, *(q-1));
00189 }
00190 errors++;
00191 }
00192
00193 if (!silent && errors)
00194 utlog("}\n");
00195
00196 return errors;
00197 }
00198
00199 #define _MAGIC_(I) (MAGIC + (I)*0x101)
00200
00201 #define SET_MAGIC(OP) ((OP)->magic = XM_MAGIC)
00202 #define CHECK_MAGIC(OP) ((OP)->magic == XM_MAGIC)
00203 #define RESET_MAGIC(OP) ((OP)->magic = 0)
00204
00205 static void
00206 XMMutexInit(XMHandle *xmh)
00207 {
00208 XMMap *map = xmh->map;
00209 #ifdef XM_CONCURRENT
00210 pthread_mutexattr_t mattr;
00211 pthread_mutexattr_init(&mattr);
00212 #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
00213 #ifdef _POSIX_THREAD_PROCESS_SHARED
00214 pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
00215 #endif
00216 #endif
00217
00218 #ifdef XM_ESM_MUTEX
00219 xmh->mp = (Mutex *)m_calloc(sizeof(Mutex), 1);
00220 mutexInit((DbDescription *)xmh->x, xmh->mp, &map->mp, "xm_alloc");
00221
00222 #else
00223 pthread_mutex_init(&map->mp, &mattr);
00224 #endif
00225
00226 #endif
00227 }
00228
00229 static void
00230 XMMutexLightInit(XMHandle *xmh)
00231 {
00232 XMMap *map = xmh->map;
00233
00234 #ifdef XM_ESM_MUTEX
00235 xmh->mp = (Mutex *)m_calloc(sizeof(Mutex), 1);
00236 mutexLightInit((DbDescription *)xmh->x, xmh->mp, &map->mp);
00237 #endif
00238 }
00239
00240 static void
00241 XMHeapInit(XMHandle *xmh, XMOffset data, unsigned int size)
00242 {
00243 XMMap *map = xmh->map;
00244 int which;
00245 XMOverhead *op;
00246
00247 #ifdef XM_ALIGN8
00248 size &= ~0x7;
00249 #endif
00250 memset(map, 0, sizeof(*map));
00251
00252
00253 XMMutexInit(xmh);
00254
00255 map->magic = XM_MAGIC;
00256 map->heapsize = size;
00257 map->heap = data;
00258 #ifdef XM_MEM_ZERO
00259 memset((char *)map + data, XM_ZERO, size);
00260 #endif
00261 which = XMGetFreelist(size-XM_OVERHEAD);
00262 map->freelist[which] = map->heap;
00263
00264 op = XM_OP(map, map->freelist[which]);
00265 op->size = map->heapsize - XM_OVERHEAD;
00266 map->dataup = map->heap + map->heapsize - 1;
00267 op->next = 0;
00268 op->prev = 0;
00269 op->free = 1;
00270 op->prevmap = 0;
00271 map->upmap = map->freelist[which];
00272 #ifdef XM_CHECK
00273 SET_MAGIC(op);
00274 #endif
00275 map->totalsize = op->size;
00276
00277 #ifdef XM_TRACE
00278 utlog("LOG_ALLOC creating heap ADDR %p, SIZE %p\n", data, size);
00279 #endif
00280 map->used_cells = 0;
00281 map->free_cells = 1;
00282 }
00283
00284 static int
00285 XMCheckMap(XMHandle *xmh, int silent)
00286 {
00287 #ifdef XM_CHECK
00288 XMMap *map = xmh->map;
00289 char *end = XM_ADDR_(map, map->heap) + map->heapsize, *p;
00290 int cnt_free = 0, cnt_alloc = 0, errors = 0, size_free = 0, size_alloc = 0,
00291 zero_errors = 0, which, ncnt_free = 0, ncnt_alloc = 0;
00292 XMOverhead *op;
00293 int maxfreesize = 0;
00294
00295 XM_LOCK(xmh);
00296 printf("Log Memory Allocator [total size = %u, addr = %p] {\n",
00297 map->totalsize, map);
00298 utlog("LOG_ALLOC Log Memory Allocator [addr = %p] {\n", map);
00299 for (p = XM_ADDR_(map, map->heap); p < end; )
00300 {
00301 op = (XMOverhead *)p;
00302 if (!CHECK_MAGIC(op))
00303 {
00304 errors++;
00305 if (!silent)
00306 {
00307 printf("check_memory: error cell #%d [p = %p], [magic = %p]\n",
00308 cnt_free+cnt_alloc, p + XM_OVERHEAD, op->magic);
00309 utlog("LOG_ALLOC error cell #%d [p = %p], [magic = %p]\n",
00310 cnt_free+cnt_alloc, p + XM_OVERHEAD, op->magic);
00311 }
00312 }
00313 else
00314 {
00315 if (op->free)
00316 {
00317 cnt_free++;
00318 size_free += op->size;
00319 if (op->size > maxfreesize)
00320 maxfreesize = op->size;
00321 #ifdef XM_MEM_ZERO
00322 zero_errors += XMCheckAllZero(p + XM_OVERHEAD, op->size, 0);
00323 #endif
00324 }
00325 else
00326 {
00327 cnt_alloc++;
00328 size_alloc += op->size;
00329 #if 0
00330 printf("Used Size -> %d\n", op->size);
00331 #endif
00332 }
00333
00334 #ifdef XM_ALIGN8
00335 if (op->size & 0x7)
00336 {
00337 printf("check_memory: error size %d\n", op->size);
00338 utlog("LOG_ALLOC error size %d\n", op->size);
00339 errors++;
00340 }
00341 #endif
00342 }
00343 p += op->size + XM_OVERHEAD;
00344 }
00345
00346 for (which = 0; which < XM_NFL; which++)
00347 {
00348 XMOverhead *pop = 0;
00349 op = XM_OP(map, map->freelist[which]);
00350
00351 while (op)
00352 {
00353 if (XM_OP(map, op->prev) != pop)
00354 {
00355 printf("mem_check_memory: link error in #%d p = %p\n",
00356 which, (char *)(op)+XM_OVERHEAD);
00357 utlog("LOG_ALLOC link error in #%d p = %p\n",
00358 which, (char *)(op)+XM_OVERHEAD);
00359 errors++;
00360 }
00361
00362 if (!op->free)
00363 {
00364 printf("mem_check_memory: free cell expected %p\n", op);
00365 utlog("LOG_ALLOC free cell expected %p\n", op);
00366 errors++;
00367 }
00368
00369 ncnt_free++;
00370
00371 pop = op;
00372 op = XM_OP(map, op->next);
00373 }
00374 }
00375
00376 if (ncnt_free != cnt_free)
00377 {
00378 errors++;
00379 printf("free count incohency %d versus %d\n", cnt_free, ncnt_free);
00380 utlog("LOG_ALLOC free count incohency %d versus %d\n", cnt_free, ncnt_free);
00381 }
00382
00383
00384 ncnt_free = 0;
00385 ncnt_alloc = 0;
00386
00387 for (op = XM_OP(map, map->upmap); op; op = XM_OP(map, op->prevmap))
00388 {
00389 if (!CHECK_MAGIC(op))
00390 {
00391 errors++;
00392 if (!silent)
00393 {
00394 printf("check_memory: error cell #%d [p = %p], [magic = %p]\n",
00395 ncnt_free+ncnt_alloc, p + XM_OVERHEAD, op->magic);
00396 utlog("LOG_ALLOC error cell #%d [p = %p], [magic = %p]\n",
00397 ncnt_free+ncnt_alloc, p + XM_OVERHEAD, op->magic);
00398 }
00399 }
00400
00401 if (op->free)
00402 ncnt_free++;
00403 else
00404 ncnt_alloc++;
00405 }
00406
00407 if (ncnt_free != cnt_free)
00408 {
00409 errors++;
00410 printf("free count incohency for prevmap %d versus %d\n", cnt_free, ncnt_free);
00411 utlog("LOG_ALLOC free count incohency for prevmap %d versus %d\n", cnt_free, ncnt_free);
00412 }
00413
00414 if (ncnt_alloc != cnt_alloc)
00415 {
00416 errors++;
00417 printf("alloc count incohency for prevmap %d versus %d\n",
00418 cnt_alloc, ncnt_alloc);
00419 utlog("LOG_ALLOC alloc count incohency for prevmap %d versus %d\n",
00420 cnt_alloc, ncnt_alloc);
00421 }
00422
00423 if (!silent)
00424 {
00425 printf("\tFatal Errors : %d\n", errors);
00426 utlog("LOG_ALLOC \tFatal Errors : %d\n", errors);
00427 #ifdef XM_MEM_ZERO
00428 printf("\tZeroed Errors : %d\n", zero_errors);
00429 utlog("LOG_ALLOC \tZeroed Errors : %d\n", zero_errors);
00430 #endif
00431 printf("\tFree Cells : %d\n", cnt_free);
00432 utlog("LOG_ALLOC \tFree Cells : %d\n", cnt_free);
00433 printf("\tUsed Cells : %d\n", cnt_alloc);
00434 utlog("LOG_ALLOC \tUsed Cells : %d\n", cnt_alloc);
00435 printf("\tFree Bytes : %d\n", size_free);
00436 utlog("LOG_ALLOC \tFree Bytes : %d\n", size_free);
00437 printf("\tUsed Bytes : %d\n", size_alloc);
00438 utlog("LOG_ALLOC \tUsed Bytes : %d\n", size_alloc);
00439 printf("\t*Used Bytes* : %d\n",
00440 size_alloc + (cnt_alloc + cnt_free) * XM_OVERHEAD);
00441 utlog("LOG_ALLOC \t*Used Bytes* : %d\n",
00442 size_alloc + (cnt_alloc + cnt_free) * XM_OVERHEAD);
00443 printf("\tMax Free Size : %d\n", maxfreesize);
00444 utlog("LOG_ALLOC \tMax Free Size : %d\n", maxfreesize);
00445 }
00446
00447 printf("}\n");
00448 utlog("LOG_ALLOC }\n");
00449 XM_UNLOCK(xmh);
00450 return errors;
00451 #else
00452 return 0;
00453 #endif
00454 }
00455
00456 int
00457 XMCheckMemory(XMHandle *xmh)
00458 {
00459 #ifdef XM_CHECK
00460 return XMCheckMap(xmh, 0);
00461 #else
00462 XMShowMemory(xmh);
00463 return 0;
00464 #endif
00465 }
00466
00467 void
00468 XMShowMemory(XMHandle *xmh)
00469 {
00470 XMMap *map = xmh->map;
00471 XM_LOCK(xmh);
00472 printf("Log Memory Allocator [addr = %p] {\n", map);
00473 printf("\tFree Cells : %d\n", map->free_cells);
00474 printf("\tUsed Cells : %d\n", map->used_cells);
00475 printf("\tFree Bytes : %d [%d Kb]\n",
00476 map->totalsize, (map->totalsize)/1024);
00477 printf("\tUsed Bytes : %d [%d Kb]\n",
00478 (map->heapsize - map->totalsize),
00479 ((map->heapsize - map->totalsize))/1024);
00480 printf("}\n");
00481 XM_UNLOCK(xmh);
00482 }
00483
00484 void
00485 XMGetInfo(XMHandle *xmh, int *free_cells, int *used_cells, int *used, int *left)
00486 {
00487 XMMap *map = xmh->map;
00488 XM_LOCK(xmh);
00489 if (free_cells)
00490 *free_cells = map->free_cells;
00491 if (used_cells)
00492 *used_cells = map->used_cells;
00493 if (used)
00494 *used = (map->heapsize - map->totalsize);
00495 if (left)
00496 *left = map->totalsize;
00497 XM_UNLOCK(xmh);
00498 }
00499
00500 XMHandle *
00501 XMCreate(char *addr, unsigned int size, void *x)
00502 {
00503 XMHandle *xmh;
00504
00505 XMInitFLIdx();
00506
00507
00508
00509 xmh = (XMHandle *)m_calloc(sizeof(XMHandle), 1);
00510 xmh->map = (XMMap *)addr;
00511 xmh->x = x;
00512 XMHeapInit(xmh, sizeof(XMMap), size - sizeof(XMMap));
00513
00514 return xmh;
00515 }
00516
00517 XMHandle *
00518 XMOpen(char *addr, void *x)
00519 {
00520 XMHandle *xmh;
00521
00522 XMInitFLIdx();
00523
00524 xmh = (XMHandle *)m_calloc(sizeof(XMHandle), 1);
00525 xmh->x = x;
00526 xmh->map = (XMMap *)addr;
00527
00528
00529 if (xmh->x)
00530 XMMutexLightInit(xmh);
00531
00532
00533 if (xmh->map->magic != XM_MAGIC)
00534 return (XMHandle *)0;
00535
00536 return xmh;
00537 }
00538
00539 void
00540 XMInit(XMHandle *xmh)
00541 {
00542
00543 XMMutexInit(xmh);
00544 }
00545
00546 void
00547 XMClose(XMHandle *xmh)
00548 {
00549 free(xmh);
00550 }
00551
00552 static
00553 int XMExtendMap(XMHandle *xmh, unsigned int nbytes)
00554 {
00555 return 0;
00556 #if 0
00557 int incsize = 4096, which;
00558 void *x;
00559 XMOverhead *freelist;
00560
00561
00562 while (incsize <= nbytes+OVERHEAD)
00563 incsize += 4096;
00564
00565 x = sbrk(incsize);
00566
00567 #ifdef XMZERO
00568 memset(x, ZERO, incsize);
00569 #endif
00570
00571 #ifdef XM_TRACE
00572 utlog("LOG_ALLOC XMExtendMap(%p, nbytes = %d, incsize = %d) -> %p\n", map, nbytes, incsize, x);
00573 #endif
00574
00575 if (!x)
00576 return 0;
00577
00578 which = XMGetFreelist(incsize-OVERHEAD);
00579
00580 freelist = map->freelist[which];
00581
00582 if (!map->heap)
00583 map->heap = x;
00584
00585 map->freelist[which] = (XMOverhead *)(map->heap + map->heapsize);
00586
00587 map->freelist[which]->next = freelist;
00588 map->freelist[which]->prev = 0;
00589 map->freelist[which]->prevmap = map->upmap;
00590
00591 if (freelist)
00592 freelist->prev = map->freelist[which];
00593
00594 map->freelist[which]->free = 1;
00595 #ifdef XM_CHECK
00596 SET_MAGIC(map->freelist[which]);
00597 #endif
00598 map->heapsize += incsize;
00599 map->freelist[which]->size = incsize - XM_OVERHEAD;
00600 map->dataup = (unsigned int)&map->heap[map->heapsize-1];
00601 map->totalsize += incsize - XM_OVERHEAD;
00602 map->upmap = map->freelist[which];
00603 map->free_cells++;
00604 #endif
00605 return 1;
00606 }
00607
00608 void
00609 XMLock(XMHandle *xmh)
00610 {
00611 XM_LOCK(xmh);
00612 }
00613
00614 void
00615 XMUnlock(XMHandle *xmh)
00616 {
00617 XM_UNLOCK(xmh);
00618 }
00619
00620 void *XMAllocZero(XMHandle *xmh, unsigned int nbytes)
00621 {
00622 void *p;
00623
00624 p = XMAlloc(xmh, nbytes);
00625
00626 if (p)
00627 memset(p, 0, nbytes);
00628
00629 return p;
00630 }
00631
00632
00633
00634
00635
00636 void *XMAlloc(XMHandle *xmh, unsigned int nbytes)
00637 {
00638 void *p;
00639 XMMap *map = xmh->map;
00640
00641 if (!nbytes)
00642 {
00643 utlog("LOG_ALLOC XMAlloc(nbytes=0)\n");
00644 return 0;
00645 }
00646
00647 XM_ALIGN(nbytes);
00648
00649 XM_LOCK(xmh);
00650 p = XMMallocRealize(map, nbytes);
00651 XM_UNLOCK(xmh);
00652
00653 #ifdef XM_TRACE
00654 utlog("LOG_ALLOC XMAlloc(%p, %d) = %p [%d]\n", map, nbytes, p,
00655 map->heapsize - map->totalsize);
00656 #endif
00657 #ifdef XM_MEM_ZERO
00658 if (p)
00659 memset(p, 0, nbytes);
00660 #endif
00661 if (!p)
00662 {
00663 if (XMExtendMap(xmh, nbytes))
00664 return XMAlloc(xmh, nbytes);
00665 utlog("LOG_ALLOC allocation failed for byte count = %d\n", nbytes);
00666 printf("LOG_ALLOC allocation failed for byte count = %d\n", nbytes);
00667 XMCheckMap(xmh, 0);
00668 return 0;
00669 }
00670 return p;
00671 }
00672
00673 void *XMRealloc(XMHandle *xmh, void *p, unsigned int nbytes)
00674 {
00675 XMOverhead *op = (XMOverhead *)((char *)p - XM_OVERHEAD);
00676 void *r;
00677 int osize;
00678
00679 if (!p)
00680 return XMAlloc(xmh, nbytes);
00681
00682 if (op->free)
00683 {
00684 utlog("LOG_ALLOC realloc failed [op->free] byte count = %d\n", nbytes);
00685 XMErrorHere(0);
00686 return 0;
00687 }
00688
00689 #ifdef XM_CHECK
00690 if (!CHECK_MAGIC(op))
00691 {
00692 utlog("LOG_ALLOC XMRealloc: op->magic != XM_MAGIC realloc(%d)\n", nbytes);
00693 XMErrorHere(0);
00694 return 0;
00695 }
00696 #endif
00697
00698 XM_ALIGN(nbytes);
00699
00700 osize = op->size;
00701
00702 if (osize >= nbytes)
00703 return p;
00704
00705 if (!(r = XMAlloc(xmh, nbytes)))
00706 return 0;
00707
00708 memcpy(r, p, osize);
00709 #ifdef XM_MEM_ZERO
00710 memset((char *)r + osize, 0, nbytes - osize);
00711 #endif
00712 XMFree(xmh, p);
00713
00714 #ifdef XM_TRACE
00715 utlog("LOG_ALLOC m_realloc(%p, %x, %d) = %x\n", xmh, p, nbytes, r);
00716 #endif
00717 return r;
00718 }
00719
00720 static void
00721 XMSuppressFL(XMMap *map, XMOverhead *op)
00722 {
00723 if (op->prev)
00724 XM_OP(map, op->prev)->next = op->next;
00725 else
00726 map->freelist[XMGetFreelist(op->size)] = op->next;
00727
00728 if (op->next)
00729 XM_OP(map, op->next)->prev = op->prev;
00730
00731 op->free = 0;
00732 map->free_cells--;
00733 }
00734
00735 static void
00736 XMSuppress(XMMap *map, XMOverhead *op)
00737 {
00738 XMSuppressFL(map, op);
00739
00740 if ((char *)(op)+op->size+XM_OVERHEAD == XM_ADDR_(map, map->dataup) + 1)
00741 map->upmap = op->prevmap;
00742 else
00743 {
00744 XMOverhead *top = (XMOverhead *)((char *)(op) + op->size + XM_OVERHEAD);
00745 top->prevmap = op->prevmap;
00746 }
00747 }
00748
00749 static void
00750 XMInsert(XMMap *map, XMOverhead *op)
00751 {
00752 int which = XMGetFreelist(op->size);
00753 XMOverhead *freelist = XM_OP(map, map->freelist[which]);
00754
00755 #ifdef XM_CHECK
00756 if (freelist)
00757 assert(CHECK_MAGIC(freelist));
00758 #endif
00759
00760 map->freelist[which] = XM_OFFSET_(map, op);
00761 op->prev = 0;
00762 op->next = XM_OFFSET_(map, freelist);
00763
00764 if (freelist)
00765 freelist->prev = XM_OFFSET_(map, op);
00766
00767 #ifdef XM_MEM_ZERO
00768 memset((char *)(op) + XM_OVERHEAD, XM_ZERO, op->size);
00769 #endif
00770 #ifdef XM_CHECK
00771 SET_MAGIC(op);
00772 #endif
00773 op->free = 1;
00774 map->free_cells++;
00775
00776 if ((char *)(op) + op->size + XM_OVERHEAD == XM_ADDR_(map, map->dataup) + 1)
00777 map->upmap = XM_OFFSET_(map, op);
00778 else
00779 {
00780 XMOverhead *top = (XMOverhead *)((char *)(op) + op->size + XM_OVERHEAD);
00781 top->prevmap = XM_OFFSET_(map, op);
00782 }
00783 }
00784
00785 static void
00786 XMFreeCell(XMMap *map, XMOverhead *op)
00787 {
00788 XMOverhead *next, *prev;
00789 int *x;
00790 char *top;
00791
00792 #ifdef XM_MEM_ZERO
00793 memset((char *)(op) + XM_OVERHEAD, XM_ZERO, op->size);
00794 #endif
00795
00796 next = (XMOverhead *)((char *)op + op->size + XM_OVERHEAD);
00797 if ((char *)next >= XM_ADDR_(map, map->dataup))
00798 next = 0;
00799
00800 prev = XM_OP(map, op->prevmap);
00801
00802 #ifdef XM_CHECK
00803 if (prev && !CHECK_MAGIC(prev))
00804 {
00805 utlog("LOG_ALLOC XMFree: prevmap not good magic!\n");
00806 XMErrorHere(map);
00807 }
00808 #endif
00809
00810 if (prev && prev->free && next && next->free)
00811 {
00812 XMSuppress(map, prev);
00813 XMSuppress(map, next);
00814 map->totalsize += op->size + 2 * XM_OVERHEAD;
00815 prev->size += op->size + next->size + 2 * XM_OVERHEAD;
00816 XMInsert(map, prev);
00817 #ifdef XM_MEM_ZERO
00818 memset(next, XM_ZERO, XM_OVERHEAD);
00819 memset(op, XM_ZERO, XM_OVERHEAD);
00820 #endif
00821 }
00822 else if (prev && prev->free)
00823 {
00824 XMSuppress(map, prev);
00825 map->totalsize += op->size + XM_OVERHEAD;
00826 prev->size += op->size + XM_OVERHEAD;
00827 XMInsert(map, prev);
00828 #ifdef XM_MEM_ZERO
00829 memset(op, XM_ZERO, XM_OVERHEAD);
00830 #endif
00831 }
00832 else if (next && next->free)
00833 {
00834 XMSuppress(map, next);
00835 map->totalsize += op->size + XM_OVERHEAD;
00836 op->size += next->size + XM_OVERHEAD;
00837 XMInsert(map, op);
00838 #ifdef XM_MEM_ZERO
00839 memset(next, XM_ZERO, XM_OVERHEAD);
00840 #endif
00841 }
00842 else
00843 {
00844 map->totalsize += op->size;
00845 XMInsert(map, op);
00846 }
00847 }
00848
00849 int
00850 XMFree(XMHandle *xmh, void *p)
00851 {
00852 XMOverhead *op = (XMOverhead *)((char *)p - XM_OVERHEAD), *freelist;
00853 XMMap *map = xmh->map;
00854 unsigned int size, which;
00855
00856 if (!p)
00857 return 0;
00858
00859 #ifdef XM_CHECK
00860 if (!CHECK_MAGIC(op))
00861 {
00862 utlog("LOG_ALLOC XMFree: op->magic != XM_MAGIC m_s_free(%x)\n", p);
00863 XMErrorHere(map);
00864 return 0;
00865 }
00866 #endif
00867
00868 if (op->free)
00869 {
00870 utlog("LOG_ALLOC XMFree(%p): pointer not allocated\n", p);
00871 XMErrorHere(0);
00872 return 0;
00873 }
00874
00875 size = op->size;
00876
00877 XM_LOCK(xmh);
00878 XMFreeCell(map, op);
00879 map->used_cells--;
00880 XM_UNLOCK(xmh);
00881
00882 #ifdef TRACE
00883 utlog("LOG_ALLOC XMFree(%p, %x, %d)\n", map, p, size);
00884 #endif
00885 return size;
00886 }
00887
00888 int
00889 XMGetSize(XMHandle *xmh, void *p)
00890 {
00891 XMOverhead *op = (XMOverhead *)((char *)p - XM_OVERHEAD);
00892 unsigned int size;
00893
00894 if (!p || op->free)
00895 return 0;
00896
00897 #ifdef XM_CHECK
00898 if (!CHECK_MAGIC(op))
00899 {
00900 utlog("LOG_ALLOC op->magic != XM_MAGIC m_s_free(%x)\n", p);
00901 return 0;
00902 }
00903 #endif
00904
00905 return op->size;
00906 }
00907
00908 static void *
00909 XMMallocRealize(XMMap *map, unsigned int nbytes)
00910 {
00911 XMOverhead *op, *bestfit;
00912 unsigned int sdiff, sizediff = (unsigned int)0xFFFFFFFF;
00913 int which = XMGetFreelist(nbytes), lo = 0;
00914
00915 bestfit = 0;
00916
00917 if (which < XM_NFL - 1)
00918 which++;
00919
00920 loop:
00921 for ( ; which < XM_NFL; which++)
00922 {
00923 op = XM_OP(map, map->freelist[which]);
00924
00925 while(op)
00926 {
00927 #ifdef XM_CHECK
00928 if (!CHECK_MAGIC(op))
00929 {
00930 utlog("LOG_ALLOC XMMallocRealize: invalid magics for %p\n", op);
00931 XMErrorHere(map);
00932 return 0;
00933 }
00934
00935 if (!op->free)
00936 {
00937 utlog("LOG_ALLOC XMMallocRealize: not free %d\n", nbytes);
00938 XMErrorHere(map);
00939 op = XM_OP(map, op->next);
00940 continue;
00941 }
00942 #endif
00943
00944
00945 if ((int)(sdiff = (op->size - nbytes)) >= 0)
00946 {
00947 if (sdiff < sizediff)
00948 {
00949 bestfit = op;
00950 sizediff = sdiff;
00951 if (!sdiff)
00952 break;
00953 #ifndef XM_BESTFIT
00954 goto out;
00955 #endif
00956 }
00957 }
00958
00959 op = XM_OP(map, op->next);
00960 }
00961 }
00962
00963 out:
00964 if (!bestfit)
00965 {
00966 which = XMGetFreelist(nbytes);
00967 if (!lo && which < XM_NFL - 1)
00968 {
00969 lo = 1;
00970 goto loop;
00971 }
00972 return 0;
00973 }
00974
00975 if (sizediff <= XM_OVERHEAD)
00976 {
00977 XMSuppressFL(map, bestfit);
00978 map->totalsize -= bestfit->size;
00979 map->used_cells++;
00980 return (void *)((char *)bestfit + XM_OVERHEAD);
00981 }
00982 else
00983 {
00984 XMOverhead *top = (XMOverhead *)((char *)bestfit + nbytes + XM_OVERHEAD);
00985
00986 if ((char *)top < XM_ADDR_(map, map->dataup))
00987 {
00988 top->size = bestfit->size - nbytes - XM_OVERHEAD;
00989 top->prevmap = XM_OFFSET_(map, bestfit);
00990 XMInsert(map, top);
00991 }
00992
00993 XMSuppressFL(map, bestfit);
00994
00995 bestfit->size = nbytes;
00996
00997 map->totalsize -= (nbytes + XM_OVERHEAD);
00998 map->used_cells++;
00999 return (void *)((char *)bestfit + XM_OVERHEAD);
01000 }
01001 }
01002
01003 }