00001
00002
00003
00004
00005
00006
00007
00008 #define malloc mm_malloc
00009 #define free mm_free
00010 #define calloc mm_calloc
00011 #define cfree mm_cfree
00012 #define realloc mm_realloc
00013 #define memalign mm_memalign
00014 #define valloc mm_valloc
00015 #define MM_LINK static
00016
00017 #undef sun
00018 #undef BSD
00019 #if CMK_GETPAGESIZE_AVAILABLE
00020 #define HAVE_GETPAGESIZE
00021 #endif
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
00287
00288
00289 #define SBRK_UNIT 8192
00290
00291
00292
00293
00294
00295
00296 #define MAX_PREALLOCS 64
00297
00298
00299
00300 #ifndef __STD_C
00301 #ifdef __STDC__
00302 #define __STD_C 1
00303 #else
00304 #if __cplusplus
00305 #define __STD_C 1
00306 #else
00307 #define __STD_C 0
00308 #endif
00309 #endif
00310 #endif
00311
00312 #ifndef _BEGIN_EXTERNS_
00313 #if __cplusplus
00314 #define _BEGIN_EXTERNS_ extern "C" {
00315 #define _END_EXTERNS_ }
00316 #else
00317 #define _BEGIN_EXTERNS_
00318 #define _END_EXTERNS_
00319 #endif
00320 #endif
00321
00322 #ifndef _ARG_
00323 #if __STD_C
00324 #define _ARG_(x) x
00325 #else
00326 #define _ARG_(x) ()
00327 #endif
00328 #endif
00329
00330
00331
00332 #ifndef Void_t
00333 #if __STD_C
00334 #define Void_t void
00335 #else
00336 #define Void_t char
00337 #endif
00338 #endif
00339
00340 #ifndef NIL
00341 #define NIL(type) ((type)0)
00342 #endif
00343
00344 #if __STD_C
00345 #include <stddef.h>
00346 #else
00347 #include <sys/types.h>
00348 #endif
00349
00350 #include <stdio.h>
00351
00352 #ifdef __cplusplus
00353 extern "C" {
00354 #endif
00355
00356
00357
00358 #if defined(BSD) || defined(DGUX) || defined(sun) || defined(_WIN32) || defined(HAVE_GETPAGESIZE)
00359 # define malloc_getpagesize getpagesize()
00360 #else
00361 # include <sys/param.h>
00362 # ifdef EXEC_PAGESIZE
00363 # define malloc_getpagesize EXEC_PAGESIZE
00364 # else
00365 # ifdef NBPG
00366 # ifndef CLSIZE
00367 # define malloc_getpagesize NBPG
00368 # else
00369 # define malloc_getpagesize (NBPG * CLSIZE)
00370 # endif
00371 # else
00372 # ifdef NBPC
00373 # define malloc_getpagesize NBPC
00374 # else
00375 # define malloc_getpagesize SBRK_UNIT
00376 # endif
00377 # endif
00378 # endif
00379 #endif
00380
00381 #ifdef __cplusplus
00382 };
00383 #endif
00384
00385
00386
00387
00388
00389
00390 struct malloc_chunk
00391 {
00392 size_t size;
00393
00394
00395 struct malloc_chunk* fd;
00396 struct malloc_chunk* bk;
00397
00398 };
00399
00400 typedef struct malloc_chunk* mchunkptr;
00401
00402
00403
00404 #define SIZE_SZ (sizeof(size_t))
00405 #define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ)
00406 #define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1)
00407 #define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ)
00408
00409
00410
00411
00412 #define request2size(req) \
00413 (((long)(req) <= 0) ? MINSIZE : \
00414 (((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
00415 & ~(MALLOC_ALIGN_MASK)))
00416
00417 #define fastrequest2size(req) \
00418 ((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
00419 & ~(MALLOC_ALIGN_MASK)
00420
00421
00422
00423
00424 #define exact_fit(ptr, req) ((unsigned long)((ptr)->size - (req)) < MINSIZE)
00425
00426
00427
00428 #define INUSE 0x1
00429
00430
00431 #define inuse(p) ((p)->size & INUSE)
00432 #define set_inuse(p) ((p)->size |= INUSE)
00433 #define clear_inuse(p) ((p)->size &= ~INUSE)
00434
00435
00436
00437
00438
00439
00440
00441 #define next_chunk(p)\
00442 ((mchunkptr)( ((char*)(p)) + ((p)->size & ~INUSE) ))
00443
00444
00445
00446 #define prev_chunk(p)\
00447 ((mchunkptr)( ((char*)(p)) - ( *((size_t*)((char*)(p) - SIZE_SZ)) & ~INUSE)))
00448
00449
00450
00451 #define set_size(P, Sz) \
00452 { \
00453 size_t Sss = (Sz); \
00454 (P)->size = *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
00455 } \
00456
00457
00458 #define set_inuse_size(P, Sz) \
00459 { \
00460 size_t Sss = (Sz); \
00461 *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
00462 (P)->size = Sss | INUSE; \
00463 } \
00464
00465
00466
00467
00468 #define chunk2mem(p) ((Void_t*)((char*)(p) + SIZE_SZ))
00469 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - SIZE_SZ))
00470
00471
00472
00473
00474
00475
00476 struct malloc_bin
00477 {
00478 struct malloc_chunk dhd;
00479 struct malloc_chunk chd;
00480 };
00481
00482 typedef struct malloc_bin* mbinptr;
00483
00484
00485
00486
00487 #define clean_head(b) (&((b)->chd))
00488 #define first_clean(b) ((b)->chd.fd)
00489 #define last_clean(b) ((b)->chd.bk)
00490
00491 #define dirty_head(b) (&((b)->dhd))
00492 #define first_dirty(b) ((b)->dhd.fd)
00493 #define last_dirty(b) ((b)->dhd.bk)
00494
00495
00496
00497 #define bin_use(b) ((b)->dhd.size)
00498 #define add_bin_use(b, nu) ((b)->dhd.size += (nu))
00499 #define inc_bin_use(b) ((b)->dhd.size++)
00500 #define halve_bin_use(b) ((b)->dhd.size=(unsigned long)((b)->dhd.size) >> 1)
00501 #define clr_bin_use(b) ((b)->dhd.size = 0)
00502 #define set_bin_use(b) ((b)->dhd.size = 1)
00503
00504 #define prealloc_size(b) ((b)->chd.size)
00505 #define set_prealloc_size(b, sz) ((b)->chd.size = (sz))
00506
00507
00508
00509
00510
00511 #define NBINS 128
00512
00513 #define FIRSTBIN (&(av[2]))
00514 #define LASTBIN (&(av[NBINS-2]))
00515
00516 #define PRE_FIRSTBIN (&(av[1]))
00517 #define POST_LASTBIN (&(av[NBINS-1]))
00518
00519
00520
00521
00522 #define MAX_SMALLBIN_SIZE 512
00523 #define SMALLBIN_SIZE 8
00524
00525
00526 #define IAV(i)\
00527 {{ 0, &(av[i].dhd), &(av[i].dhd) }, { 0, &(av[i].chd), &(av[i].chd) }}
00528
00529 static struct malloc_bin av[NBINS] =
00530 {
00531 IAV(0), IAV(1), IAV(2), IAV(3), IAV(4),
00532 IAV(5), IAV(6), IAV(7), IAV(8), IAV(9),
00533 IAV(10), IAV(11), IAV(12), IAV(13), IAV(14),
00534 IAV(15), IAV(16), IAV(17), IAV(18), IAV(19),
00535 IAV(20), IAV(21), IAV(22), IAV(23), IAV(24),
00536 IAV(25), IAV(26), IAV(27), IAV(28), IAV(29),
00537 IAV(30), IAV(31), IAV(32), IAV(33), IAV(34),
00538 IAV(35), IAV(36), IAV(37), IAV(38), IAV(39),
00539 IAV(40), IAV(41), IAV(42), IAV(43), IAV(44),
00540 IAV(45), IAV(46), IAV(47), IAV(48), IAV(49),
00541 IAV(50), IAV(51), IAV(52), IAV(53), IAV(54),
00542 IAV(55), IAV(56), IAV(57), IAV(58), IAV(59),
00543 IAV(60), IAV(61), IAV(62), IAV(63), IAV(64),
00544 IAV(65), IAV(66), IAV(67), IAV(68), IAV(69),
00545 IAV(70), IAV(71), IAV(72), IAV(73), IAV(74),
00546 IAV(75), IAV(76), IAV(77), IAV(78), IAV(79),
00547 IAV(80), IAV(81), IAV(82), IAV(83), IAV(84),
00548 IAV(85), IAV(86), IAV(87), IAV(88), IAV(89),
00549 IAV(90), IAV(91), IAV(92), IAV(93), IAV(94),
00550 IAV(95), IAV(96), IAV(97), IAV(98), IAV(99),
00551 IAV(100), IAV(101), IAV(102), IAV(103), IAV(104),
00552 IAV(105), IAV(106), IAV(107), IAV(108), IAV(109),
00553 IAV(110), IAV(111), IAV(112), IAV(113), IAV(114),
00554 IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
00555 IAV(120), IAV(121), IAV(122), IAV(123), IAV(124),
00556 IAV(125), IAV(126), IAV(127)
00557 };
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 static mchunkptr returns = 0;
00573
00574
00575
00576
00577
00578
00579 static mchunkptr last_remainder = 0;
00580
00581
00582
00583
00584
00585
00586
00587
00588 static mbinptr maxClean = PRE_FIRSTBIN;
00589 static mbinptr minClean = POST_LASTBIN;
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 #define findbin(Sizefb, Bfb) \
00612 { \
00613 unsigned long Ofb = (Sizefb) >> 3; \
00614 unsigned long Nfb = Ofb >> 6; \
00615 if (Nfb != 0) { \
00616 if (Nfb < 5) Ofb = (Ofb >> 3) + 56; \
00617 else if (Nfb < 21) Ofb = (Ofb >> 6) + 91; \
00618 else if (Nfb < 85) Ofb = (Ofb >> 9) + 110; \
00619 else if (Nfb < 341) Ofb = (Ofb >> 12) + 119; \
00620 else if (Nfb < 1365) Ofb = (Ofb >> 15) + 124; \
00621 else Ofb = 126; \
00622 } \
00623 (Bfb) = av + Ofb; \
00624 } \
00625
00626
00627
00628 #define smallfindbin(Sizefb, Bfb) (Bfb) = av + ((unsigned long)(Sizefb) >> 3)
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 #define unlink(Qul) \
00641 { \
00642 mchunkptr Bul = (Qul)->bk; \
00643 mchunkptr Ful = (Qul)->fd; \
00644 Ful->bk = Bul; Bul->fd = Ful; \
00645 } \
00646
00647
00648
00649
00650 #define dirtylink(Qdl) \
00651 { \
00652 mchunkptr Pdl = (Qdl); \
00653 mbinptr Bndl; \
00654 mchunkptr Hdl, Fdl; \
00655 clear_inuse(Pdl); \
00656 findbin(Pdl->size, Bndl); \
00657 Hdl = dirty_head(Bndl); \
00658 Fdl = Hdl->fd; \
00659 Pdl->bk = Hdl; Pdl->fd = Fdl; Fdl->bk = Hdl->fd = Pdl; \
00660 } \
00661
00662
00663
00664
00665 #define cleanlink(Qcl) \
00666 { \
00667 mchunkptr Pcl = (Qcl); \
00668 mbinptr Bcl; \
00669 mchunkptr Hcl, Fcl; \
00670 \
00671 findbin(Qcl->size, Bcl); \
00672 Hcl = clean_head(Bcl); \
00673 Fcl = Hcl->fd; \
00674 if (Hcl == Fcl) { \
00675 if (Bcl < minClean) minClean = Bcl; \
00676 if (Bcl > maxClean) maxClean = Bcl; \
00677 } \
00678 Pcl->bk = Hcl; Pcl->fd = Fcl; Fcl->bk = Hcl->fd = Pcl; \
00679 } \
00680
00681
00682 #if __STD_C
00683 static void callcleanlink(mchunkptr p)
00684 #else
00685 static void callcleanlink(p) mchunkptr p;
00686 #endif
00687 {
00688 cleanlink(p);
00689 }
00690
00691
00692
00693
00694
00695 #define consolidate(Qc) \
00696 { \
00697 for (;;) \
00698 { \
00699 mchunkptr Pc = prev_chunk(Qc); \
00700 if (!inuse(Pc)) \
00701 { \
00702 unlink(Pc); \
00703 set_size(Pc, Pc->size + (Qc)->size); \
00704 (Qc) = Pc; \
00705 } \
00706 else break; \
00707 } \
00708 for (;;) \
00709 { \
00710 mchunkptr Nc = next_chunk(Qc); \
00711 if (!inuse(Nc)) \
00712 { \
00713 unlink(Nc); \
00714 set_size((Qc), (Qc)->size + Nc->size); \
00715 } \
00716 else break; \
00717 } \
00718 } \
00719
00720
00721
00722
00723 #define returnlink(Prc) \
00724 { \
00725 (Prc)->fd = returns; \
00726 returns = (Prc); \
00727 } \
00728
00729
00730
00731
00732
00733
00734
00735 static void clear_aux_lists()
00736 {
00737 if (last_remainder != 0)
00738 {
00739 cleanlink(last_remainder);
00740 last_remainder = 0;
00741 }
00742
00743 while (returns != 0)
00744 {
00745 mchunkptr p = returns;
00746 returns = p->fd;
00747 dirtylink(p);
00748 }
00749 }
00750
00751
00752
00753
00754
00755
00756
00757 static size_t sbrked_mem = 0;
00758
00759 #if __STD_C
00760 static mchunkptr malloc_from_sys(size_t nb)
00761 #else
00762 static mchunkptr malloc_from_sys(nb) size_t nb;
00763 #endif
00764 {
00765
00766
00767 static size_t* last_sbrk_end = 0;
00768
00769 mchunkptr p;
00770 size_t* ip;
00771 char* cp;
00772 int offs;
00773
00774
00775
00776
00777
00778 size_t sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ)
00779 / SBRK_UNIT) * SBRK_UNIT;
00780
00781 cp = (char*)(sbrk(sbrk_size));
00782 if (cp == (char*)(-1))
00783 return 0;
00784 sbrked_mem += sbrk_size;
00785
00786 if (((size_t)cp) & MALLOC_ALIGN_MASK) {
00787 offs = ((size_t)cp) & MALLOC_ALIGN_MASK;
00788 cp += MALLOC_MIN_OVERHEAD - offs;
00789 sbrk_size -= MALLOC_MIN_OVERHEAD;
00790 sbrk(- offs);
00791 }
00792
00793 ip = (size_t*)cp;
00794
00795 if (last_sbrk_end != &ip[-1])
00796 {
00797
00798
00799
00800
00801
00802
00803 *ip++ = SIZE_SZ | INUSE;
00804
00805 p = (mchunkptr)ip;
00806 set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ));
00807
00808 }
00809 else
00810 {
00811 mchunkptr l;
00812
00813
00814
00815
00816
00817 p = (mchunkptr)(last_sbrk_end);
00818 set_size(p, sbrk_size);
00819
00820
00821
00822 l = prev_chunk(p);
00823 if (!inuse(l))
00824 {
00825 unlink(l);
00826 set_size(l, p->size + l->size);
00827 p = l;
00828 }
00829
00830 }
00831
00832
00833
00834 last_sbrk_end = (size_t*)((char*)p + p->size);
00835 *last_sbrk_end = SIZE_SZ | INUSE;
00836
00837 return p;
00838 }
00839
00840
00841
00842
00843
00844
00845 #if __STD_C
00846 static mchunkptr malloc_consolidate(size_t nb)
00847 #else
00848 static mchunkptr malloc_consolidate(nb) size_t nb;
00849 #endif
00850 {
00851 static mbinptr rover = LASTBIN;
00852
00853 mbinptr origin, b;
00854
00855
00856
00857
00858
00859
00860 mchunkptr victim = last_remainder;
00861 last_remainder = 0;
00862
00863 if (victim != 0)
00864 {
00865 consolidate(victim);
00866
00867 if (victim->size >= nb)
00868 return victim;
00869 else
00870 cleanlink(victim);
00871 }
00872
00873
00874
00875 origin = rover;
00876 b = rover;
00877 do
00878 {
00879 halve_bin_use(b);
00880
00881 while ( (victim = last_dirty(b)) != dirty_head(b))
00882 {
00883 unlink(victim);
00884 consolidate(victim);
00885
00886 if (victim->size >= nb)
00887 {
00888 rover = b;
00889 return victim;
00890 }
00891 else
00892 cleanlink(victim);
00893 }
00894
00895
00896 b = (b <= FIRSTBIN)? LASTBIN : b - 1;
00897
00898 } while (b != origin);
00899
00900
00901
00902
00903 return malloc_from_sys(nb);
00904 }
00905
00906
00907 #if __STD_C
00908 MM_LINK Void_t* malloc(size_t bytes)
00909 #else
00910 MM_LINK Void_t* malloc(bytes) size_t bytes;
00911 #endif
00912 {
00913 static mchunkptr bad_rl_chunk = 0;
00914 static mbinptr prevClean = FIRSTBIN;
00915
00916 mchunkptr victim;
00917 mbinptr bin;
00918
00919
00920
00921 mchunkptr rl = returns;
00922 size_t nb = request2size(bytes) ;
00923
00924 if (rl != 0)
00925 {
00926 mchunkptr snd = rl->fd;
00927 if (exact_fit(rl, nb))
00928 {
00929 returns = snd;
00930 return chunk2mem(rl);
00931 }
00932 else if (snd != 0 && exact_fit(snd, nb))
00933 {
00934 returns->fd = snd->fd;
00935 return chunk2mem(snd);
00936 }
00937 else if (rl == bad_rl_chunk)
00938 {
00939 dirtylink(rl);
00940 returns = rl = snd;
00941 }
00942 bad_rl_chunk = rl;
00943 }
00944
00945
00946
00947
00948
00949 if (nb < (MAX_SMALLBIN_SIZE - SMALLBIN_SIZE))
00950 {
00951
00952
00953
00954 smallfindbin(nb, bin);
00955
00956 if ( ((victim = last_dirty(bin)) != dirty_head(bin)) ||
00957 ((victim = last_clean(bin)) != clean_head(bin)) ||
00958 ((victim = last_dirty(bin+1)) != dirty_head(bin+1)))
00959 {
00960 unlink(victim);
00961 set_inuse(victim);
00962 return chunk2mem(victim);
00963 }
00964
00965 }
00966 else
00967 {
00968 findbin(nb, bin);
00969
00970 for (victim=last_dirty(bin); victim != dirty_head(bin); victim=victim->bk)
00971 {
00972 if (exact_fit(victim, nb))
00973 {
00974 unlink(victim);
00975 set_inuse(victim);
00976 return chunk2mem(victim);
00977 }
00978 }
00979
00980 for (victim=last_clean(bin); victim != clean_head(bin); victim=victim->bk)
00981 {
00982 if (victim->size >= nb)
00983 {
00984 unlink(victim);
00985 goto split;
00986 }
00987 }
00988 }
00989
00990
00991
00992
00993
00994 if (rl != 0)
00995 {
00996 victim = rl;
00997 rl = rl->fd;
00998 for (;;)
00999 {
01000 dirtylink(victim);
01001 if (rl == 0)
01002 {
01003 returns = rl;
01004 break;
01005 }
01006 victim = rl;
01007 rl = rl->fd;
01008 if (exact_fit(victim, nb))
01009 {
01010 bad_rl_chunk = returns = rl;
01011 return chunk2mem(victim);
01012 }
01013 }
01014 }
01015
01016 if (bin < maxClean)
01017 {
01018 mbinptr b;
01019
01020
01021
01022 if (bin < prevClean)
01023 {
01024 if ( (victim = last_clean(prevClean)) != clean_head(prevClean) )
01025 {
01026 unlink(victim);
01027 goto split;
01028 }
01029 }
01030
01031
01032
01033
01034 for (b = (bin < minClean)? minClean : (bin + 1); b <= maxClean; ++b)
01035 {
01036 if ( (victim = last_clean(b)) != clean_head(b) )
01037 {
01038
01039 if (bin_use(b) == 0 && victim->bk != clean_head(b)) prevClean = b;
01040 else { halve_bin_use(b); prevClean = FIRSTBIN; }
01041
01042 unlink(victim);
01043 if (bin < minClean) minClean = b;
01044 goto split;
01045 }
01046 }
01047
01048
01049
01050 while (maxClean >= FIRSTBIN && clean_head(maxClean)==last_clean(maxClean))
01051 --maxClean;
01052 if (maxClean < FIRSTBIN)
01053 minClean = POST_LASTBIN;
01054 else
01055 {
01056 while (minClean < maxClean && clean_head(minClean)==last_clean(minClean))
01057 ++minClean;
01058 }
01059
01060 prevClean = FIRSTBIN;
01061
01062 }
01063
01064
01065
01066
01067 if ( (victim = last_remainder) != 0)
01068 {
01069 if (victim->size >= nb)
01070 {
01071 last_remainder = 0;
01072 goto split;
01073 }
01074 }
01075
01076
01077
01078
01079 victim = malloc_consolidate(nb);
01080 if (victim == 0) return 0;
01081
01082
01083
01084
01085 split:
01086 {
01087 size_t room = victim->size - nb;
01088
01089 if (room < MINSIZE)
01090 {
01091 set_inuse(victim);
01092 return chunk2mem(victim);
01093 }
01094 else
01095 {
01096 mchunkptr remainder;
01097 int desired;
01098
01099 set_inuse_size(victim, nb);
01100 remainder = (mchunkptr)((char*)(victim) + nb);
01101
01102 desired = inc_bin_use(bin);
01103
01104
01105
01106 if (nb < MAX_SMALLBIN_SIZE && room >= nb + MINSIZE && desired != 0)
01107 {
01108 int actual = 1;
01109
01110
01111 mchunkptr first = remainder;
01112 mchunkptr last = remainder;
01113 set_inuse_size(remainder, nb);
01114 remainder = (mchunkptr)((char*)(remainder) + nb);
01115
01116 if (desired > MAX_PREALLOCS) desired = MAX_PREALLOCS;
01117
01118 while ( (room -= nb) >= nb + MINSIZE && actual < desired)
01119 {
01120 ++actual;
01121 set_inuse_size(remainder, nb);
01122 last->fd = remainder;
01123 last = remainder;
01124 remainder = (mchunkptr)((char*)(remainder) + nb);
01125 }
01126
01127 last->fd = returns;
01128 returns = first;
01129
01130 add_bin_use(bin, actual);
01131 }
01132
01133
01134
01135 set_size(remainder, room);
01136
01137
01138 if (last_remainder != 0) callcleanlink(last_remainder);
01139 last_remainder = remainder;
01140
01141 return chunk2mem(victim);
01142
01143 }
01144 }
01145 }
01146
01147
01148
01149
01150 #if __STD_C
01151 MM_LINK void free(Void_t* mem)
01152 #else
01153 MM_LINK void free(mem) Void_t* mem;
01154 #endif
01155 {
01156 if (mem != 0)
01157 {
01158 mchunkptr p = mem2chunk(mem);
01159 returnlink(p);
01160 }
01161 }
01162
01163
01164
01165
01166
01167
01168
01169 #define SCopy(SCs,SCd,SCc) \
01170 { \
01171 size_t * SCsrc = (size_t*) SCs; \
01172 size_t * SCdst = (size_t*) SCd; \
01173 size_t SCcount = (SCc - SIZE_SZ) / sizeof(size_t); \
01174 do { *SCdst++ = *SCsrc++; } while (--SCcount > 0); \
01175 }
01176
01177
01178 #if __STD_C
01179 MM_LINK Void_t* realloc(Void_t* mem, size_t bytes)
01180 #else
01181 MM_LINK Void_t* realloc(mem, bytes) Void_t* mem; size_t bytes;
01182 #endif
01183 {
01184 if (mem == 0)
01185 return malloc(bytes);
01186 else
01187 {
01188 size_t nb = request2size(bytes);
01189 mchunkptr p = mem2chunk(mem);
01190 size_t oldsize;
01191 Void_t* newmem;
01192 size_t room;
01193 int back_expanded = 0;
01194
01195 if (p == returns)
01196 returns = returns->fd;
01197
01198 clear_inuse(p);
01199 oldsize = p->size;
01200
01201
01202
01203 clear_aux_lists();
01204
01205 if (p->size < nb)
01206 {
01207 for (;;)
01208 {
01209 mchunkptr nxt = next_chunk(p);
01210 if (!inuse(nxt))
01211 {
01212 unlink(nxt);
01213 set_size(p, p->size + nxt->size);
01214 }
01215 else break;
01216 }
01217 }
01218
01219 while (p->size < nb)
01220 {
01221 mchunkptr prv = prev_chunk(p);
01222 if (!inuse(prv))
01223 {
01224 back_expanded = 1;
01225 unlink(prv);
01226 set_size(prv, prv->size + p->size);
01227 p = prv;
01228 }
01229 else break;
01230 }
01231
01232 if (p->size < nb)
01233 {
01234 mchunkptr newp;
01235
01236 set_inuse(p);
01237 newmem = malloc(nb);
01238 newp = mem2chunk(newmem);
01239
01240
01241
01242
01243
01244 if (newp == next_chunk(p))
01245 {
01246
01247 if (back_expanded)
01248 SCopy(mem, chunk2mem(p), oldsize);
01249
01250 clear_inuse(p);
01251 clear_inuse(newp);
01252 set_size(p, p->size + newp->size);
01253
01254 room = p->size - nb;
01255 if (room >= MINSIZE)
01256 {
01257 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01258 set_size(remainder, room);
01259 set_size(p, nb);
01260
01261
01262 clear_aux_lists();
01263 for (;;)
01264 {
01265 mchunkptr nxt = next_chunk(remainder);
01266 if (!inuse(nxt))
01267 {
01268 unlink(nxt);
01269 set_size(remainder, remainder->size + nxt->size);
01270 }
01271 else break;
01272 }
01273 last_remainder = remainder;
01274 }
01275
01276 set_inuse(p);
01277 return chunk2mem(p);
01278 }
01279 else
01280 {
01281 if (newmem != 0) SCopy(mem, newmem, oldsize);
01282 returnlink(p);
01283 return newmem;
01284 }
01285 }
01286 else
01287 {
01288 room = p->size - nb;
01289 newmem = chunk2mem(p);
01290
01291 if (back_expanded) SCopy(mem, newmem, oldsize);
01292
01293 if (room >= MINSIZE)
01294 {
01295 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01296 set_size(remainder, room);
01297 dirtylink(remainder);