00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 #define SBRK_UNIT 8192
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 #define MAX_PREALLOCS 5
00241
00242
00243
00244 #ifndef __STD_C
00245 #ifdef __STDC__
00246 #define __STD_C 1
00247 #else
00248 #if __cplusplus
00249 #define __STD_C 1
00250 #else
00251 #define __STD_C 0
00252 #endif
00253 #endif
00254 #endif
00255
00256
00257 #ifndef _BEGIN_EXTERNS_
00258 #ifdef __cplusplus
00259 #define _BEGIN_EXTERNS_ extern "C" {
00260 #define _END_EXTERNS_ }
00261 #else
00262 #define _BEGIN_EXTERNS_
00263 #define _END_EXTERNS_
00264 #endif
00265 #endif
00266
00267 #ifndef _ARG_
00268 #if __STD_C
00269 #define _ARG_(x) x
00270 #else
00271 #define _ARG_(x) ()
00272 #endif
00273 #endif
00274
00275 #ifndef Void_t
00276 #if __STD_C
00277 #define Void_t void
00278 #else
00279 #define Void_t char
00280 #endif
00281 #endif
00282
00283 #ifndef NIL
00284 #define NIL(type) ((type)0)
00285 #endif
00286
00287 #if __STD_C
00288 #include <stddef.h>
00289 #else
00290 #include <sys/types.h>
00291 #endif
00292 #include <stdio.h>
00293
00294 #include "dlmalloc.h"
00295
00296 #define DLMALLOC_PHEAP_BASE 0xc00000000
00297 #define DLMALLOC_PHEAP_SIZE (512*1024*1024)
00298
00299 #ifdef __cplusplus
00300 extern "C" {
00301 #endif
00302
00303
00304
00305 #if defined(BSD) || defined(DGUX) || defined(sun) || defined(HAVE_GETPAGESIZE)
00306 extern size_t getpagesize();
00307 # define malloc_getpagesize getpagesize()
00308 #else
00309 # include <sys/param.h>
00310 # ifdef EXEC_PAGESIZE
00311 # define malloc_getpagesize EXEC_PAGESIZE
00312 # else
00313 # ifdef NBPG
00314 # ifndef CLSIZE
00315 # define malloc_getpagesize NBPG
00316 # else
00317 # define malloc_getpagesize (NBPG * CLSIZE)
00318 # endif
00319 # else
00320 # ifdef NBPC
00321 # define malloc_getpagesize NBPC
00322 # else
00323 # define malloc_getpagesize SBRK_UNIT
00324 # endif
00325 # endif
00326 # endif
00327 #endif
00328
00329 #ifdef __cplusplus
00330 }
00331 #endif
00332
00333 #include <mnemosyne.h>
00334 #include <stdint.h>
00335 #include <stdlib.h>
00336 #include <sys/mman.h>
00337 #include <pcm.h>
00338
00339
00340
00341
00342
00343 struct malloc_chunk
00344 {
00345 uint64_t size;
00346 struct malloc_chunk* fd;
00347 struct malloc_chunk* bk;
00348
00349 };
00350
00351 typedef struct malloc_chunk* mchunkptr;
00352
00353
00354
00355 #define SIZE_SZ (sizeof(size_t))
00356 #define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ)
00357 #define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1)
00358 #define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ)
00359
00360
00361
00362
00363 #define request2size(req) \
00364 (((long)(req) <= 0) ? MINSIZE : \
00365 (((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
00366 & ~(MALLOC_ALIGN_MASK)))
00367
00368
00369
00370
00371 #define aligned_OK(m) (((size_t)((m)) & (MALLOC_ALIGN_MASK)) == 0)
00372
00373
00374
00375
00376 #define exact_fit(ptr, req) ((unsigned)((ptr)->size - (req)) < MINSIZE)
00377
00378
00379
00380 #define INUSE 0x1
00381
00382
00383 #define inuse(p) ((p)->size & INUSE)
00384 #define set_inuse(p) ((p)->size |= INUSE)
00385 #define clear_inuse(p) ((p)->size &= ~INUSE)
00386
00387
00388
00389
00390
00391
00392
00393 #define next_chunk(p)\
00394 ((mchunkptr)( ((char*)(p)) + ((p)->size & ~INUSE) ))
00395
00396
00397
00398 #define prev_chunk(p)\
00399 ((mchunkptr)( ((char*)(p)) - ( *((size_t*)((char*)(p) - SIZE_SZ)) & ~INUSE)))
00400
00401
00402
00403 #define set_size(P, Sz) \
00404 { \
00405 size_t Sss = (Sz); \
00406 (P)->size = *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
00407 } \
00408
00409
00410
00411
00412 #define chunk2mem(p) ((Void_t*)((char*)(p) + SIZE_SZ))
00413 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - SIZE_SZ))
00414
00415
00416
00417
00418
00419
00420 struct malloc_bin
00421 {
00422 struct malloc_chunk dhd;
00423 struct malloc_chunk chd;
00424 };
00425
00426 typedef struct malloc_bin* mbinptr;
00427
00428
00429
00430
00431 #define clean_head(b) (&((b)->chd))
00432 #define first_clean(b) ((b)->chd.fd)
00433 #define last_clean(b) ((b)->chd.bk)
00434
00435 #define dirty_head(b) (&((b)->dhd))
00436 #define first_dirty(b) ((b)->dhd.fd)
00437 #define last_dirty(b) ((b)->dhd.bk)
00438
00439
00440
00441
00442
00443
00444 #define NBINS 128
00445 #define LASTBIN (&(av[NBINS-1]))
00446 #define FIRSTBIN (&(av[2]))
00447
00448
00449
00450 #define MAX_SMALLBIN_OFFSET 18
00451 #define MAX_SMALLBIN_SIZE 144
00452
00453
00454 #define IAV(i)\
00455 {{ 0, &(av[i].dhd), &(av[i].dhd) }, { 0, &(av[i].chd), &(av[i].chd) }}
00456
00457 __attribute__ ((section("PERSISTENT"))) uint64_t dlmalloc_pheap = 0x0;
00458 __attribute__ ((section("PERSISTENT"))) size_t sbrk_limit = 0;
00459 __attribute__ ((section("PERSISTENT"))) int init_done = 0;
00460 __attribute__ ((section("PERSISTENT"))) struct malloc_bin *av;
00461
00462
00463 __attribute__ ((section("PERSISTENT"))) size_t* last_sbrk_end = 0;
00464 __attribute__ ((section("PERSISTENT"))) size_t sbrked_mem = 0;
00465
00466
00467
00468 __attribute__ ((section("PERSISTENT"))) mbinptr maxClean;
00469
00470
00471 TM_CALLABLE static
00472 void *
00473 persistent_sbrk(size_t size)
00474 {
00475 sbrk_limit += size;
00476 return (void *) (dlmalloc_pheap + sbrk_limit);
00477 }
00478
00479 TM_PURE static inline
00480 size_t
00481 init_bin_lists(pcm_storeset_t *set, uintptr_t av_base)
00482 {
00483 int i;
00484
00485 av = (struct malloc_bin *) av_base;
00486 for (i=0; i<NBINS; i++) {
00487 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].dhd.size, (pcm_word_t) 0);
00488 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].dhd.fd, (pcm_word_t) &(av[i].dhd));
00489 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].dhd.bk, (pcm_word_t) &(av[i].dhd));
00490 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].chd.size, (pcm_word_t) 0);
00491 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].chd.fd, (pcm_word_t) &(av[i].chd));
00492 PCM_NT_STORE(set, (volatile pcm_word_t *) &av[i].chd.bk, (pcm_word_t) &(av[i].chd));
00493 }
00494 return NBINS*sizeof(struct malloc_bin);
00495 }
00496
00497 TM_PURE static inline
00498 void
00499 init(void)
00500 {
00501 size_t av_size;
00502 pcm_storeset_t *set;
00503
00504 if (init_done) {
00505 return;
00506 }
00507
00508 set = pcm_storeset_get ();
00509
00510 if (dlmalloc_pheap == 0x0) {
00511
00512 TM_WAIVER {
00513 dlmalloc_pheap = (uint64_t) m_pmap((void *) DLMALLOC_PHEAP_BASE, DLMALLOC_PHEAP_SIZE, PROT_READ|PROT_WRITE, 0);
00514 }
00515 if ((void *) dlmalloc_pheap == (void *) -1) {
00516 TM_WAIVER {
00517 abort();
00518 }
00519 }
00520 }
00521
00522 av_size = init_bin_lists(set, dlmalloc_pheap);
00523 maxClean = FIRSTBIN;
00524
00525
00526
00527
00528 persistent_sbrk(av_size + 2*MINSIZE);
00529 last_sbrk_end = (size_t *) (av_size + dlmalloc_pheap + MINSIZE);
00530 *last_sbrk_end = SIZE_SZ | INUSE;
00531 PCM_NT_FLUSH(set);
00532 init_done = 1;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 __attribute__ ((section("PERSISTENT"))) mchunkptr returned_list = 0;
00548 __attribute__ ((section("PERSISTENT"))) mchunkptr last_remainder = 0;
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 #define findbin(Sizefb, Bfb) \
00568 { \
00569 size_t Sfb = (Sizefb); \
00570 if (Sfb < MAX_SMALLBIN_SIZE) \
00571 (Bfb) = (av + (Sfb >> 3)); \
00572 else \
00573 { \
00574 \
00575 size_t Ifb = MAX_SMALLBIN_OFFSET; \
00576 Sfb >>= 3; \
00577 \
00578 while (Sfb >= (MINSIZE * 2)) { Ifb += 4; Sfb >>= 1; } \
00579 \
00580 Ifb += (Sfb - MINSIZE) >> 2; \
00581 (Bfb) = av + Ifb; \
00582 } \
00583 } \
00584
00585
00586
00587
00588 #define reset_maxClean \
00589 { \
00590 while (maxClean > FIRSTBIN && clean_head(maxClean)==last_clean(maxClean)) \
00591 --maxClean; \
00592 } \
00593
00594
00595
00596
00597
00598
00599 #define unlink(Qul) \
00600 { \
00601 mchunkptr Bul = (Qul)->bk; \
00602 mchunkptr Ful = (Qul)->fd; \
00603 Ful->bk = Bul; Bul->fd = Ful; \
00604 } \
00605
00606
00607
00608
00609 #define dirtylink(Qdl) \
00610 { \
00611 mchunkptr Pdl = (Qdl); \
00612 mbinptr Bndl; \
00613 mchunkptr Hdl, Fdl; \
00614 \
00615 findbin(Pdl->size, Bndl); \
00616 Hdl = dirty_head(Bndl); \
00617 Fdl = Hdl->fd; \
00618 \
00619 Pdl->bk = Hdl; Pdl->fd = Fdl; Fdl->bk = Hdl->fd = Pdl; \
00620 } \
00621
00622
00623
00624
00625
00626 #define cleanlink(Qcl) \
00627 { \
00628 mchunkptr Pcl = (Qcl); \
00629 mbinptr Bcl; \
00630 mchunkptr Hcl, Fcl; \
00631 \
00632 findbin(Qcl->size, Bcl); \
00633 Hcl = clean_head(Bcl); \
00634 Fcl = Hcl->fd; \
00635 if (Hcl == Fcl && Bcl > maxClean) maxClean = Bcl; \
00636 \
00637 Pcl->bk = Hcl; Pcl->fd = Fcl; Fcl->bk = Hcl->fd = Pcl; \
00638 } \
00639
00640
00641
00642
00643
00644 #define consolidate(Qc) \
00645 { \
00646 for (;;) \
00647 { \
00648 mchunkptr Pc = prev_chunk(Qc); \
00649 if (!inuse(Pc)) \
00650 { \
00651 unlink(Pc); \
00652 set_size(Pc, Pc->size + (Qc)->size); \
00653 (Qc) = Pc; \
00654 } \
00655 else break; \
00656 } \
00657 for (;;) \
00658 { \
00659 mchunkptr Nc = next_chunk(Qc); \
00660 if (!inuse(Nc)) \
00661 { \
00662 unlink(Nc); \
00663 set_size((Qc), (Qc)->size + Nc->size); \
00664 } \
00665 else break; \
00666 } \
00667 } \
00668
00669
00670
00671
00672
00673
00674 #define clear_last_remainder \
00675 { \
00676 if (last_remainder != 0) \
00677 { \
00678 cleanlink(last_remainder); \
00679 last_remainder = 0; \
00680 } \
00681 } \
00682
00683
00684
00685
00686 #define return_chunk(Prc) \
00687 { \
00688 (Prc)->fd = returned_list; \
00689 returned_list = (Prc); \
00690 } \
00691
00692
00693
00694
00695
00696
00697 TM_CALLABLE static void free_returned_list()
00698 {
00699 clear_last_remainder;
00700 while (returned_list != 0)
00701 {
00702 mchunkptr p = returned_list;
00703 returned_list = p->fd;
00704 clear_inuse(p);
00705 dirtylink(p);
00706 }
00707 }
00708
00709
00710
00711
00712 TM_PURE static size_t gcd(size_t a, size_t b)
00713 {
00714 size_t tmp;
00715
00716 if (b > a)
00717 {
00718 tmp = a; a = b; b = tmp;
00719 }
00720 for(;;)
00721 {
00722 if (b == 0)
00723 return a;
00724 else if (b == 1)
00725 return b;
00726 else
00727 {
00728 tmp = b;
00729 b = a % b;
00730 a = tmp;
00731 }
00732 }
00733 }
00734
00735 TM_PURE static size_t lcm(size_t x, size_t y)
00736 {
00737 return x / gcd(x, y) * y;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747 TM_CALLABLE static mchunkptr malloc_from_sys(size_t nb)
00748 {
00749 mchunkptr p;
00750 size_t* ip;
00751 char* cp;
00752
00753
00754
00755
00756
00757 size_t sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ)
00758 / SBRK_UNIT) * SBRK_UNIT;
00759
00760 cp = (char*)(persistent_sbrk(sbrk_size));
00761 if (cp == (char*)(-1))
00762 return 0;
00763
00764 ip = (size_t*)cp;
00765
00766 sbrked_mem += sbrk_size;
00767
00768 if (last_sbrk_end != &ip[-1])
00769 {
00770
00771
00772
00773
00774 while (!aligned_OK(ip)) { ++ip; sbrk_size -= SIZE_SZ; }
00775
00776
00777
00778
00779 *ip++ = SIZE_SZ | INUSE;
00780
00781 p = (mchunkptr)ip;
00782 set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ));
00783
00784 }
00785 else
00786 {
00787 mchunkptr l;
00788
00789
00790
00791
00792
00793 p = (mchunkptr)(last_sbrk_end);
00794 set_size(p, sbrk_size);
00795
00796
00797
00798 l = prev_chunk(p);
00799 if (!inuse(l))
00800 {
00801 unlink(l);
00802 set_size(l, p->size + l->size);
00803 p = l;
00804 }
00805
00806 }
00807
00808
00809
00810 last_sbrk_end = (size_t*)((char*)p + p->size);
00811 *last_sbrk_end = SIZE_SZ | INUSE;
00812
00813 return p;
00814 }
00815
00816
00817
00818
00819
00820
00821 TM_CALLABLE static mchunkptr malloc_find_space(size_t nb)
00822 {
00823
00824 static int rover_init = 0;
00825 static mbinptr rover;
00826
00827 if (rover_init == 0) {
00828 rover = LASTBIN;
00829 rover_init = 1;
00830 }
00831 mbinptr origin = rover;
00832 mbinptr b = rover;
00833
00834
00835 clear_last_remainder;
00836 reset_maxClean;
00837
00838 do
00839 {
00840 mchunkptr p;
00841
00842 while ( (p = last_dirty(b)) != dirty_head(b))
00843 {
00844 unlink(p);
00845 consolidate(p);
00846
00847 if (p->size >= nb)
00848 {
00849 rover = b;
00850 return p;
00851 }
00852 else
00853 cleanlink(p);
00854 }
00855
00856 b = (b == FIRSTBIN)? LASTBIN : b - 1;
00857
00858 } while (b != origin);
00859
00860
00861 return malloc_from_sys(nb);
00862 }
00863
00864
00865
00866
00867
00868 TM_CALLABLE static void malloc_clean_bin(mbinptr bin)
00869 {
00870 mchunkptr p;
00871
00872 clear_last_remainder;
00873
00874 while ( (p = last_dirty(bin)) != dirty_head(bin))
00875 {
00876 unlink(p);
00877 consolidate(p);
00878 cleanlink(p);
00879 }
00880
00881 while (returned_list != 0)
00882 {
00883 p = returned_list;
00884 returned_list = p->fd;
00885 clear_inuse(p);
00886 consolidate(p);
00887 cleanlink(p);
00888 }
00889 }
00890
00891
00892
00893
00894 TM_CALLABLE Void_t* PDL_MALLOC(size_t bytes)
00895 {
00896 static size_t previous_request = 0;
00897
00898 size_t nb = request2size(bytes);
00899 mbinptr bin;
00900 mchunkptr victim;
00901
00902 init();
00903
00904
00905 if ((victim = returned_list) != 0 &&
00906 exact_fit(victim, nb))
00907 {
00908 returned_list = victim->fd;
00909 return chunk2mem(victim);
00910 }
00911
00912 findbin(nb, bin);
00913
00914
00915
00916
00917
00918
00919
00920 if (nb < MAX_SMALLBIN_SIZE)
00921 {
00922 if ( ((victim = first_dirty(bin)) != dirty_head(bin)) ||
00923 ((victim = last_clean(bin)) != clean_head(bin)))
00924 {
00925 unlink(victim);
00926 set_inuse(victim);
00927 return chunk2mem(victim);
00928 }
00929 }
00930 else
00931 {
00932 if ( (victim = first_dirty(bin)) != dirty_head(bin))
00933 {
00934 do
00935 {
00936 if (exact_fit(victim, nb))
00937 {
00938 unlink(victim);
00939 set_inuse(victim);
00940 return chunk2mem(victim);
00941 }
00942 else victim = victim->fd;
00943 } while (victim != dirty_head(bin));
00944
00945
00946
00947
00948
00949 malloc_clean_bin(bin);
00950 }
00951 }
00952
00953
00954
00955 if ( (victim = returned_list) != 0)
00956 {
00957 do
00958 {
00959 mchunkptr next = victim->fd;
00960 if (exact_fit(victim, nb))
00961 {
00962 returned_list = next;
00963 return chunk2mem(victim);
00964 }
00965 else
00966 {
00967 clear_inuse(victim);
00968 dirtylink(victim);
00969 victim = next;
00970 }
00971 } while (victim != 0);
00972 returned_list = 0;
00973 }
00974
00975
00976
00977 if ( (victim = last_remainder) != 0 && victim->size >= nb)
00978 {
00979 last_remainder = 0;
00980 goto split;
00981 }
00982
00983
00984
00985
00986
00987
00988 for (victim = last_clean(bin); victim != clean_head(bin); victim=victim->bk)
00989 {
00990 if (victim->size >= nb)
00991 {
00992 unlink(victim);
00993 goto split;
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 {
01004 mbinptr b;
01005
01006 for (b = bin + 1; b <= maxClean; ++b)
01007 {
01008 if ( (victim = last_clean(b)) != clean_head(b) )
01009 {
01010 unlink(victim);
01011 goto split;
01012 }
01013 }
01014 }
01015
01016
01017
01018 victim = malloc_find_space(nb);
01019
01020 if (victim == 0)
01021 return 0;
01022
01023
01024
01025 split:
01026 {
01027 size_t room = victim->size - nb;
01028 if (room >= MINSIZE)
01029 {
01030 mchunkptr v = victim;
01031
01032 set_size(victim, nb);
01033
01034
01035
01036
01037
01038
01039 if (previous_request == nb)
01040 {
01041 int i;
01042
01043 for (i = 0; i < MAX_PREALLOCS && room >= nb + MINSIZE; ++i)
01044 {
01045 room -= nb;
01046
01047 v = (mchunkptr)((char*)(v) + nb);
01048 set_size(v, nb);
01049 set_inuse(v);
01050 return_chunk(v);
01051 }
01052 }
01053
01054 previous_request = nb;
01055
01056
01057
01058
01059 if (last_remainder != 0) cleanlink(last_remainder);
01060
01061 last_remainder = (mchunkptr)((char*)(v) + nb);
01062 set_size(last_remainder, room);
01063 }
01064
01065 set_inuse(victim);
01066 return chunk2mem(victim);
01067 }
01068 }
01069
01070
01071 TM_CALLABLE void PDL_FREE(Void_t* mem)
01072 {
01073 if (mem != 0)
01074 {
01075 mchunkptr p = mem2chunk(mem);
01076 return_chunk(p);
01077 }
01078 }
01079
01080
01081 TM_CALLABLE Void_t* PDL_REALLOC(Void_t* mem, size_t bytes)
01082 {
01083 if (mem == 0) {
01084 return PDL_MALLOC(bytes);
01085 }
01086 else
01087 {
01088 size_t nb = request2size(bytes);
01089 mchunkptr p = mem2chunk(mem);
01090 size_t oldsize;
01091 long room;
01092 mchunkptr nxt;
01093
01094 if (p == returned_list)
01095 returned_list = returned_list->fd;
01096
01097 clear_inuse(p);
01098 oldsize = p->size;
01099
01100
01101
01102 free_returned_list();
01103
01104 while (!inuse(nxt = next_chunk(p)))
01105 {
01106 unlink(nxt);
01107 set_size(p, p->size + nxt->size);
01108 }
01109
01110 room = p->size - nb;
01111 if (room >= 0)
01112 {
01113 if (room >= MINSIZE)
01114 {
01115 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01116 set_size(remainder, room);
01117 cleanlink(remainder);
01118 set_size(p, nb);
01119 }
01120 set_inuse(p);
01121 return chunk2mem(p);
01122 }
01123 else
01124 {
01125 Void_t* newmem;
01126 size_t count;
01127 size_t* src;
01128 size_t* dst;
01129
01130 set_inuse(p);
01131 newmem = PDL_MALLOC(nb);
01132
01133 if (newmem != 0) {
01134
01135 src = (size_t*) mem;
01136 dst = (size_t*) newmem;
01137 count = (oldsize - SIZE_SZ) / sizeof(size_t);
01138 while (count-- > 0) *dst++ = *src++;
01139 }
01140
01141 PDL_FREE(mem);
01142 return newmem;
01143 }
01144 }
01145 }
01146
01147
01148
01149
01150
01151 TM_CALLABLE Void_t* PDL_MEMALIGN(size_t alignment, size_t bytes)
01152 {
01153 mchunkptr p;
01154 size_t nb = request2size(bytes);
01155 size_t room;
01156
01157
01158
01159 size_t align = lcm(alignment, MALLOC_MIN_OVERHEAD);
01160
01161
01162
01163
01164 size_t req = nb + align + MINSIZE;
01165 Void_t* m = PDL_MALLOC(req);
01166
01167 if (m == 0) return 0;
01168
01169 p = mem2chunk(m);
01170 clear_inuse(p);
01171
01172
01173 if (((size_t)(m) % align) != 0)
01174 {
01175
01176
01177
01178 mchunkptr ap = (mchunkptr)((((size_t)(m) + align-1) & -align) - SIZE_SZ);
01179
01180 size_t gap = (size_t)(ap) - (size_t)(p);
01181
01182
01183
01184 if (gap < MINSIZE)
01185 {
01186
01187
01188
01189 ap = (mchunkptr)( (size_t)(ap) + align );
01190 gap += align;
01191 }
01192
01193 room = p->size - gap;
01194
01195
01196 set_size(p, gap);
01197 dirtylink(p);
01198
01199
01200 p = ap;
01201 set_size(p, room);
01202 }
01203
01204
01205
01206 room = p->size - nb;
01207 if (room >= MINSIZE)
01208 {
01209 mchunkptr remainder = (mchunkptr)((char*)(p) + nb);
01210 set_size(remainder, room);
01211 dirtylink(remainder);
01212 set_size(p, nb);
01213 }
01214
01215 set_inuse(p);
01216 return chunk2mem(p);
01217
01218 }
01219
01220
01221
01222
01223 TM_CALLABLE Void_t* PDL_VALLOC(size_t bytes)
01224 {
01225
01226 static size_t malloc_pagesize = 0;
01227
01228 if (malloc_pagesize == 0) malloc_pagesize = malloc_getpagesize;
01229 return PDL_MEMALIGN (malloc_pagesize, bytes);
01230 }
01231
01232
01233 TM_CALLABLE Void_t* PDL_CALLOC(size_t n, size_t elem_size)
01234 {
01235 size_t sz = n * elem_size;
01236 Void_t* p = PDL_MALLOC(sz);
01237 char* q = (char*) p;
01238 while (sz-- > 0) *q++ = 0;
01239 return p;
01240 }
01241
01242 TM_CALLABLE void PDL_CFREE(Void_t *mem)
01243 {
01244 PDL_FREE(mem);
01245 }
01246
01247 TM_CALLABLE size_t PDL_GET_USABLE_SIZE(Void_t* mem)
01248 {
01249 if (mem == 0)
01250 return 0;
01251 else
01252 {
01253 mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ);
01254 size_t sz = p->size & ~(INUSE);
01255
01256 if (p->size == sz || sz != *((size_t*)((char*)(p) + sz - SIZE_SZ)))
01257 return 0;
01258 else
01259 return sz - MALLOC_MIN_OVERHEAD;
01260 }
01261 }
01262
01263 TM_CALLABLE void PDL_MALLOC_STATS()
01264 {
01265
01266
01267
01268 size_t avail = 0;
01269 size_t malloced_mem;
01270
01271 mbinptr b;
01272
01273 free_returned_list();
01274
01275 for (b = FIRSTBIN; b <= LASTBIN; ++b)
01276 {
01277 mchunkptr p;
01278
01279 for (p = first_dirty(b); p != dirty_head(b); p = p->fd)
01280 avail += p->size;
01281
01282 for (p = first_clean(b); p != clean_head(b); p = p->fd)
01283 avail += p->size;
01284 }
01285
01286 malloced_mem = sbrked_mem - avail;
01287
01288 TM_WAIVER {
01289 fprintf(stderr, "total mem = %10u\n", (unsigned int) sbrked_mem);
01290 fprintf(stderr, "in use = %10u\n", (unsigned int) malloced_mem);
01291 }
01292
01293 }