00001 #define malloc mm_malloc
00002 #define free mm_free
00003 #define calloc mm_calloc
00004 #define cfree mm_cfree
00005 #define realloc mm_realloc
00006 #define memalign mm_memalign
00007 #define valloc mm_valloc
00008 #define MM_LINK static
00009
00010 extern CMK_TYPEDEF_UINT8 _memory_allocated;
00011 extern CMK_TYPEDEF_UINT8 _memory_allocated_max;
00012 extern CMK_TYPEDEF_UINT8 _memory_allocated_min;
00013
00014 #undef sun
00015 #undef BSD
00016 #if CMK_GETPAGESIZE_AVAILABLE
00017 #define HAVE_GETPAGESIZE
00018 #endif
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
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
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
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
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 #define SBRK_UNIT 8192
00287
00288
00289
00290
00291
00292
00293 #define MAX_PREALLOCS 64
00294
00295
00296
00297 #ifndef __STD_C
00298 #ifdef __STDC__
00299 #define __STD_C 1
00300 #else
00301 #if __cplusplus
00302 #define __STD_C 1
00303 #else
00304 #define __STD_C 0
00305 #endif
00306 #endif
00307 #endif
00308
00309 #ifndef _BEGIN_EXTERNS_
00310 #if __cplusplus
00311 #define _BEGIN_EXTERNS_ extern "C" {
00312 #define _END_EXTERNS_ }
00313 #else
00314 #define _BEGIN_EXTERNS_
00315 #define _END_EXTERNS_
00316 #endif
00317 #endif
00318
00319 #ifndef _ARG_
00320 #if __STD_C
00321 #define _ARG_(x) x
00322 #else
00323 #define _ARG_(x) ()
00324 #endif
00325 #endif
00326
00327
00328
00329 #ifndef Void_t
00330 #if __STD_C
00331 #define Void_t void
00332 #else
00333 #define Void_t char
00334 #endif
00335 #endif
00336
00337 #ifndef NIL
00338 #define NIL(type) ((type)0)
00339 #endif
00340
00341 #if __STD_C
00342 #include <stddef.h>
00343 #else
00344 #include <sys/types.h>
00345 #endif
00346
00347 #include <stdio.h>
00348
00349 #ifdef __cplusplus
00350 extern "C" {
00351 #endif
00352
00353
00354
00355 #if defined(BSD) || defined(DGUX) || defined(sun) || defined(_WIN32) || defined(HAVE_GETPAGESIZE)
00356 # define malloc_getpagesize getpagesize()
00357 #else
00358 # include <sys/param.h>
00359 # ifdef EXEC_PAGESIZE
00360 # define malloc_getpagesize EXEC_PAGESIZE
00361 # else
00362 # ifdef NBPG
00363 # ifndef CLSIZE
00364 # define malloc_getpagesize NBPG
00365 # else
00366 # define malloc_getpagesize (NBPG * CLSIZE)
00367 # endif
00368 # else
00369 # ifdef NBPC
00370 # define malloc_getpagesize NBPC
00371 # else
00372 # define malloc_getpagesize SBRK_UNIT
00373 # endif
00374 # endif
00375 # endif
00376 #endif
00377
00378 #ifdef __cplusplus
00379 };
00380 #endif
00381
00382
00383
00384
00385
00386
00387 struct malloc_chunk
00388 {
00389 size_t size;
00390
00391
00392 struct malloc_chunk* fd;
00393 struct malloc_chunk* bk;
00394
00395 };
00396
00397 typedef struct malloc_chunk* mchunkptr;
00398
00399
00400
00401 #define SIZE_SZ (sizeof(size_t))
00402 #define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ)
00403 #define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1)
00404 #define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ)
00405
00406
00407
00408
00409 #define request2size(req) \
00410 (((long)(req) <= 0) ? MINSIZE : \
00411 (((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
00412 & ~(MALLOC_ALIGN_MASK)))
00413
00414 #define fastrequest2size(req) \
00415 ((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
00416 & ~(MALLOC_ALIGN_MASK)
00417
00418
00419
00420
00421 #define exact_fit(ptr, req) ((unsigned long)((ptr)->size - (req)) < MINSIZE)
00422
00423
00424
00425 #define INUSE 0x1
00426
00427
00428 #define inuse(p) ((p)->size & INUSE)
00429 #define set_inuse(p) ((p)->size |= INUSE)
00430 #define clear_inuse(p) ((p)->size &= ~INUSE)
00431
00432
00433
00434
00435
00436
00437
00438 #define next_chunk(p)\
00439 ((mchunkptr)( ((char*)(p)) + ((p)->size & ~INUSE) ))
00440
00441
00442
00443 #define prev_chunk(p)\
00444 ((mchunkptr)( ((char*)(p)) - ( *((size_t*)((char*)(p) - SIZE_SZ)) & ~INUSE)))
00445
00446
00447
00448 #define set_size(P, Sz) \
00449 { \
00450 size_t Sss = (Sz); \
00451 (P)->size = *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
00452 } \
00453
00454
00455 #define set_inuse_size(P, Sz) \
00456 { \
00457 size_t Sss = (Sz); \
00458 *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
00459 (P)->size = Sss | INUSE; \
00460 } \
00461
00462
00463
00464
00465 #define chunk2mem(p) ((Void_t*)((char*)(p) + SIZE_SZ))
00466 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - SIZE_SZ))
00467
00468
00469
00470
00471
00472
00473 struct malloc_bin
00474 {
00475 struct malloc_chunk dhd;
00476 struct malloc_chunk chd;
00477 };
00478
00479 typedef struct malloc_bin* mbinptr;
00480
00481
00482
00483
00484 #define clean_head(b) (&((b)->chd))
00485 #define first_clean(b) ((b)->chd.fd)
00486 #define last_clean(b) ((b)->chd.bk)
00487
00488 #define dirty_head(b) (&((b)->dhd))
00489 #define first_dirty(b) ((b)->dhd.fd)
00490 #define last_dirty(b) ((b)->dhd.bk)
00491
00492
00493
00494 #define bin_use(b) ((b)->dhd.size)
00495 #define add_bin_use(b, nu) ((b)->dhd.size += (nu))
00496 #define inc_bin_use(b) ((b)->dhd.size++)
00497 #define halve_bin_use(b) ((b)->dhd.size=(unsigned long)((b)->dhd.size) >> 1)
00498 #define clr_bin_use(b) ((b)->dhd.size = 0)
00499 #define set_bin_use(b) ((b)->dhd.size = 1)
00500
00501 #define prealloc_size(b) ((b)->chd.size)
00502 #define set_prealloc_size(b, sz) ((b)->chd.size = (sz))
00503
00504
00505
00506
00507
00508 #define NBINS 128
00509
00510 #define FIRSTBIN (&(av[2]))
00511 #define LASTBIN (&(av[NBINS-2]))
00512
00513 #define PRE_FIRSTBIN (&(av[1]))
00514 #define POST_LASTBIN (&(av[NBINS-1]))
00515
00516
00517
00518
00519 #define MAX_SMALLBIN_SIZE 512
00520 #define SMALLBIN_SIZE 8
00521
00522
00523 #define IAV(i)\
00524 {{ 0, &(av[i].dhd), &(av[i].dhd) }, { 0, &(av[i].chd), &(av[i].chd) }}
00525
00526 static struct malloc_bin av[NBINS] =
00527 {
00528 IAV(0), IAV(1), IAV(2), IAV(3), IAV(4),
00529 IAV(5), IAV(6), IAV(7), IAV(8), IAV(9),
00530 IAV(10), IAV(11), IAV(12), IAV(13), IAV(14),
00531 IAV(15), IAV(16), IAV(17), IAV(18), IAV(19),
00532 IAV(20), IAV(21), IAV(22), IAV(23), IAV(24),
00533 IAV(25), IAV(26), IAV(27), IAV(28), IAV(29),
00534 IAV(30), IAV(31), IAV(32), IAV(33), IAV(34),
00535 IAV(35), IAV(36), IAV(37), IAV(38), IAV(39),
00536 IAV(40), IAV(41), IAV(42), IAV(43), IAV(44),
00537 IAV(45), IAV(46), IAV(47), IAV(48), IAV(49),
00538 IAV(50), IAV(51), IAV(52), IAV(53), IAV(54),
00539 IAV(55), IAV(56), IAV(57), IAV(58), IAV(59),
00540 IAV(60), IAV(61), IAV(62), IAV(63), IAV(64),
00541 IAV(65), IAV(66), IAV(67), IAV(68), IAV(69),
00542 IAV(70), IAV(71), IAV(72), IAV(73), IAV(74),
00543 IAV(75), IAV(76), IAV(77), IAV(78), IAV(79),
00544 IAV(80), IAV(81), IAV(82), IAV(83), IAV(84),
00545 IAV(85), IAV(86), IAV(87), IAV(88), IAV(89),
00546 IAV(90), IAV(91), IAV(92), IAV(93), IAV(94),
00547 IAV(95), IAV(96), IAV(97), IAV(98), IAV(99),
00548 IAV(100), IAV(101), IAV(102), IAV(103), IAV(104),
00549 IAV(105), IAV(106), IAV(107), IAV(108), IAV(109),
00550 IAV(110), IAV(111), IAV(112), IAV(113), IAV(114),
00551 IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
00552 IAV(120), IAV(121), IAV(122), IAV(123), IAV(124),
00553 IAV(125), IAV(126), IAV(127)
00554 };
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 static mchunkptr returns = 0;
00570
00571
00572
00573
00574
00575
00576 static mchunkptr last_remainder = 0;
00577
00578
00579
00580
00581
00582
00583
00584
00585 static mbinptr maxClean = PRE_FIRSTBIN;
00586 static mbinptr minClean = POST_LASTBIN;
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 #define findbin(Sizefb, Bfb) \
00609 { \
00610 unsigned long Ofb = (Sizefb) >> 3; \
00611 unsigned long Nfb = Ofb >> 6; \
00612 if (Nfb != 0) { \
00613 if (Nfb < 5) Ofb = (Ofb >> 3) + 56; \
00614 else if (Nfb < 21) Ofb = (Ofb >> 6) + 91; \
00615 else if (Nfb < 85) Ofb = (Ofb >> 9) + 110; \
00616 else if (Nfb < 341) Ofb = (Ofb >> 12) + 119; \
00617 else if (Nfb < 1365) Ofb = (Ofb >> 15) + 124; \
00618 else Ofb = 126; \
00619 } \
00620 (Bfb) = av + Ofb; \
00621 } \
00622
00623
00624
00625 #define smallfindbin(Sizefb, Bfb) (Bfb) = av + ((unsigned long)(Sizefb) >> 3)
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 #define unlink(Qul) \
00638 { \
00639 mchunkptr Bul = (Qul)->bk; \
00640 mchunkptr Ful = (Qul)->fd; \
00641 Ful->bk = Bul; Bul->fd = Ful; \
00642 } \
00643
00644
00645
00646
00647 #define dirtylink(Qdl) \
00648 { \
00649 mchunkptr Pdl = (Qdl); \
00650 mbinptr Bndl; \
00651 mchunkptr Hdl, Fdl; \
00652 clear_inuse(Pdl); \
00653 findbin(Pdl->size, Bndl); \
00654 Hdl = dirty_head(Bndl); \
00655 Fdl = Hdl->fd; \
00656 Pdl->bk = Hdl; Pdl->fd = Fdl; Fdl->bk = Hdl->fd = Pdl; \
00657 } \
00658
00659
00660
00661
00662 #define cleanlink(Qcl) \
00663 { \
00664 mchunkptr Pcl = (Qcl); \
00665 mbinptr Bcl; \
00666 mchunkptr Hcl, Fcl; \
00667 \
00668 findbin(Qcl->size, Bcl); \
00669 Hcl = clean_head(Bcl); \
00670 Fcl = Hcl->fd; \
00671 if (Hcl == Fcl) { \
00672 if (Bcl < minClean) minClean = Bcl; \
00673 if (Bcl > maxClean) maxClean = Bcl; \
00674 } \
00675 Pcl->bk = Hcl; Pcl->fd = Fcl; Fcl->bk = Hcl->fd = Pcl; \
00676 } \
00677
00678
00679 #if __STD_C
00680 static void callcleanlink(mchunkptr p)
00681 #else
00682 static void callcleanlink(p) mchunkptr p;
00683 #endif
00684 {
00685 cleanlink(p);
00686 }
00687
00688
00689
00690
00691
00692 #define consolidate(Qc) \
00693 { \
00694 for (;;) \
00695 { \
00696 mchunkptr Pc = prev_chunk(Qc); \
00697 if (!inuse(Pc)) \
00698 { \
00699 unlink(Pc); \
00700 set_size(Pc, Pc->size + (Qc)->size); \
00701 (Qc) = Pc; \
00702 } \
00703 else break; \
00704 } \
00705 for (;;) \
00706 { \
00707 mchunkptr Nc = next_chunk(Qc); \
00708 if (!inuse(Nc)) \
00709 { \
00710 unlink(Nc); \
00711 set_size((Qc), (Qc)->size + Nc->size); \
00712 } \
00713 else break; \
00714 } \
00715 } \
00716
00717
00718
00719
00720 #define returnlink(Prc) \
00721 { \
00722 (Prc)->fd = returns; \
00723 returns = (Prc); \
00724 } \
00725
00726
00727
00728
00729
00730
00731
00732 static void clear_aux_lists()
00733 {
00734 if (last_remainder != 0)
00735 {
00736 cleanlink(last_remainder);
00737 last_remainder = 0;
00738 }
00739
00740 while (returns != 0)
00741 {
00742 mchunkptr p = returns;
00743 returns = p->fd;
00744 dirtylink(p);
00745 }
00746 }
00747
00748
00749
00750
00751
00752
00753
00754 static size_t sbrked_mem = 0;
00755
00756 #if __STD_C
00757 static mchunkptr malloc_from_sys(size_t nb)
00758 #else
00759 static mchunkptr malloc_from_sys(nb) size_t nb;
00760 #endif
00761 {
00762
00763
00764 static size_t* last_sbrk_end = 0;
00765
00766 mchunkptr p;
00767 size_t* ip;
00768 char* cp;
00769 int offs;
00770
00771
00772
00773
00774
00775 size_t sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ)
00776 / SBRK_UNIT) * SBRK_UNIT;
00777
00778 cp = (char*)(sbrk(sbrk_size));
00779 if (cp == (char*)(-1))
00780 return 0;
00781 sbrked_mem += sbrk_size;
00782
00783 if (((size_t)cp) & MALLOC_ALIGN_MASK) {
00784 offs = ((size_t)cp) & MALLOC_ALIGN_MASK;
00785 cp += MALLOC_MIN_OVERHEAD - offs;
00786 sbrk_size -= MALLOC_MIN_OVERHEAD;
00787 sbrk(- offs);
00788 }
00789
00790 ip = (size_t*)cp;
00791
00792 if (last_sbrk_end != &ip[-1])
00793 {
00794
00795
00796
00797
00798
00799
00800 *ip++ = SIZE_SZ | INUSE;
00801
00802 p = (mchunkptr)ip;
00803 set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ));
00804
00805 }
00806 else
00807 {
00808 mchunkptr l;
00809
00810
00811
00812
00813
00814 p = (mchunkptr)(last_sbrk_end);
00815 set_size(p, sbrk_size);
00816
00817
00818
00819 l = prev_chunk(p);
00820 if (!inuse(l))
00821 {
00822 unlink(l);
00823 set_size(l, p->size + l->size);
00824 p = l;
00825 }
00826
00827 }
00828
00829
00830
00831 last_sbrk_end = (size_t*)((char*)p + p->size);
00832 *last_sbrk_end = SIZE_SZ | INUSE;
00833
00834 return p;
00835 }
00836
00837
00838
00839
00840
00841
00842 #if __STD_C
00843 static mchunkptr malloc_consolidate(size_t nb)
00844 #else
00845 static mchunkptr malloc_consolidate(nb) size_t nb;
00846 #endif
00847 {
00848 static mbinptr rover = LASTBIN;
00849
00850 mbinptr origin, b;
00851
00852
00853
00854
00855
00856
00857 mchunkptr victim = last_remainder;
00858 last_remainder = 0;
00859
00860 if (victim != 0)
00861 {
00862 consolidate(victim);
00863
00864 if (victim->size >= nb)
00865 return victim;
00866 else
00867 cleanlink(victim);
00868 }
00869
00870
00871
00872 origin = rover;
00873 b = rover;
00874 do
00875 {
00876 halve_bin_use(b);
00877
00878 while ( (victim = last_dirty(b)) != dirty_head(b))
00879 {
00880 unlink(victim);
00881 consolidate(victim);
00882
00883 if (victim->size >= nb)
00884 {
00885 rover = b;
00886 return victim;
00887 }
00888 else
00889 cleanlink(victim);
00890 }
00891
00892
00893 b = (b <= FIRSTBIN)? LASTBIN : b - 1;
00894
00895 } while (b != origin);
00896
00897
00898
00899
00900 return malloc_from_sys(nb);
00901 }
00902
00903
00904 #if __STD_C
00905 MM_LINK Void_t* malloc(size_t bytes)
00906 #else
00907 MM_LINK Void_t* malloc(bytes) size_t bytes;
00908 #endif
00909 {
00910 static mchunkptr bad_rl_chunk = 0;
00911 static mbinptr prevClean = FIRSTBIN;
00912
00913 mchunkptr victim;
00914 mbinptr bin;
00915
00916
00917
00918 mchunkptr rl = returns;
00919 size_t nb = request2size(bytes) ;
00920
00921 _memory_allocated += nb;
00922
00923 if(_memory_allocated > _memory_allocated_max)
00924 _memory_allocated_max=_memory_allocated;
00925 if(_memory_allocated < _memory_allocated_min)
00926 _memory_allocated_min=_memory_allocated;
00927
00928 if (rl != 0)
00929 {
00930 mchunkptr snd = rl->fd;
00931 if (exact_fit(rl, nb))
00932 {
00933 returns = snd;
00934 return chunk2mem(rl);
00935 }
00936 else if (snd != 0 && exact_fit(snd, nb))
00937 {
00938 returns->fd = snd->fd;
00939 return chunk2mem(snd);
00940 }
00941 else if (rl == bad_rl_chunk)
00942 {
00943 dirtylink(rl);
00944 returns = rl = snd;
00945 }
00946 bad_rl_chunk = rl;
00947 }
00948
00949
00950
00951
00952
00953 if (nb < (MAX_SMALLBIN_SIZE - SMALLBIN_SIZE))
00954 {
00955
00956
00957
00958 smallfindbin(nb, bin);
00959
00960 if ( ((victim = last_dirty(bin)) != dirty_head(bin)) ||
00961 ((victim = last_clean(bin)) != clean_head(bin)) ||
00962 ((victim = last_dirty(bin+1)) != dirty_head(bin+1)))
00963 {
00964 unlink(victim);
00965 set_inuse(victim);
00966 return chunk2mem(victim);
00967 }
00968
00969 }
00970 else
00971 {
00972 findbin(nb, bin);
00973
00974 for (victim=last_dirty(bin); victim != dirty_head(bin); victim=victim->bk)
00975 {
00976 if (exact_fit(victim, nb))
00977 {
00978 unlink(victim);
00979 set_inuse(victim);
00980 return chunk2mem(victim);
00981 }
00982 }
00983
00984 for (victim=last_clean(bin); victim != clean_head(bin); victim=victim->bk)
00985 {
00986 if (victim->size >= nb)
00987 {
00988 unlink(victim);
00989 goto split;
00990 }
00991 }
00992 }
00993
00994
00995
00996
00997
00998 if (rl != 0)
00999 {
01000 victim = rl;
01001 rl = rl->fd;
01002 for (;;)
01003 {
01004 dirtylink(victim);
01005 if (rl == 0)
01006 {
01007 returns = rl;
01008 break;
01009 }
01010 victim = rl;
01011 rl = rl->fd;
01012 if (exact_fit(victim, nb))
01013 {
01014 bad_rl_chunk = returns = rl;
01015 return chunk2mem(victim);
01016 }
01017 }
01018 }
01019
01020 if (bin < maxClean)
01021 {
01022 mbinptr b;
01023
01024
01025
01026 if (bin < prevClean)
01027 {
01028 if ( (victim = last_clean(prevClean)) != clean_head(prevClean) )
01029 {
01030 unlink(victim);
01031 goto split;
01032 }
01033 }
01034
01035
01036
01037
01038 for (b = (bin < minClean)? minClean : (bin + 1); b <= maxClean; ++b)
01039 {
01040 if ( (victim = last_clean(b)) != clean_head(b) )
01041 {
01042
01043 if (bin_use(b) == 0 && victim->bk != clean_head(b)) prevClean = b;
01044 else { halve_bin_use(b); prevClean = FIRSTBIN; }
01045
01046 unlink(victim);
01047 if (bin < minClean) minClean = b;
01048 goto split;
01049 }
01050 }
01051
01052
01053
01054 while (maxClean >= FIRSTBIN && clean_head(maxClean)==last_clean(maxClean))
01055 --maxClean;
01056 if (maxClean < FIRSTBIN)
01057 minClean = POST_LASTBIN;
01058 else
01059 {
01060 while (minClean < maxClean && clean_head(minClean)==last_clean(minClean))
01061 ++minClean;
01062 }
01063
01064 prevClean = FIRSTBIN;
01065
01066 }
01067
01068
01069
01070
01071 if ( (victim = last_remainder) != 0)
01072 {
01073 if (victim->size >= nb)
01074 {
01075 last_remainder = 0;
01076 goto split;
01077 }
01078 }
01079
01080
01081
01082
01083 victim = malloc_consolidate(nb);
01084 if (victim == 0) return 0;
01085
01086
01087
01088
01089 split:
01090 {
01091 size_t room = victim->size - nb;
01092
01093 if (room < MINSIZE)
01094 {
01095 set_inuse(victim);
01096 return chunk2mem(victim);
01097 }
01098 else
01099 {
01100 mchunkptr remainder;
01101 int desired;
01102
01103 set_inuse_size(victim, nb);
01104 remainder = (mchunkptr)((char*)(victim) + nb);
01105
01106 desired = inc_bin_use(bin);
01107
01108
01109
01110 if (nb < MAX_SMALLBIN_SIZE && room >= nb + MINSIZE && desired != 0)
01111 {
01112 int actual = 1;
01113
01114
01115 mchunkptr first = remainder;
01116 mchunkptr last = remainder;
01117 set_inuse_size(remainder, nb);
01118 remainder = (mchunkptr)((char*)(remainder) + nb);
01119
01120 if (desired > MAX_PREALLOCS) desired = MAX_PREALLOCS;
01121
01122 while ( (room -= nb) >= nb + MINSIZE && actual < desired)
01123 {
01124 ++actual;
01125 set_inuse_size(remainder, nb);
01126 last->fd = remainder;
01127 last = remainder;
01128 remainder = (mchunkptr)((char*)(remainder) + nb);
01129 }
01130
01131 last->fd = returns;
01132 returns = first;
01133
01134 add_bin_use(bin, actual);
01135 }
01136
01137
01138
01139 set_size(remainder, room);
01140
01141
01142 if (last_remainder != 0) callcleanlink(last_remainder);
01143 last_remainder = remainder;
01144
01145 return chunk2mem(victim);
01146
01147 }
01148 }
01149 }
01150
01151
01152
01153
01154 #if __STD_C
01155 MM_LINK void free(Void_t* mem)
01156 #else
01157 MM_LINK void free(mem) Void_t* mem;
01158 #endif
01159 {
01160 if (mem != 0)
01161 {
01162 mchunkptr p = mem2chunk(mem);
01163 _memory_allocated -= p->size;
01164 returnlink(p);
01165 }
01166 }
01167
01168
01169
01170
01171
01172
01173
01174 #define SCopy(SCs,SCd,SCc) \
01175 { \
01176 size_t * SCsrc = (size_t*) SCs; \
01177 size_t * SCdst = (size_t*) SCd; \
01178 size_t SCcount = (SCc - SIZE_SZ) / sizeof(size_t); \
01179 do { *SCdst++ = *SCsrc++; } while (--SCcount > 0); \
01180 }
01181
01182
01183 #if __STD_C
01184 MM_LINK Void_t* realloc(Void_t* mem, size_t bytes)
01185 #else
01186 MM_LINK Void_t* realloc(mem, bytes) Void_t* mem; size_t bytes;
01187 #endif
01188 {
01189 if (mem == 0)
01190 return malloc(bytes);
01191 else
01192 {
01193 size_t nb = request2size(bytes);
01194 mchunkptr p = mem2chunk(mem);
01195 size_t oldsize;
01196 Void_t* newmem;
01197 size_t room;
01198 int back_expanded = 0;
01199
01200 if (p == returns)
01201 returns = returns->fd;
01202
01203 clear_inuse(p);
01204 oldsize = p->size;
01205
01206
01207
01208 clear_aux_lists();
01209
01210 if (p->size < nb)
01211 {
01212 for (;;)
01213 {
01214 mchunkptr nxt = next_chunk(p);
01215 if (!inuse(nxt))
01216 {
01217 unlink(nxt);
01218 set_size(p, p->size + nxt->size);
01219 }
01220 else break;
01221 }
01222 }
01223
01224 while (p->size < nb)
01225 {
01226 mchunkptr prv = prev_chunk(p);
01227 if (!inuse(prv))
01228 {
01229 back_expanded = 1;
01230 unlink(prv);
01231 set_size(prv, prv->size + p->size);
01232 p = prv;
01233 }
01234 else break;
01235 }
01236
01237 if (p->size < nb)
01238 {
01239 mchunkptr newp;
01240
01241 set_inuse(p);
01242 newmem = malloc(nb);
01243 newp = mem2chunk(newmem);
01244
01245
01246
01247
01248
01249 if (newp == next_chunk(p))
01250 {
01251
01252 if (back_expanded)
01253 SCopy(mem, chunk2mem(p), oldsize);
01254
01255 clear_inuse(p);
01256 clear_inuse(newp);
01257 set_size(p, p->size + newp->size);
01258
01259 room = p->size - nb;
01260 if (room >= MINSIZE)
01261 {
01262 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01263 set_size(remainder, room);
01264 set_size(p, nb);
01265
01266
01267 clear_aux_lists();
01268 for (;;)
01269 {
01270 mchunkptr nxt = next_chunk(remainder);
01271 if (!inuse(nxt))
01272 {
01273 unlink(nxt);
01274 set_size(remainder, remainder->size + nxt->size);
01275 }
01276 else break;
01277 }
01278 last_remainder = remainder;
01279 }
01280
01281 set_inuse(p);
01282 return chunk2mem(p);
01283 }
01284 else
01285 {
01286 if (newmem != 0) SCopy(mem, newmem, oldsize);
01287 returnlink(p);
01288 return newmem;
01289 }
01290 }
01291 else
01292 {
01293 room = p->size - nb;
01294 newmem = chunk2mem(p);
01295
01296 if (back_expanded) SCopy(mem, newmem, oldsize);
01297
01298 if (room >= MINSIZE)
01299 {
01300 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01301 set_size(remainder, room);
01302 dirtylink(remainder);
01303 set_size(p, nb);
01304 }
01305
01306 set_inuse(p);
01307 return chunk2mem(p);
01308 }
01309 }
01310 }
01311
01312
01313
01314
01315
01316
01317 #if __STD_C
01318 MM_LINK Void_t* memalign(size_t alignment, size_t bytes)
01319 #else
01320 MM_LINK Void_t* memalign(alignment, bytes) size_t alignment; size_t bytes;
01321 #endif
01322 {
01323 mchunkptr p;
01324 size_t nb = request2size(bytes);
01325 size_t room;
01326
01327
01328
01329 size_t align = (alignment > MALLOC_MIN_OVERHEAD) ?
01330 alignment : MALLOC_MIN_OVERHEAD;
01331
01332
01333
01334
01335 size_t req = nb + align + MINSIZE;
01336 Void_t* m = malloc(req);
01337
01338 if (m == 0) return 0;
01339
01340 p = mem2chunk(m);
01341 clear_inuse(p);
01342
01343
01344 if (((size_t)(m) % align) != 0)
01345 {
01346
01347
01348
01349 mchunkptr ap = (mchunkptr)((((size_t)(m) + align-1) & -align) - SIZE_SZ);
01350
01351 size_t gap = (size_t)(ap) - (size_t)(p);
01352
01353
01354
01355 if (gap < MINSIZE)
01356 {
01357
01358
01359
01360 ap = (mchunkptr)( (size_t)(ap) + align );
01361 gap += align;
01362 }
01363
01364 room = p->size - gap;
01365
01366
01367 set_size(p, gap);
01368 dirtylink(p);
01369
01370
01371 p = ap;
01372 set_size(p, room);
01373 }
01374
01375
01376
01377 room = p->size - nb;
01378 if (room >= MINSIZE)
01379 {
01380 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01381 set_size(remainder, room);
01382 dirtylink(remainder);
01383 set_size(p, nb);
01384 }
01385
01386 set_inuse(p);
01387 return chunk2mem(p);
01388
01389 }
01390
01391
01392
01393
01394
01395 #if __STD_C
01396 MM_LINK Void_t* valloc(size_t bytes)
01397 #else
01398 MM_LINK Void_t* valloc(bytes) size_t bytes;
01399 #endif
01400 {
01401
01402 static size_t malloc_pagesize = 0;
01403
01404 if (malloc_pagesize == 0) malloc_pagesize = malloc_getpagesize;
01405 return memalign (malloc_pagesize, bytes);
01406 }
01407
01408
01409 #if __STD_C
01410 MM_LINK Void_t* calloc(size_t n, size_t elem_size)
01411 #else
01412 MM_LINK Void_t* calloc(n, elem_size) size_t n; size_t elem_size;
01413 #endif
01414 {
01415 size_t sz = n * elem_size;
01416 Void_t* p = malloc(sz);
01417 char* q = (char*) p;
01418 while (sz-- > 0) *q++ = 0;
01419 return p;
01420 }
01421
01422 #if __STD_C
01423 MM_LINK void cfree(Void_t *mem)
01424 #else
01425 MM_LINK void cfree(mem) Void_t *mem;
01426 #endif
01427 {
01428 free(mem);
01429 }
01430
01431 #if __STD_C
01432 size_t malloc_usable_size(Void_t* mem)
01433 #else
01434 size_t malloc_usable_size(mem) Void_t* mem;
01435 #endif
01436 {
01437 if (mem == 0)
01438 return 0;
01439 else
01440 {
01441 mchunkptr p = mem2chunk(mem);
01442 size_t sz = p->size & ~(INUSE);
01443
01444 if (p->size == sz || sz != *((size_t*)((char*)(p) + sz - SIZE_SZ)))
01445 return 0;
01446 else
01447 return sz - MALLOC_MIN_OVERHEAD;
01448 }
01449 }
01450
01451
01452 void malloc_stats()
01453 {
01454
01455
01456
01457 size_t avail = 0;
01458 size_t malloced_mem;
01459
01460 mbinptr b;
01461
01462 clear_aux_lists();
01463
01464 for (b = FIRSTBIN; b <= LASTBIN; ++b)
01465 {
01466 mchunkptr p;
01467
01468 for (p = first_dirty(b); p != dirty_head(b); p = p->fd)
01469 avail += p->size;
01470
01471 for (p = first_clean(b); p != clean_head(b); p = p->fd)
01472 avail += p->size;
01473 }
01474
01475 malloced_mem = sbrked_mem - avail;
01476
01477 fprintf(stderr, "total mem = %10u\n", (unsigned int)sbrked_mem);
01478 fprintf(stderr, "in use = %10u\n", (unsigned int)malloced_mem);
01479
01480 }
01481
01482 #undef malloc
01483 #undef free
01484 #undef calloc
01485 #undef cfree
01486 #undef realloc
01487 #undef memalign
01488 #undef valloc
01489