Changeset 19e5d65d


Ignore:
Timestamp:
Apr 24, 2022, 10:47:18 AM (19 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
Children:
3229b4f
Parents:
58e97d9
Message:

second update of heap allocator towards new heap-per-thread version

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/heap.cfa

    r58e97d9 r19e5d65d  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 22 18:25:23 2022
    13 // Update Count     : 1121
     12// Last Modified On : Sun Apr 24 09:58:01 2022
     13// Update Count     : 1146
    1414//
    1515
     
    240240static_assert( NoBucketSizes == sizeof(bucketSizes) / sizeof(bucketSizes[0] ), "size of bucket array wrong" );
    241241
    242 
    243242// The constructor for heapManager is called explicitly in memory_startup.
    244243static Heap heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
     244
     245
     246//####################### Memory Allocation Routines Helpers ####################
    245247
    246248
     
    327329
    328330// Use "write" because streams may be shutdown when calls are made.
    329 static void printStats() {                                                              // see malloc_stats
     331static int printStats() {                                                               // see malloc_stats
    330332        char helpText[sizeof(prtFmt) + 1024];                           // space for message and values
    331         __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), prtFmt,
     333        return __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), prtFmt,
    332334                        stats.malloc_calls, stats.malloc_0_calls, stats.malloc_storage_request, stats.malloc_storage_alloc,
    333335                        stats.aalloc_calls, stats.aalloc_0_calls, stats.aalloc_storage_request, stats.aalloc_storage_alloc,
     
    417419// <-----------------<------------+-----------------------------> bsize (bucket size)
    418420//                   |fake-header | addr
    419 #define headerAddr( addr ) ((Heap.Storage.Header *)( (char *)addr - sizeof(Heap.Storage) ))
    420 #define realHeader( header ) ((Heap.Storage.Header *)((char *)header - header->kind.fake.offset))
     421#define HeaderAddr( addr ) ((Heap.Storage.Header *)( (char *)addr - sizeof(Heap.Storage) ))
     422#define RealHeader( header ) ((Heap.Storage.Header *)((char *)header - header->kind.fake.offset))
    421423
    422424// <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
     
    426428// <------------------------------<<---------- dsize --------->>> bsize (bucket size)
    427429//                   |fake-header |addr
    428 #define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
     430#define DataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
    429431
    430432
    431433static inline void checkAlign( size_t alignment ) {
    432         if ( alignment < libAlign() || ! is_pow2( alignment ) ) {
    433                 abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
     434        if ( unlikely( alignment < libAlign() || ! is_pow2( alignment ) ) ) {
     435                abort( "**** Error **** alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
    434436        } // if
    435437} // checkAlign
     
    438440static inline void checkHeader( bool check, const char name[], void * addr ) {
    439441        if ( unlikely( check ) ) {                                                      // bad address ?
    440                 abort( "Attempt to %s storage %p with address outside the heap.\n"
     442                abort( "**** Error **** attempt to %s storage %p with address outside the heap.\n"
    441443                           "Possible cause is duplicate free on same block or overwriting of memory.",
    442444                           name, addr );
     
    445447
    446448
     449// Manipulate sticky bits stored in unused 3 low-order bits of an address.
     450//   bit0 => alignment => fake header
     451//   bit1 => zero filled (calloc)
     452//   bit2 => mapped allocation versus sbrk
     453#define StickyBits( header ) (((header)->kind.real.blockSize & 0x7))
     454#define ClearStickyBits( addr ) (typeof(addr))((uintptr_t)(addr) & ~7)
     455#define MarkAlignmentBit( align ) ((align) | 1)
     456#define AlignmentBit( header ) ((((header)->kind.fake.alignment) & 1))
     457#define ClearAlignmentBit( header ) (((header)->kind.fake.alignment) & ~1)
     458#define ZeroFillBit( header ) ((((header)->kind.real.blockSize) & 2))
     459#define ClearZeroFillBit( header ) ((((header)->kind.real.blockSize) &= ~2))
     460#define MarkZeroFilledBit( header ) ((header)->kind.real.blockSize |= 2)
     461#define MmappedBit( header ) ((((header)->kind.real.blockSize) & 4))
     462#define MarkMmappedBit( size ) ((size) | 4)
     463
     464
    447465static inline void fakeHeader( Heap.Storage.Header *& header, size_t & alignment ) {
    448         if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    449                 alignment = header->kind.fake.alignment & -2;   // remove flag from value
     466        if ( unlikely( AlignmentBit( header ) ) ) {                     // fake header ?
     467                alignment = ClearAlignmentBit( header );                // clear flag from value
    450468                #ifdef __CFA_DEBUG__
    451469                checkAlign( alignment );                                                // check alignment
    452470                #endif // __CFA_DEBUG__
    453                 header = realHeader( header );                                  // backup from fake to real header
     471                header = RealHeader( header );                                  // backup from fake to real header
    454472        } else {
    455473                alignment = libAlign();                                                 // => no fake header
     
    458476
    459477
    460 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, Heap.Storage.Header *& header, Heap.FreeHeader *& freeElem,
    461                                                         size_t & size, size_t & alignment ) with( heapManager ) {
    462         header = headerAddr( addr );
    463 
    464   if ( unlikely( addr < heapBegin || heapEnd < addr ) ) { // mmapped ?
    465                 fakeHeader( header, alignment );
    466                 size = header->kind.real.blockSize & -3;                // mmap size
    467                 return true;
    468         } // if
     478static inline bool headers( const char name[] __attribute__(( unused )), void * addr, Heap.Storage.Header *& header,
     479                                                        Heap.FreeHeader *& freeHead, size_t & size, size_t & alignment ) with( heapManager ) {
     480        header = HeaderAddr( addr );
    469481
    470482        #ifdef __CFA_DEBUG__
     
    472484        #endif // __CFA_DEBUG__
    473485
    474         // header may be safe to dereference
    475         fakeHeader( header, alignment );
     486        if ( likely( ! StickyBits( header ) ) ) {                       // no sticky bits ?
     487                freeHead = (Heap.FreeHeader *)(header->kind.real.home);
     488                alignment = libAlign();
     489        } else {
     490                fakeHeader( header, alignment );
     491                if ( unlikely( MmappedBit( header ) ) ) {
     492                        assert( addr < heapBegin || heapEnd < addr );
     493                        size = ClearStickyBits( header->kind.real.blockSize ); // mmap size
     494                        return true;
     495                } // if
     496
     497                freeHead = (Heap.FreeHeader *)(ClearStickyBits( header->kind.real.home ));
     498        } // if
     499        size = freeHead->blockSize;
     500
    476501        #ifdef __CFA_DEBUG__
    477502        checkHeader( header < (Heap.Storage.Header *)heapBegin || (Heap.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     503
     504        if ( freeHead < &freeLists[0] || &freeLists[NoBucketSizes] <= freeHead ) {
     505                abort( "Attempt to %s storage %p with corrupted header.\n"
     506                           "Possible cause is duplicate free on same block or overwriting of header information.",
     507                           name, addr );
     508        } // if
    478509        #endif // __CFA_DEBUG__
    479510
    480         freeElem = (Heap.FreeHeader *)((size_t)header->kind.real.home & -3);
    481         #ifdef __CFA_DEBUG__
    482         if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
    483                 abort( "Attempt to %s storage %p with corrupted header.\n"
    484                            "Possible cause is duplicate free on same block or overwriting of header information.",
    485                            name, addr );
    486         } // if
    487         #endif // __CFA_DEBUG__
    488         size = freeElem->blockSize;
    489511        return false;
    490512} // headers
     
    513535static inline void * extend( size_t size ) with( heapManager ) {
    514536        lock( extlock __cfaabi_dbg_ctx2 );
     537
    515538        ptrdiff_t rem = heapRemaining - size;
    516         if ( rem < 0 ) {
     539        if ( unlikely( rem < 0 ) ) {
    517540                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    518541
    519                 size_t increase = ceiling2( size > heapExpand ? size : heapExpand, __page_size );
     542                size_t increase = ceiling2( size > heapExpand ? size : heapExpand, libAlign() );
    520543                // Do not call abort or strerror( errno ) as they may call malloc.
    521544                if ( sbrk( increase ) == (void *)-1 ) {                 // failed, no memory ?
     
    524547                        _exit( EXIT_FAILURE );                                          // give up
    525548                } // if
     549
    526550                // Make storage executable for thunks.
    527                 if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) {
    528                         unlock( extlock );
    529                         __cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno );
    530                         _exit( EXIT_FAILURE );
    531                 } // if
     551                // if ( mprotect( (char *)heapEnd + heapRemaining, increase, __map_prot ) ) {
     552                //      unlock( extlock );
     553                //      __cfaabi_bits_print_nolock( STDERR_FILENO, "extend() : internal error, mprotect failure, heapEnd:%p size:%zd, errno:%d.\n", heapEnd, increase, errno );
     554                //      _exit( EXIT_FAILURE );
     555                // } // if
     556
    532557                #ifdef __STATISTICS__
    533558                sbrk_calls += 1;
     
    555580        // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
    556581        // along with the block and is a multiple of the alignment size.
    557 
    558   if ( unlikely( size > ULONG_MAX - sizeof(Heap.Storage) ) ) return 0p;
    559582        size_t tsize = size + sizeof(Heap.Storage);
     583
    560584        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
    561585                size_t posn;
     
    615639                //Memset( block, tsize );
    616640                #endif // __CFA_DEBUG__
    617                 block->header.kind.real.blockSize = tsize;              // storage size for munmap
     641                block->header.kind.real.blockSize = MarkMmappedBit( tsize ); // storage size for munmap
    618642        } // if
    619643
     
    825849
    826850        // address of header from malloc
    827         Heap.Storage.Header * realHeader = headerAddr( addr );
    828         realHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
     851        Heap.Storage.Header * RealHeader = HeaderAddr( addr );
     852        RealHeader->kind.real.size = size;                                      // correct size to eliminate above alignment offset
    829853        // address of fake header * before* the alignment location
    830         Heap.Storage.Header * fakeHeader = headerAddr( user );
     854        Heap.Storage.Header * fakeHeader = HeaderAddr( user );
    831855        // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
    832         fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
     856        fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)RealHeader;
    833857        // SKULLDUGGERY: odd alignment imples fake header
    834         fakeHeader->kind.fake.alignment = alignment | 1;
     858        fakeHeader->kind.fake.alignment = MarkAlignmentBit( alignment );
    835859
    836860        return user;
    837861} // memalignNoStats
     862
     863
     864//####################### Memory Allocation Routines ####################
    838865
    839866
     
    904931                        memset( addr, '\0', size );                                     // set to zeros
    905932
    906                 header->kind.real.blockSize |= 2;                               // mark as zero filled
     933                MarkZeroFilledBit( header );                                    // mark as zero fill
    907934                return addr;
    908935        } // calloc
     
    938965                headers( "resize", oaddr, header, freeElem, bsize, oalign );
    939966
    940                 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     967                size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
    941968                // same size, DO NOT preserve STICKY PROPERTIES.
    942969                if ( oalign == libAlign() && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
    943                         header->kind.real.blockSize &= -2;                      // no alignment and turn off 0 fill
     970                        ClearZeroFillBit( header );                                     // no alignment and turn off 0 fill
    944971                        header->kind.real.size = size;                          // reset allocation size
    945972                        return oaddr;
     
    9831010                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    9841011
    985                 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1012                size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
    9861013                size_t osize = header->kind.real.size;                  // old allocation size
    987                 bool ozfill = (header->kind.real.blockSize & 2); // old allocation zero filled
     1014                bool ozfill = ZeroFillBit( header );                    // old allocation zero filled
    9881015          if ( unlikely( size <= odsize ) && odsize <= size * 2 ) { // allow up to 50% wasted storage
    9891016                        header->kind.real.size = size;                          // reset allocation size
     
    10121039
    10131040                if ( unlikely( ozfill ) ) {                                             // previous request zero fill ?
    1014                         header->kind.real.blockSize |= 2;                       // mark new request as zero filled
     1041                        MarkZeroFilledBit( header );                            // mark new request as zero filled
    10151042                        if ( size > osize ) {                                           // previous request larger ?
    10161043                                memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage
     
    10191046                return naddr;
    10201047        } // realloc
     1048
     1049
     1050        // Same as realloc() except the new allocation size is large enough for an array of nelem elements of size elsize.
     1051        void * reallocarray( void * oaddr, size_t dim, size_t elemSize ) {
     1052                return realloc( oaddr, dim * elemSize );
     1053        } // reallocarray
    10211054
    10221055
     
    10851118                        memset( addr, '\0', size );                                     // set to zeros
    10861119
    1087                 header->kind.real.blockSize |= 2;                               // mark as zero filled
     1120                MarkZeroFilledBit( header );                                    // mark as zero filled
    10881121                return addr;
    10891122        } // cmemalign
     
    10911124
    10921125        // Same as memalign(), but ISO/IEC 2011 C11 Section 7.22.2 states: the value of size shall be an integral multiple
    1093     // of alignment. This requirement is universally ignored.
     1126        // of alignment. This requirement is universally ignored.
    10941127        void * aligned_alloc( size_t alignment, size_t size ) {
    10951128                return memalign( alignment, size );
     
    11021135        // free(3).
    11031136        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    1104           if ( alignment < libAlign() || ! is_pow2( alignment ) ) return EINVAL; // check alignment
    1105                 * memptr = memalign( alignment, size );
     1137                if ( unlikely( alignment < libAlign() || ! is_pow2( alignment ) ) ) return EINVAL; // check alignment
     1138                *memptr = memalign( alignment, size );
    11061139                return 0;
    11071140        } // posix_memalign
     
    11171150        // Same as valloc but rounds size to multiple of page size.
    11181151        void * pvalloc( size_t size ) {
    1119                 return memalign( __page_size, ceiling2( size, __page_size ) );
     1152                return memalign( __page_size, ceiling2( size, __page_size ) ); // round size to multiple of page size
    11201153        } // pvalloc
    11211154
     
    11471180        size_t malloc_alignment( void * addr ) {
    11481181          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    1149                 Heap.Storage.Header * header = headerAddr( addr );
    1150                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1151                         return header->kind.fake.alignment & -2;        // remove flag from value
     1182                Heap.Storage.Header * header = HeaderAddr( addr );
     1183                if ( unlikely( AlignmentBit( header ) ) ) {             // fake header ?
     1184                        return ClearAlignmentBit( header );                     // clear flag from value
    11521185                } else {
    11531186                        return libAlign();                                                      // minimum alignment
     
    11571190
    11581191        // Set the alignment for an the allocation and return previous alignment or 0 if no alignment.
    1159         size_t malloc_alignment_set$( void * addr, size_t alignment ) {
    1160           if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    1161                 size_t ret;
    1162                 Heap.Storage.Header * header = headerAddr( addr );
    1163                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1164                         ret = header->kind.fake.alignment & -2;         // remove flag from old value
    1165                         header->kind.fake.alignment = alignment | 1; // add flag to new value
    1166                 } else {
    1167                         ret = 0;                                                                        // => no alignment to change
    1168                 } // if
    1169                 return ret;
    1170         } // malloc_alignment_set$
     1192        // size_t malloc_alignment_set$( void * addr, size_t alignment ) {
     1193        //   if ( unlikely( addr == 0p ) ) return libAlign();   // minimum alignment
     1194        //      size_t ret;
     1195        //      Heap.Storage.Header * header = HeaderAddr( addr );
     1196        //      if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     1197        //              ret = header->kind.fake.alignment & -2;         // remove flag from old value
     1198        //              header->kind.fake.alignment = alignment | 1; // add flag to new value
     1199        //      } else {
     1200        //              ret = 0;                                                                        // => no alignment to change
     1201        //      } // if
     1202        //      return ret;
     1203        // } // malloc_alignment_set$
    11711204
    11721205
     
    11741207        bool malloc_zero_fill( void * addr ) {
    11751208          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    1176                 Heap.Storage.Header * header = headerAddr( addr );
    1177                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1178                         header = realHeader( header );                          // backup from fake to real header
    1179                 } // if
    1180                 return (header->kind.real.blockSize & 2) != 0;  // zero filled ?
     1209                Heap.Storage.Header * header = HeaderAddr( addr );
     1210                if ( unlikely( AlignmentBit( header ) ) ) {             // fake header ?
     1211                        header = RealHeader( header );                          // backup from fake to real header
     1212                } // if
     1213                return ZeroFillBit( header );                                   // zero filled ?
    11811214        } // malloc_zero_fill
    11821215
    11831216        // Set allocation is zero filled and return previous zero filled.
    1184         bool malloc_zero_fill_set$( void * addr ) {
    1185           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    1186                 Heap.Storage.Header * header = headerAddr( addr );
    1187                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1188                         header = realHeader( header );                          // backup from fake to real header
    1189                 } // if
    1190                 bool ret = (header->kind.real.blockSize & 2) != 0; // zero filled ?
    1191                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    1192                 return ret;
    1193         } // malloc_zero_fill_set$
    1194 
    1195 
    1196         // Returns original total allocation size (not bucket size) => array size is dimension * sizeif(T).
     1217        // bool malloc_zero_fill_set$( void * addr ) {
     1218        //   if ( unlikely( addr == 0p ) ) return false;                // null allocation is not zero fill
     1219        //      Heap.Storage.Header * header = HeaderAddr( addr );
     1220        //      if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     1221        //              header = RealHeader( header );                          // backup from fake to real header
     1222        //      } // if
     1223        //      bool ret = (header->kind.real.blockSize & 2) != 0; // zero filled ?
     1224        //      header->kind.real.blockSize |= 2;                               // mark as zero filled
     1225        //      return ret;
     1226        // } // malloc_zero_fill_set$
     1227
     1228
     1229        // Returns original total allocation size (not bucket size) => array size is dimension * sizeof(T).
    11971230        size_t malloc_size( void * addr ) {
    11981231          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    1199                 Heap.Storage.Header * header = headerAddr( addr );
    1200                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1201                         header = realHeader( header );                          // backup from fake to real header
     1232                Heap.Storage.Header * header = HeaderAddr( addr );
     1233                if ( unlikely( AlignmentBit( header ) ) ) {             // fake header ?
     1234                        header = RealHeader( header );                          // backup from fake to real header
    12021235                } // if
    12031236                return header->kind.real.size;
     
    12051238
    12061239        // Set allocation size and return previous size.
    1207         size_t malloc_size_set$( void * addr, size_t size ) {
    1208           if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    1209                 Heap.Storage.Header * header = headerAddr( addr );
    1210                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1211                         header = realHeader( header );                          // backup from fake to real header
    1212                 } // if
    1213                 size_t ret = header->kind.real.size;
    1214                 header->kind.real.size = size;
    1215                 return ret;
    1216         } // malloc_size_set$
     1240        // size_t malloc_size_set$( void * addr, size_t size ) {
     1241        //   if ( unlikely( addr == 0p ) ) return 0;                    // null allocation has 0 size
     1242        //      Heap.Storage.Header * header = HeaderAddr( addr );
     1243        //      if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     1244        //              header = RealHeader( header );                          // backup from fake to real header
     1245        //      } // if
     1246        //      size_t ret = header->kind.real.size;
     1247        //      header->kind.real.size = size;
     1248        //      return ret;
     1249        // } // malloc_size_set$
    12171250
    12181251
     
    12261259
    12271260                headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
    1228                 return dataStorage( bsize, addr, header );              // data storage in bucket
     1261                return DataStorage( bsize, addr, header );              // data storage in bucket
    12291262        } // malloc_usable_size
    12301263
     
    12391272
    12401273
    1241         // Changes the file descripter where malloc_stats() writes statistics.
     1274        // Changes the file descriptor where malloc_stats() writes statistics.
    12421275        int malloc_stats_fd( int fd __attribute__(( unused )) ) {
    12431276                #ifdef __STATISTICS__
     
    12461279                return temp;
    12471280                #else
    1248                 return -1;
     1281                return -1;                                                                              // unsupported
    12491282                #endif // __STATISTICS__
    12501283        } // malloc_stats_fd
     1284
     1285
     1286        // Prints an XML string that describes the current state of the memory-allocation implementation in the caller.
     1287        // The string is printed on the file stream stream.  The exported string includes information about all arenas (see
     1288        // malloc).
     1289        int malloc_info( int options, FILE * stream __attribute__(( unused )) ) {
     1290          if ( options != 0 ) { errno = EINVAL; return -1; }
     1291                #ifdef __STATISTICS__
     1292                return printStatsXML( stream );
     1293                #else
     1294                return 0;                                                                               // unsupported
     1295                #endif // __STATISTICS__
     1296        } // malloc_info
    12511297
    12521298
     
    12541300        // specifies the parameter to be modified, and value specifies the new value for that parameter.
    12551301        int mallopt( int option, int value ) {
     1302          if ( value < 0 ) return 0;
    12561303                choose( option ) {
    12571304                  case M_TOP_PAD:
    1258                         heapExpand = ceiling2( value, __page_size ); return 1;
     1305                        heapExpand = ceiling2( value, __page_size );
     1306                        return 1;
    12591307                  case M_MMAP_THRESHOLD:
    12601308                        if ( setMmapStart( value ) ) return 1;
    1261                         break;
    1262                 } // switch
     1309                } // choose
    12631310                return 0;                                                                               // error, unsupported
    12641311        } // mallopt
     
    12691316                return 0;                                                                               // => impossible to release memory
    12701317        } // malloc_trim
    1271 
    1272 
    1273         // Exports an XML string that describes the current state of the memory-allocation implementation in the caller.
    1274         // The string is printed on the file stream stream.  The exported string includes information about all arenas (see
    1275         // malloc).
    1276         int malloc_info( int options, FILE * stream __attribute__(( unused )) ) {
    1277           if ( options != 0 ) { errno = EINVAL; return -1; }
    1278                 #ifdef __STATISTICS__
    1279                 return printStatsXML( stream );
    1280                 #else
    1281                 return 0;                                                                               // unsupported
    1282                 #endif // __STATISTICS__
    1283         } // malloc_info
    12841318
    12851319
     
    12991333        } // malloc_set_state
    13001334
     1335
    13011336        // Sets the amount (bytes) to extend the heap when there is insufficent free storage to service an allocation.
    13021337        __attribute__((weak)) size_t malloc_expansion() { return __CFA_DEFAULT_HEAP_EXPANSION__; }
     
    13351370
    13361371        // Attempt to reuse existing alignment.
    1337         Heap.Storage.Header * header = headerAddr( oaddr );
    1338         bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
     1372        Heap.Storage.Header * header = HeaderAddr( oaddr );
     1373        bool isFakeHeader = AlignmentBit( header );                     // old fake header ?
    13391374        size_t oalign;
    1340         if ( isFakeHeader ) {
    1341                 oalign = header->kind.fake.alignment & -2;              // old alignment
    1342                 if ( (uintptr_t)oaddr % nalign == 0                             // lucky match ?
     1375
     1376        if ( unlikely( isFakeHeader ) ) {
     1377                oalign = ClearAlignmentBit( header );                   // old alignment
     1378                if ( unlikely( (uintptr_t)oaddr % nalign == 0   // lucky match ?
    13431379                         && ( oalign <= nalign                                          // going down
    13441380                                  || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ?
    1345                         ) {
    1346                         headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
     1381                        ) ) {
     1382                        HeaderAddr( oaddr )->kind.fake.alignment = MarkAlignmentBit( nalign ); // update alignment (could be the same)
    13471383                        Heap.FreeHeader * freeElem;
    13481384                        size_t bsize, oalign;
    13491385                        headers( "resize", oaddr, header, freeElem, bsize, oalign );
    1350                         size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1386                        size_t odsize = DataStorage( bsize, oaddr, header ); // data storage available in bucket
    13511387
    13521388                        if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage
    1353                                 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1354 
    1355                                 header->kind.real.blockSize &= -2;              // turn off 0 fill
     1389                                HeaderAddr( oaddr )->kind.fake.alignment = MarkAlignmentBit( nalign ); // update alignment (could be the same)
     1390                                ClearZeroFillBit( header );                             // turn off 0 fill
    13561391                                header->kind.real.size = size;                  // reset allocation size
    13571392                                return oaddr;
     
    13971432
    13981433        // Attempt to reuse existing alignment.
    1399         Heap.Storage.Header * header = headerAddr( oaddr );
    1400         bool isFakeHeader = header->kind.fake.alignment & 1; // old fake header ?
     1434        Heap.Storage.Header * header = HeaderAddr( oaddr );
     1435        bool isFakeHeader = AlignmentBit( header );                     // old fake header ?
    14011436        size_t oalign;
    1402         if ( isFakeHeader ) {
    1403                 oalign = header->kind.fake.alignment & -2;              // old alignment
    1404                 if ( (uintptr_t)oaddr % nalign == 0                             // lucky match ?
     1437        if ( unlikely( isFakeHeader ) ) {
     1438                oalign = ClearAlignmentBit( header );                   // old alignment
     1439                if ( unlikely( (uintptr_t)oaddr % nalign == 0   // lucky match ?
    14051440                         && ( oalign <= nalign                                          // going down
    14061441                                  || (oalign >= nalign && oalign <= 256) ) // little alignment storage wasted ?
    1407                         ) {
    1408                         headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1409                         return realloc( oaddr, size );                          // duplicate alignment and special case checks
     1442                        ) ) {
     1443                        HeaderAddr( oaddr )->kind.fake.alignment = MarkAlignmentBit( nalign ); // update alignment (could be the same)
     1444                        return realloc( oaddr, size );                          // duplicate special case checks
    14101445                } // if
    14111446        } else if ( ! isFakeHeader                                                      // old real header (aligned on libAlign) ?
    1412                                 && nalign == libAlign() )                               // new alignment also on libAlign => no fake header needed
    1413                 return realloc( oaddr, size );                                  // duplicate alignment and special case checks
     1447                                && nalign == libAlign() ) {                             // new alignment also on libAlign => no fake header needed
     1448                return realloc( oaddr, size );                                  // duplicate special case checks
     1449        } // if
    14141450
    14151451        #ifdef __STATISTICS__
     
    14251461
    14261462        size_t osize = header->kind.real.size;                          // old allocation size
    1427         bool ozfill = (header->kind.real.blockSize & 2);        // old allocation zero filled
     1463        bool ozfill = ZeroFillBit( header );                            // old allocation zero filled
    14281464
    14291465        void * naddr = memalignNoStats( nalign, size );         // create new aligned area
     
    14341470
    14351471        if ( unlikely( ozfill ) ) {                                                     // previous request zero fill ?
    1436                 header->kind.real.blockSize |= 2;                               // mark new request as zero filled
     1472                MarkZeroFilledBit( header );                                    // mark new request as zero filled
    14371473                if ( size > osize ) {                                                   // previous request larger ?
    14381474                        memset( (char *)naddr + osize, '\0', size - osize ); // initialize added storage
Note: See TracChangeset for help on using the changeset viewer.