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