Changeset ce55a81 for libcfa


Ignore:
Timestamp:
Sep 4, 2020, 2:14:10 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
14d8a9b
Parents:
56c44dc (diff), 2801829 (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' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
libcfa
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/Makefile.am

    r56c44dc rce55a81  
    2222cfalibdir = ${CFA_LIBDIR}
    2323cfalib_DATA = gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c defines.hfa
     24
     25EXTRA_DIST = bootloader.cf builtins.c builtins.def extras.c extras.regx extras.regx2 prelude-gen.cc prototypes.awk prototypes.c prototypes.sed sync-builtins.cf
    2426
    2527CC = @LOCAL_CFACC@
  • libcfa/src/Makefile.am

    r56c44dc rce55a81  
    3131# AM_CFAFLAGS for only cfa source
    3232# use -no-include-stdhdr to prevent rebuild cycles
    33 # The built sources must not depend on the installed headers
    34 AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
     33# The built sources must not depend on the installed inst_headers_src
     34AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr -I$(srcdir)/concurrency $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    3535AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -fexceptions -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3636AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
     
    3939#----------------------------------------------------------------------------------------------------------------
    4040if BUILDLIB
    41 headers_nosrc = bitmanip.hfa exception.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \
    42                 bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa \
    43                 containers/list.hfa containers/stackLockFree.hfa concurrency/iofwd.hfa
     41inst_headers_nosrc = \
     42        bitmanip.hfa \
     43        clock.hfa \
     44        exception.hfa \
     45        gmp.hfa \
     46        math.hfa \
     47        time_t.hfa \
     48        bits/align.hfa \
     49        bits/containers.hfa \
     50        bits/debug.hfa \
     51        bits/defs.hfa \
     52        bits/locks.hfa \
     53        concurrency/iofwd.hfa \
     54        containers/list.hfa \
     55        containers/stackLockFree.hfa
    4456
    45 headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \
    46                 time.hfa stdlib.hfa parseargs.hfa \
    47                 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
     57inst_headers_src = \
     58        common.hfa \
     59        fstream.hfa \
     60        heap.hfa \
     61        iostream.hfa \
     62        iterator.hfa \
     63        limits.hfa \
     64        parseargs.hfa \
     65        rational.hfa \
     66        stdlib.hfa \
     67        time.hfa \
     68        containers/maybe.hfa \
     69        containers/pair.hfa \
     70        containers/result.hfa \
     71        containers/vector.hfa
    4872
    49 libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c ${headers:.hfa=.cfa}
     73libsrc = ${inst_headers_src} ${inst_headers_src:.hfa=.cfa} \
     74        assert.cfa \
     75        bits/algorithm.hfa \
     76        bits/debug.cfa \
     77        exception.c \
     78        exception.h \
     79        interpose.cfa \
     80        lsda.h \
     81        startup.cfa \
     82        startup.hfa \
     83        virtual.c \
     84        virtual.h
    5085
    5186# not all platforms support concurrency, add option do disable it
    52 thread_headers_nosrc = bits/random.hfa concurrency/invoke.h concurrency/kernel/fwd.hfa
     87inst_thread_headers_nosrc = \
     88        bits/random.hfa \
     89        concurrency/invoke.h \
     90        concurrency/kernel/fwd.hfa
    5391
    54 thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa \
    55                 concurrency/monitor.hfa concurrency/mutex.hfa concurrency/exception.hfa
     92inst_thread_headers_src = \
     93        concurrency/coroutine.hfa \
     94        concurrency/exception.hfa \
     95        concurrency/kernel.hfa \
     96        concurrency/monitor.hfa \
     97        concurrency/mutex.hfa \
     98        concurrency/thread.hfa
    5699
    57 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \
    58                 concurrency/invoke.c concurrency/io.cfa concurrency/iocall.cfa \
    59                 concurrency/io/setup.cfa \
    60                 concurrency/kernel/startup.cfa concurrency/preemption.cfa \
    61                 concurrency/ready_queue.cfa concurrency/stats.cfa \
    62                 ${thread_headers:.hfa=.cfa}
     100thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \
     101        bits/signal.hfa \
     102        concurrency/alarm.cfa \
     103        concurrency/alarm.hfa \
     104        concurrency/CtxSwitch-@ARCHITECTURE@.S \
     105        concurrency/invoke.c \
     106        concurrency/io.cfa \
     107        concurrency/io/setup.cfa \
     108        concurrency/io/types.hfa \
     109        concurrency/iocall.cfa \
     110        concurrency/iofwd.hfa \
     111        concurrency/kernel_private.hfa \
     112        concurrency/kernel/startup.cfa \
     113        concurrency/preemption.cfa \
     114        concurrency/preemption.hfa \
     115        concurrency/ready_queue.cfa \
     116        concurrency/ready_subqueue.hfa \
     117        concurrency/snzi.hfa \
     118        concurrency/stats.cfa \
     119        concurrency/stats.hfa \
     120        concurrency/stats.hfa
     121
    63122else
    64 headers =
    65 thread_headers =
    66 headers_nosrc =
    67 thread_headers_nosrc =
     123inst_headers_src =
     124inst_thread_headers_src =
     125inst_headers_nosrc =
     126inst_thread_headers_nosrc =
    68127libsrc =
    69128endif
     
    115174
    116175#----------------------------------------------------------------------------------------------------------------
    117 libcfa_la_SOURCES = prelude.cfa ${libsrc}
     176libcfa_la_SOURCES = ${libsrc}
     177nodist_libcfa_la_SOURCES = prelude.cfa
    118178libcfa_la_LDFLAGS = -version-info @CFA_VERSION@
    119179
     
    124184
    125185cfa_includedir = $(CFA_INCDIR)
    126 nobase_cfa_include_HEADERS = ${stdhdr} ${headers} ${headers_nosrc} ${thread_headers} ${thread_headers_nosrc}
     186nobase_cfa_include_HEADERS = ${stdhdr} ${inst_headers_src} ${inst_headers_nosrc} ${inst_thread_headers_src} ${inst_thread_headers_nosrc}
     187EXTRA_DIST = stdhdr
    127188
    128189#----------------------------------------------------------------------------------------------------------------
  • libcfa/src/bits/defs.hfa

    r56c44dc rce55a81  
    1010// Created On       : Thu Nov  9 13:24:10 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 13 22:00:23 2020
    13 // Update Count     : 19
     12// Last Modified On : Wed Aug 26 16:22:32 2020
     13// Update Count     : 20
    1414//
    1515
     
    4949
    5050static inline long long int rdtscl(void) {
    51         #if defined( __aarch64__ )
     51        #if defined( __i386 ) || defined( __x86_64 )
     52        unsigned int lo, hi;
     53        __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
     54        return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
     55        #elif defined( __aarch64__ ) || defined( __arm__ )
    5256        // https://github.com/google/benchmark/blob/v1.1.0/src/cycleclock.h#L116
    5357        long long int virtual_timer_value;
     
    5559        return virtual_timer_value;
    5660        #else
    57         unsigned int lo, hi;
    58         __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    59         return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
     61                #error unsupported hardware architecture
    6062        #endif // __ARM_ARCH
    6163}
  • libcfa/src/bits/locks.hfa

    r56c44dc rce55a81  
    218218        }
    219219
    220         // Semaphore which only supports a single thread and one post
    221         // Semaphore which only supports a single thread
     220        // Synchronozation primitive which only supports a single thread and one post
     221        // Similar to a binary semaphore with a 'one shot' semantic
     222        // is expected to be discarded after each party call their side
    222223        struct oneshot {
     224                // Internal state :
     225                //     0p     : is initial state (wait will block)
     226                //     1p     : fulfilled (wait won't block)
     227                // any thread : a thread is currently waiting
    223228                struct $thread * volatile ptr;
    224229        };
     
    231236                void ^?{}(oneshot & this) {}
    232237
     238                // Wait for the post, return immidiately if it already happened.
     239                // return true if the thread was parked
    233240                bool wait(oneshot & this) {
    234241                        for() {
     
    244251                }
    245252
     253                // Mark as fulfilled, wake thread if needed
     254                // return true if a thread was unparked
    246255                bool post(oneshot & this) {
    247256                        struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
     
    251260                }
    252261        }
     262
     263        // base types for future to build upon
     264        // It is based on the 'oneshot' type to allow multiple futures
     265        // to block on the same instance, permitting users to block a single
     266        // thread on "any of" [a given set of] futures.
     267        // does not support multiple threads waiting on the same future
     268        struct future_t {
     269                // Internal state :
     270                //     0p      : is initial state (wait will block)
     271                //     1p      : fulfilled (wait won't block)
     272                //     2p      : in progress ()
     273                //     3p      : abandoned, server should delete
     274                // any oneshot : a context has been setup to wait, a thread could wait on it
     275                struct oneshot * volatile ptr;
     276        };
     277
     278        static inline {
     279                void  ?{}(future_t & this) {
     280                        this.ptr = 0p;
     281                }
     282
     283                void ^?{}(future_t & this) {}
     284
     285                // check if the future is available
     286                bool available( future_t & this ) {
     287                        return this.ptr == 1p;
     288                }
     289
     290                // Prepare the future to be waited on
     291                // intented to be use by wait, wait_any, waitfor, etc. rather than used directly
     292                bool setup( future_t & this, oneshot & wait_ctx ) {
     293                        /* paranoid */ verify( wait_ctx.ptr == 0p );
     294                        // The future needs to set the wait context
     295                        for() {
     296                                struct oneshot * expected = this.ptr;
     297                                // Is the future already fulfilled?
     298                                if(expected == 1p) return false; // Yes, just return false (didn't block)
     299
     300                                // The future is not fulfilled, try to setup the wait context
     301                                /* paranoid */ verify( expected == 0p );
     302                                if(__atomic_compare_exchange_n(&this.ptr, &expected, &wait_ctx, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     303                                        return true;
     304                                }
     305                        }
     306                }
     307
     308                // Stop waiting on a future
     309                // When multiple futures are waited for together in "any of" pattern
     310                // futures that weren't fulfilled before the thread woke up
     311                // should retract the wait ctx
     312                // intented to be use by wait, wait_any, waitfor, etc. rather than used directly
     313                void retract( future_t & this, oneshot & wait_ctx ) {
     314                        // Remove the wait context
     315                        struct oneshot * got = __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST);
     316
     317                        // got == 0p: future was never actually setup, just return
     318                        if( got == 0p ) return;
     319
     320                        // got == wait_ctx: since fulfil does an atomic_swap,
     321                        // if we got back the original then no one else saw context
     322                        // It is safe to delete (which could happen after the return)
     323                        if( got == &wait_ctx ) return;
     324
     325                        // got == 1p: the future is ready and the context was fully consumed
     326                        // the server won't use the pointer again
     327                        // It is safe to delete (which could happen after the return)
     328                        if( got == 1p ) return;
     329
     330                        // got == 2p: the future is ready but the context hasn't fully been consumed
     331                        // spin until it is safe to move on
     332                        if( got == 2p ) {
     333                                while( this.ptr != 1p ) Pause();
     334                                return;
     335                        }
     336
     337                        // got == any thing else, something wen't wrong here, abort
     338                        abort("Future in unexpected state");
     339                }
     340
     341                // Mark the future as abandoned, meaning it will be deleted by the server
     342                void abandon( future_t & this ) {
     343                        struct oneshot * got = __atomic_exchange_n( &this.ptr, 3p, __ATOMIC_SEQ_CST);
     344
     345                        // got == 2p: the future is ready but the context hasn't fully been consumed
     346                        // spin until it is safe to move on
     347                        if( got == 2p ) {
     348                                while( this.ptr != 1p ) Pause();
     349                        }
     350                        return;
     351                }
     352
     353                // from the server side, mark the future as fulfilled
     354                // delete it if needed
     355                bool fulfil( future_t & this ) {
     356                        for() {
     357                                struct oneshot * expected = this.ptr;
     358                                // was this abandoned?
     359                                if( expected == 3p ) { free( &this ); return false; }
     360
     361                                /* paranoid */ verify( expected != 1p ); // Future is already fulfilled, should not happen
     362                                /* paranoid */ verify( expected != 2p ); // Future is bein fulfilled by someone else, this is even less supported then the previous case.
     363
     364                                // If there is a wait context, we need to consume it and mark it as consumed after
     365                                // If there is no context then we can skip the in progress phase
     366                                struct oneshot * want = expected == 0p ? 1p : 2p;
     367                                if(__atomic_compare_exchange_n(&this.ptr, &expected, want, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     368                                        if( expected == 0p ) { /* paranoid */ verify( this.ptr == 1p); return false; }
     369                                        bool ret = post( *expected );
     370                                        __atomic_store_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
     371                                        return ret;
     372                                }
     373                        }
     374
     375                }
     376
     377                // Wait for the future to be fulfilled
     378                bool wait( future_t & this ) {
     379                        oneshot temp;
     380                        if( !setup(this, temp) ) return false;
     381
     382                        // Wait context is setup, just wait on it
     383                        bool ret = wait( temp );
     384
     385                        // Wait for the future to tru
     386                        while( this.ptr == 2p ) Pause();
     387                        // Make sure the state makes sense
     388                        // Should be fulfilled, could be in progress but it's out of date if so
     389                        // since if that is the case, the oneshot was fulfilled (unparking this thread)
     390                        // and the oneshot should not be needed any more
     391                        __attribute__((unused)) struct oneshot * was = this.ptr;
     392                        /* paranoid */ verifyf( was == 1p, "Expected this.ptr to be 1p, was %p\n", was );
     393
     394                        // Mark the future as fulfilled, to be consistent
     395                        // with potential calls to avail
     396                        // this.ptr = 1p;
     397                        return ret;
     398                }
     399        }
    253400#endif
  • libcfa/src/concurrency/CtxSwitch-arm64.S

    r56c44dc rce55a81  
    22// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    33//
    4 // CtxSwitch-arm.S --
     4// CtxSwitch-arm64.S --
    55//
    66// Author           : Peter A. Buhr
    77// Created On       : Sun Aug 16 07:50:13 2020
    88// Last Modified By : Peter A. Buhr
    9 // Last Modified On : Thu Aug 20 18:43:51 2020
    10 // Update Count     : 24
     9// Last Modified On : Wed Aug 26 16:24:59 2020
     10// Update Count     : 25
    1111//
    1212
     
    2626#define SAVE            20 * 8
    2727
    28         .file "CtxSwitch-arm.S"
     28        .file "CtxSwitch-arm64.S"
    2929        .text
    3030        .align 2
    3131        .global __cfactx_switch
    32         .type __cfactx_switch, @function
     32        .type __cfactx_switch, %function
    3333__cfactx_switch:
    3434
     
    9191        .align 2
    9292        .global __cfactx_invoke_stub
    93         .type __cfactx_invoke_stub, @function
     93        .type __cfactx_invoke_stub, %function
    9494__cfactx_invoke_stub:
    9595        mov x0, x19                                                     // load main as parameter 0
  • libcfa/src/concurrency/kernel.cfa

    r56c44dc rce55a81  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 14 15:23:00 2020
    13 // Update Count     : 69
     12// Last Modified On : Mon Aug 31 07:08:20 2020
     13// Update Count     : 71
    1414//
    1515
     
    7474                )
    7575
    76 #elif defined( __ARM_ARCH )
     76#elif defined( __arm__ )
     77        #define __x87_store
     78        #define __x87_load
     79
     80#elif defined( __aarch64__ )
    7781        #define __x87_store              \
    7882                uint32_t __fpcntl[2];    \
     
    9397
    9498#else
    95         #error unknown hardware architecture
     99        #error unsupported hardware architecture
    96100#endif
    97101
  • libcfa/src/concurrency/preemption.cfa

    r56c44dc rce55a81  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 21 13:45:32 2020
    13 // Update Count     : 52
     12// Last Modified On : Wed Aug 26 16:46:03 2020
     13// Update Count     : 53
    1414//
    1515
     
    5656#elif defined( __x86_64 )
    5757#define CFA_REG_IP gregs[REG_RIP]
    58 #elif defined( __ARM_ARCH )
     58#elif defined( __arm__ )
     59#define CFA_REG_IP arm_pc
     60#elif defined( __aarch64__ )
    5961#define CFA_REG_IP pc
    6062#else
    61 #error unknown hardware architecture
     63#error unsupported hardware architecture
    6264#endif
    6365
  • libcfa/src/exception.c

    r56c44dc rce55a81  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 21 11:27:56 2020
    13 // Update Count     : 29
     12// Last Modified On : Sat Aug 29 15:52:22 2020
     13// Update Count     : 34
    1414//
    1515
     
    1818
    1919#include "exception.h"
    20 
    21 // Implementation of the secret header is hardware dependent.
    22 #if defined( __x86_64 ) || defined( __i386 )
    23 #elif defined( __ARM_ARCH )
    24 #warning FIX ME: check if anything needed for ARM
    25 #else
    26 #warning Exception Handling: No known architecture detected.
    27 #endif
    2820
    2921#include <stdlib.h>
     
    3426#include "stdhdr/assert.h"
    3527
    36 // FIX ME: temporary hack to keep ARM build working
     28#if defined( __ARM_ARCH )
     29#warning FIX ME: temporary hack to keep ARM build working
    3730#ifndef _URC_FATAL_PHASE1_ERROR
    3831#define _URC_FATAL_PHASE1_ERROR 3
     
    4134#define _URC_FATAL_PHASE2_ERROR 2
    4235#endif // ! _URC_FATAL_PHASE2_ERROR
     36#endif // __ARM_ARCH
    4337
    4438#include "lsda.h"
     
    626620
    627621#pragma GCC pop_options
     622
     623#elif defined( __ARM_ARCH )
     624_Unwind_Reason_Code __gcfa_personality_v0(
     625                int version,
     626                _Unwind_Action actions,
     627                unsigned long long exception_class,
     628                struct _Unwind_Exception * unwind_exception,
     629                struct _Unwind_Context * unwind_context) {
     630        return _URC_CONTINUE_UNWIND;
     631}
     632
     633__attribute__((noinline))
     634void __cfaehm_try_terminate(void (*try_block)(),
     635                void (*catch_block)(int index, exception_t * except),
     636                __attribute__((unused)) int (*match_block)(exception_t * except)) {
     637}
     638#else
     639        #error unsupported hardware architecture
    628640#endif // __x86_64 || __i386
  • libcfa/src/heap.cfa

    r56c44dc rce55a81  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 24 20:29:24 2020
    13 // Update Count     : 926
     12// Last Modified On : Thu Sep  3 16:22:54 2020
     13// Update Count     : 943
    1414//
    1515
     
    2929#include "math.hfa"                                                                             // ceiling
    3030#include "bitmanip.hfa"                                                                 // is_pow2, ceiling2
    31 
    32 #define MIN(x, y) (y > x ? x : y)
    3331
    3432static bool traceHeap = false;
     
    956954
    957955                headers( "realloc", naddr, header, freeElem, bsize, oalign );
    958                 memcpy( naddr, oaddr, MIN( osize, size ) );             // copy bytes
     956                memcpy( naddr, oaddr, min( osize, size ) );             // copy bytes
    959957                free( oaddr );
    960958
     
    12181216        #endif // __STATISTICS__
    12191217
    1220         // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    1221   if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
    1222   if ( unlikely( oaddr == 0p ) ) {
    1223                 #ifdef __STATISTICS__
    1224                 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );
    1225                 #endif // __STATISTICS__
    1226                 return memalignNoStats( nalign, size );
    1227         } // if
    1228 
    12291218        if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum
    12301219        #ifdef __CFA_DEBUG__
     
    12331222        #endif // __CFA_DEBUG__
    12341223
    1235         HeapManager.Storage.Header * header;
    1236         HeapManager.FreeHeader * freeElem;
    1237         size_t bsize, oalign;
    1238         headers( "resize", oaddr, header, freeElem, bsize, oalign );
    1239         size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    1240 
    1241         if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match
    1242                 if ( oalign > libAlign() ) {                                    // fake header ?
     1224        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1225  if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
     1226  if ( unlikely( oaddr == 0p ) ) {
     1227                #ifdef __STATISTICS__
     1228                __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );
     1229                #endif // __STATISTICS__
     1230                return memalignNoStats( nalign, size );
     1231        } // if
     1232
     1233        // Attempt to reuse existing storage.
     1234        HeapManager.Storage.Header * header = headerAddr( oaddr );
     1235        if ( unlikely ( ( header->kind.fake.alignment & 1 == 1 &&       // old fake header ?
     1236                                 (uintptr_t)oaddr % nalign == 0 &&                              // lucky match ?
     1237                                 header->kind.fake.alignment <= nalign &&               // ok to leave LSB at 1
     1238                                 nalign <= 128 )                                                                // not too much alignment storage wasted ?
     1239                        ||   ( header->kind.fake.alignment & 1 != 1 &&          // old real header ( aligned on libAlign ) ?
     1240                                 nalign == libAlign() ) ) ) {                                   // new alignment also on libAlign
     1241
     1242                HeapManager.FreeHeader * freeElem;
     1243                size_t bsize, oalign;
     1244                headers( "resize", oaddr, header, freeElem, bsize, oalign );
     1245                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1246
     1247                if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage
    12431248                        headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1244                 } // if
    1245                 if ( size <= odsize && odsize <= size * 2 ) {   // allow 50% wasted storage for smaller size
    1246                         header->kind.real.blockSize &= -2;                      // turn off 0 fill
    1247                         header->kind.real.size = size;                          // reset allocation size
     1249
     1250                        header->kind.real.blockSize &= -2;              // turn off 0 fill
     1251                        header->kind.real.size = size;                  // reset allocation size
    12481252                        return oaddr;
    12491253                } // if
     
    12671271        #endif // __CFA_DEBUG__
    12681272
     1273        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1274  if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
     1275  if ( unlikely( oaddr == 0p ) ) {
     1276                #ifdef __STATISTICS__
     1277                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     1278                __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     1279                #endif // __STATISTICS__
     1280                return memalignNoStats( nalign, size );
     1281        } // if
     1282
    12691283        HeapManager.Storage.Header * header;
    12701284        HeapManager.FreeHeader * freeElem;
     
    12721286        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
    12731287
    1274         if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match
    1275                 if ( oalign > libAlign() ) {                                    // fake header ?
    1276                         headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    1277                 } // if
     1288        // Attempt to reuse existing storage.
     1289        if ( unlikely ( ( header->kind.fake.alignment & 1 == 1 &&       // old fake header ?
     1290                                 (uintptr_t)oaddr % nalign == 0 &&                              // lucky match ?
     1291                                 header->kind.fake.alignment <= nalign &&               // ok to leave LSB at 1
     1292                                 nalign <= 128 )                                                                // not too much alignment storage wasted ?
     1293                        ||   ( header->kind.fake.alignment & 1 != 1 &&          // old real header ( aligned on libAlign ) ?
     1294                                 nalign == libAlign() ) ) ) {                                   // new alignment also on libAlign
     1295
     1296                headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
    12781297                return realloc( oaddr, size );
     1298
    12791299        } // if
    12801300
     
    12861306        #endif // __STATISTICS__
    12871307
    1288         // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
    1289   if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases
    1290   if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size );
    1291 
    12921308        size_t osize = header->kind.real.size;                          // old allocation size
    12931309        bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled
     
    12961312
    12971313        headers( "realloc", naddr, header, freeElem, bsize, oalign );
    1298         memcpy( naddr, oaddr, MIN( osize, size ) );                     // copy bytes
     1314        memcpy( naddr, oaddr, min( osize, size ) );                     // copy bytes
    12991315        free( oaddr );
    13001316
  • libcfa/src/stdlib.hfa

    r56c44dc rce55a81  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 14 23:38:50 2020
    13 // Update Count     : 504
     12// Last Modified On : Tue Sep  1 20:32:34 2020
     13// Update Count     : 505
    1414//
    1515
     
    4444
    4545// Macro because of returns
    46 #define $VAR_ALLOC( allocation, alignment ) \
    47         if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( (size_t)sizeof(T) ); /* C allocation */ \
    48         else return (T *)alignment( _Alignof(T), sizeof(T) )
    49 
    5046#define $ARRAY_ALLOC( allocation, alignment, dim ) \
    5147        if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( dim, (size_t)sizeof(T) ); /* C allocation */ \
    5248        else return (T *)alignment( _Alignof(T), dim, sizeof(T) )
    5349
    54 #define $RE_SPECIALS( ptr, size, allocation, alignment ) \
    55         if ( unlikely( size == 0 ) || unlikely( ptr == 0p ) ) { \
    56                 if ( unlikely( size == 0 ) ) free( ptr ); \
    57                 $VAR_ALLOC( malloc, memalign ); \
    58         } /* if */
    59 
    6050static inline forall( dtype T | sized(T) ) {
    6151        // Cforall safe equivalents, i.e., implicit size specification
    6252
    6353        T * malloc( void ) {
    64                 $VAR_ALLOC( malloc, memalign );
     54                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( (size_t)sizeof(T) ); // C allocation
     55                else return (T *)memalign( _Alignof(T), sizeof(T) );
    6556        } // malloc
    6657
     
    7465
    7566        T * resize( T * ptr, size_t size ) {                            // CFA resize, eliminate return-type cast
    76                 $RE_SPECIALS( ptr, size, malloc, memalign );
    7767                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)resize( (void *)ptr, size ); // CFA resize
    7868                else return (T *)(void *)resize( (void *)ptr, _Alignof(T), size ); // CFA resize
     
    8070
    8171        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
    82                 $RE_SPECIALS( ptr, size, malloc, memalign );
    8372                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
    8473                else return (T *)(void *)realloc( (void *)ptr, _Alignof(T), size ); // CFA realloc
     
    189178                size_t copy_end = 0;
    190179
    191                 if(Resize) {
    192                         ptr = (T*) (void *) resize( (int *)Resize, Align, Dim * size );
    193                 } else if (Realloc) {
     180                if ( Resize ) {
     181                        ptr = (T*) (void *) resize( (void *)Resize, Align, Dim * size );
     182                } else if ( Realloc ) {
    194183                        if (Fill.tag != '0') copy_end = min(malloc_size( Realloc ), Dim * size);
    195                         ptr = (T*) (void *) realloc( (int *)Realloc, Align, Dim * size );
     184                        ptr = (T*) (void *) realloc( (void *)Realloc, Align, Dim * size );
    196185                } else {
    197186                        ptr = (T*) (void *) memalign( Align, Dim * size );
     
    201190                        memset( (char *)ptr + copy_end, (int)Fill.c, Dim * size - copy_end );
    202191                } else if(Fill.tag == 't') {
    203                         for ( int i = copy_end; i <= Dim * size - size ; i += size ) {
     192                        for ( int i = copy_end; i < Dim * size; i += size ) {
    204193                                memcpy( (char *)ptr + i, &Fill.t, size );
    205194                        }
     
    207196                        memcpy( (char *)ptr + copy_end, Fill.at, min(Dim * size - copy_end, Fill.size) );
    208197                } else if(Fill.tag == 'T') {
    209                         for ( int i = copy_end; i <= Dim * size - size ; i += size ) {
     198                        for ( int i = copy_end; i < Dim * size; i += size ) {
    210199                                memcpy( (char *)ptr + i, Fill.at, size );
    211200                        }
Note: See TracChangeset for help on using the changeset viewer.