Changeset 2fa5bd2 for libcfa/src


Ignore:
Timestamp:
Dec 12, 2019, 10:04:15 AM (6 years ago)
Author:
Dmitry Kobets <dkobets@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
e752e4e
Parents:
aca6a54c (diff), 2cd949b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into vector-generic

Location:
libcfa/src
Files:
28 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    raca6a54c r2fa5bd2  
    3333# The built sources must not depend on the installed headers
    3434AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    35 AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC @ARCH_FLAGS@ @CONFIG_CFLAGS@
     35AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3636AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3737CFACC = @CFACC@
  • libcfa/src/Makefile.in

    raca6a54c r2fa5bd2  
    416416LTCFACOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    417417        $(LIBTOOLFLAGS) --mode=compile $(CFACC) $(DEFS) \
    418         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) \
    419         $(AM_CFLAGS) $(CFLAGS)
     418        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(AM_CFLAGS) $(CFAFLAGS) $(CFLAGS)
    420419
    421420AM_V_CFA = $(am__v_CFA_@AM_V@)
     
    445444# The built sources must not depend on the installed headers
    446445AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    447 AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC @ARCH_FLAGS@ @CONFIG_CFLAGS@
     446AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    448447AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
    449448@BUILDLIB_FALSE@headers_nosrc =
  • libcfa/src/assert.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:10:26 2017
    13 // Update Count     : 2
     12// Last Modified On : Thu Nov 21 17:09:26 2019
     13// Update Count     : 5
    1414//
    1515
     
    1717#include <stdarg.h>                                                             // varargs
    1818#include <stdio.h>                                                              // fprintf
     19#include <unistd.h>                                                             // STDERR_FILENO
    1920#include "bits/debug.hfa"
    2021
     
    2627        // called by macro assert in assert.h
    2728        void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function ) {
    28                 __cfaabi_dbg_bits_print_safe( CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
     29                __cfaabi_bits_print_safe( STDERR_FILENO, CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
    2930                abort();
    3031        }
     
    3233        // called by macro assertf
    3334        void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {
    34                 __cfaabi_dbg_bits_acquire();
    35                 __cfaabi_dbg_bits_print_nolock( CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
     35                __cfaabi_bits_acquire();
     36                __cfaabi_bits_print_nolock( STDERR_FILENO, CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
    3637
    3738                va_list args;
    3839                va_start( args, fmt );
    39                 __cfaabi_dbg_bits_print_vararg( fmt, args );
     40                __cfaabi_bits_print_vararg( STDERR_FILENO, fmt, args );
    4041                va_end( args );
    4142
    42                 __cfaabi_dbg_bits_print_nolock( "\n" );
    43                 __cfaabi_dbg_bits_release();
     43                __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
     44                __cfaabi_bits_release();
    4445                abort();
    4546        }
  • libcfa/src/bits/align.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 23:05:35 2017
    13 // Update Count     : 2
     12// Last Modified On : Sat Nov 16 18:58:22 2019
     13// Update Count     : 3
    1414//
    1515// This  library is free  software; you  can redistribute  it and/or  modify it
     
    3333
    3434// Minimum size used to align memory boundaries for memory allocations.
    35 #define libAlign() (sizeof(double))
     35//#define libAlign() (sizeof(double))
     36// gcc-7 uses xmms instructions, which require 16 byte alignment.
     37#define libAlign() (16)
    3638
    3739// Check for power of 2
  • libcfa/src/bits/debug.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Thu Mar 30 12:30:01 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 22:17:35 2019
    13 // Update Count     : 4
     12// Last Modified On : Thu Nov 21 17:16:30 2019
     13// Update Count     : 10
    1414//
    1515
     
    2828extern "C" {
    2929
    30         void __cfaabi_dbg_bits_write( const char *in_buffer, int len ) {
     30        void __cfaabi_bits_write( int fd, const char *in_buffer, int len ) {
    3131                // ensure all data is written
    3232                for ( int count = 0, retcode; count < len; count += retcode ) {
     
    3434
    3535                        for ( ;; ) {
    36                                 retcode = write( STDERR_FILENO, in_buffer, len - count );
     36                                retcode = write( fd, in_buffer, len - count );
    3737
    3838                                // not a timer interrupt ?
     
    4444        }
    4545
    46         void __cfaabi_dbg_bits_acquire() __attribute__((__weak__)) {}
    47         void __cfaabi_dbg_bits_release() __attribute__((__weak__)) {}
     46        void __cfaabi_bits_acquire() __attribute__((__weak__)) {}
     47        void __cfaabi_bits_release() __attribute__((__weak__)) {}
    4848
    49         void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     49        void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
    5050                va_list args;
    5151
    5252                va_start( args, fmt );
    53                 __cfaabi_dbg_bits_acquire();
     53                __cfaabi_bits_acquire();
    5454
    5555                int len = vsnprintf( buffer, buffer_size, fmt, args );
    56                 __cfaabi_dbg_bits_write( buffer, len );
     56                __cfaabi_bits_write( fd, buffer, len );
    5757
    58                 __cfaabi_dbg_bits_release();
     58                __cfaabi_bits_release();
    5959                va_end( args );
    6060        }
    6161
    62         void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     62        void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
    6363                va_list args;
    6464
     
    6666
    6767                int len = vsnprintf( buffer, buffer_size, fmt, args );
    68                 __cfaabi_dbg_bits_write( buffer, len );
     68                __cfaabi_bits_write( fd, buffer, len );
    6969
    7070                va_end( args );
    7171        }
    7272
    73         void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list args ) {
     73        void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list args ) {
    7474                int len = vsnprintf( buffer, buffer_size, fmt, args );
    75                 __cfaabi_dbg_bits_write( buffer, len );
     75                __cfaabi_bits_write( fd, buffer, len );
    7676        }
    7777
    78         void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )) {
     78        void __cfaabi_bits_print_buffer( int fd, char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) )) {
    7979                va_list args;
    8080
     
    8282
    8383                int len = vsnprintf( in_buffer, in_buffer_size, fmt, args );
    84                 __cfaabi_dbg_bits_write( in_buffer, len );
     84                __cfaabi_bits_write( fd, in_buffer, len );
    8585
    8686                va_end( args );
  • libcfa/src/bits/debug.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 12:35:19 2018
    13 // Update Count     : 2
     12// Last Modified On : Thu Nov 21 17:06:58 2019
     13// Update Count     : 8
    1414//
    1515
     
    3838        #include <stdio.h>
    3939
    40       extern void __cfaabi_dbg_bits_write( const char *buffer, int len );
    41       extern void __cfaabi_dbg_bits_acquire();
    42       extern void __cfaabi_dbg_bits_release();
    43       extern void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
    44       extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
    45       extern void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list arg );
    46       extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) ));
     40        extern void __cfaabi_bits_write( int fd, const char *buffer, int len );
     41        extern void __cfaabi_bits_acquire();
     42        extern void __cfaabi_bits_release();
     43        extern void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
     44        extern void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
     45        extern void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list arg );
     46        extern void __cfaabi_bits_print_buffer( int fd, char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) ));
    4747#ifdef __cforall
    4848}
     
    5050
    5151#ifdef __CFA_DEBUG_PRINT__
    52         #define __cfaabi_dbg_write( buffer, len )         __cfaabi_dbg_bits_write( buffer, len )
    53         #define __cfaabi_dbg_acquire()                    __cfaabi_dbg_bits_acquire()
    54         #define __cfaabi_dbg_release()                    __cfaabi_dbg_bits_release()
    55         #define __cfaabi_dbg_print_safe(...)              __cfaabi_dbg_bits_print_safe   (__VA_ARGS__)
    56         #define __cfaabi_dbg_print_nolock(...)            __cfaabi_dbg_bits_print_nolock (__VA_ARGS__)
    57         #define __cfaabi_dbg_print_buffer(...)            __cfaabi_dbg_bits_print_buffer (__VA_ARGS__)
    58         #define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
    59         #define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
     52        #define __cfaabi_dbg_write( buffer, len )         __cfaabi_bits_write( STDERR_FILENO, buffer, len )
     53        #define __cfaabi_dbg_acquire()                    __cfaabi_bits_acquire()
     54        #define __cfaabi_dbg_release()                    __cfaabi_bits_release()
     55        #define __cfaabi_dbg_print_safe(...)              __cfaabi_bits_print_safe   (__VA_ARGS__)
     56        #define __cfaabi_dbg_print_nolock(...)            __cfaabi_bits_print_nolock (__VA_ARGS__)
     57        #define __cfaabi_dbg_print_buffer(...)            __cfaabi_bits_print_buffer (__VA_ARGS__)
     58        #define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_bits_write( __dbg_text, __dbg_len );
     59        #define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_write( __dbg_text, __dbg_len );
    6060#else
    6161        #define __cfaabi_dbg_write(...)               ((void)0)
  • libcfa/src/bits/defs.hfa

    raca6a54c r2fa5bd2  
    4747#define OPTIONAL_THREAD __attribute__((weak))
    4848#endif
     49
     50static inline long long rdtscl(void) {
     51    unsigned int lo, hi;
     52    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
     53    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
     54}
  • libcfa/src/concurrency/alarm.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Fri Jun 2 11:31:25 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri May 25 06:25:47 2018
    13 // Update Count     : 67
     12// Last Modified On : Tue Dec  3 22:47:24 2019
     13// Update Count     : 68
    1414//
    1515
     
    4040void __kernel_set_timer( Duration alarm ) {
    4141        verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (%jins)", alarm.tv);
    42         setitimer( ITIMER_REAL, &(itimerval){ alarm }, NULL );
     42        setitimer( ITIMER_REAL, &(itimerval){ alarm }, 0p );
    4343}
    4444
     
    113113                        this->tail = &this->head;
    114114                }
    115                 head->next = NULL;
     115                head->next = 0p;
    116116        }
    117117        verify( validate( this ) );
     
    127127                this->tail = it;
    128128        }
    129         n->next = NULL;
     129        n->next = 0p;
    130130
    131131        verify( validate( this ) );
  • libcfa/src/concurrency/coroutine.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 17:20:57 2018
    13 // Update Count     : 9
     12// Last Modified On : Thu Dec  5 14:37:29 2019
     13// Update Count     : 15
    1414//
    1515
     
    9090
    9191void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
    92         (this.context){NULL, NULL};
     92        (this.context){0p, 0p};
    9393        (this.stack){storage, storageSize};
    9494        this.name = name;
    9595        state = Start;
    96         starter = NULL;
    97         last = NULL;
    98         cancellation = NULL;
     96        starter = 0p;
     97        last = 0p;
     98        cancellation = 0p;
    9999}
    100100
     
    131131
    132132[void *, size_t] __stack_alloc( size_t storageSize ) {
    133         static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     133        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    134134        assert(__page_size != 0l);
    135135        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
     
    157157
    158158void __stack_prepare( __stack_info_t * this, size_t create_size ) {
    159         static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     159        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    160160        bool userStack;
    161161        void * storage;
  • libcfa/src/concurrency/coroutine.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 17:49:39 2019
    13 // Update Count     : 9
     12// Last Modified On : Tue Dec  3 22:47:58 2019
     13// Update Count     : 10
    1414//
    1515
     
    3838void ^?{}( coroutine_desc & this );
    3939
    40 static inline void ?{}( coroutine_desc & this)                                       { this{ "Anonymous Coroutine", NULL, 0 }; }
    41 static inline void ?{}( coroutine_desc & this, size_t stackSize)                     { this{ "Anonymous Coroutine", NULL, stackSize }; }
     40static inline void ?{}( coroutine_desc & this)                                       { this{ "Anonymous Coroutine", 0p, 0 }; }
     41static inline void ?{}( coroutine_desc & this, size_t stackSize)                     { this{ "Anonymous Coroutine", 0p, stackSize }; }
    4242static inline void ?{}( coroutine_desc & this, void * storage, size_t storageSize )  { this{ "Anonymous Coroutine", storage, storageSize }; }
    43 static inline void ?{}( coroutine_desc & this, const char * name)                    { this{ name, NULL, 0 }; }
    44 static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, NULL, stackSize }; }
     43static inline void ?{}( coroutine_desc & this, const char * name)                    { this{ name, 0p, 0 }; }
     44static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, 0p, stackSize }; }
    4545
    4646//-----------------------------------------------------------------------------
     
    8989        src->state = Active;
    9090
    91         if( unlikely(src->cancellation != NULL) ) {
     91        if( unlikely(src->cancellation != 0p) ) {
    9292                _CtxCoroutine_Unwind(src->cancellation, src);
    9393        }
     
    128128        coroutine_desc * dst = get_coroutine(cor);
    129129
    130         if( unlikely(dst->context.SP == NULL) ) {
     130        if( unlikely(dst->context.SP == 0p) ) {
    131131                __stack_prepare(&dst->stack, 65000);
    132132                CtxStart(&cor, CtxInvokeCoroutine);
  • libcfa/src/concurrency/invoke.h

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 22 18:19:13 2019
    13 // Update Count     : 40
     12// Last Modified On : Thu Dec  5 16:26:03 2019
     13// Update Count     : 44
    1414//
    1515
     
    4646        #ifdef __cforall
    4747        extern "Cforall" {
    48                 extern thread_local struct KernelThreadData {
     48                extern __attribute__((aligned(128))) thread_local struct KernelThreadData {
    4949                        struct thread_desc    * volatile this_thread;
    5050                        struct processor      * volatile this_processor;
     
    5555                                volatile bool in_progress;
    5656                        } preemption_state;
     57
     58                        uint32_t rand_seed;
    5759                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    5860        }
     
    205207
    206208                static inline void ?{}(__monitor_group_t & this) {
    207                         (this.data){NULL};
     209                        (this.data){0p};
    208210                        (this.size){0};
    209211                        (this.func){NULL};
  • libcfa/src/concurrency/kernel.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun 20 17:21:23 2019
    13 // Update Count     : 25
     12// Last Modified On : Thu Dec  5 16:25:52 2019
     13// Update Count     : 52
    1414//
    1515
     
    2626#include <signal.h>
    2727#include <unistd.h>
     28#include <limits.h>                                                                             // PTHREAD_STACK_MIN
     29#include <sys/mman.h>                                                                   // mprotect
    2830}
    2931
     
    4042//-----------------------------------------------------------------------------
    4143// Some assembly required
    42 #if   defined( __i386 )
     44#if defined( __i386 )
    4345        #define CtxGet( ctx )        \
    4446                __asm__ volatile (     \
     
    123125
    124126extern "C" {
    125 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
     127        struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    126128}
    127129
     
    131133// Global state
    132134thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) = {
     135        NULL,                                                                                           // cannot use 0p
    133136        NULL,
    134         NULL,
    135         { 1, false, false }
     137        { 1, false, false },
     138        6u //this should be seeded better but due to a bug calling rdtsc doesn't work
    136139};
    137140
     
    139142// Struct to steal stack
    140143struct current_stack_info_t {
    141         __stack_t * storage;            // pointer to stack object
    142         void *base;                             // base of stack
    143         void *limit;                    // stack grows towards stack limit
    144         void *context;                  // address of cfa_context_t
     144        __stack_t * storage;                                                            // pointer to stack object
     145        void * base;                                                                            // base of stack
     146        void * limit;                                                                           // stack grows towards stack limit
     147        void * context;                                                                         // address of cfa_context_t
    145148};
    146149
     
    171174        name = "Main Thread";
    172175        state = Start;
    173         starter = NULL;
    174         last = NULL;
    175         cancellation = NULL;
     176        starter = 0p;
     177        last = 0p;
     178        cancellation = 0p;
    176179}
    177180
     
    184187        self_mon.recursion = 1;
    185188        self_mon_p = &self_mon;
    186         next = NULL;
    187 
    188         node.next = NULL;
    189         node.prev = NULL;
     189        next = 0p;
     190
     191        node.next = 0p;
     192        node.prev = 0p;
    190193        doregister(curr_cluster, this);
    191194
     
    211214        terminated{ 0 };
    212215        do_terminate = false;
    213         preemption_alarm = NULL;
     216        preemption_alarm = 0p;
    214217        pending_preemption = false;
    215218        runner.proc = &this;
     
    231234        }
    232235
    233         pthread_join( kernel_thread, NULL );
     236        pthread_join( kernel_thread, 0p );
     237        free( this.stack );
    234238}
    235239
     
    260264//Main of the processor contexts
    261265void main(processorCtx_t & runner) {
     266        // Because of a bug, we couldn't initialized the seed on construction
     267        // Do it here
     268        kernelTLS.rand_seed ^= rdtscl();
     269
    262270        processor * this = runner.proc;
    263271        verify(this);
     
    273281                __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
    274282
    275                 thread_desc * readyThread = NULL;
    276                 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ )
    277                 {
     283                thread_desc * readyThread = 0p;
     284                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) {
    278285                        readyThread = nextThread( this->cltr );
    279286
    280                         if(readyThread)
    281                         {
     287                        if(readyThread) {
    282288                                verify( ! kernelTLS.preemption_state.enabled );
    283289
     
    290296
    291297                                spin_count = 0;
    292                         }
    293                         else
    294                         {
     298                        } else {
    295299                                // spin(this, &spin_count);
    296300                                halt(this);
     
    405409        processor * proc = (processor *) arg;
    406410        kernelTLS.this_processor = proc;
    407         kernelTLS.this_thread    = NULL;
     411        kernelTLS.this_thread    = 0p;
    408412        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
    409413        // SKULLDUGGERY: We want to create a context for the processor coroutine
     
    418422
    419423        //Set global state
    420         kernelTLS.this_thread    = NULL;
     424        kernelTLS.this_thread = 0p;
    421425
    422426        //We now have a proper context from which to schedule threads
     
    434438        __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner);
    435439
    436         return NULL;
     440        return 0p;
     441}
     442
     443static void Abort( int ret, const char * func ) {
     444        if ( ret ) {                                                                            // pthread routines return errno values
     445                abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) );
     446        } // if
     447} // Abort
     448
     449void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
     450        pthread_attr_t attr;
     451
     452        Abort( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     453
     454        size_t stacksize;
     455        // default stack size, normally defined by shell limit
     456        Abort( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     457        assert( stacksize >= PTHREAD_STACK_MIN );
     458
     459        void * stack;
     460        __cfaabi_dbg_debug_do(
     461                stack = memalign( __page_size, stacksize + __page_size );
     462                // pthread has no mechanism to create the guard page in user supplied stack.
     463                if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     464                        abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     465                } // if
     466        );
     467        __cfaabi_dbg_no_debug_do(
     468                stack = malloc( stacksize );
     469        );
     470
     471        Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     472
     473        Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     474        return stack;
    437475}
    438476
     
    440478        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);
    441479
    442         pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
     480        this->stack = create_pthread( &this->kernel_thread, CtxInvokeProcessor, (void *)this );
    443481
    444482        __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
     
    497535        verify( ! kernelTLS.preemption_state.enabled );
    498536
    499         verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
     537        verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
    500538
    501539        with( *thrd->curr_cluster ) {
     
    676714        void ?{}(processorCtx_t & this, processor * proc) {
    677715                (this.__cor){ "Processor" };
    678                 this.__cor.starter = NULL;
     716                this.__cor.starter = 0p;
    679717                this.proc = proc;
    680718        }
     
    685723                terminated{ 0 };
    686724                do_terminate = false;
    687                 preemption_alarm = NULL;
     725                preemption_alarm = 0p;
    688726                pending_preemption = false;
    689727                kernel_thread = pthread_self();
     
    819857        if(thrd) {
    820858                int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd );
    821                 __cfaabi_dbg_bits_write( abort_text, len );
     859                __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    822860
    823861                if ( &thrd->self_cor != thrd->curr_cor ) {
    824862                        len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor );
    825                         __cfaabi_dbg_bits_write( abort_text, len );
     863                        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    826864                }
    827865                else {
    828                         __cfaabi_dbg_bits_write( ".\n", 2 );
     866                        __cfaabi_bits_write( STDERR_FILENO, ".\n", 2 );
    829867                }
    830868        }
    831869        else {
    832870                int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" );
    833                 __cfaabi_dbg_bits_write( abort_text, len );
     871                __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    834872        }
    835873}
     
    842880
    843881extern "C" {
    844         void __cfaabi_dbg_bits_acquire() {
     882        void __cfaabi_bits_acquire() {
    845883                lock( kernel_debug_lock __cfaabi_dbg_ctx2 );
    846884        }
    847885
    848         void __cfaabi_dbg_bits_release() {
     886        void __cfaabi_bits_release() {
    849887                unlock( kernel_debug_lock );
    850888        }
     
    879917
    880918void V(semaphore & this) with( this ) {
    881         thread_desc * thrd = NULL;
     919        thread_desc * thrd = 0p;
    882920        lock( lock __cfaabi_dbg_ctx2 );
    883921        count += 1;
  • libcfa/src/concurrency/kernel.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 22 11:39:17 2019
    13 // Update Count     : 16
     12// Last Modified On : Wed Dec  4 07:54:51 2019
     13// Update Count     : 18
    1414//
    1515
     
    2020#include "invoke.h"
    2121#include "time_t.hfa"
     22#include "coroutine.hfa"
    2223
    2324extern "C" {
     
    8889static inline void ?{}(FinishAction & this) {
    8990        this.action_code = No_Action;
    90         this.thrd = NULL;
    91         this.lock = NULL;
     91        this.thrd = 0p;
     92        this.lock = 0p;
    9293}
    9394static inline void ^?{}(FinishAction &) {}
     
    134135        semaphore terminated;
    135136
     137        // pthread Stack
     138        void * stack;
     139
    136140        // Link lists fields
    137141        struct __dbg_node_proc {
  • libcfa/src/concurrency/kernel_private.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Feb 13 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 29 14:06:40 2018
    13 // Update Count     : 3
     12// Last Modified On : Sat Nov 30 19:25:02 2019
     13// Update Count     : 8
    1414//
    1515
     
    5757void main(processorCtx_t *);
    5858
     59void * create_pthread( pthread_t *, void * (*)(void *), void * );
     60
    5961static inline void wake_fast(processor * this) {
    6062        __cfaabi_dbg_print_safe("Kernel : Waking up processor %p\n", this);
     
    101103#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    102104
     105static inline uint32_t tls_rand() {
     106        kernelTLS.rand_seed ^= kernelTLS.rand_seed << 6;
     107        kernelTLS.rand_seed ^= kernelTLS.rand_seed >> 21;
     108        kernelTLS.rand_seed ^= kernelTLS.rand_seed << 7;
     109        return kernelTLS.rand_seed;
     110}
     111
    103112
    104113void doregister( struct cluster & cltr );
  • libcfa/src/concurrency/monitor.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 14:30:26 2018
    13 // Update Count     : 9
     12// Last Modified On : Wed Dec  4 07:55:14 2019
     13// Update Count     : 10
    1414//
    1515
     
    363363        this.waiting_thread = waiting_thread;
    364364        this.count = count;
    365         this.next = NULL;
     365        this.next = 0p;
    366366        this.user_info = user_info;
    367367}
     
    369369void ?{}(__condition_criterion_t & this ) with( this ) {
    370370        ready  = false;
    371         target = NULL;
    372         owner  = NULL;
    373         next   = NULL;
     371        target = 0p;
     372        owner  = 0p;
     373        next   = 0p;
    374374}
    375375
     
    378378        this.target = target;
    379379        this.owner  = &owner;
    380         this.next   = NULL;
     380        this.next   = 0p;
    381381}
    382382
     
    387387
    388388        // Check that everything is as expected
    389         assertf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
     389        assertf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
    390390        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    391391        verifyf( this.monitor_count < 32u, "Excessive monitor count (%"PRIiFAST16")", this.monitor_count );
     
    449449
    450450        // Lock all monitors
    451         lock_all( this.monitors, NULL, count );
     451        lock_all( this.monitors, 0p, count );
    452452
    453453        //Pop the head of the waiting queue
     
    471471
    472472        //Check that everything is as expected
    473         verifyf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
     473        verifyf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
    474474        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    475475
     
    674674
    675675static inline void reset_mask( monitor_desc * this ) {
    676         this->mask.accepted = NULL;
    677         this->mask.data = NULL;
     676        this->mask.accepted = 0p;
     677        this->mask.data = 0p;
    678678        this->mask.size = 0;
    679679}
     
    816816        }
    817817
    818         __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : NULL );
    819         return ready2run ? node->waiting_thread : NULL;
     818        __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : 0p );
     819        return ready2run ? node->waiting_thread : 0p;
    820820}
    821821
     
    824824        if( !this.monitors ) {
    825825                // __cfaabi_dbg_print_safe( "Branding\n" );
    826                 assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
     826                assertf( thrd->monitors.data != 0p, "No current monitor to brand condition %p", thrd->monitors.data );
    827827                this.monitor_count = thrd->monitors.size;
    828828
  • libcfa/src/concurrency/monitor.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct  7 18:06:45 2017
    13 // Update Count     : 10
     12// Last Modified On : Wed Dec  4 07:55:32 2019
     13// Update Count     : 11
    1414//
    1515
     
    3131        entry_queue{};
    3232        signal_stack{};
    33         owner         = NULL;
     33        owner         = 0p;
    3434        recursion     = 0;
    35         mask.accepted = NULL;
    36         mask.data     = NULL;
     35        mask.accepted = 0p;
     36        mask.data     = 0p;
    3737        mask.size     = 0;
    38         dtor_node     = NULL;
     38        dtor_node     = 0p;
    3939}
     40
     41static inline void ^?{}(monitor_desc & ) {}
    4042
    4143struct monitor_guard_t {
     
    120122
    121123static inline void ?{}( condition & this ) {
    122         this.monitors = NULL;
     124        this.monitors = 0p;
    123125        this.monitor_count = 0;
    124126}
  • libcfa/src/concurrency/mutex.cfa

    raca6a54c r2fa5bd2  
    1111// Author           : Thierry Delisle
    1212// Created On       : Fri May 25 01:37:11 2018
    13 // Last Modified By : Thierry Delisle
    14 // Last Modified On : Fri May 25 01:37:51 2018
    15 // Update Count     : 0
     13// Last Modified By : Peter A. Buhr
     14// Last Modified On : Wed Dec  4 09:16:39 2019
     15// Update Count     : 1
    1616//
    1717
     
    7373        this.lock{};
    7474        this.blocked_threads{};
    75         this.owner = NULL;
     75        this.owner = 0p;
    7676        this.recursion_count = 0;
    7777}
     
    8383void lock(recursive_mutex_lock & this) with(this) {
    8484        lock( lock __cfaabi_dbg_ctx2 );
    85         if( owner == NULL ) {
     85        if( owner == 0p ) {
    8686                owner = kernelTLS.this_thread;
    8787                recursion_count = 1;
     
    101101        bool ret = false;
    102102        lock( lock __cfaabi_dbg_ctx2 );
    103         if( owner == NULL ) {
     103        if( owner == 0p ) {
    104104                owner = kernelTLS.this_thread;
    105105                recursion_count = 1;
  • libcfa/src/concurrency/mutex.hfa

    raca6a54c r2fa5bd2  
    1111// Author           : Thierry Delisle
    1212// Created On       : Fri May 25 01:24:09 2018
    13 // Last Modified By : Thierry Delisle
    14 // Last Modified On : Fri May 25 01:24:12 2018
    15 // Update Count     : 0
     13// Last Modified By : Peter A. Buhr
     14// Last Modified On : Wed Dec  4 09:16:53 2019
     15// Update Count     : 1
    1616//
    1717
     
    110110
    111111        static inline void ?{}(lock_scope(L) & this) {
    112                 this.locks = NULL;
     112                this.locks = 0p;
    113113                this.count = 0;
    114114        }
  • libcfa/src/concurrency/preemption.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 17:35:49 2018
    13 // Update Count     : 37
     12// Last Modified On : Thu Dec  5 16:34:05 2019
     13// Update Count     : 43
    1414//
    1515
     
    2424#include <string.h>
    2525#include <unistd.h>
     26#include <limits.h>                                                                             // PTHREAD_STACK_MIN
    2627}
    2728
     
    6465event_kernel_t * event_kernel;                        // kernel public handle to even kernel
    6566static pthread_t alarm_thread;                        // pthread handle to alarm thread
     67static void * alarm_stack;                                                        // pthread stack for alarm thread
    6668
    6769static void ?{}(event_kernel_t & this) with( this ) {
     
    8183// Get next expired node
    8284static inline alarm_node_t * get_expired( alarm_list_t * alarms, Time currtime ) {
    83         if( !alarms->head ) return NULL;                          // If no alarms return null
    84         if( alarms->head->alarm >= currtime ) return NULL;        // If alarms head not expired return null
    85         return pop(alarms);                                       // Otherwise just pop head
     85        if( !alarms->head ) return 0p;                                          // If no alarms return null
     86        if( alarms->head->alarm >= currtime ) return 0p;        // If alarms head not expired return null
     87        return pop(alarms);                                                                     // Otherwise just pop head
    8688}
    8789
    8890// Tick one frame of the Discrete Event Simulation for alarms
    8991static void tick_preemption() {
    90         alarm_node_t * node = NULL;                     // Used in the while loop but cannot be declared in the while condition
    91         alarm_list_t * alarms = &event_kernel->alarms;  // Local copy for ease of reading
    92         Time currtime = __kernel_get_time();                    // Check current time once so we everything "happens at once"
     92        alarm_node_t * node = 0p;                                                       // Used in the while loop but cannot be declared in the while condition
     93        alarm_list_t * alarms = &event_kernel->alarms;          // Local copy for ease of reading
     94        Time currtime = __kernel_get_time();                            // Check current time once so everything "happens at once"
    9395
    9496        //Loop throught every thing expired
     
    243245        sigaddset( &mask, sig );
    244246
    245         if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     247        if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
    246248            abort( "internal error, pthread_sigmask" );
    247249        }
     
    254256        sigaddset( &mask, sig );
    255257
    256         if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     258        if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    257259            abort( "internal error, pthread_sigmask" );
    258260        }
     
    301303
    302304        // Setup proper signal handlers
    303         __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART );         // CtxSwitch handler
     305        __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART ); // CtxSwitch handler
    304306
    305307        signal_block( SIGALRM );
    306308
    307         pthread_create( &alarm_thread, NULL, alarm_loop, NULL );
     309        alarm_stack = create_pthread( &alarm_thread, alarm_loop, 0p );
    308310}
    309311
     
    316318        sigset_t mask;
    317319        sigfillset( &mask );
    318         sigprocmask( SIG_BLOCK, &mask, NULL );
     320        sigprocmask( SIG_BLOCK, &mask, 0p );
    319321
    320322        // Notify the alarm thread of the shutdown
     
    323325
    324326        // Wait for the preemption thread to finish
    325         pthread_join( alarm_thread, NULL );
     327
     328        pthread_join( alarm_thread, 0p );
     329        free( alarm_stack );
    326330
    327331        // Preemption is now fully stopped
     
    380384        static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
    381385        #endif
    382         if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), NULL ) == -1 ) {
     386        if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
    383387                abort( "internal error, sigprocmask" );
    384388        }
     
    399403        sigset_t mask;
    400404        sigfillset(&mask);
    401         if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     405        if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    402406            abort( "internal error, pthread_sigmask" );
    403407        }
     
    420424                                        {__cfaabi_dbg_print_buffer_decl( " KERNEL: Spurious wakeup %d.\n", err );}
    421425                                        continue;
    422                         case EINVAL :
     426                                case EINVAL :
    423427                                        abort( "Timeout was invalid." );
    424428                                default:
     
    453457EXIT:
    454458        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    455         return NULL;
     459        return 0p;
    456460}
    457461
     
    466470        sigset_t oldset;
    467471        int ret;
    468         ret = pthread_sigmask(0, NULL, &oldset);
     472        ret = pthread_sigmask(0, 0p, &oldset);
    469473        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    470474
  • libcfa/src/concurrency/thread.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 17:19:52 2018
    13 // Update Count     : 8
     12// Last Modified On : Wed Dec  4 09:17:49 2019
     13// Update Count     : 9
    1414//
    1515
     
    3333// Thread ctors and dtors
    3434void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
    35         context{ NULL, NULL };
     35        context{ 0p, 0p };
    3636        self_cor{ name, storage, storageSize };
    3737        state = Start;
     
    4141        self_mon_p = &self_mon;
    4242        curr_cluster = &cl;
    43         next = NULL;
     43        next = 0p;
    4444
    45         node.next = NULL;
    46         node.prev = NULL;
     45        node.next = 0p;
     46        node.prev = 0p;
    4747        doregister(curr_cluster, this);
    4848
  • libcfa/src/concurrency/thread.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 17:51:33 2019
    13 // Update Count     : 5
     12// Last Modified On : Wed Dec  4 09:18:14 2019
     13// Update Count     : 6
    1414//
    1515
     
    6161void ^?{}(thread_desc & this);
    6262
    63 static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 65000 }; }
    64 static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
     63static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, 0p, 65000 }; }
     64static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, 0p, stackSize }; }
    6565static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
    66 static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 65000 }; }
    67 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, NULL, stackSize }; }
     66static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, 0p, 65000 }; }
     67static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0p, stackSize }; }
    6868static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
    69 static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 65000 }; }
    70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 65000 }; }
    71 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
     69static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, 0p, 65000 }; }
     70static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, 0p, 65000 }; }
     71static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, 0p, stackSize }; }
    7272
    7373//-----------------------------------------------------------------------------
  • libcfa/src/fstream.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Sep 10 22:19:56 2019
    13 // Update Count     : 354
     12// Last Modified On : Fri Nov 29 06:56:46 2019
     13// Update Count     : 355
    1414//
    1515
     
    6666} // ?{}
    6767
     68void ^?{}( ofstream & os ) {
     69        close( os );
     70} // ^?{}
     71
    6872void sepOn( ofstream & os ) { os.sepOnOff = ! getNL( os ); }
    6973void sepOff( ofstream & os ) { os.sepOnOff = false; }
     
    195199} // ?{}
    196200
     201void ^?{}( ifstream & is ) {
     202        close( is );
     203} // ^?{}
     204
    197205void nlOn( ifstream & os ) { os.nlOnOff = true; }
    198206void nlOff( ifstream & os ) { os.nlOnOff = false; }
  • libcfa/src/fstream.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul 15 18:10:23 2019
    13 // Update Count     : 167
     12// Last Modified On : Fri Nov 29 06:56:02 2019
     13// Update Count     : 168
    1414//
    1515
     
    7272void ?{}( ofstream & os, const char * name, const char * mode );
    7373void ?{}( ofstream & os, const char * name );
     74void ^?{}( ofstream & os );
    7475
    7576extern ofstream & sout, & stdout, & serr, & stderr;             // aliases
     
    101102void ?{}( ifstream & is, const char * name, const char * mode );
    102103void ?{}( ifstream & is, const char * name );
     104void ^?{}( ifstream & is );
    103105
    104106extern ifstream & sin, & stdin;                                                 // aliases
  • libcfa/src/heap.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct 18 07:42:09 2019
    13 // Update Count     : 556
     12// Last Modified On : Wed Dec  4 21:42:46 2019
     13// Update Count     : 646
    1414//
    1515
     
    1818#include <stdio.h>                                                                              // snprintf, fileno
    1919#include <errno.h>                                                                              // errno
     20#include <string.h>                                                                             // memset, memcpy
    2021extern "C" {
    2122#include <sys/mman.h>                                                                   // mmap, munmap
     
    2728#include "bits/locks.hfa"                                                               // __spinlock_t
    2829#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    29 #include "stdlib.hfa"                                                                   // bsearchl
     30//#include "stdlib.hfa"                                                                 // bsearchl
    3031#include "malloc.h"
    3132
     33#define MIN(x, y) (y > x ? x : y)
    3234
    3335static bool traceHeap = false;
    3436
    35 inline bool traceHeap() {
    36         return traceHeap;
    37 } // traceHeap
     37inline bool traceHeap() { return traceHeap; }
    3838
    3939bool traceHeapOn() {
     
    4949} // traceHeapOff
    5050
    51 
    52 static bool checkFree = false;
    53 
    54 inline bool checkFree() {
    55         return checkFree;
    56 } // checkFree
    57 
    58 bool checkFreeOn() {
    59         bool temp = checkFree;
    60         checkFree = true;
     51bool traceHeapTerm() { return false; }
     52
     53
     54static bool prtFree = false;
     55
     56inline bool prtFree() {
     57        return prtFree;
     58} // prtFree
     59
     60bool prtFreeOn() {
     61        bool temp = prtFree;
     62        prtFree = true;
    6163        return temp;
    62 } // checkFreeOn
    63 
    64 bool checkFreeOff() {
    65         bool temp = checkFree;
    66         checkFree = false;
     64} // prtFreeOn
     65
     66bool prtFreeOff() {
     67        bool temp = prtFree;
     68        prtFree = false;
    6769        return temp;
    68 } // checkFreeOff
    69 
    70 
    71 // static bool traceHeapTerm = false;
    72 
    73 // inline bool traceHeapTerm() {
    74 //      return traceHeapTerm;
    75 // } // traceHeapTerm
    76 
    77 // bool traceHeapTermOn() {
    78 //      bool temp = traceHeapTerm;
    79 //      traceHeapTerm = true;
    80 //      return temp;
    81 // } // traceHeapTermOn
    82 
    83 // bool traceHeapTermOff() {
    84 //      bool temp = traceHeapTerm;
    85 //      traceHeapTerm = false;
    86 //      return temp;
    87 // } // traceHeapTermOff
     70} // prtFreeOff
    8871
    8972
    9073enum {
     74        // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
     75        // the brk address is extended by the extension amount.
     76        __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
     77
     78        // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
     79        // values greater than or equal to this value are mmap from the operating system.
    9180        __CFA_DEFAULT_MMAP_START__ = (512 * 1024 + 1),
    92         __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
    9381};
    9482
     
    10593static unsigned int allocFree;                                                  // running total of allocations minus frees
    10694
    107 static void checkUnfreed() {
     95static void prtUnfreed() {
    10896        if ( allocFree != 0 ) {
    10997                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    110                 // char helpText[512];
    111                 // int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
    112                 //                                      "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    113                 //                                      (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
    114                 // __cfaabi_dbg_bits_write( helpText, len );
    115         } // if
    116 } // checkUnfreed
     98                char helpText[512];
     99                int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
     100                                                        "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
     101                                                        (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
     102                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     103        } // if
     104} // prtUnfreed
    117105
    118106extern "C" {
     
    123111        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    124112                fclose( stdin ); fclose( stdout );
    125                 checkUnfreed();
     113                prtUnfreed();
    126114        } // heapAppStop
    127115} // extern "C"
    128116#endif // __CFA_DEBUG__
     117
    129118
    130119// statically allocated variables => zero filled.
     
    134123static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    135124
    136 
    137 // #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
    138 #define ALIGN 16
    139125
    140126#define SPINLOCK 0
     
    147133// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    148134// Break recusion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    149 enum { NoBucketSizes = 93 };                                                    // number of buckets sizes
     135enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
    150136
    151137struct HeapManager {
     
    194180                        } kind; // Kind
    195181                } header; // Header
    196                 char pad[ALIGN - sizeof( Header )];
     182                char pad[libAlign() - sizeof( Header )];
    197183                char data[0];                                                                   // storage
    198184        }; // Storage
    199185
    200         static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
     186        static_assert( libAlign() >= sizeof( Storage ), "libAlign() < sizeof( Storage )" );
    201187
    202188        struct FreeHeader {
     
    228214#define __STATISTICS__
    229215
     216// Bucket size must be multiple of 16.
    230217// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
    231218static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    232         16, 32, 48, 64,
    233         64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
    234         256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
    235         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,
    236         8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
    237         16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
    238         32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
    239         65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
    240         131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
    241         262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
    242         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,
    243         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,
    244         4_194_304 + sizeof(HeapManager.Storage)
     219        16, 32, 48, 64 + sizeof(HeapManager.Storage), // 4
     220        96, 112, 128 + sizeof(HeapManager.Storage), // 3
     221        160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
     222        320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
     223        640, 768, 896, 1_024 + sizeof(HeapManager.Storage), // 4
     224        1_536, 2_048 + sizeof(HeapManager.Storage), // 2
     225        2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), // 4
     226        6_144, 8_192 + sizeof(HeapManager.Storage), // 2
     227        9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(HeapManager.Storage), // 8
     228        18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(HeapManager.Storage), // 8
     229        36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(HeapManager.Storage), // 8
     230        73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(HeapManager.Storage), // 8
     231        147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(HeapManager.Storage), // 8
     232        294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(HeapManager.Storage), // 8
     233        655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), // 4
     234        1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), // 8
     235        2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(HeapManager.Storage), // 4
    245236};
    246237
     
    251242static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    252243#endif // FASTLOOKUP
     244
    253245static int mmapFd = -1;                                                                 // fake or actual fd for anonymous file
    254 
    255 
    256246#ifdef __CFA_DEBUG__
    257247static bool heapBoot = 0;                                                               // detect recursion during boot
     
    259249static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    260250
    261 // #comment TD : The return type of this function should be commented
    262 static inline bool setMmapStart( size_t value ) {
    263   if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
    264         mmapStart = value;                                                                      // set global
    265 
    266         // find the closest bucket size less than or equal to the mmapStart size
    267         maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    268         assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    269         assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    270         return false;
    271 } // setMmapStart
    272 
    273 
    274 static void ?{}( HeapManager & manager ) with ( manager ) {
    275         pageSize = sysconf( _SC_PAGESIZE );
    276 
    277         for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    278                 freeLists[i].blockSize = bucketSizes[i];
    279         } // for
    280 
    281         #ifdef FASTLOOKUP
    282         unsigned int idx = 0;
    283         for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    284                 if ( i > bucketSizes[idx] ) idx += 1;
    285                 lookup[i] = idx;
    286         } // for
    287         #endif // FASTLOOKUP
    288 
    289         if ( setMmapStart( default_mmap_start() ) ) {
    290                 abort( "HeapManager : internal error, mmap start initialization failure." );
    291         } // if
    292         heapExpand = default_heap_expansion();
    293 
    294         char * End = (char *)sbrk( 0 );
    295         sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    296         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
    297 } // HeapManager
    298 
    299 
    300 static void ^?{}( HeapManager & ) {
    301         #ifdef __STATISTICS__
    302         // if ( traceHeapTerm() ) {
    303         //      printStats();
    304         //      if ( checkfree() ) checkFree( heapManager, true );
    305         // } // if
    306         #endif // __STATISTICS__
    307 } // ~HeapManager
    308 
    309 
    310 static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
    311 void memory_startup( void ) {
    312         #ifdef __CFA_DEBUG__
    313         if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
    314                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    315                 abort( "boot() : internal error, recursively invoked during system boot." );
    316         } // if
    317         heapBoot = true;
    318         #endif // __CFA_DEBUG__
    319 
    320         //assert( heapManager.heapBegin != 0 );
    321         //heapManager{};
    322         if ( heapManager.heapBegin == 0 ) heapManager{};
    323 } // memory_startup
    324 
    325 static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
    326 void memory_shutdown( void ) {
    327         ^heapManager{};
    328 } // memory_shutdown
    329 
    330251
    331252#ifdef __STATISTICS__
    332 static unsigned long long int mmap_storage;                             // heap statistics counters
     253// Heap statistics counters.
     254static unsigned long long int mmap_storage;
    333255static unsigned int mmap_calls;
    334256static unsigned long long int munmap_storage;
     
    348270static unsigned long long int realloc_storage;
    349271static unsigned int realloc_calls;
    350 
    351 static int statfd;                                                                              // statistics file descriptor (changed by malloc_stats_fd)
    352 
     272// Statistics file descriptor (changed by malloc_stats_fd).
     273static int statfd = STDERR_FILENO;                                              // default stderr
    353274
    354275// Use "write" because streams may be shutdown when calls are made.
    355276static void printStats() {
    356277        char helpText[512];
    357         __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
     278        __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    358279                                                                        "\nHeap statistics:\n"
    359280                                                                        "  malloc: calls %u / storage %llu\n"
     
    405326                                                sbrk_calls, sbrk_storage
    406327                );
    407         return write( fileno( stream ), helpText, len );        // -1 => error
     328        __cfaabi_bits_write( fileno( stream ), helpText, len ); // ensures all bytes written or exit
     329        return len;
    408330} // printStatsXML
    409331#endif // __STATISTICS__
     332
    410333
    411334// #comment TD : Is this the samething as Out-of-Memory?
     
    418341
    419342static inline void checkAlign( size_t alignment ) {
    420         if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
    421                 abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
     343        if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     344                abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
    422345        } // if
    423346} // checkAlign
     
    431354
    432355
    433 static inline void checkHeader( bool check, const char * name, void * addr ) {
    434         if ( unlikely( check ) ) {                                                      // bad address ?
    435                 abort( "Attempt to %s storage %p with address outside the heap.\n"
    436                            "Possible cause is duplicate free on same block or overwriting of memory.",
    437                            name, addr );
    438         } // if
    439 } // checkHeader
    440 
    441 // #comment TD : function should be commented and/or have a more evocative name
    442 //               this isn't either a check or a constructor which is what I would expect this function to be
    443 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
    444         if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    445                 size_t offset = header->kind.fake.offset;
    446                 alignment = header->kind.fake.alignment & -2;   // remove flag from value
    447                 #ifdef __CFA_DEBUG__
    448                 checkAlign( alignment );                                                // check alignment
    449                 #endif // __CFA_DEBUG__
    450                 header = (HeapManager.Storage.Header *)((char *)header - offset);
    451         } // if
    452 } // fakeHeader
    453 
    454 // #comment TD : Why is this a define
    455 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    456 
    457 static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    458         header = headerAddr( addr );
    459 
    460         if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
    461                 fakeHeader( header, size, alignment );
    462                 size = header->kind.real.blockSize & -3;                // mmap size
    463                 return true;
    464         } // if
    465 
    466         #ifdef __CFA_DEBUG__
    467         checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    468         #endif // __CFA_DEBUG__
    469 
    470         // #comment TD : This code looks weird...
    471         //               It's called as the first statement of both branches of the last if, with the same parameters in all cases
    472 
    473         // header may be safe to dereference
    474         fakeHeader( header, size, alignment );
    475         #ifdef __CFA_DEBUG__
    476         checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    477         #endif // __CFA_DEBUG__
    478 
    479         freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
    480         #ifdef __CFA_DEBUG__
    481         if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
    482                 abort( "Attempt to %s storage %p with corrupted header.\n"
    483                            "Possible cause is duplicate free on same block or overwriting of header information.",
    484                            name, addr );
    485         } // if
    486         #endif // __CFA_DEBUG__
    487         size = freeElem->blockSize;
    488         return false;
    489 } // headers
    490 
    491 
    492 static inline void * extend( size_t size ) with ( heapManager ) {
    493         lock( extlock __cfaabi_dbg_ctx2 );
    494         ptrdiff_t rem = heapRemaining - size;
    495         if ( rem < 0 ) {
    496                 // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    497 
    498                 size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
    499                 if ( sbrk( increase ) == (void *)-1 ) {
    500                         unlock( extlock );
    501                         errno = ENOMEM;
    502                         return 0;
    503                 } // if
    504                 #ifdef __STATISTICS__
    505                 sbrk_calls += 1;
    506                 sbrk_storage += increase;
    507                 #endif // __STATISTICS__
    508                 #ifdef __CFA_DEBUG__
    509                 // Set new memory to garbage so subsequent uninitialized usages might fail.
    510                 memset( (char *)heapEnd + heapRemaining, '\377', increase );
    511                 #endif // __CFA_DEBUG__
    512                 rem = heapRemaining + increase - size;
    513         } // if
    514 
    515         HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
    516         heapRemaining = rem;
    517         heapEnd = (char *)heapEnd + size;
    518         unlock( extlock );
    519         return block;
    520 } // extend
    521 
    522 
     356// thunk problem
    523357size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
    524358        size_t l = 0, m, h = dim;
     
    535369
    536370
     371static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
     372  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     373        mmapStart = value;                                                                      // set global
     374
     375        // find the closest bucket size less than or equal to the mmapStart size
     376        maxBucketsUsed = Bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     377        assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
     378        assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     379        return false;
     380} // setMmapStart
     381
     382
     383static inline void checkHeader( bool check, const char * name, void * addr ) {
     384        if ( unlikely( check ) ) {                                                      // bad address ?
     385                abort( "Attempt to %s storage %p with address outside the heap.\n"
     386                           "Possible cause is duplicate free on same block or overwriting of memory.",
     387                           name, addr );
     388        } // if
     389} // checkHeader
     390
     391
     392static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) {
     393        if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
     394                size_t offset = header->kind.fake.offset;
     395                alignment = header->kind.fake.alignment & -2;   // remove flag from value
     396                #ifdef __CFA_DEBUG__
     397                checkAlign( alignment );                                                // check alignment
     398                #endif // __CFA_DEBUG__
     399                header = (HeapManager.Storage.Header *)((char *)header - offset);
     400        } // if
     401} // fakeHeader
     402
     403
     404// <-------+----------------------------------------------------> bsize (bucket size)
     405// |header |addr
     406//==================================================================================
     407//                                | alignment
     408// <-----------------<------------+-----------------------------> bsize (bucket size)
     409//                   |fake-header | addr
     410#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
     411
     412// <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
     413// |header |addr
     414//==================================================================================
     415//                                | alignment
     416// <------------------------------<<---------- dsize --------->>> bsize (bucket size)
     417//                   |fake-header |addr
     418#define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
     419
     420
     421static inline bool headers( const char * name __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
     422        header = headerAddr( addr );
     423
     424        if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
     425                fakeHeader( header, alignment );
     426                size = header->kind.real.blockSize & -3;                // mmap size
     427                return true;
     428        } // if
     429
     430        #ifdef __CFA_DEBUG__
     431        checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     432        #endif // __CFA_DEBUG__
     433
     434        // header may be safe to dereference
     435        fakeHeader( header, alignment );
     436        #ifdef __CFA_DEBUG__
     437        checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     438        #endif // __CFA_DEBUG__
     439
     440        freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
     441        #ifdef __CFA_DEBUG__
     442        if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
     443                abort( "Attempt to %s storage %p with corrupted header.\n"
     444                           "Possible cause is duplicate free on same block or overwriting of header information.",
     445                           name, addr );
     446        } // if
     447        #endif // __CFA_DEBUG__
     448        size = freeElem->blockSize;
     449        return false;
     450} // headers
     451
     452
     453static inline void * extend( size_t size ) with ( heapManager ) {
     454        lock( extlock __cfaabi_dbg_ctx2 );
     455        ptrdiff_t rem = heapRemaining - size;
     456        if ( rem < 0 ) {
     457                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
     458
     459                size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
     460                if ( sbrk( increase ) == (void *)-1 ) {
     461                        unlock( extlock );
     462                        errno = ENOMEM;
     463                        return 0p;
     464                } // if
     465                #ifdef __STATISTICS__
     466                sbrk_calls += 1;
     467                sbrk_storage += increase;
     468                #endif // __STATISTICS__
     469                #ifdef __CFA_DEBUG__
     470                // Set new memory to garbage so subsequent uninitialized usages might fail.
     471                memset( (char *)heapEnd + heapRemaining, '\377', increase );
     472                #endif // __CFA_DEBUG__
     473                rem = heapRemaining + increase - size;
     474        } // if
     475
     476        HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
     477        heapRemaining = rem;
     478        heapEnd = (char *)heapEnd + size;
     479        unlock( extlock );
     480        return block;
     481} // extend
     482
     483
    537484static inline void * doMalloc( size_t size ) with ( heapManager ) {
    538485        HeapManager.Storage * block;                                            // pointer to new block of storage
     
    541488        // along with the block and is a multiple of the alignment size.
    542489
    543   if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0;
     490  if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p;
    544491        size_t tsize = size + sizeof(HeapManager.Storage);
    545492        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     
    574521                block = freeElem->freeList.pop();
    575522                #endif // SPINLOCK
    576                 if ( unlikely( block == 0 ) ) {                                 // no free block ?
     523                if ( unlikely( block == 0p ) ) {                                // no free block ?
    577524                        #if defined( SPINLOCK )
    578525                        unlock( freeElem->lock );
     
    583530
    584531                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    585   if ( unlikely( block == 0 ) ) return 0;
    586                         #if defined( SPINLOCK )
     532  if ( unlikely( block == 0p ) ) return 0p;
     533                #if defined( SPINLOCK )
    587534                } else {
    588535                        freeElem->freeList = block->header.kind.real.next;
    589536                        unlock( freeElem->lock );
    590                         #endif // SPINLOCK
     537                #endif // SPINLOCK
    591538                } // if
    592539
    593540                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    594541        } else {                                                                                        // large size => mmap
    595   if ( unlikely( size > ~0ul - pageSize ) ) return 0;
     542  if ( unlikely( size > ~0ul - pageSize ) ) return 0p;
    596543                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    597544                #ifdef __STATISTICS__
     
    611558        } // if
    612559
    613         void * area = &(block->data);                                           // adjust off header to user bytes
     560        void * addr = &(block->data);                                           // adjust off header to user bytes
    614561
    615562        #ifdef __CFA_DEBUG__
    616         assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
     563        assert( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ?
    617564        __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
    618565        if ( traceHeap() ) {
    619566                enum { BufferSize = 64 };
    620567                char helpText[BufferSize];
    621                 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
    622                 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
    623                 __cfaabi_dbg_bits_write( helpText, len );
     568                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
     569                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", addr, size );
     570                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    624571        } // if
    625572        #endif // __CFA_DEBUG__
    626573
    627         return area;
     574        return addr;
    628575} // doMalloc
    629576
     
    631578static inline void doFree( void * addr ) with ( heapManager ) {
    632579        #ifdef __CFA_DEBUG__
    633         if ( unlikely( heapManager.heapBegin == 0 ) ) {
     580        if ( unlikely( heapManager.heapBegin == 0p ) ) {
    634581                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
    635582        } // if
     
    677624                char helpText[BufferSize];
    678625                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    679                 __cfaabi_dbg_bits_write( helpText, len );
     626                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    680627        } // if
    681628        #endif // __CFA_DEBUG__
     
    683630
    684631
    685 size_t checkFree( HeapManager & manager ) with ( manager ) {
     632size_t prtFree( HeapManager & manager ) with ( manager ) {
    686633        size_t total = 0;
    687634        #ifdef __STATISTICS__
    688         __cfaabi_dbg_bits_acquire();
    689         __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
     635        __cfaabi_bits_acquire();
     636        __cfaabi_bits_print_nolock( STDERR_FILENO, "\nBin lists (bin size : free blocks on list)\n" );
    690637        #endif // __STATISTICS__
    691638        for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     
    696643
    697644                #if defined( SPINLOCK )
    698                 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
     645                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    699646                #else
    700                 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
     647                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
    701648                #endif // SPINLOCK
    702649                        total += size;
     
    707654
    708655                #ifdef __STATISTICS__
    709                 __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
    710                 if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
     656                __cfaabi_bits_print_nolock( STDERR_FILENO, "%7zu, %-7u  ", size, N );
     657                if ( (i + 1) % 8 == 0 ) __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
    711658                #endif // __STATISTICS__
    712659        } // for
    713660        #ifdef __STATISTICS__
    714         __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
    715         __cfaabi_dbg_bits_release();
     661        __cfaabi_bits_print_nolock( STDERR_FILENO, "\ntotal free blocks:%zu\n", total );
     662        __cfaabi_bits_release();
    716663        #endif // __STATISTICS__
    717664        return (char *)heapEnd - (char *)heapBegin - total;
    718 } // checkFree
     665} // prtFree
     666
     667
     668static void ?{}( HeapManager & manager ) with ( manager ) {
     669        pageSize = sysconf( _SC_PAGESIZE );
     670
     671        for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     672                freeLists[i].blockSize = bucketSizes[i];
     673        } // for
     674
     675        #ifdef FASTLOOKUP
     676        unsigned int idx = 0;
     677        for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     678                if ( i > bucketSizes[idx] ) idx += 1;
     679                lookup[i] = idx;
     680        } // for
     681        #endif // FASTLOOKUP
     682
     683        if ( setMmapStart( default_mmap_start() ) ) {
     684                abort( "HeapManager : internal error, mmap start initialization failure." );
     685        } // if
     686        heapExpand = default_heap_expansion();
     687
     688        char * end = (char *)sbrk( 0 );
     689        sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
     690        heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     691} // HeapManager
     692
     693
     694static void ^?{}( HeapManager & ) {
     695        #ifdef __STATISTICS__
     696        if ( traceHeapTerm() ) {
     697                printStats();
     698                // if ( prtfree() ) prtFree( heapManager, true );
     699        } // if
     700        #endif // __STATISTICS__
     701} // ~HeapManager
     702
     703
     704static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
     705void memory_startup( void ) {
     706        #ifdef __CFA_DEBUG__
     707        if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
     708                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     709                abort( "boot() : internal error, recursively invoked during system boot." );
     710        } // if
     711        heapBoot = true;
     712        #endif // __CFA_DEBUG__
     713
     714        //assert( heapManager.heapBegin != 0 );
     715        //heapManager{};
     716        if ( heapManager.heapBegin == 0p ) heapManager{};
     717} // memory_startup
     718
     719static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
     720void memory_shutdown( void ) {
     721        ^heapManager{};
     722} // memory_shutdown
    719723
    720724
    721725static inline void * mallocNoStats( size_t size ) {             // necessary for malloc statistics
    722726        //assert( heapManager.heapBegin != 0 );
    723         if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ?
    724         void * area = doMalloc( size );
    725         if ( unlikely( area == 0 ) ) errno = ENOMEM;            // POSIX
    726         return area;
     727        if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ?
     728        void * addr = doMalloc( size );
     729        if ( unlikely( addr == 0p ) ) errno = ENOMEM;           // POSIX
     730        return addr;
    727731} // mallocNoStats
     732
     733
     734static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) {
     735        size_t size = noOfElems * elemSize;
     736        char * addr = (char *)mallocNoStats( size );
     737  if ( unlikely( addr == 0p ) ) return 0p;
     738
     739        HeapManager.Storage.Header * header;
     740        HeapManager.FreeHeader * freeElem;
     741        size_t bsize, alignment;
     742        bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );
     743        #ifndef __CFA_DEBUG__
     744        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     745        if ( ! mapped )
     746        #endif // __CFA_DEBUG__
     747                // Zero entire data space even when > than size => realloc without a new allocation and zero fill works.
     748                // <-------00000000000000000000000000000000000000000000000000000> bsize (bucket size)
     749                // `-header`-addr                      `-size
     750                memset( addr, '\0', bsize - sizeof(HeapManager.Storage) ); // set to zeros
     751
     752        header->kind.real.blockSize |= 2;                                       // mark as zero filled
     753        return addr;
     754} // callocNoStats
    728755
    729756
     
    745772        // subtract libAlign() because it is already the minimum alignment
    746773        // add sizeof(Storage) for fake header
    747         // #comment TD : this is the only place that calls doMalloc without calling mallocNoStats, why ?
    748         char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    749   if ( unlikely( area == 0 ) ) return area;
     774        char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     775  if ( unlikely( addr == 0p ) ) return addr;
    750776
    751777        // address in the block of the "next" alignment address
    752         char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
     778        char * user = (char *)libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );
    753779
    754780        // address of header from malloc
    755         HeapManager.Storage.Header * realHeader = headerAddr( area );
     781        HeapManager.Storage.Header * realHeader = headerAddr( addr );
    756782        // address of fake header * before* the alignment location
    757783        HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     
    763789        return user;
    764790} // memalignNoStats
     791
     792
     793static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) {
     794        size_t size = noOfElems * elemSize;
     795        char * addr = (char *)memalignNoStats( alignment, size );
     796  if ( unlikely( addr == 0p ) ) return 0p;
     797        HeapManager.Storage.Header * header;
     798        HeapManager.FreeHeader * freeElem;
     799        size_t bsize;
     800        bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );
     801        #ifndef __CFA_DEBUG__
     802        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     803        if ( ! mapped )
     804        #endif // __CFA_DEBUG__
     805                memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros
     806        header->kind.real.blockSize |= 2;                               // mark as zero filled
     807
     808        return addr;
     809} // cmemalignNoStats
    765810
    766811
     
    776821extern "C" {
    777822        // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not
    778         // initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be
     823        // initialized. If size is 0, then malloc() returns either 0p, or a unique pointer value that can later be
    779824        // successfully passed to free().
    780825        void * malloc( size_t size ) {
     
    788833
    789834        // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to
    790         // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a
     835        // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either 0p, or a
    791836        // unique pointer value that can later be successfully passed to free().
    792837        void * calloc( size_t noOfElems, size_t elemSize ) {
    793                 size_t size = noOfElems * elemSize;
    794838                #ifdef __STATISTICS__
    795839                __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    796                 __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
    797                 #endif // __STATISTICS__
    798 
    799                 char * area = (char *)mallocNoStats( size );
    800           if ( unlikely( area == 0 ) ) return 0;
     840                __atomic_add_fetch( &calloc_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
     841                #endif // __STATISTICS__
     842
     843                return callocNoStats( noOfElems, elemSize );
     844        } // calloc
     845
     846        // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
     847        // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
     848        // is larger than the old size, the added memory will not be initialized.  If ptr is 0p, then the call is
     849        // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not 0p, then the call
     850        // is equivalent to free(ptr). Unless ptr is 0p, it must have been returned by an earlier call to malloc(),
     851        // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
     852        void * realloc( void * oaddr, size_t size ) {
     853                #ifdef __STATISTICS__
     854                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     855                #endif // __STATISTICS__
     856
     857                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     858          if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases
     859          if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
    801860
    802861                HeapManager.Storage.Header * header;
    803862                HeapManager.FreeHeader * freeElem;
    804                 size_t asize, alignment;
    805                 bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
    806                 #ifndef __CFA_DEBUG__
    807                 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    808                 if ( ! mapped )
    809                 #endif // __CFA_DEBUG__
    810                         memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
    811 
    812                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    813                 return area;
    814         } // calloc
    815 
    816         // #comment TD : Document this function
    817         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
    818                 size_t size = noOfElems * elemSize;
    819                 #ifdef __STATISTICS__
    820                 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    821                 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
    822                 #endif // __STATISTICS__
    823 
    824                 char * area = (char *)memalignNoStats( alignment, size );
    825           if ( unlikely( area == 0 ) ) return 0;
    826                 HeapManager.Storage.Header * header;
    827                 HeapManager.FreeHeader * freeElem;
    828                 size_t asize;
    829                 bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
    830                 #ifndef __CFA_DEBUG__
    831                 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    832                 if ( ! mapped )
    833                         #endif // __CFA_DEBUG__
    834                         memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros
    835                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    836 
    837                 return area;
    838         } // cmemalign
    839 
    840         // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
    841         // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
    842         // is larger than the old size, the added memory will not be initialized.  If ptr is NULL, then the call is
    843         // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call
    844         // is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(),
    845         // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
    846         void * realloc( void * addr, size_t size ) {
    847                 #ifdef __STATISTICS__
    848                 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    849                 #endif // __STATISTICS__
    850 
    851           if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases
    852           if ( unlikely( size == 0 ) ) { free( addr ); return 0; }
    853 
    854                 HeapManager.Storage.Header * header;
    855                 HeapManager.FreeHeader * freeElem;
    856                 size_t asize, alignment = 0;
    857                 headers( "realloc", addr, header, freeElem, asize, alignment );
    858 
    859                 size_t usize = asize - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    860                 if ( usize >= size ) {                                                  // already sufficient storage
     863                size_t bsize, oalign = 0;
     864                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     865
     866                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     867          if ( size <= odsize && odsize <= size * 2 ) { // allow up to 50% wasted storage in smaller size
     868                        // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know
     869                        // where to start filling, i.e., do not overwrite existing values in space.
     870                        //
    861871                        // This case does not result in a new profiler entry because the previous one still exists and it must match with
    862872                        // the free for this memory.  Hence, this realloc does not appear in the profiler output.
    863                         return addr;
     873                        return oaddr;
    864874                } // if
    865875
     
    868878                #endif // __STATISTICS__
    869879
    870                 void * area;
    871                 if ( unlikely( alignment != 0 ) ) {                             // previous request memalign?
    872                         area = memalign( alignment, size );                     // create new aligned area
     880                // change size and copy old content to new storage
     881
     882                void * naddr;
     883                if ( unlikely( oalign != 0 ) ) {                                // previous request memalign?
     884                        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     885                                naddr = cmemalignNoStats( oalign, 1, size ); // create new aligned area
     886                        } else {
     887                                naddr = memalignNoStats( oalign, size ); // create new aligned area
     888                        } // if
    873889                } else {
    874                         area = mallocNoStats( size );                           // create new area
     890                        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     891                                naddr = callocNoStats( 1, size );               // create new area
     892                        } else {
     893                                naddr = mallocNoStats( size );                  // create new area
     894                        } // if
    875895                } // if
    876           if ( unlikely( area == 0 ) ) return 0;
    877                 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ?
    878                         assert( (header->kind.real.blockSize & 1) == 0 );
    879                         bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
    880                         #ifndef __CFA_DEBUG__
    881                         // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    882                         if ( ! mapped )
    883                         #endif // __CFA_DEBUG__
    884                                 memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part
    885                         header->kind.real.blockSize |= 2;                       // mark new request as zero fill
    886                 } // if
    887                 memcpy( area, addr, usize );                                    // copy bytes
    888                 free( addr );
    889                 return area;
     896          if ( unlikely( naddr == 0p ) ) return 0p;
     897
     898                headers( "realloc", naddr, header, freeElem, bsize, oalign );
     899                size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
     900                // To preserve prior fill, the entire bucket must be copied versus the size.
     901                memcpy( naddr, oaddr, MIN( odsize, ndsize ) );  // copy bytes
     902                free( oaddr );
     903                return naddr;
    890904        } // realloc
    891905
     
    898912                #endif // __STATISTICS__
    899913
    900                 void * area = memalignNoStats( alignment, size );
    901 
    902                 return area;
     914                return memalignNoStats( alignment, size );
    903915        } // memalign
     916
     917
     918        // The cmemalign() function is the same as calloc() with memory alignment.
     919        void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
     920                #ifdef __STATISTICS__
     921                __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     922                __atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
     923                #endif // __STATISTICS__
     924
     925                return cmemalignNoStats( alignment, noOfElems, elemSize );
     926        } // cmemalign
    904927
    905928        // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a
     
    912935        // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The
    913936        // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of
    914         // sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later
     937        // sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later
    915938        // be successfully passed to free(3).
    916939        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    917940          if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
    918941                * memptr = memalign( alignment, size );
    919           if ( unlikely( * memptr == 0 ) ) return ENOMEM;
     942          if ( unlikely( * memptr == 0p ) ) return ENOMEM;
    920943                return 0;
    921944        } // posix_memalign
     
    930953        // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to
    931954        // malloc(), calloc() or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behavior
    932         // occurs. If ptr is NULL, no operation is performed.
     955        // occurs. If ptr is 0p, no operation is performed.
    933956        void free( void * addr ) {
    934957                #ifdef __STATISTICS__
     
    936959                #endif // __STATISTICS__
    937960
    938                 // #comment TD : To decrease nesting I would but the special case in the
    939                 //               else instead, plus it reads more naturally to have the
    940                 //               short / normal case instead
    941                 if ( unlikely( addr == 0 ) ) {                                  // special case
    942                         #ifdef __CFA_DEBUG__
    943                         if ( traceHeap() ) {
    944                                 #define nullmsg "Free( 0x0 ) size:0\n"
    945                                 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    946                                 __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
    947                         } // if
    948                         #endif // __CFA_DEBUG__
     961          if ( unlikely( addr == 0p ) ) {                                       // special case
     962                        // #ifdef __CFA_DEBUG__
     963                        // if ( traceHeap() ) {
     964                        //      #define nullmsg "Free( 0x0 ) size:0\n"
     965                        //      // Do not debug print free( 0p ), as it can cause recursive entry from sprintf.
     966                        //      __cfaabi_dbg_write( nullmsg, sizeof(nullmsg) - 1 );
     967                        // } // if
     968                        // #endif // __CFA_DEBUG__
    949969                        return;
    950970                } // exit
     
    953973        } // free
    954974
    955         // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
    956         // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
    957         // parameter.
    958         int mallopt( int option, int value ) {
    959                 choose( option ) {
    960                   case M_TOP_PAD:
    961                         if ( setHeapExpand( value ) ) fallthru default;
    962                   case M_MMAP_THRESHOLD:
    963                         if ( setMmapStart( value ) ) fallthru default;
    964                   default:
    965                         // #comment TD : 1 for unsopported feels wrong
    966                         return 1;                                                                       // success, or unsupported
    967                 } // switch
    968                 return 0;                                                                               // error
    969         } // mallopt
    970 
    971         // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
    972         // suitable argument).
    973         int malloc_trim( size_t ) {
    974                 return 0;                                                                               // => impossible to release memory
    975         } // malloc_trim
    976 
    977         // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
    978         // a block of memory allocated by malloc(3) or a related function.
    979         size_t malloc_usable_size( void * addr ) {
    980           if ( unlikely( addr == 0 ) ) return 0;                        // null allocation has 0 size
    981 
    982                 HeapManager.Storage.Header * header;
    983                 HeapManager.FreeHeader * freeElem;
    984                 size_t size, alignment;
    985 
    986                 headers( "malloc_usable_size", addr, header, freeElem, size, alignment );
    987                 size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    988                 return usize;
    989         } // malloc_usable_size
    990 
    991 
    992     // The malloc_alignment() function returns the alignment of the allocation.
     975
     976        // The malloc_alignment() function returns the alignment of the allocation.
    993977        size_t malloc_alignment( void * addr ) {
    994           if ( unlikely( addr == 0 ) ) return libAlign();       // minimum alignment
     978          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
    995979                HeapManager.Storage.Header * header = headerAddr( addr );
    996980                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    1002986
    1003987
    1004     // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
     988        // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
    1005989        bool malloc_zero_fill( void * addr ) {
    1006           if ( unlikely( addr == 0 ) ) return false;            // null allocation is not zero fill
     990          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
    1007991                HeapManager.Storage.Header * header = headerAddr( addr );
    1008992                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    1013997
    1014998
    1015     // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
    1016     // related functions.
     999        // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
     1000        // a block of memory allocated by malloc(3) or a related function.
     1001        size_t malloc_usable_size( void * addr ) {
     1002          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
     1003                HeapManager.Storage.Header * header;
     1004                HeapManager.FreeHeader * freeElem;
     1005                size_t bsize, alignment;
     1006
     1007                headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
     1008                return dataStorage( bsize, addr, header );      // data storage in bucket
     1009        } // malloc_usable_size
     1010
     1011
     1012        // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
     1013        // related functions.
    10171014        void malloc_stats( void ) {
    10181015                #ifdef __STATISTICS__
    10191016                printStats();
    1020                 if ( checkFree() ) checkFree( heapManager );
     1017                if ( prtFree() ) prtFree( heapManager );
    10211018                #endif // __STATISTICS__
    10221019        } // malloc_stats
    10231020
    10241021        // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.
    1025         int malloc_stats_fd( int fd ) {
     1022        int malloc_stats_fd( int fd __attribute__(( unused )) ) {
    10261023                #ifdef __STATISTICS__
    10271024                int temp = statfd;
     
    10331030        } // malloc_stats_fd
    10341031
     1032
     1033        // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
     1034        // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that
     1035        // parameter.
     1036        int mallopt( int option, int value ) {
     1037                choose( option ) {
     1038                  case M_TOP_PAD:
     1039                        if ( setHeapExpand( value ) ) return 1;
     1040                  case M_MMAP_THRESHOLD:
     1041                        if ( setMmapStart( value ) ) return 1;
     1042                } // switch
     1043                return 0;                                                                               // error, unsupported
     1044        } // mallopt
     1045
     1046        // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a
     1047        // suitable argument).
     1048        int malloc_trim( size_t ) {
     1049                return 0;                                                                               // => impossible to release memory
     1050        } // malloc_trim
     1051
     1052
    10351053        // The malloc_info() function exports an XML string that describes the current state of the memory-allocation
    10361054        // implementation in the caller.  The string is printed on the file stream stream.  The exported string includes
    10371055        // information about all arenas (see malloc(3)).
    10381056        int malloc_info( int options, FILE * stream ) {
     1057                if ( options != 0 ) { errno = EINVAL; return -1; }
    10391058                return printStatsXML( stream );
    10401059        } // malloc_info
     
    10461065        // structure is returned as the function result.  (It is the caller's responsibility to free(3) this memory.)
    10471066        void * malloc_get_state( void ) {
    1048                 return 0;                                                                               // unsupported
     1067                return 0p;                                                                              // unsupported
    10491068        } // malloc_get_state
    10501069
     
    10581077
    10591078
     1079// Must have CFA linkage to overload with C linkage realloc.
     1080void * realloc( void * oaddr, size_t nalign, size_t size ) {
     1081        #ifdef __STATISTICS__
     1082        __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     1083        #endif // __STATISTICS__
     1084
     1085        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1086  if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases
     1087  if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
     1088
     1089        if ( unlikely( nalign == 0 ) ) nalign = libAlign();     // reset alignment to minimum
     1090        #ifdef __CFA_DEBUG__
     1091        else
     1092                checkAlign( nalign );                                                   // check alignment
     1093        #endif // __CFA_DEBUG__
     1094
     1095        HeapManager.Storage.Header * header;
     1096        HeapManager.FreeHeader * freeElem;
     1097        size_t bsize, oalign = 0;
     1098        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     1099        size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1100
     1101  if ( oalign != 0 && (uintptr_t)oaddr % nalign == 0 ) { // has alignment and just happens to work out
     1102                headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
     1103                return realloc( oaddr, size );
     1104        } // if
     1105
     1106        #ifdef __STATISTICS__
     1107        __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     1108        #endif // __STATISTICS__
     1109
     1110        // change size and copy old content to new storage
     1111
     1112        void * naddr;
     1113        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     1114                naddr = cmemalignNoStats( nalign, 1, size );    // create new aligned area
     1115        } else {
     1116                naddr = memalignNoStats( nalign, size );                // create new aligned area
     1117        } // if
     1118
     1119        headers( "realloc", naddr, header, freeElem, bsize, oalign );
     1120        size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
     1121        // To preserve prior fill, the entire bucket must be copied versus the size.
     1122        memcpy( naddr, oaddr, MIN( odsize, ndsize ) );          // copy bytes
     1123        free( oaddr );
     1124        return naddr;
     1125} // realloc
     1126
     1127
    10601128// Local Variables: //
    10611129// tab-width: 4 //
  • libcfa/src/interpose.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 22:57:16 2019
    13 // Update Count     : 116
     12// Last Modified On : Sat Nov 30 07:09:42 2019
     13// Update Count     : 119
    1414//
    1515
     
    163163        abort_lastframe = kernel_abort_lastframe();
    164164        len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
    165         __cfaabi_dbg_bits_write( abort_text, len );
     165        __cfaabi_dbg_write( abort_text, len );
    166166
    167167        if ( fmt ) {
     
    171171                len = vsnprintf( abort_text, abort_text_size, fmt, args );
    172172                va_end( args );
    173                 __cfaabi_dbg_bits_write( abort_text, len );
     173                __cfaabi_dbg_write( abort_text, len );
    174174
    175175                if ( fmt[strlen( fmt ) - 1] != '\n' ) {         // add optional newline if missing at the end of the format text
    176                         __cfaabi_dbg_bits_write( "\n", 1 );
     176                        __cfaabi_dbg_write( "\n", 1 );
    177177                }
    178178        }
     
    194194        // find executable name
    195195        *index( messages[0], '(' ) = '\0';
    196         __cfaabi_dbg_bits_print_nolock( "Stack back trace for: %s\n", messages[0]);
    197 
    198         for ( int i = Start; i < size - abort_lastframe && messages != NULL; i += 1 ) {
    199                 char * name = NULL, * offset_begin = NULL, * offset_end = NULL;
     196        __cfaabi_bits_print_nolock( STDERR_FILENO, "Stack back trace for: %s\n", messages[0]);
     197
     198        for ( int i = Start; i < size - abort_lastframe && messages != 0p; i += 1 ) {
     199                char * name = 0p, * offset_begin = 0p, * offset_end = 0p;
    200200
    201201                for ( char * p = messages[i]; *p; ++p ) {
    202                         //__cfaabi_dbg_bits_print_nolock( "X %s\n", p);
     202                        //__cfaabi_bits_print_nolock( "X %s\n", p);
    203203                        // find parantheses and +offset
    204204                        if ( *p == '(' ) {
     
    220220                        *offset_end++ = '\0';
    221221
    222                         __cfaabi_dbg_bits_print_nolock( "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     222                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
    223223                } else {                                                                                // otherwise, print the whole line
    224                         __cfaabi_dbg_bits_print_nolock( "(%i) %s\n", frameNo, messages[i] );
     224                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s\n", frameNo, messages[i] );
    225225                }
    226226        }
  • libcfa/src/startup.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 25 16:42:01 2018
    13 // Update Count     : 11
     12// Last Modified On : Sat Nov 30 07:07:56 2019
     13// Update Count     : 13
    1414//
    1515
    1616#include "startup.hfa"
    17 #include <unistd.h>
    18 
     17#include <time.h>                                                                               // tzset
    1918
    2019extern "C" {
    2120    static void __cfaabi_appready_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_APPREADY ) ));
    2221    void __cfaabi_appready_startup( void ) {
     22                tzset();                                                                                // initialize time global variables
    2323                #ifdef __CFA_DEBUG__
    2424                extern void heapAppStart();
  • libcfa/src/stdlib.cfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 22 08:57:52 2019
    13 // Update Count     : 478
     12// Last Modified On : Wed Nov 20 17:22:47 2019
     13// Update Count     : 485
    1414//
    1515
     
    3030        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
    3131                size_t olen = malloc_usable_size( ptr );                // current allocation
    32                 char * nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     32                void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    3333                size_t nlen = malloc_usable_size( nptr );               // new allocation
    3434                if ( nlen > olen ) {                                                    // larger ?
    35                         memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     35                        memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    3636                } // if
    3737                return (T *)nptr;
    3838        } // alloc_set
    3939
    40         T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
    41                 char * nptr;
    42                 size_t alignment = malloc_alignment( ptr );
    43                 if ( align != alignment && (uintptr_t)ptr % align != 0 ) {
    44                         size_t olen = malloc_usable_size( ptr );        // current allocation
    45                         nptr = (char *)memalign( align, olen );
    46                         size_t nlen = malloc_usable_size( nptr );       // new allocation
    47                         size_t lnth = olen < nlen ? olen : nlen;        // min
    48                         memcpy( nptr, ptr, lnth );                                      // initialize storage
    49                         free( ptr );
    50                 } else {
    51                         nptr = (char *)ptr;
    52                 } // if
    53                 return (T *)nptr;
    54         } // alloc_align
    55 
    56         T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
    57                 char * nptr;
    58                 size_t alignment = malloc_alignment( ptr );
    59                 if ( align != alignment ) {
    60                         size_t olen = malloc_usable_size( ptr );        // current allocation
    61                         nptr = (char *)memalign( align, dim * sizeof(T) );
    62                         size_t nlen = malloc_usable_size( nptr );       // new allocation
    63                         size_t lnth = olen < nlen ? olen : nlen;        // min
    64                         memcpy( nptr, ptr, lnth );                                      // initialize storage
    65                         free( ptr );
    66                 } else {
    67                         nptr = (char *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    68                 } // if
    69                 return (T *)nptr;
    70         } // alloc_align
    71 
    7240        T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
    7341                size_t olen = malloc_usable_size( ptr );                // current allocation
    74                 char * nptr = alloc_align( ptr, align );
     42                void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
     43                // char * nptr = alloc_align( ptr, align );
    7544                size_t nlen = malloc_usable_size( nptr );               // new allocation
    7645                if ( nlen > olen ) {                                                    // larger ?
    77                         memset( nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     46                        memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    7847                } // if
    7948                return (T *)nptr;
  • libcfa/src/stdlib.hfa

    raca6a54c r2fa5bd2  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 20 22:57:33 2019
    13 // Update Count     : 390
     12// Last Modified On : Fri Nov 29 23:08:02 2019
     13// Update Count     : 400
    1414//
    1515
     
    2828} // extern "C"
    2929
     30void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap
     31
    3032//---------------------------------------
    3133
     
    5052        } // calloc
    5153
    52         T * realloc( T * ptr, size_t size ) {
    53                 if ( unlikely( ptr == 0 ) ) return malloc();
     54        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
    5455                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
    5556        } // realloc
     
    5960        } // memalign
    6061
     62        T * cmemalign( size_t align, size_t dim  ) {
     63                return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
     64        } // cmemalign
     65
    6166        T * aligned_alloc( size_t align ) {
    6267                return (T *)aligned_alloc( align, sizeof(T) );  // C aligned_alloc
     
    7984
    8085        T * alloc( T ptr[], size_t dim ) {                                      // realloc
    81                 return realloc( ptr, dim * sizeof(T) );
     86                return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    8287        } // alloc
    8388
     
    118123        } // alloc_align
    119124
     125        T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
     126                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
     127        } // alloc_align
     128
     129        T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
     130                return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc
     131        } // alloc_align
     132
    120133        T * alloc_align_set( size_t align, char fill ) {
    121134                return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
     
    142155
    143156forall( dtype T | sized(T) ) {
    144         T * alloc_align( T ptr[], size_t align );                       // realign
    145         T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
    146157        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill
    147158} // distribution
     
    199210
    200211static inline {
    201         int ato( const char * sptr ) { return (int)strtol( sptr, 0, 10 ); }
    202         unsigned int ato( const char * sptr ) { return (unsigned int)strtoul( sptr, 0, 10 ); }
    203         long int ato( const char * sptr ) { return strtol( sptr, 0, 10 ); }
    204         unsigned long int ato( const char * sptr ) { return strtoul( sptr, 0, 10 ); }
    205         long long int ato( const char * sptr ) { return strtoll( sptr, 0, 10 ); }
    206         unsigned long long int ato( const char * sptr ) { return strtoull( sptr, 0, 10 ); }
    207 
    208         float ato( const char * sptr ) { return strtof( sptr, 0 ); }
    209         double ato( const char * sptr ) { return strtod( sptr, 0 ); }
    210         long double ato( const char * sptr ) { return strtold( sptr, 0 ); }
    211 
    212         float _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
    213         double _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
    214         long double _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
     212        int ato( const char * sptr ) { return (int)strtol( sptr, 0p, 10 ); }
     213        unsigned int ato( const char * sptr ) { return (unsigned int)strtoul( sptr, 0p, 10 ); }
     214        long int ato( const char * sptr ) { return strtol( sptr, 0p, 10 ); }
     215        unsigned long int ato( const char * sptr ) { return strtoul( sptr, 0p, 10 ); }
     216        long long int ato( const char * sptr ) { return strtoll( sptr, 0p, 10 ); }
     217        unsigned long long int ato( const char * sptr ) { return strtoull( sptr, 0p, 10 ); }
     218
     219        float ato( const char * sptr ) { return strtof( sptr, 0p ); }
     220        double ato( const char * sptr ) { return strtod( sptr, 0p ); }
     221        long double ato( const char * sptr ) { return strtold( sptr, 0p ); }
     222
     223        float _Complex ato( const char * sptr ) { return strto( sptr, 0p ); }
     224        double _Complex ato( const char * sptr ) { return strto( sptr, 0p ); }
     225        long double _Complex ato( const char * sptr ) { return strto( sptr, 0p ); }
    215226} // distribution
    216227
Note: See TracChangeset for help on using the changeset viewer.