xm_alloc.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 
00025 #define XM_CHECK
00026 /*#define XM_MEM_ZERO*/
00027 /*#define XM_TRACE*/
00028 #define XM_ALIGN8
00029 /*#define XM_BESTFIT*/
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 /* utility functions */
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   if (map)
00123     XMCheckMap(map, 0);
00124   */
00125   /*  abort(); */
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   /*se_mutexInit(xmh->x, 0, &map->mp, "xm_alloc");*/
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   /*if (xmh->x)*/ /* disconnected the 4/09/01 */
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   /* check prevmap */
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   /*  utlog("LOG_ALLOC XMCreate(%p)\n", addr);*/
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   /* added the 6/12/00 */
00529   if (xmh->x)
00530     XMMutexLightInit(xmh); /* changed XMMutexInit to XMMutexLightInit the 4/09/01 */
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   /*if (xmh->x)*/ /* disconnected the 4/09/01 */
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  * XMAlloc(XMMap *map, nbytes): allocates nbytes of memory in statical heap
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           /*      if ((sdiff = (unsigned int)(op->size - nbytes)) >= 0)*/
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 }

Generated on Mon Dec 22 18:16:15 2008 for eyedb by  doxygen 1.5.3