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 }