00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #ifndef MTHREAD
00025 #define MTHREAD 0
00026 #endif
00027 
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 
00031 
00032 #include <stddef.h>
00033 #ifdef _DEBUG
00034 #include <memory.h>
00035 #endif
00036 
00037 #include "myalloc.h"
00038 
00039 static unsigned long MaxNetSize,
00040                      MinNetSize,
00041                      MaxBruSize,
00042                      MinBruSize,
00043                      ActNetSize,
00044                      ActBruSize;
00045 #if MTHREAD
00046 #include "thread.h"
00047 
00048 #define LOCK_SEGMENT    thread_LockMutex(&(pMemorySegment->mxSegment));
00049 #define UNLOCK_SEGMENT  thread_UnlockMutex(&(pMemorySegment->mxSegment));
00050 
00051 static unsigned char fLockMalloc=0;
00052 static MUTEX mxMalloc;
00053 #define LOCK_MALLOC   if( fLockMalloc )thread_LockMutex(&mxMalloc);
00054 #define UNLOCK_MALLOC if( fLockMalloc )thread_UnlockMutex(&mxMalloc);
00055 
00056 static MUTEX mxStat;
00057 #define LOCK_STAT   thread_LockMutex(&mxStat);
00058 #define UNLOCK_STAT thread_UnlockMutex(&mxStat);
00059 
00060 #else
00061 
00062 #define LOCK_SEGMENT
00063 #define UNLOCK_SEGMENT
00064 #define LOCK_MALLOC
00065 #define UNLOCK_MALLOC
00066 #define LOCK_STAT
00067 #define UNLOCK_STAT
00068 #endif
00069 
00070 
00071 #define STAT_ADD(NET,BRU) LOCK_STAT \
00072                           ActNetSize += (NET); \
00073                           if( ActNetSize > MaxNetSize )MaxNetSize = ActNetSize; \
00074                           if( ActNetSize < MinNetSize )MinNetSize = ActNetSize; \
00075                           ActBruSize += (BRU); \
00076                           if( ActBruSize > MaxBruSize )MaxBruSize = ActBruSize; \
00077                           if( ActBruSize < MinBruSize )MinBruSize = ActBruSize; \
00078                           UNLOCK_STAT
00079 
00080 #define STAT_SUB(NET,BRU) LOCK_STAT \
00081                           ActNetSize -= (NET); \
00082                           if( ActNetSize > MaxNetSize )MaxNetSize = ActNetSize; \
00083                           if( ActNetSize < MinNetSize )MinNetSize = ActNetSize; \
00084                           ActBruSize -= (BRU); \
00085                           if( ActBruSize > MaxBruSize )MaxBruSize = ActBruSize; \
00086                           if( ActBruSize < MinBruSize )MinBruSize = ActBruSize; \
00087                           UNLOCK_STAT
00088 
00089 typedef struct _AllocUnit {
00090   unsigned long      Size;          
00091   struct _AllocUnit *next;     
00092   struct _AllocUnit *prev;     
00093   unsigned char      memory[1];     
00094   } AllocUnit, *pAllocUnit;
00095 
00096 
00097 
00098 typedef struct _MyAlloc {
00099 #if MTHREAD
00100   MUTEX mxSegment;
00101 #endif
00102   void * (*memory_allocating_function)(size_t);
00103   void (*memory_releasing_function)(void *);
00104 
00105   unsigned long MaxSize,CurrentSize,
00106                 MaxNetSize,MinNetSize;
00107 
00108   pAllocUnit FirstUnit;
00109   } MyAlloc, *pMyAlloc;
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 void *alloc_InitSegment(void * (*maf)(size_t), 
00147                         void   (*mrf)(void *)
00148   ){
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156   pMyAlloc pMemorySegment;
00157 
00158   
00159 
00160   if( mrf == NULL ){
00161     pMemorySegment = (pMyAlloc)maf;
00162     maf = pMemorySegment->memory_allocating_function;
00163     mrf = pMemorySegment->memory_releasing_function;
00164     }
00165 
00166 #if MTHREAD
00167   if( fLockMalloc )thread_LockMutex(&mxMalloc);
00168 #endif
00169 
00170   pMemorySegment = (pMyAlloc)maf(sizeof(MyAlloc));
00171   STAT_ADD( 0 , sizeof(MyAlloc) )
00172 
00173 #if MTHREAD
00174   if( fLockMalloc )thread_UnlockMutex(&mxMalloc);
00175 #endif
00176 
00177   if( pMemorySegment == NULL )return NULL;
00178   pMemorySegment->memory_allocating_function = maf;
00179   pMemorySegment->memory_releasing_function = mrf;
00180   pMemorySegment->FirstUnit = NULL;
00181   pMemorySegment->CurrentSize = 0; 
00182   pMemorySegment->MaxSize = 0; 
00183   pMemorySegment->MaxNetSize = 0;
00184   pMemorySegment->MinNetSize = 0;
00185 #if MTHREAD
00186   thread_InitMutex(&(pMemorySegment->mxSegment));
00187 #endif
00188   return (void *)pMemorySegment;
00189   }
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 void alloc_GlobalUseGlobalMutex(
00200   ){
00201 
00202 
00203 #if MTHREAD
00204   fLockMalloc = 1;
00205   thread_InitMutex(&mxMalloc);
00206 #else
00207   exit(63);
00208 #endif
00209   }
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 long alloc_SegmentLimit(void *p,
00236                         unsigned long NewMaxSize
00237   ){
00238 
00239 
00240   pMyAlloc pMemorySegment = (pMyAlloc)p;
00241   unsigned long lOldValue;
00242 
00243   LOCK_SEGMENT
00244   lOldValue = pMemorySegment->MaxSize;
00245   pMemorySegment->MaxSize = NewMaxSize;
00246   UNLOCK_SEGMENT
00247   return lOldValue;
00248   }
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 void alloc_FreeSegment(void *p
00261   ){
00262 
00263 
00264   pMyAlloc pMemorySegment = (pMyAlloc)p;
00265   void   (*mrf)(void *);
00266   pAllocUnit pAllU = pMemorySegment->FirstUnit;
00267   pAllocUnit pNext;
00268 
00269   if( !p )return;
00270   mrf = pMemorySegment->memory_releasing_function;
00271   LOCK_SEGMENT
00272   while( pAllU ){
00273     pNext = pAllU->next;
00274     LOCK_MALLOC
00275     STAT_SUB( pAllU->Size , pAllU->Size+sizeof(AllocUnit)-1 )
00276 #ifdef _DEBUG
00277 
00278 #endif
00279     mrf(pAllU);
00280     UNLOCK_MALLOC
00281     pAllU = pNext;
00282     }
00283   pMemorySegment->FirstUnit = NULL;
00284   pMemorySegment->CurrentSize = 0; 
00285   pMemorySegment->MinNetSize = 0; 
00286   UNLOCK_SEGMENT
00287   }
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 void alloc_FinishSegment(void *p
00298   ){
00299 
00300 
00301   pMyAlloc pMemorySegment = (pMyAlloc)p;
00302   void   (*mrf)(void *);
00303 
00304   if( !p )return;
00305   mrf = pMemorySegment->memory_releasing_function;
00306   alloc_FreeSegment(p);
00307 #if MTHREAD
00308   thread_FinishMutex(&(pMemorySegment->mxSegment));
00309 #endif
00310   
00311   LOCK_MALLOC
00312   mrf(pMemorySegment);
00313   UNLOCK_MALLOC
00314   STAT_SUB( 0 , sizeof(pMyAlloc) );
00315   }
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 void *alloc_Alloc(size_t n,
00324                   void *p
00325   ){
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333   pMyAlloc pMemorySegment = (pMyAlloc)p;
00334   pAllocUnit pAllU;
00335 
00336   if( n == 0 )
00337     return NULL;
00338 #ifdef _DEBUG
00339   if( pMemorySegment == NULL ){
00340     exit(666);
00341     }
00342 #endif
00343   
00344   if( pMemorySegment->MaxSize && pMemorySegment->MaxSize < pMemorySegment->CurrentSize + n )
00345     return NULL;
00346 
00347   LOCK_SEGMENT
00348 
00349   LOCK_MALLOC
00350 
00351 
00352 
00353 
00354 
00355 
00356 #ifdef _DEBUG
00357 #define EXTRA_BYTE (0)
00358 #else
00359 #define EXTRA_BYTE (1)
00360 #endif
00361 
00362   pAllU = (pAllocUnit)pMemorySegment->memory_allocating_function( n + offsetof(struct _AllocUnit,memory) + EXTRA_BYTE);
00363   UNLOCK_MALLOC
00364 
00365   if( pAllU == NULL ){
00366     UNLOCK_SEGMENT
00367     return NULL;
00368     }
00369 
00370   pAllU->prev = NULL;
00371   pAllU->next = pMemorySegment->FirstUnit;
00372   pAllU->Size = n;
00373 
00374   pMemorySegment->CurrentSize += n;
00375   if( pMemorySegment->CurrentSize > pMemorySegment->MaxNetSize )
00376     pMemorySegment->MaxNetSize = pMemorySegment->CurrentSize;
00377 
00378   if( pMemorySegment->FirstUnit )pMemorySegment->FirstUnit->prev = pAllU;
00379   pMemorySegment->FirstUnit = pAllU;
00380   
00381   UNLOCK_SEGMENT
00382 
00383   STAT_ADD( n , n-1 + sizeof(AllocUnit) )
00384   return (void *)( pAllU->memory );
00385   }
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 void alloc_Free(void *pMem, void *p
00398   ){
00399 
00400 
00401   pMyAlloc pMemorySegment = (pMyAlloc)p;
00402   pAllocUnit pAllU,pAllUi;
00403 
00404   if( pMemorySegment == NULL )return;
00405   if( pMem == NULL )return;
00406   LOCK_SEGMENT
00407   pAllU = (pAllocUnit)( ((unsigned char *)pMem) - offsetof(struct _AllocUnit,memory) ); 
00408 #ifdef _DEBUG
00409   pAllUi = pMemorySegment->FirstUnit;
00410   while( pAllUi ){
00411     if( pAllUi == pAllU )break;
00412     pAllUi = pAllUi->next;
00413     }
00414   if( pAllUi == NULL ){
00415     printf("Memory segment was released not belonging to the segment.\n");
00416     exit(1);
00417     }
00418 #endif
00419   pMemorySegment->CurrentSize -= pAllU->Size;
00420   if( pMemorySegment->CurrentSize < pMemorySegment->MinNetSize )
00421     pMemorySegment->MinNetSize = pMemorySegment->CurrentSize;
00422 
00423   if( pAllU->next )
00424     pAllU->next->prev = pAllU->prev;
00425   if( pAllU->prev )
00426     pAllU->prev->next = pAllU->next;
00427   else
00428     pMemorySegment->FirstUnit = pAllU->next;
00429 
00430   STAT_SUB( pAllU->Size , pAllU->Size + sizeof(AllocUnit) -1 )
00431 
00432 #ifdef _DEBUG
00433 
00434 #endif
00435   LOCK_MALLOC
00436   pMemorySegment->memory_releasing_function(pAllU);
00437   UNLOCK_MALLOC
00438 
00439   UNLOCK_SEGMENT
00440   }
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 void alloc_Merge(void *p1, void *p2
00455   ){
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473   pMyAlloc p1MemorySegment = (pMyAlloc)p1;
00474   pMyAlloc p2MemorySegment = (pMyAlloc)p2;
00475   pAllocUnit *p,q;
00476 
00477 #if MTHREAD
00478   thread_LockMutex(&(p1MemorySegment->mxSegment));
00479   thread_LockMutex(&(p2MemorySegment->mxSegment));
00480 #endif
00481   
00482   p = &(p1MemorySegment->FirstUnit);
00483   q = p1MemorySegment->FirstUnit;
00484   while( *p )p = &((q=*p)->next);
00485   
00486   *p = p2MemorySegment->FirstUnit;
00487   if( *p )(*p)->prev = q;
00488 
00489   
00490   p2MemorySegment->FirstUnit = NULL;
00491   p1MemorySegment->CurrentSize += p2MemorySegment->CurrentSize;
00492 #if MTHREAD
00493   thread_UnlockMutex(&(p2MemorySegment->mxSegment));
00494   thread_UnlockMutex(&(p1MemorySegment->mxSegment));
00495 #endif
00496   }
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 
00505 
00506 void alloc_MergeAndFinish(void *p1, void *p2
00507   ){
00508 
00509 
00510   
00511   alloc_Merge(p1,p2);
00512   
00513   alloc_FinishSegment( p2 );
00514   }
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 void alloc_InitStat(
00526   ){
00527 
00528 
00529 
00530 #if MTHREAD
00531   thread_InitMutex(&mxStat);
00532 #endif
00533 
00534   MaxNetSize = 0;
00535   MinNetSize = 0;
00536   MaxBruSize = 0;
00537   MinBruSize = 0;
00538   ActNetSize = 0;
00539   ActBruSize = 0;
00540   }
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 void alloc_GlobalGetStat(unsigned long *pNetMax,
00554                          unsigned long *pNetMin,
00555                          unsigned long *pBruMax,
00556                          unsigned long *pBruMin,
00557                          unsigned long *pNetSize,
00558                          unsigned long *pBruSize
00559   ){
00560 
00561 
00562 
00563   LOCK_STAT
00564 
00565   if( pNetMax )*pNetMax = MaxNetSize;
00566   MaxNetSize = ActNetSize;
00567   if( pNetMin )*pNetMin = MinNetSize;
00568   MinNetSize = ActNetSize;
00569   if( pBruMax )*pBruMax = MaxBruSize;
00570   MaxBruSize = ActBruSize;
00571   if( pBruMin )*pBruMin = MinBruSize;
00572   MinBruSize = ActBruSize;
00573 
00574   if( pNetSize )*pNetSize = ActNetSize;
00575   if( pBruSize )*pBruSize = ActBruSize;
00576 
00577   UNLOCK_STAT
00578   }
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 void alloc_GetStat(void *p,
00592                    unsigned long *pMax,
00593                    unsigned long *pMin,
00594                    unsigned long *pActSize
00595   ){
00596 
00597 
00598   pMyAlloc pMemorySegment = (pMyAlloc)p;
00599 
00600   LOCK_SEGMENT
00601   if( pMax )*pMax = pMemorySegment->MaxNetSize;
00602   pMemorySegment->MaxNetSize = pMemorySegment->CurrentSize;
00603   if( pMin )*pMin = pMemorySegment->MinNetSize;
00604   pMemorySegment->MinNetSize = pMemorySegment->CurrentSize;
00605 
00606   if( pActSize )*pActSize = pMemorySegment->CurrentSize;
00607   UNLOCK_SEGMENT
00608 
00609   }