Changes in / [341bb80:8bdc1c36]


Ignore:
Files:
1 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    r341bb80 r8bdc1c36  
    66node ('master'){
    77
    8         // Globals
    9         BuildDir  = pwd tmp: true
    10         SrcDir    = pwd tmp: false
    11         Settings  = null
    12         StageName = ''
    13 
    14         // Local variables
     8        boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
    159        def err = null
    1610        def log_needed = false
     11
     12        stage_name              = ''
     13
     14        compiler                = null
     15        arch_name               = ''
     16        architecture    = ''
     17
     18        do_alltests             = false
     19        do_benchmark    = false
     20        do_doc          = false
     21        do_publish              = false
     22        do_sendemail    = true
     23
     24        builddir = pwd tmp: true
     25        srcdir   = pwd tmp: false
    1726
    1827        currentBuild.result = "SUCCESS"
     
    2433                        notify_server(0)
    2534
    26                         Settings = prepare_build()
     35                        prepare_build()
    2736
    2837                        clean()
     
    5261                err = caughtError
    5362
    54                 echo err.toString()
    55 
    5663                //An error has occured, the build log is relevent
    5764                log_needed = true
    5865
    5966                //Store the result of the build log
    60                 currentBuild.result = "${StageName} FAILURE".trim()
     67                currentBuild.result = "${stage_name} FAILURE".trim()
    6168        }
    6269
    6370        finally {
    6471                //Send email with final results if this is not a full build
    65                 if( Settings && !Settings.Silent ) {
    66                         email(log_needed, Settings.IsSandbox)
     72                if( do_sendemail ) {
     73                        echo 'Notifying users of result'
     74                        email(currentBuild.result, log_needed, bIsSandbox)
    6775                }
    6876
     
    7785
    7886//===========================================================================================================
    79 // Main compilation routines
    80 //===========================================================================================================
    81 def clean() {
    82         build_stage('Cleanup') {
    83                 // clean the build by wipping the build directory
    84                 dir(BuildDir) {
    85                         deleteDir()
    86                 }
    87         }
    88 }
    89 
    90 //Compilation script is done here but environnement set-up and error handling is done in main loop
    91 def checkout() {
    92         build_stage('Checkout') {
    93                 //checkout the source code and clean the repo
    94                 final scmVars = checkout scm
    95                 Settings.GitNewRef = scmVars.GIT_COMMIT
    96                 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
    97 
    98                 echo GitLogMessage()
    99         }
    100 }
    101 
    102 def build() {
    103         build_stage('Build') {
    104                 // Build outside of the src tree to ease cleaning
    105                 dir (BuildDir) {
    106                         //Configure the conpilation (Output is not relevant)
    107                         //Use the current directory as the installation target so nothing escapes the sandbox
    108                         //Also specify the compiler by hand
    109                         targets=""
    110                         if( Settings.RunAllTests ) {
    111                                 targets="--with-target-hosts='host:debug,host:nodebug'"
    112                         } else {
    113                                 targets="--with-target-hosts='host:debug'"
    114                         }
    115 
    116                         sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
    117 
    118                         //Compile the project
    119                         sh 'make -j 8 --no-print-directory'
    120                 }
    121         }
    122 }
    123 
    124 def test() {
    125         build_stage('Test') {
    126 
    127                 dir (BuildDir) {
    128                         //Run the tests from the tests directory
    129                         if ( Settings.RunAllTests ) {
    130                                 sh 'make --no-print-directory -C tests all-tests debug=yes'
    131                                 sh 'make --no-print-directory -C tests all-tests debug=no '
    132                         }
    133                         else {
    134                                 sh 'make --no-print-directory -C tests'
    135                         }
    136                 }
    137         }
    138 }
    139 
    140 def benchmark() {
    141         build_stage('Benchmark') {
    142 
    143                 if( !Settings.RunBenchmark ) return
    144 
    145                 dir (BuildDir) {
    146                         //Append bench results
    147                         sh "make --no-print-directory -C benchmark jenkins githash=${Settings.GitNewRef} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
    148                 }
    149         }
    150 }
    151 
    152 def build_doc() {
    153         build_stage('Documentation') {
    154 
    155                 if( !Settings.BuildDocumentation ) return
    156 
    157                 dir ('doc/user') {
    158                         make_doc()
    159                 }
    160 
    161                 dir ('doc/refrat') {
    162                         make_doc()
    163                 }
    164         }
    165 }
    166 
    167 def publish() {
    168         build_stage('Publish') {
    169 
    170                 if( !Settings.Publish ) return
    171 
    172                 //Then publish the results
    173                 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
    174         }
    175 }
    176 
    177 //===========================================================================================================
    178 //Routine responsible of sending the email notification once the build is completed
    179 //===========================================================================================================
    180 def GitLogMessage() {
    181         if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
    182 
    183         sh "${SrcDir}/tools/PrettyGitLogs.sh ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
    184 
    185         def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
    186         def gitLog    = readFile("${BuildDir}/GIT_LOG")
    187         def gitDiff   = readFile("${BuildDir}/GIT_DIFF")
    188 
    189         return """
    190 The branch ${env.BRANCH_NAME} has been updated.
    191 ${gitUpdate}
    192 
    193 Check console output at ${env.BUILD_URL} to view the results.
    194 
    195 - Status --------------------------------------------------------------
    196 
    197 BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
    198 
    199 - Log -----------------------------------------------------------------
    200 ${gitLog}
    201 -----------------------------------------------------------------------
    202 Summary of changes:
    203 ${gitDiff}
    204 """
    205 }
    206 
    207 //Standard build email notification
    208 def email(boolean log, boolean bIsSandbox) {
    209         //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    210         //Configurations for email format
    211         echo 'Notifying users of result'
    212 
    213         def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
    214         def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
    215         def email_body = """This is an automated email from the Jenkins build machine. It was
    216 generated because of a git hooks/post-receive script following
    217 a ref change which was pushed to the Cforall repository.
    218 """ + GitLogMessage()
    219 
    220         def email_to = "cforall@lists.uwaterloo.ca"
    221 
    222         if( Settings && !Settings.IsSandbox ) {
    223                 //send email notification
    224                 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
    225         } else {
    226                 echo "Would send email to: ${email_to}"
    227                 echo "With title: ${email_subject}"
    228                 echo "Content: \n${email_body}"
    229         }
    230 }
    231 
    232 //===========================================================================================================
    23387// Helper classes/variables/routines
    23488//===========================================================================================================
    235 //Description of a compiler (Must be serializable since pipelines are persistent)
    236 class CC_Desc implements Serializable {
    237         public String cc_name
    238         public String cpp_cc
    239         public String cfa_cc
    240 
    241         CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
    242                 this.cc_name = cc_name
    243                 this.cpp_cc = cpp_cc
    244                 this.cfa_cc = cfa_cc
    245         }
    246 }
    247 
    248 //Description of an architecture (Must be serializable since pipelines are persistent)
    249 class Arch_Desc implements Serializable {
    250         public String name
    251         public String flags
    252 
    253         Arch_Desc(String name, String flags) {
    254                 this.name  = name
    255                 this.flags = flags
    256         }
    257 }
    258 
    259 class BuildSettings implements Serializable {
    260         public final CC_Desc Compiler
    261         public final Arch_Desc Architecture
    262         public final Boolean RunAllTests
    263         public final Boolean RunBenchmark
    264         public final Boolean BuildDocumentation
    265         public final Boolean Publish
    266         public final Boolean Silent
    267         public final Boolean IsSandbox
    268         public final String DescLong
    269         public final String DescShort
    270 
    271         public String GitNewRef
    272         public String GitOldRef
    273 
    274         BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
    275                 switch( param.Compiler ) {
    276                         case 'gcc-6':
    277                                 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
    278                         break
    279                         case 'gcc-5':
    280                                 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
    281                         break
    282                         case 'gcc-4.9':
    283                                 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
    284                         break
    285                         case 'clang':
    286                                 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
    287                         break
    288                         default :
    289                                 error "Unhandled compiler : ${cc}"
    290                 }
    291 
    292                 switch( param.Architecture ) {
    293                         case 'x64':
    294                                 this.Architecture = new Arch_Desc('x64', '--host=x86_64')
    295                         break
    296                         case 'x86':
    297                                 this.Architecture = new Arch_Desc('x86', '--host=i386')
    298                         break
    299                         default :
    300                                 error "Unhandled architecture : ${arch}"
    301                 }
    302 
    303                 this.RunAllTests        = param.RunAllTests
    304                 this.RunBenchmark       = param.RunBenchmark
    305                 this.BuildDocumentation = param.BuildDocumentation
    306                 this.Publish            = param.Publish
    307                 this.Silent             = param.Silent
    308                 this.IsSandbox          = (branch == "jenkins-sandbox")
    309 
    310                 def full = param.RunAllTests ? " (Full)" : ""
    311                 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
    312 
    313                 this.DescLong = """Compiler              : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc })
    314 Architecture            : ${ this.Architecture.name }
    315 Arc Flags               : ${ this.Architecture.flags }
    316 Run All Tests           : ${ this.RunAllTests.toString() }
    317 Run Benchmark           : ${ this.RunBenchmark.toString() }
    318 Build Documentation     : ${ this.BuildDocumentation.toString() }
    319 Publish                 : ${ this.Publish.toString() }
    320 Silent                  : ${ this.Silent.toString() }
    321 """
    322 
    323                 this.GitNewRef = ''
    324                 this.GitOldRef = ''
    325         }
     89//Helper routine to collect information about the git history
     90def collect_git_info() {
     91
     92        checkout scm
     93
     94        //create the temporary output directory in case it doesn't already exist
     95        def out_dir = pwd tmp: true
     96        sh "mkdir -p ${out_dir}"
     97
     98        //parse git logs to find what changed
     99        gitRefName = env.BRANCH_NAME
     100        sh "git reflog > ${out_dir}/GIT_COMMIT"
     101        git_reflog = readFile("${out_dir}/GIT_COMMIT")
     102        gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
     103        gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
    326104}
    327105
    328106def prepare_build() {
    329         // prepare the properties
    330107        properties ([                                                                                                   \
    331108                [$class: 'ParametersDefinitionProperty',                                                                \
     
    371148                ]])
    372149
    373         final settings = new BuildSettings(params, env.BRANCH_NAME)
    374 
    375         currentBuild.description = settings.DescShort
    376         echo                       settings.DescLong
    377 
    378         return settings
     150        compiler                = compiler_from_params( params.Compiler )
     151        arch_name               = params.Architecture
     152        architecture    = architecture_from_params( arch_name )
     153
     154        do_alltests             = (params.RunAllTests == 'true')
     155        do_benchmark    = (params.RunBenchmark == 'true')
     156        do_doc          = (params.BuildDocumentation == 'true')
     157        do_publish              = (params.Publish == 'true')
     158        do_sendemail    = ! (params.Silent == 'true')
     159
     160        collect_git_info()
     161
     162        def full = do_alltests ? " (Full)" : ""
     163        currentBuild.description = "${compiler.cc_name}:${arch_name}${full}"
     164
     165        echo """Compiler                 : ${ compiler.cc_name } (${ compiler.cpp_cc }/${ compiler.cfa_cc })
     166Architecture            : ${ arch_name }
     167Arc Flags               : ${ architecture }
     168Run All Tests           : ${ params.RunAllTests.toString() }
     169Run Benchmark           : ${ params.RunBenchmark.toString() }
     170Build Documentation     : ${ params.BuildDocumentation.toString() }
     171Publish                 : ${ params.Publish.toString() }
     172Silent                  : ${ params.Silent.toString() }
     173"""
    379174}
    380175
    381176def build_stage(String name, Closure block ) {
    382         StageName = name
    383         echo " -------- ${StageName} -------- "
     177        stage_name = name
    384178        stage(name, block)
    385179}
     
    404198        }
    405199}
     200
     201//Description of a compiler (Must be serializable since pipelines are persistent)
     202class CC_Desc implements Serializable {
     203        public String cc_name
     204        public String cpp_cc
     205        public String cfa_cc
     206
     207        CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
     208                this.cc_name = cc_name
     209                this.cpp_cc = cpp_cc
     210                this.cfa_cc = cfa_cc
     211        }
     212}
     213
     214def compiler_from_params(cc) {
     215        switch( cc ) {
     216                case 'gcc-6':
     217                        return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
     218                break
     219                case 'gcc-5':
     220                        return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
     221                break
     222                case 'gcc-4.9':
     223                        return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
     224                break
     225                case 'clang':
     226                        return new CC_Desc('clang', 'clang++', 'gcc-6')
     227                break
     228                default :
     229                        error "Unhandled compiler : ${cc}"
     230        }
     231}
     232
     233def architecture_from_params( arch ) {
     234        switch( arch ) {
     235                case 'x64':
     236                        return '--host=x86_64'
     237                break
     238                case 'x86':
     239                        return '--host=i386'
     240                break
     241                default :
     242                        error "Unhandled architecture : ${arch}"
     243        }
     244}
     245
     246//===========================================================================================================
     247// Main compilation routines
     248//===========================================================================================================
     249def clean() {
     250        build_stage('Cleanup') {
     251                // clean the build by wipping the build directory
     252                dir(builddir) {
     253                        deleteDir()
     254                }
     255
     256                //Clean all temporary files to make sure no artifacts of the previous build remain
     257                sh 'git clean -fdqx'
     258
     259                //Reset the git repo so no local changes persist
     260                sh 'git reset --hard'
     261        }
     262}
     263
     264//Compilation script is done here but environnement set-up and error handling is done in main loop
     265def checkout() {
     266        build_stage('Checkout') {
     267                //checkout the source code and clean the repo
     268                checkout scm
     269        }
     270}
     271
     272def build() {
     273        build_stage('Build') {
     274                // Build outside of the src tree to ease cleaning
     275                dir (builddir) {
     276                        //Configure the conpilation (Output is not relevant)
     277                        //Use the current directory as the installation target so nothing escapes the sandbox
     278                        //Also specify the compiler by hand
     279                        targets=""
     280                        if(do_alltests) {
     281                                targets="--with-target-hosts='host:debug,host:nodebug'"
     282                        } else {
     283                                targets="--with-target-hosts='host:debug'"
     284                        }
     285
     286                        sh "${srcdir}/configure CXX=${compiler.cpp_cc} ${architecture} ${targets} --with-backend-compiler=${compiler.cfa_cc} --quiet"
     287
     288                        //Compile the project
     289                        sh 'make -j 8 --no-print-directory'
     290                }
     291        }
     292}
     293
     294def test() {
     295        build_stage('Test') {
     296
     297                dir (builddir) {
     298                        //Run the tests from the tests directory
     299                        if ( do_alltests ) {
     300                                sh 'make --no-print-directory -C tests all-tests debug=yes'
     301                                sh 'make --no-print-directory -C tests all-tests debug=no '
     302                        }
     303                        else {
     304                                sh 'make --no-print-directory -C tests'
     305                        }
     306                }
     307        }
     308}
     309
     310def benchmark() {
     311        build_stage('Benchmark') {
     312
     313                if( !do_benchmark ) return
     314
     315                dir (builddir) {
     316                        //Append bench results
     317                        sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${arch_name} | tee ${srcdir}/bench.json"
     318                }
     319        }
     320}
     321
     322def build_doc() {
     323        build_stage('Documentation') {
     324
     325                if( !do_doc ) return
     326
     327                dir ('doc/user') {
     328                        make_doc()
     329                }
     330
     331                dir ('doc/refrat') {
     332                        make_doc()
     333                }
     334        }
     335}
     336
     337def publish() {
     338        build_stage('Publish') {
     339
     340                if( !do_publish ) return
     341
     342                //Then publish the results
     343                sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
     344        }
     345}
     346
     347//===========================================================================================================
     348//Routine responsible of sending the email notification once the build is completed
     349//===========================================================================================================
     350def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
     351        def update = ""
     352        sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
     353        readFile('GIT_LOG').eachLine { rev ->
     354                sh "git cat-file -t ${rev} > GIT_TYPE"
     355                def type = readFile('GIT_TYPE')
     356
     357                update += "       via  ${rev} (${type})\n"
     358        }
     359        def rev = gitRefOldValue
     360        sh "git cat-file -t ${rev} > GIT_TYPE"
     361        def type = readFile('GIT_TYPE')
     362
     363        update += "      from  ${rev} (${type})\n"
     364        return update
     365
     366def output=readFile('result').trim()
     367echo "output=$output";
     368}
     369
     370//Standard build email notification
     371def email(String status, boolean log, boolean bIsSandbox) {
     372        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
     373        //Configurations for email format
     374        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
     375
     376        def gitLog = 'Error retrieving git logs'
     377        def gitDiff = 'Error retrieving git diff'
     378        def gitUpdate = 'Error retrieving update'
     379
     380        try {
     381                gitUpdate = gitBranchUpdate(gitRefOldValue, gitRefNewValue)
     382
     383                sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
     384                gitLog = readFile('GIT_LOG')
     385
     386                sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
     387                gitDiff = readFile('GIT_DIFF')
     388        }
     389        catch (Exception error) {
     390                echo error.toString()
     391                echo error.getMessage()
     392        }
     393
     394        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
     395        def email_body = """This is an automated email from the Jenkins build machine. It was
     396generated because of a git hooks/post-receive script following
     397a ref change was pushed to the repository containing
     398the project "UNNAMED PROJECT".
     399
     400The branch ${env.BRANCH_NAME} has been updated.
     401${gitUpdate}
     402
     403Check console output at ${env.BUILD_URL} to view the results.
     404
     405- Status --------------------------------------------------------------
     406
     407BUILD# ${env.BUILD_NUMBER} - ${status}
     408
     409- Log -----------------------------------------------------------------
     410${gitLog}
     411-----------------------------------------------------------------------
     412Summary of changes:
     413${gitDiff}
     414"""
     415
     416        def email_to = "cforall@lists.uwaterloo.ca"
     417
     418        if( !bIsSandbox ) {
     419                //send email notification
     420                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
     421        } else {
     422                echo "Would send email to: ${email_to}"
     423                echo "With title: ${email_subject}"
     424                echo "Content: \n${email_body}"
     425        }
     426}
  • libcfa/src/heap.cfa

    r341bb80 r8bdc1c36  
    1 // #comment TD : this file uses both spaces and tabs for indentation
    2 
    31//
    42// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
     
    2422} // extern "C"
    2523
    26 // #comment TD : Many of these should be merged into math I believe
    2724#include "bits/align.hfa"                                                                       // libPow2
    2825#include "bits/defs.hfa"                                                                        // likely, unlikely
     
    3936
    4037size_t default_mmap_start() __attribute__(( weak )) {
    41         return __CFA_DEFAULT_MMAP_START__;
     38    return __CFA_DEFAULT_MMAP_START__;
    4239} // default_mmap_start
    4340
    4441size_t default_heap_expansion() __attribute__(( weak )) {
    45         return __CFA_DEFAULT_HEAP_EXPANSION__;
     42    return __CFA_DEFAULT_HEAP_EXPANSION__;
    4643} // default_heap_expansion
    4744
     
    6562#endif // LOCKFREE
    6663
    67 // #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
    6864#define ALIGN 16
    6965
     
    140136
    141137static void checkUnfreed() {
    142         if ( allocFree != 0 ) {
     138    if ( allocFree != 0 ) {
    143139                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    144140                // char helpText[512];
     
    147143                //                                      (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
    148144                // __cfaabi_dbg_bits_write( helpText, len );
    149         } // if
     145    } // if
    150146} // checkUnfreed
    151147
     
    171167                                struct RealHeader {
    172168                                        union {
    173                                                 // #comment TD : this code use byte size but the comment uses bit size
    174 
    175169                                                struct {                                                // 32-bit word => 64-bit header, 64-bit word => 128-bit header
    176170                                                        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4
     
    192186
    193187                                                };
    194 
    195                                                 // #comment TD : C++ code
    196188                                                #if BUCKLOCK == LOCKFREE
    197189                                                Stack<Storage>::Link next;              // freed block points next freed block of same size (double-wide)
     
    223215            Storage * freeList;
    224216                #elif BUCKLOCK == LOCKFREE
    225                 // #comment TD : C++ code
    226217            StackLF<Storage> freeList;
    227218                #else
     
    249240static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    250241
    251 // #comment TD : This array is not const but it feels like it should be
    252242// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
    253243static unsigned int bucketSizes[NoBucketSizes] @= {             // different bucket sizes
    254         16, 32, 48, 64,
    255         64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
    256         256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
    257         1_024 + sizeof(HeapManager.Storage), 1_536, 2_048 + sizeof(HeapManager.Storage), 2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), 6_144,
    258         8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
    259         16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
    260         32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
    261         65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
    262         131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
    263         262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
    264         524_288 + sizeof(HeapManager.Storage), 655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), 1_179_648, 1_310_720, 1_441_792,
    265         1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), 2_621_440, 3_145_728, 3_670_016,
    266         4_194_304 + sizeof(HeapManager.Storage)
     244    16, 32, 48, 64,
     245    64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
     246    256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
     247    1_024 + sizeof(HeapManager.Storage), 1_536, 2_048 + sizeof(HeapManager.Storage), 2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), 6_144,
     248    8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
     249    16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
     250    32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
     251    65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
     252    131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
     253    262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
     254    524_288 + sizeof(HeapManager.Storage), 655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), 1_179_648, 1_310_720, 1_441_792,
     255    1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), 2_621_440, 3_145_728, 3_670_016,
     256    4_194_304 + sizeof(HeapManager.Storage)
    267257};
    268258#ifdef FASTLOOKUP
     
    277267static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    278268
    279 // #comment TD : The return type of this function should be commented
     269
    280270static inline bool setMmapStart( size_t value ) {
    281         if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
    282         mmapStart = value;                                                                      // set global
    283 
    284         // find the closest bucket size less than or equal to the mmapStart size
    285         maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    286         assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    287         assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    288         return false;
     271    if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     272    mmapStart = value;                                                                  // set global
     273
     274    // find the closest bucket size less than or equal to the mmapStart size
     275    maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     276    assert( maxBucketsUsed < NoBucketSizes );                   // subscript failure ?
     277    assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     278    return false;
    289279} // setMmapStart
    290280
    291281
    292282static void ?{}( HeapManager & manager ) with ( manager ) {
    293         pageSize = sysconf( _SC_PAGESIZE );
    294 
    295         for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     283    pageSize = sysconf( _SC_PAGESIZE );
     284
     285    for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    296286                freeLists[i].blockSize = bucketSizes[i];
    297         } // for
     287    } // for
    298288
    299289        #ifdef FASTLOOKUP
    300         unsigned int idx = 0;
    301         for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     290    unsigned int idx = 0;
     291    for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    302292                if ( i > bucketSizes[idx] ) idx += 1;
    303293                lookup[i] = idx;
    304         } // for
     294    } // for
    305295        #endif // FASTLOOKUP
    306296
    307         if ( setMmapStart( default_mmap_start() ) ) {
     297    if ( setMmapStart( default_mmap_start() ) ) {
    308298                abort( "HeapManager : internal error, mmap start initialization failure." );
    309         } // if
    310         heapExpand = default_heap_expansion();
    311 
    312         char * End = (char *)sbrk( 0 );
    313         sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    314         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     299    } // if
     300    heapExpand = default_heap_expansion();
     301
     302    char * End = (char *)sbrk( 0 );
     303    sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
     304    heapBegin = heapEnd = sbrk( 0 );                                    // get new start point
    315305} // HeapManager
    316306
     
    336326        #endif // __CFA_DEBUG__
    337327
    338         // #comment TD : This assertion seems redundent with the above code
    339328        assert( heapManager.heapBegin == 0 );
    340329        heapManager{};
     
    372361// Use "write" because streams may be shutdown when calls are made.
    373362static void printStats() {
    374         char helpText[512];
     363    char helpText[512];
    375364        __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
    376365                        "\nHeap statistics:\n"
     
    396385} // printStats
    397386
    398 // #comment TD : Why do we have this?
     387
    399388static int printStatsXML( FILE * stream ) {
    400         char helpText[512];
    401         int len = snprintf( helpText, sizeof(helpText),
     389    char helpText[512];
     390    int len = snprintf( helpText, sizeof(helpText),
    402391                                                "<malloc version=\"1\">\n"
    403392                                                "<heap nr=\"0\">\n"
     
    424413                                                sbrk_calls, sbrk_storage
    425414                );
    426         return write( fileno( stream ), helpText, len );        // -1 => error
     415    return write( fileno( stream ), helpText, len );    // -1 => error
    427416} // printStatsXML
    428417#endif // __STATISTICS__
    429418
    430 // #comment TD : Is this the samething as Out-of-Memory?
     419
    431420static inline void noMemory() {
    432         abort( "Heap memory exhausted at %zu bytes.\n"
     421    abort( "Heap memory exhausted at %zu bytes.\n"
    433422                        "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    434423                        ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
     
    437426
    438427static inline void checkAlign( size_t alignment ) {
    439         if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
     428    if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
    440429                abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
    441         } // if
     430    } // if
    442431} // checkAlign
    443432
    444433
    445434static inline bool setHeapExpand( size_t value ) {
    446         if ( heapExpand < pageSize ) return true;
    447         heapExpand = value;
    448         return false;
     435    if ( heapExpand < pageSize ) return true;
     436    heapExpand = value;
     437    return false;
    449438} // setHeapExpand
    450439
    451440
    452441static inline void checkHeader( bool check, const char * name, void * addr ) {
    453         if ( unlikely( check ) ) {                                                      // bad address ?
     442    if ( unlikely( check ) ) {                                                  // bad address ?
    454443                abort( "Attempt to %s storage %p with address outside the heap.\n"
    455444                                "Possible cause is duplicate free on same block or overwriting of memory.",
    456445                                name, addr );
    457         } // if
     446    } // if
    458447} // checkHeader
    459448
    460 // #comment TD : function should be commented and/or have a more evocative name
    461 //               this isn't either a check or a constructor which is what I would expect this function to be
     449
    462450static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
    463         if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
     451    if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    464452                size_t offset = header->kind.fake.offset;
    465453                alignment = header->kind.fake.alignment & -2;   // remove flag from value
     
    468456                #endif // __CFA_DEBUG__
    469457                header = (HeapManager.Storage.Header *)((char *)header - offset);
    470         } // if
     458    } // if
    471459} // fakeHeader
    472460
    473 // #comment TD : Why is this a define
     461
    474462#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    475463
    476464static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    477         header = headerAddr( addr );
    478 
    479         if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
     465    header = headerAddr( addr );
     466
     467    if ( unlikely( heapEnd < addr ) ) {                                 // mmapped ?
    480468                fakeHeader( header, size, alignment );
    481469                size = header->kind.real.blockSize & -3;                // mmap size
    482470                return true;
    483         } // if
     471    } // if
    484472
    485473        #ifdef __CFA_DEBUG__
    486                         checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     474    checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    487475        #endif // __CFA_DEBUG__
    488 
    489         // #comment TD : This code looks weird...
    490         //               It's called as the first statement of both branches of the last if, with the same parameters in all cases
    491 
    492                 // header may be safe to dereference
    493                 fakeHeader( header, size, alignment );
     476    // header may be safe to dereference
     477    fakeHeader( header, size, alignment );
    494478        #ifdef __CFA_DEBUG__
    495                         checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     479    checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    496480        #endif // __CFA_DEBUG__
    497481
    498                 freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
     482    freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
    499483        #ifdef __CFA_DEBUG__
    500                         if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
    501                         abort( "Attempt to %s storage %p with corrupted header.\n"
    502                                 "Possible cause is duplicate free on same block or overwriting of header information.",
    503                                         name, addr );
    504                         } // if
     484    if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
     485                abort( "Attempt to %s storage %p with corrupted header.\n"
     486                          "Possible cause is duplicate free on same block or overwriting of header information.",
     487                           name, addr );
     488    } // if
    505489        #endif // __CFA_DEBUG__
    506                 size = freeElem->blockSize;
    507                 return false;
     490    size = freeElem->blockSize;
     491    return false;
    508492} // headers
    509493
    510494
    511495static inline void * extend( size_t size ) with ( heapManager ) {
    512         lock( extlock __cfaabi_dbg_ctx2 );
    513         ptrdiff_t rem = heapRemaining - size;
    514         if ( rem < 0 ) {
     496    lock( extlock __cfaabi_dbg_ctx2 );
     497    ptrdiff_t rem = heapRemaining - size;
     498    if ( rem < 0 ) {
    515499                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    516500
     
    530514#endif // __CFA_DEBUG__
    531515                rem = heapRemaining + increase - size;
    532         } // if
    533 
    534         HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
    535         heapRemaining = rem;
    536         heapEnd = (char *)heapEnd + size;
    537         unlock( extlock );
    538         return block;
     516    } // if
     517
     518    HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
     519    heapRemaining = rem;
     520    heapEnd = (char *)heapEnd + size;
     521    unlock( extlock );
     522    return block;
    539523} // extend
    540524
    541525
    542526static inline void * doMalloc( size_t size ) with ( heapManager ) {
    543         HeapManager.Storage * block;
    544 
    545         // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
    546         // along with the block and is a multiple of the alignment size.
    547 
    548         size_t tsize = size + sizeof(HeapManager.Storage);
    549         if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     527    HeapManager.Storage * block;
     528
     529    // Look up size in the size list.  Make sure the user request includes space for the header that must be allocated
     530    // along with the block and is a multiple of the alignment size.
     531
     532    size_t tsize = size + sizeof(HeapManager.Storage);
     533    if ( likely( tsize < mmapStart ) ) {                                // small size => sbrk
    550534                HeapManager.FreeHeader * freeElem =
    551535                        #ifdef FASTLOOKUP
     
    560544
    561545                #if defined( SPINLOCK )
    562                         lock( freeElem->lock __cfaabi_dbg_ctx2 );
    563                         block = freeElem->freeList;                                             // remove node from stack
     546                lock( freeElem->lock __cfaabi_dbg_ctx2 );
     547                block = freeElem->freeList;                                             // remove node from stack
    564548                #else
    565                         block = freeElem->freeList.pop();
     549                block = freeElem->freeList.pop();
    566550                #endif // SPINLOCK
    567551                if ( unlikely( block == 0 ) ) {                                 // no free block ?
     
    582566
    583567                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    584                 } else {                                                                                        // large size => mmap
     568    } else {                                                                                    // large size => mmap
    585569                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    586570                #ifdef __STATISTICS__
    587                         __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
    588                         __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );
     571                __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST );
     572                __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST );
    589573                #endif // __STATISTICS__
    590574                block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 );
     
    598582#endif // __CFA_DEBUG__
    599583                block->header.kind.real.blockSize = tsize;              // storage size for munmap
    600                 } // if
    601 
    602                 void * area = &(block->data);                                           // adjust off header to user bytes
     584    } // if
     585
     586    void * area = &(block->data);                                               // adjust off header to user bytes
    603587
    604588        #ifdef __CFA_DEBUG__
    605                         assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
    606                         __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
    607                 if ( traceHeap() ) {
    608                         enum { BufferSize = 64 };
    609                         char helpText[BufferSize];
    610                         int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
    611                         // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
    612                         __cfaabi_dbg_bits_write( helpText, len );
    613                 } // if
     589    assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
     590    __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
     591        if ( traceHeap() ) {
     592                enum { BufferSize = 64 };
     593                char helpText[BufferSize];
     594                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
     595                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
     596                __cfaabi_dbg_bits_write( helpText, len );
     597        } // if
    614598        #endif // __CFA_DEBUG__
    615599
    616         return area;
     600    return area;
    617601} // doMalloc
    618602
     
    620604static inline void doFree( void * addr ) with ( heapManager ) {
    621605        #ifdef __CFA_DEBUG__
    622                 if ( unlikely( heapManager.heapBegin == 0 ) ) {
    623                         abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
    624                 } // if
     606    if ( unlikely( heapManager.heapBegin == 0 ) ) {
     607                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
     608    } // if
    625609        #endif // __CFA_DEBUG__
    626610
    627         HeapManager.Storage.Header * header;
    628         HeapManager.FreeHeader * freeElem;
    629         size_t size, alignment;                                                         // not used (see realloc)
    630 
    631         if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
    632                 #ifdef __STATISTICS__
    633                         __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );
    634                         __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST );
     611    HeapManager.Storage.Header * header;
     612    HeapManager.FreeHeader * freeElem;
     613    size_t size, alignment;                                                             // not used (see realloc)
     614
     615    if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ?
     616                #ifdef __STATISTICS__
     617                __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST );
     618                __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST );
    635619                #endif // __STATISTICS__
    636620                if ( munmap( header, size ) == -1 ) {
     
    641625                        #endif // __CFA_DEBUG__
    642626                } // if
    643                 } else {
     627    } else {
    644628                #ifdef __CFA_DEBUG__
    645                         // Set free memory to garbage so subsequent usages might fail.
    646                         memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
     629                // Set free memory to garbage so subsequent usages might fail.
     630                memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) );
    647631                #endif // __CFA_DEBUG__
    648632
    649633                #ifdef __STATISTICS__
    650                         free_storage += size;
     634                free_storage += size;
    651635                #endif // __STATISTICS__
    652636                #if defined( SPINLOCK )
    653                         lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
    654                         header->kind.real.next = freeElem->freeList;    // push on stack
    655                         freeElem->freeList = (HeapManager.Storage *)header;
    656                         unlock( freeElem->lock );                                               // release spin lock
     637                lock( freeElem->lock __cfaabi_dbg_ctx2 );               // acquire spin lock
     638                header->kind.real.next = freeElem->freeList;    // push on stack
     639                freeElem->freeList = (HeapManager.Storage *)header;
     640                unlock( freeElem->lock );                                               // release spin lock
    657641                #else
    658                         freeElem->freeList.push( *(HeapManager.Storage *)header );
     642                freeElem->freeList.push( *(HeapManager.Storage *)header );
    659643                #endif // SPINLOCK
    660                 } // if
     644    } // if
    661645
    662646        #ifdef __CFA_DEBUG__
    663                  __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );
    664                 if ( traceHeap() ) {
    665                         char helpText[64];
    666                         int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    667                         __cfaabi_dbg_bits_write( helpText, len );
    668                 } // if
     647    __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST );
     648    if ( traceHeap() ) {
     649                char helpText[64];
     650                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
     651                __cfaabi_dbg_bits_write( helpText, len );
     652    } // if
    669653        #endif // __CFA_DEBUG__
    670654} // doFree
     
    672656
    673657size_t checkFree( HeapManager & manager ) with ( manager ) {
    674         size_t total = 0;
     658    size_t total = 0;
    675659        #ifdef __STATISTICS__
    676                 __cfaabi_dbg_bits_acquire();
    677                 __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
     660    __cfaabi_dbg_bits_acquire();
     661    __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
    678662        #endif // __STATISTICS__
    679         for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     663    for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
    680664                size_t size = freeLists[i].blockSize;
    681665                #ifdef __STATISTICS__
    682666                unsigned int N = 0;
    683667                #endif // __STATISTICS__
    684 
    685668                #if defined( SPINLOCK )
    686669                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
     
    692675                        N += 1;
    693676                        #endif // __STATISTICS__
    694                 } // for
    695 
    696                 #ifdef __STATISTICS__
    697                         __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
    698                         if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
     677            } // for
     678                #ifdef __STATISTICS__
     679            __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
     680            if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
    699681                #endif // __STATISTICS__
    700682        } // for
    701683        #ifdef __STATISTICS__
    702                 __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
    703                 __cfaabi_dbg_bits_release();
     684        __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
     685        __cfaabi_dbg_bits_release();
    704686        #endif // __STATISTICS__
    705687        return (char *)heapEnd - (char *)heapBegin - total;
    706688} // checkFree
    707689
    708 // #comment TD : This is not a good name, plus this feels like it could easily be folded into doMalloc
     690
    709691static inline void * malloc2( size_t size ) {                   // necessary for malloc statistics
    710692        assert( heapManager.heapBegin != 0 );
    711         void * area = doMalloc( size );
    712         if ( unlikely( area == 0 ) ) errno = ENOMEM;            // POSIX
    713         return area;
     693    void * area = doMalloc( size );
     694    if ( unlikely( area == 0 ) ) errno = ENOMEM;                // POSIX
     695    return area;
    714696} // malloc2
    715697
     
    717699static inline void * memalign2( size_t alignment, size_t size ) { // necessary for malloc statistics
    718700#ifdef __CFA_DEBUG__
    719         checkAlign( alignment );                                                        // check alignment
     701    checkAlign( alignment );                                                    // check alignment
    720702#endif // __CFA_DEBUG__
    721703
    722         // if alignment <= default alignment, do normal malloc as two headers are unnecessary
    723         if ( unlikely( alignment <= libAlign() ) ) return malloc2( size );
    724 
    725         // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for
    726         // administrative storage. NOTE, WHILE THERE ARE 2 HEADERS, THE FIRST ONE IS IMPLICITLY CREATED BY DOMALLOC.
    727         //      .-------------v-----------------v----------------v----------,
    728         //      | Real Header | ... padding ... |   Fake Header  | data ... |
    729         //      `-------------^-----------------^-+--------------^----------'
    730         //      |<--------------------------------' offset/align |<-- alignment boundary
    731 
    732         // subtract libAlign() because it is already the minimum alignment
    733         // add sizeof(Storage) for fake header
    734         // #comment TD : this is the only place that calls doMalloc without calling malloc2, why ?
    735         char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    736         if ( unlikely( area == 0 ) ) return area;
    737 
    738         // address in the block of the "next" alignment address
    739         char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
    740 
    741         // address of header from malloc
    742         HeapManager.Storage.Header * realHeader = headerAddr( area );
    743         // address of fake header * before* the alignment location
    744         HeapManager.Storage.Header * fakeHeader = headerAddr( user );
    745         // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
    746         fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
    747         // SKULLDUGGERY: odd alignment imples fake header
    748         fakeHeader->kind.fake.alignment = alignment | 1;
    749 
    750         return user;
     704    // if alignment <= default alignment, do normal malloc as two headers are unnecessary
     705    if ( unlikely( alignment <= libAlign() ) ) return malloc2( size );
     706
     707    // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for
     708    // administrative storage. NOTE, WHILE THERE ARE 2 HEADERS, THE FIRST ONE IS IMPLICITLY CREATED BY DOMALLOC.
     709    //      .-------------v-----------------v----------------v----------,
     710    //      | Real Header | ... padding ... |   Fake Header  | data ... |
     711    //      `-------------^-----------------^-+--------------^----------'
     712    //      |<--------------------------------' offset/align |<-- alignment boundary
     713
     714    // subtract libAlign() because it is already the minimum alignment
     715    // add sizeof(Storage) for fake header
     716    char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     717    if ( unlikely( area == 0 ) ) return area;
     718
     719    // address in the block of the "next" alignment address
     720    char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
     721
     722    // address of header from malloc
     723    HeapManager.Storage.Header * realHeader = headerAddr( area );
     724    // address of fake header * before* the alignment location
     725    HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     726    // SKULLDUGGERY: insert the offset to the start of the actual storage block and remember alignment
     727    fakeHeader->kind.fake.offset = (char *)fakeHeader - (char *)realHeader;
     728    // SKULLDUGGERY: odd alignment imples fake header
     729    fakeHeader->kind.fake.alignment = alignment | 1;
     730
     731    return user;
    751732} // memalign2
    752733
    753734
    754735extern "C" {
    755         // The malloc() function allocates size bytes and returns a pointer to the
    756         // allocated memory. The memory is not initialized. If size is 0, then malloc()
    757         // returns either NULL, or a unique pointer value that can later be successfully
    758         // passed to free().
    759         void * malloc( size_t size ) {
    760                 #ifdef __STATISTICS__
    761                         __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST );
    762                         __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST );
     736    void * malloc( size_t size ) {
     737                #ifdef __STATISTICS__
     738                __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST );
     739                __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST );
    763740                #endif // __STATISTICS__
    764741
    765742                return malloc2( size );
    766                 } // malloc
    767 
    768         // The calloc() function allocates memory for an array of nmemb elements of
    769         // size bytes each and returns a pointer to the allocated memory. The memory
    770         // is set to zero. If nmemb or size is 0, then calloc() returns either NULL,
    771         // or a unique pointer value that can later be successfully passed to free().
    772                 void * calloc( size_t noOfElems, size_t elemSize ) {
     743    } // malloc
     744
     745
     746    void * calloc( size_t noOfElems, size_t elemSize ) {
    773747                size_t size = noOfElems * elemSize;
    774748                #ifdef __STATISTICS__
    775                         __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    776                         __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
     749                __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
     750                __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
    777751                #endif // __STATISTICS__
    778752
    779753                char * area = (char *)malloc2( size );
    780754                if ( unlikely( area == 0 ) ) return 0;
    781 
    782755                HeapManager.Storage.Header * header;
    783756                HeapManager.FreeHeader * freeElem;
     
    789762                #endif // __CFA_DEBUG__
    790763                        memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
    791 
    792764                header->kind.real.blockSize |= 2;               // mark as zero filled
    793765                return area;
    794                 } // calloc
    795 
    796         // #comment TD : Document this function
    797         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
     766    } // calloc
     767
     768
     769    void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
    798770                size_t size = noOfElems * elemSize;
    799771                #ifdef __STATISTICS__
    800                         __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    801                         __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
     772                __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     773                __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
    802774                #endif // __STATISTICS__
    803775
     
    816788
    817789                return area;
    818                 } // cmemalign
    819 
    820         // The realloc() function changes the size of the memory block pointed to by
    821         // ptr to size bytes. The contents will be unchanged in the range from the
    822         // start of the region up to the minimum of the old and new sizes. If the new
    823         // size is larger than the old size, the added memory will not be initialized.
    824         // If ptr is NULL, then the call is equivalent to malloc(size), for all values
    825         // of size; if size is equal to zero, and ptr is not NULL, then the call is
    826         // equivalent to free(ptr). Unless ptr is NULL, it must have been returned by
    827         // an earlier call to malloc(), calloc() or realloc(). If the area pointed to
    828         // was moved, a free(ptr) is done.
    829                 void * realloc( void * addr, size_t size ) {
    830                 #ifdef __STATISTICS__
    831                         __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     790    } // cmemalign
     791
     792
     793    void * realloc( void * addr, size_t size ) {
     794                #ifdef __STATISTICS__
     795                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    832796                #endif // __STATISTICS__
    833797
     
    848812
    849813                #ifdef __STATISTICS__
    850                         __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     814                __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
    851815                #endif // __STATISTICS__
    852816
     
    871835                free( addr );
    872836                return area;
    873         } // realloc
    874 
    875 
    876         // The obsolete function memalign() allocates size bytes and returns
    877         // a pointer to the allocated memory. The memory address will be a
    878         // multiple of alignment, which must be a power of two.
    879         void * memalign( size_t alignment, size_t size ) __attribute__ ((deprecated));
    880                 void * memalign( size_t alignment, size_t size ) {
     837    } // realloc
     838
     839
     840    void * memalign( size_t alignment, size_t size ) {
    881841                #ifdef __STATISTICS__
    882842                __atomic_add_fetch( &memalign_calls, 1, __ATOMIC_SEQ_CST );
     
    887847
    888848                return area;
    889                 } // memalign
    890 
    891         // The function aligned_alloc() is the same as memalign(), except for
    892         // the added restriction that size should be a multiple of alignment.
    893         void * aligned_alloc( size_t alignment, size_t size ) {
     849    } // memalign
     850
     851
     852    void * aligned_alloc( size_t alignment, size_t size ) {
    894853                return memalign( alignment, size );
    895         } // aligned_alloc
    896 
    897 
    898         // The function posix_memalign() allocates size bytes and places the address
    899         // of the allocated memory in *memptr. The address of the allocated memory
    900         // will be a multiple of alignment, which must be a power of two and a multiple
    901         // of sizeof(void *). If size is 0, then posix_memalign() returns either NULL,
    902         // or a unique pointer value that can later be successfully passed to free(3).
    903         int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
     854    } // aligned_alloc
     855
     856
     857    int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    904858                if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
    905859                * memptr = memalign( alignment, size );
    906860                if ( unlikely( * memptr == 0 ) ) return ENOMEM;
    907861                return 0;
    908         } // posix_memalign
    909 
    910         // The obsolete function valloc() allocates size bytes and returns a pointer
    911         // to the allocated memory. The memory address will be a multiple of the page size.
    912         // It is equivalent to memalign(sysconf(_SC_PAGESIZE),size).
    913         void * valloc( size_t size ) __attribute__ ((deprecated));
    914         void * valloc( size_t size ) {
     862    } // posix_memalign
     863
     864
     865    void * valloc( size_t size ) {
    915866                return memalign( pageSize, size );
    916         } // valloc
    917 
    918 
    919         // The free() function frees the memory space pointed to by ptr, which must
    920         // have been returned by a previous call to malloc(), calloc() or realloc().
    921         // Otherwise, or if free(ptr) has already been called before, undefined
    922         // behavior occurs. If ptr is NULL, no operation is performed.
    923         void free( void * addr ) {
    924                 #ifdef __STATISTICS__
    925                         __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );
    926                 #endif // __STATISTICS__
    927 
    928                 // #comment TD : To decrease nesting I would but the special case in the
    929                 //               else instead, plus it reads more naturally to have the
    930                 //               short / normal case instead
     867    } // valloc
     868
     869
     870    void free( void * addr ) {
     871                #ifdef __STATISTICS__
     872                __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST );
     873                #endif // __STATISTICS__
     874
    931875                if ( unlikely( addr == 0 ) ) {                                  // special case
    932876                        #ifdef __CFA_DEBUG__
    933                                 if ( traceHeap() ) {
    934                                         #define nullmsg "Free( 0x0 ) size:0\n"
    935                                         // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    936                                         __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
    937                                 } // if
     877                        if ( traceHeap() ) {
     878                                #define nullmsg "Free( 0x0 ) size:0\n"
     879                                // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
     880                                __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
     881                        } // if
    938882                        #endif // __CFA_DEBUG__
    939883                        return;
     
    941885
    942886                doFree( addr );
    943         } // free
    944 
    945         // The mallopt() function adjusts parameters that control the behavior of the
    946         // memory-allocation functions (see malloc(3)). The param argument specifies
    947         // the parameter to be modified, and value specifies the new value for that
    948         // parameter.
    949                 int mallopt( int option, int value ) {
     887    } // free
     888
     889
     890    int mallopt( int option, int value ) {
    950891                choose( option ) {
    951                         case M_TOP_PAD:
    952                                 if ( setHeapExpand( value ) ) fallthru default;
    953                         case M_MMAP_THRESHOLD:
    954                                 if ( setMmapStart( value ) ) fallthru default;
    955                         default:
    956                                 // #comment TD : 1 for unsopported feels wrong
    957                                 return 1;                                                                       // success, or unsupported
     892                  case M_TOP_PAD:
     893                        if ( setHeapExpand( value ) ) fallthru default;
     894                  case M_MMAP_THRESHOLD:
     895                        if ( setMmapStart( value ) ) fallthru default;
     896                  default:
     897                        return 1;                                                                       // success, or unsupported
    958898                } // switch
    959899                return 0;                                                                               // error
    960         } // mallopt
    961 
    962         // The malloc_trim() function attempts to release free memory at the top
    963         // of the heap (by calling sbrk(2) with a suitable argument).
     900    } // mallopt
     901
     902
    964903        int malloc_trim( size_t ) {
    965904                return 0;                                                                               // => impossible to release memory
    966905        } // malloc_trim
    967906
    968         // The malloc_usable_size() function returns the number of usable bytes in the
    969         // block pointed to by ptr, a pointer to a block of memory allocated by
    970         // malloc(3) or a related function.
    971                 size_t malloc_usable_size( void * addr ) {
     907    size_t malloc_usable_size( void * addr ) {
    972908                if ( unlikely( addr == 0 ) ) return 0;                  // null allocation has 0 size
    973 
    974909                HeapManager.Storage.Header * header;
    975910                HeapManager.FreeHeader * freeElem;
     
    979914                size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    980915                return usize;
    981         } // malloc_usable_size
    982 
    983 
    984                 // #comment TD : Document this function
    985         size_t malloc_alignment( void * addr ) {
     916    } // malloc_usable_size
     917
     918
     919    size_t malloc_alignment( void * addr ) {
    986920                if ( unlikely( addr == 0 ) ) return libAlign(); // minimum alignment
    987921                HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
     
    991925                        return libAlign ();                                                     // minimum alignment
    992926                } // if
    993                 } // malloc_alignment
    994 
    995 
    996                 // #comment TD : Document this function
    997         bool malloc_zero_fill( void * addr ) {
     927    } // malloc_alignment
     928
     929
     930    bool malloc_zero_fill( void * addr ) {
    998931                if ( unlikely( addr == 0 ) ) return false;              // null allocation is not zero fill
    999 
    1000932                HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
    1001933                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    1003935                } // if
    1004936                return (header->kind.real.blockSize & 2) != 0;  // zero filled (calloc/cmemalign) ?
    1005                 } // malloc_zero_fill
    1006 
    1007 
    1008         // #comment TD : Document this function
    1009         void malloc_stats( void ) {
    1010                 #ifdef __STATISTICS__
    1011                         printStats();
    1012                         if ( checkFree() ) checkFree( heapManager );
    1013                 #endif // __STATISTICS__
    1014                 } // malloc_stats
    1015 
    1016         // #comment TD : Document this function
    1017                 int malloc_stats_fd( int fd ) {
    1018                 #ifdef __STATISTICS__
    1019                         int temp = statfd;
    1020                         statfd = fd;
    1021                         return temp;
     937    } // malloc_zero_fill
     938
     939
     940    void malloc_stats( void ) {
     941                #ifdef __STATISTICS__
     942                printStats();
     943                if ( checkFree() ) checkFree( heapManager );
     944                #endif // __STATISTICS__
     945    } // malloc_stats
     946
     947
     948    int malloc_stats_fd( int fd ) {
     949                #ifdef __STATISTICS__
     950                int temp = statfd;
     951                statfd = fd;
     952                return temp;
    1022953                #else
    1023                         return -1;
    1024                 #endif // __STATISTICS__
    1025                 } // malloc_stats_fd
    1026 
    1027 
    1028         // #comment TD : Document this function
     954                return -1;
     955                #endif // __STATISTICS__
     956    } // malloc_stats_fd
     957
     958
    1029959        int malloc_info( int options, FILE * stream ) {
    1030960                return printStatsXML( stream );
     
    1032962
    1033963
    1034         // #comment TD : What are these two functions for?
    1035964        void * malloc_get_state( void ) {
    1036965                return 0;
    1037966        } // malloc_get_state
     967
    1038968
    1039969        int malloc_set_state( void * ptr ) {
Note: See TracChangeset for help on using the changeset viewer.