Changeset 93d2219 for libcfa/src


Ignore:
Timestamp:
Oct 28, 2022, 3:12:16 PM (3 years ago)
Author:
JiadaL <j82liang@…>
Branches:
ADT, ast-experimental, master
Children:
fa2e183
Parents:
e874605 (diff), 22a0e87 (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/src
Files:
3 added
2 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    re874605 r93d2219  
    6262        containers/array.hfa \
    6363        containers/list.hfa \
    64         containers/queueLockFree.hfa \
    65         containers/stackLockFree.hfa \
     64        containers/lockfree.hfa \
    6665        containers/string_sharectx.hfa \
    6766        containers/vector2.hfa \
     
    127126
    128127thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \
     128        interpose_thread.cfa \
    129129        bits/signal.hfa \
    130130        concurrency/clib/cfathread.cfa \
     
    145145        concurrency/stats.cfa \
    146146        concurrency/stats.hfa \
    147         concurrency/stats.hfa
     147        concurrency/stats.hfa \
     148        concurrency/pthread.cfa
    148149
    149150else
  • libcfa/src/concurrency/clib/cfathread.cfa

    re874605 r93d2219  
    172172
    173173                pthread_attr_t attr;
    174                 if (int ret = pthread_attr_init(&attr); 0 != ret) {
     174                if (int ret = __cfaabi_pthread_attr_init(&attr); 0 != ret) {
    175175                        abort | "failed to create master epoll thread attr: " | ret | strerror(ret);
    176176                }
    177177
    178                 if (int ret = pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
     178                if (int ret = __cfaabi_pthread_create(&master_poller, &attr, master_epoll, 0p); 0 != ret) {
    179179                        abort | "failed to create master epoll thread: " | ret | strerror(ret);
    180180                }
  • libcfa/src/concurrency/invoke.h

    re874605 r93d2219  
    214214
    215215                #if defined( __CFA_WITH_VERIFY__ )
     216                        struct processor * volatile executing;
    216217                        void * canary;
    217218                #endif
  • libcfa/src/concurrency/io.cfa

    re874605 r93d2219  
    610610                if( we ) {
    611611                        sigval_t value = { PREEMPT_IO };
    612                         pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
     612                        __cfaabi_pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
    613613                }
    614614
  • libcfa/src/concurrency/io/setup.cfa

    re874605 r93d2219  
    344344        //      iopoll.run = false;
    345345        //      sigval val = { 1 };
    346         //      pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
     346        //      __cfaabi_pthread_sigqueue( iopoll.thrd, SIGUSR1, val );
    347347
    348348        //      // Make sure all this is done
  • libcfa/src/concurrency/kernel.cfa

    re874605 r93d2219  
    321321                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    322322                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
     323                /* paranoid */ verify( __atomic_exchange_n( &thrd_dst->executing, this, __ATOMIC_SEQ_CST) == 0p );
    323324                /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
    324325
     
    332333
    333334                /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd_dst->canary );
     335                /* paranoid */ verify( __atomic_exchange_n( &thrd_dst->executing, 0p, __ATOMIC_SEQ_CST) == this );
    334336                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too large.\n", thrd_dst );
    335337                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->corctx_flag, "ERROR : Destination thread$ %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
     338                /* paranoid */ verify( thrd_dst->state != Halted );
    336339                /* paranoid */ verify( thrd_dst->context.SP );
    337                 /* paranoid */ verify( thrd_dst->curr_cluster == this->cltr );
    338340                /* paranoid */ verify( kernelTLS().this_thread == thrd_dst );
    339341                /* paranoid */ verify( ! __preemption_enabled() );
  • libcfa/src/concurrency/kernel.hfa

    re874605 r93d2219  
    160160// P9_EMBEDDED( processor, dlink(processor) )
    161161static inline tytagref( dlink(processor), dlink(processor) ) ?`inner( processor & this ) {
    162     dlink(processor) & b = this.link;
    163     tytagref( dlink(processor), dlink(processor) ) result = { b };
    164     return result;
     162        dlink(processor) & b = this.link;
     163        tytagref( dlink(processor), dlink(processor) ) result = { b };
     164        return result;
    165165}
    166166
     
    269269                io_context_params params;
    270270        } io;
     271
     272        struct {
     273                struct processor ** procs;
     274                unsigned cnt;
     275        } managed;
    271276
    272277        #if !defined(__CFA_NO_STATISTICS__)
     
    298303static inline struct cluster   * active_cluster  () { return publicTLS_get( this_processor )->cltr; }
    299304
     305// set the number of internal processors
     306// these processors are in addition to any explicitly declared processors
     307unsigned set_concurrency( cluster & this, unsigned new_count );
     308
    300309#if !defined(__CFA_NO_STATISTICS__)
    301310        void print_stats_now( cluster & this, int flags );
  • libcfa/src/concurrency/kernel/private.hfa

    re874605 r93d2219  
    2020#endif
    2121
     22#include <signal.h>
     23
    2224#include "kernel.hfa"
    2325#include "thread.hfa"
     
    4850        #endif
    4951#endif
    50 
    5152// #define READYQ_USE_LINEAR_AVG
    5253#define READYQ_USE_LOGDBL_AVG
     
    6263#error must pick a scheme for averaging
    6364#endif
     65
     66extern "C" {
     67        __attribute__((visibility("protected"))) int __cfaabi_pthread_create(pthread_t *_thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
     68        __attribute__((visibility("protected"))) int __cfaabi_pthread_join(pthread_t _thread, void **retval);
     69        __attribute__((visibility("protected"))) pthread_t __cfaabi_pthread_self(void);
     70        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_init(pthread_attr_t *attr);
     71        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_destroy(pthread_attr_t *attr);
     72        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize );
     73        __attribute__((visibility("protected"))) int __cfaabi_pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize );
     74        __attribute__((visibility("protected"))) int __cfaabi_pthread_sigqueue(pthread_t _thread, int sig, const union sigval value);
     75        __attribute__((visibility("protected"))) int __cfaabi_pthread_sigmask( int how, const sigset_t *set, sigset_t *oset);
     76}
    6477
    6578//-----------------------------------------------------------------------------
  • libcfa/src/concurrency/kernel/startup.cfa

    re874605 r93d2219  
    1616#define __cforall_thread__
    1717#define _GNU_SOURCE
     18
     19// #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
    1820
    1921// C Includes
     
    222224                ( this.runner ){};
    223225                init( this, "Main Processor", *mainCluster, 0p );
    224                 kernel_thread = pthread_self();
     226                kernel_thread = __cfaabi_pthread_self();
    225227
    226228                runner{ &this };
     
    283285}
    284286
     287extern "C"{
     288        void pthread_delete_kernel_threads_();
     289}
     290
     291
    285292static void __kernel_shutdown(void) {
    286293        if(!cfa_main_returned) return;
     294
     295        //delete kernel threads for pthread_concurrency
     296        pthread_delete_kernel_threads_();
     297
    287298        /* paranoid */ verify( __preemption_enabled() );
    288299        disable_interrupts();
     
    327338
    328339                /* paranoid */ verify( this.do_terminate == true );
    329                 __cfaabi_dbg_print_safe("Kernel : destroyed main processor context %p\n", &runner);
     340                __cfadbg_print_safe(runtime_core, "Kernel : destroyed main processor context %p\n", &runner);
    330341        }
    331342
     
    388399        (proc->runner){ proc, &info };
    389400
    390         __cfaabi_dbg_print_safe("Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
     401        __cfadbg_print_safe(runtime_core, "Coroutine : created stack %p\n", get_coroutine(proc->runner)->stack.storage);
    391402
    392403        //Set global state
     
    520531        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    521532        #if defined( __CFA_WITH_VERIFY__ )
     533                executing = 0p;
    522534                canary = 0x0D15EA5E0D15EA5Ep;
    523535        #endif
     
    652664        io.params = io_params;
    653665
     666        managed.procs = 0p;
     667        managed.cnt = 0;
     668
    654669        doregister(this);
    655670
     
    667682
    668683void ^?{}(cluster & this) libcfa_public {
     684        set_concurrency( this, 0 );
     685
    669686        destroy(this.io.arbiter);
    670687
     
    777794        pthread_attr_t attr;
    778795
    779         check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     796        check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
    780797
    781798        size_t stacksize = max( PTHREAD_STACK_MIN, DEFAULT_STACK_SIZE );
     
    804821        #endif
    805822
    806         check( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
    807         check( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     823        check( __cfaabi_pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     824        check( __cfaabi_pthread_create( pthread, &attr, start, arg ), "pthread_create" );
    808825        return stack;
    809826}
    810827
    811828void __destroy_pthread( pthread_t pthread, void * stack, void ** retval ) {
    812         int err = pthread_join( pthread, retval );
     829        int err = __cfaabi_pthread_join( pthread, retval );
    813830        if( err != 0 ) abort("KERNEL ERROR: joining pthread %p caused error %s\n", (void*)pthread, strerror(err));
    814831
     
    816833                pthread_attr_t attr;
    817834
    818                 check( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     835                check( __cfaabi_pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
    819836
    820837                size_t stacksize;
    821838                // default stack size, normally defined by shell limit
    822                 check( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     839                check( __cfaabi_pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
    823840                assert( stacksize >= PTHREAD_STACK_MIN );
    824841                stacksize += __page_size;
     
    838855}
    839856
     857unsigned set_concurrency( cluster & this, unsigned new ) libcfa_public {
     858        unsigned old = this.managed.cnt;
     859
     860        __cfadbg_print_safe(runtime_core, "Kernel : resizing cluster from %u to %u\n", old, (unsigned)new);
     861
     862        // Delete all the old unneeded procs
     863        if(old > new) for(i; (unsigned)new ~ old) {
     864                __cfadbg_print_safe(runtime_core, "Kernel : destroying %u\n", i);
     865                delete( this.managed.procs[i] );
     866        }
     867
     868        // Allocate new array (uses realloc and memcpies the data)
     869        this.managed.procs = alloc( new, this.managed.procs`realloc );
     870        this.managed.cnt = new;
     871
     872        // Create the desired new procs
     873        if(old < new) for(i; old ~ new) {
     874                __cfadbg_print_safe(runtime_core, "Kernel : constructing %u\n", i);
     875                (*(this.managed.procs[i] = alloc())){ this };
     876        }
     877
     878        // return the old count
     879        return old;
     880}
     881
    840882#if defined(__CFA_WITH_VERIFY__)
    841883static bool verify_fwd_bck_rng(void) {
  • libcfa/src/concurrency/locks.hfa

    re874605 r93d2219  
    2121
    2222#include "bits/weakso_locks.hfa"
    23 #include "containers/queueLockFree.hfa"
     23#include "containers/lockfree.hfa"
    2424#include "containers/list.hfa"
    2525
     
    423423}
    424424
    425 static inline size_t on_wait(simple_owner_lock & this) with(this) { 
     425static inline size_t on_wait(simple_owner_lock & this) with(this) {
    426426        lock( lock __cfaabi_dbg_ctx2 );
    427427        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
  • libcfa/src/concurrency/preemption.cfa

    re874605 r93d2219  
    352352        sigset_t oldset;
    353353        int ret;
    354         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     354        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    355355        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    356356
     
    385385        sigaddset( &mask, sig );
    386386
    387         if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
     387        if ( __cfaabi_pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
    388388            abort( "internal error, pthread_sigmask" );
    389389        }
     
    396396        sigaddset( &mask, sig );
    397397
    398         if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
     398        if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    399399                abort( "internal error, pthread_sigmask" );
    400400        }
     
    404404static void preempt( processor * this ) {
    405405        sigval_t value = { PREEMPT_NORMAL };
    406         pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
     406        __cfaabi_pthread_sigqueue( this->kernel_thread, SIGUSR1, value );
    407407}
    408408
     
    415415        sigset_t oldset;
    416416        int ret;
    417         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     417        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    418418        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    419419
     
    434434        sigset_t oldset;
    435435        int ret;
    436         ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     436        ret = __cfaabi_pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    437437        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    438438
     
    505505        sigval val;
    506506        val.sival_int = 0;
    507         pthread_sigqueue( alarm_thread, SIGALRM, val );
     507        __cfaabi_pthread_sigqueue( alarm_thread, SIGALRM, val );
    508508
    509509        // Wait for the preemption thread to finish
     
    579579        static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
    580580        #endif
    581         if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
     581        if ( __cfaabi_pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
    582582                abort( "internal error, sigprocmask" );
    583583        }
     
    607607        sigset_t mask;
    608608        sigfillset(&mask);
    609         if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
     609        if ( __cfaabi_pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    610610            abort( "internal error, pthread_sigmask" );
    611611        }
  • libcfa/src/concurrency/thread.cfa

    re874605 r93d2219  
    5050        random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl();
    5151        #if defined( __CFA_WITH_VERIFY__ )
     52                executing = 0p;
    5253                canary = 0x0D15EA5E0D15EA5Ep;
    5354        #endif
     
    177178
    178179//-----------------------------------------------------------------------------
     180bool migrate( thread$ * thrd, struct cluster & cl ) {
     181
     182        monitor$ * tmon = get_monitor(thrd);
     183        monitor$ * __monitors[] = { tmon };
     184        monitor_guard_t __guard = { __monitors, 1 };
     185
     186
     187        {
     188                // if nothing needs to be done, return false
     189                if( thrd->curr_cluster == &cl ) return false;
     190
     191                // are we migrating ourself?
     192                const bool local = thrd == active_thread();
     193
     194                /* paranoid */ verify( !local || &cl != active_cluster() );
     195                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
     196                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
     197                /* paranoid */ verify( local || tmon->signal_stack.top->owner->waiting_thread == thrd );
     198                /* paranoid */ verify( local || tmon->signal_stack.top );
     199
     200                // make sure we aren't interrupted while doing this
     201                // not as important if we aren't local
     202                disable_interrupts();
     203
     204                // actually move the thread
     205                unregister( thrd->curr_cluster, *thrd );
     206                thrd->curr_cluster = &cl;
     207                doregister( thrd->curr_cluster, *thrd );
     208
     209                // restore interrupts
     210                enable_interrupts();
     211
     212                // if this is the local thread, we are still running on the old cluster
     213                if(local) yield();
     214
     215                /* paranoid */ verify( !local || &cl == active_cluster() );
     216                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
     217                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
     218                /* paranoid */ verify(  local || tmon->signal_stack.top );
     219                /* paranoid */ verify(  local || tmon->signal_stack.top->owner->waiting_thread == thrd );
     220
     221                return true;
     222        }
     223}
     224
     225//-----------------------------------------------------------------------------
    179226#define GENERATOR LCG
    180227
  • libcfa/src/concurrency/thread.hfa

    re874605 r93d2219  
    132132
    133133//----------
     134// misc
     135bool migrate( thread$ * thrd, struct cluster & cl );
     136
     137forall( T & | is_thread(T) )
     138static inline bool migrate( T & mutex thrd, struct cluster & cl ) { return migrate( &(thread&)thrd, cl ); }
     139
     140
     141//----------
    134142// prng
    135143static inline {
  • libcfa/src/containers/array.hfa

    re874605 r93d2219  
     1#pragma once
     2
    13#include <assert.h>
    24
     
    1820    // About the choice of integral types offered as subscript overloads:
    1921    // Intent is to cover these use cases:
     22    //    a[0]                                                // i : zero_t
     23    //    a[1]                                                // i : one_t
     24    //    a[2]                                                // i : int
    2025    //    float foo( ptrdiff_t i ) { return a[i]; }           // i : ptrdiff_t
     26    //    float foo( size_t i ) { return a[i]; }              // i : size_t
    2127    //    forall( [N] ) ... for( i; N ) { total += a[i]; }    // i : typeof( sizeof(42) )
    2228    //    for( i; 5 ) { total += a[i]; }                      // i : int
     29    //
    2330    // It gets complicated by:
    2431    // -  CFA does overloading on concrete types, like int and unsigned int, not on typedefed
     
    2734    // -  Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it
    2835    //    should give them type size_t.
    29     //   
    30     //                          gcc -m32         cfa -m32 given bug         gcc -m64
     36    //
     37    //                          gcc -m32         cfa -m32 given bug         gcc -m64 (and cfa)
    3138    // ptrdiff_t                int              int                        long int
    3239    // size_t                   unsigned int     unsigned int               unsigned long int
    3340    // typeof( sizeof(42) )     unsigned int     unsigned long int          unsigned long int
    3441    // int                      int              int                        int
     42    //
     43    // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int}
     44    //
     45    // The solution cannot rely on implicit conversions (e.g. just have one overload for ptrdiff_t)
     46    // because assertion satisfaction requires types to match exacly.  Both higher-dimensional
     47    // subscripting and operations on slices use asserted subscript operators.  The test case
     48    // array-container/array-sbscr-cases covers the combinations.  Mike beleives that commenting out
     49    // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit.
     50    // Mike is open to being shown a smaller set of overloads that still passes the test.
     51
     52    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, zero_t ) {
     53        assert( 0 < N );
     54        return (Timmed &) a.strides[0];
     55    }
     56
     57    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, one_t ) {
     58        assert( 1 < N );
     59        return (Timmed &) a.strides[1];
     60    }
    3561
    3662    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, int i ) {
     
    3965    }
    4066
     67    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, int i ) {
     68        assert( i < N );
     69        return (Timmed &) a.strides[i];
     70    }
     71
    4172    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
    4273        assert( i < N );
     
    4475    }
    4576
     77    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
     78        assert( i < N );
     79        return (Timmed &) a.strides[i];
     80    }
     81
    4682    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, long int i ) {
    4783        assert( i < N );
     
    4985    }
    5086
     87    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, long int i ) {
     88        assert( i < N );
     89        return (Timmed &) a.strides[i];
     90    }
     91
    5192    static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
     93        assert( i < N );
     94        return (Timmed &) a.strides[i];
     95    }
     96
     97    static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
    5298        assert( i < N );
    5399        return (Timmed &) a.strides[i];
     
    57103        return N;
    58104    }
     105
     106    static inline void __taglen( tag(arpk(N, S, Timmed, Tbase)), tag(N) ) {}
    59107
    60108    // workaround #226 (and array relevance thereof demonstrated in mike102/otype-slow-ndims.cfa)
     
    83131    // Make a FOREACH macro
    84132    #define FE_0(WHAT)
    85     #define FE_1(WHAT, X) WHAT(X) 
     133    #define FE_1(WHAT, X) WHAT(X)
    86134    #define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
    87135    #define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
     
    90138    //... repeat as needed
    91139
    92     #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME 
     140    #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
    93141    #define FOR_EACH(action,...) \
    94142    GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
     
    115163}
    116164
    117 #else 
     165#else
    118166
    119167// Workaround form.  Listing all possibilities up to 4 dims.
     
    135183
    136184#endif
     185
     186// Available for users to work around Trac #265
     187// If `a[...0...]` isn't working, try `a[...ix0...]` instead.
     188
     189#define ix0 ((ptrdiff_t)0)
     190
     191
    137192
    138193//
     
    155210
    156211// Wrapper
    157 struct all_t {} all;
     212extern struct all_t {} all;
    158213forall( [N], S & | sized(S), Te &, result &, Tbase & | { tag(result) enq_( tag(Tbase), tag(N), tag(S), tag(Te) ); } )
    159214static inline result & ?[?]( arpk(N, S, Te, Tbase) & this, all_t ) {
     
    165220//
    166221
    167 trait ar(A &, Tv &) {
    168     Tv& ?[?]( A&, ptrdiff_t );
    169     size_t ?`len( A& );
    170 };
     222// desired:
     223// trait ar(A &, Tv &, [N]) {
     224//     Tv& ?[?]( A&, zero_t );
     225//     Tv& ?[?]( A&, one_t  );
     226//     Tv& ?[?]( A&, int    );
     227//                   ...
     228//     size_t ?`len( A& );
     229//     void __taglen( tag(C), tag(N) );
     230// };
     231
     232// working around N's not being accepted as arguments to traits
     233
     234#define ar(A, Tv, N) {                 \
     235    Tv& ?[?]( A&, zero_t );            \
     236    Tv& ?[?]( A&, one_t );             \
     237    Tv& ?[?]( A&, int );               \
     238    Tv& ?[?]( A&, unsigned int );      \
     239    Tv& ?[?]( A&, long int );          \
     240    Tv& ?[?]( A&, unsigned long int ); \
     241    size_t ?`len( A& );                \
     242    void __taglen( tag(A), tag(N) );   \
     243}
  • libcfa/src/device/cpu.cfa

    re874605 r93d2219  
    359359                int idxs = count_cache_indexes();
    360360
     361                // Do we actually have a cache?
     362                if(idxs == 0) {
     363                        // if not just fake the data structure, it makes things easier.
     364                        cpu_info.hthrd_count = cpus_c;
     365                        cpu_info.llc_count = 0;
     366                        struct cpu_map_entry_t * entries = alloc(cpu_info.hthrd_count);
     367                        for(i; cpu_info.hthrd_count) {
     368                                entries[i].self  = i;
     369                                entries[i].start = 0;
     370                                entries[i].count = cpu_info.hthrd_count;
     371                                entries[i].cache = 0;
     372                        }
     373                        cpu_info.llc_map = entries;
     374                        return;
     375                }
     376
    361377                // Count actual cache levels
    362378                unsigned cache_levels = 0;
    363379                unsigned llc = 0;
    364                 if (idxs != 0) {
    365                         unsigned char prev = -1u;
    366                         void first(unsigned idx, unsigned char level, const char * map, size_t len) {
    367                                 /* paranoid */ verifyf(level < prev, "Index %u of cpu 0 has cache levels out of order: %u then %u", idx, (unsigned)prev, (unsigned)level);
    368                                 llc = max(llc, level);
    369                                 prev = level;
    370                                 cache_levels++;
    371                         }
    372                         foreach_cacheidx(0, idxs, first);
    373                 }
     380
     381                unsigned char prev = -1u;
     382                void first(unsigned idx, unsigned char level, const char * map, size_t len) {
     383                        /* paranoid */ verifyf(level < prev, "Index %u of cpu 0 has cache levels out of order: %u then %u", idx, (unsigned)prev, (unsigned)level);
     384                        llc = max(llc, level);
     385                        prev = level;
     386                        cache_levels++;
     387                }
     388                foreach_cacheidx(0, idxs, first);
    374389
    375390                // Read in raw data
  • libcfa/src/heap.cfa

    re874605 r93d2219  
    211211#if BUCKETLOCK == SPINLOCK
    212212#elif BUCKETLOCK == LOCKFREE
    213 #include <stackLockFree.hfa>
     213#include <containers/lockfree.hfa>
    214214#else
    215215        #error undefined lock type for bucket lock
     
    505505                                freeLists[j].blockSize = bucketSizes[j];
    506506                        } // for
    507        
     507
    508508                        heapBuffer = 0p;
    509509                        heapReserve = 0;
  • libcfa/src/interpose.cfa

    re874605 r93d2219  
    4242
    4343typedef void (* generic_fptr_t)(void);
     44static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) {
     45        const char * error;
     46
     47        union { generic_fptr_t fptr; void * ptr; } originalFunc;
     48
     49        #if defined( _GNU_SOURCE )
     50                if ( version ) {
     51                        originalFunc.ptr = dlvsym( library, symbol, version );
     52                } else {
     53                        originalFunc.ptr = dlsym( library, symbol );
     54                }
     55        #else
     56                originalFunc.ptr = dlsym( library, symbol );
     57        #endif // _GNU_SOURCE
     58
     59        error = dlerror();
     60        if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
     61
     62        return originalFunc.fptr;
     63}
     64
    4465static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    4566        const char * error;
    4667
    4768        static void * library;
     69        static void * pthread_library;
    4870        if ( ! library ) {
    4971                #if defined( RTLD_NEXT )
     
    5880                #endif
    5981        } // if
    60 
    61         union { generic_fptr_t fptr; void * ptr; } originalFunc;
    62 
    63         #if defined( _GNU_SOURCE )
    64                 if ( version ) {
    65                         originalFunc.ptr = dlvsym( library, symbol, version );
    66                 } else {
    67                         originalFunc.ptr = dlsym( library, symbol );
    68                 }
    69         #else
    70                 originalFunc.ptr = dlsym( library, symbol );
    71         #endif // _GNU_SOURCE
    72 
    73         error = dlerror();
    74         if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
    75 
    76         return originalFunc.fptr;
     82        if ( ! pthread_library ) {
     83                #if defined( RTLD_NEXT )
     84                        pthread_library = RTLD_NEXT;
     85                #else
     86                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     87                        pthread_library = dlopen( "libpthread.so", RTLD_LAZY );
     88                        error = dlerror();
     89                        if ( error ) {
     90                                abort( "interpose_symbol : failed to open libpthread, %s\n", error );
     91                        }
     92                #endif
     93        } // if
     94
     95        return do_interpose_symbol(library, symbol, version);
    7796}
    7897
     
    97116
    98117extern "C" {
     118        void __cfathreadabi_interpose_startup( generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ) ) __attribute__((weak));
    99119        void __cfaabi_interpose_startup( void ) {
    100120                const char *version = 0p;
     
    108128                INTERPOSE_LIBC( exit , version );
    109129#pragma GCC diagnostic pop
     130
     131                if(__cfathreadabi_interpose_startup) __cfathreadabi_interpose_startup( do_interpose_symbol );
    110132
    111133                // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
  • libcfa/src/parseargs.cfa

    re874605 r93d2219  
    5050extern char ** cfa_args_envp __attribute__((weak));
    5151
    52 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
     52forall([N])
     53static void usage(char * cmd, const array( cfa_option, N ) & options, const char * usage, FILE * out)  __attribute__ ((noreturn));
    5354//-----------------------------------------------------------------------------
    5455// checking
    55 static void check_args(cfa_option options[], size_t opt_count) {
    56         for(i; opt_count) {
    57                 for(j; opt_count) {
     56forall([N])
     57static void check_args( const array( cfa_option, N ) & options ) {
     58        for(i; N) {
     59                for(j; N) {
    5860                        if(i == j) continue;
    5961
     
    7072//-----------------------------------------------------------------------------
    7173// Parsing args
    72 void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
    73         if( 0p != &cfa_args_argc ) {
    74                 parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
    75         }
    76         else {
    77                 char * temp = "";
    78                 parse_args(0, &temp, options, opt_count, usage, left );
    79         }
    80 }
    81 
    82 void parse_args(
    83         int argc,
    84         char * argv[],
    85         cfa_option options[],
    86         size_t opt_count,
    87         const char * usage,
    88         char ** & left
    89 ) {
    90         check_args(options, opt_count);
    91 
    92         int maxv = 'h';
    93         char optstring[(opt_count * 3) + 2] = { '\0' };
    94         {
    95                 int idx = 0;
    96                 for(i; opt_count) {
    97                         if (options[i].short_name) {
    98                                 maxv = max(options[i].short_name, maxv);
    99                                 optstring[idx] = options[i].short_name;
    100                                 idx++;
    101                                 if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
    102                                 && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
    103                                         optstring[idx] = ':';
     74forall([opt_count]) {
     75        void parse_args( const array( cfa_option, opt_count ) & options, const char * usage, char ** & left ) {
     76                if( 0p != &cfa_args_argc ) {
     77                        parse_args(cfa_args_argc, cfa_args_argv, options, usage, left );
     78                }
     79                else {
     80                        char * temp = "";
     81                        parse_args(0, &temp, options, usage, left );
     82                }
     83        }
     84
     85        void parse_args(
     86                int argc,
     87                char * argv[],
     88                const array( cfa_option, opt_count ) & options,
     89                const char * usage,
     90                char ** & left
     91        ) {
     92                check_args(options);
     93
     94                int maxv = 'h';
     95                char optstring[(opt_count * 3) + 2] = { '\0' };
     96                {
     97                        int idx = 0;
     98                        for(i; opt_count) {
     99                                if (options[i].short_name) {
     100                                        maxv = max(options[i].short_name, maxv);
     101                                        optstring[idx] = options[i].short_name;
     102                                        idx++;
     103                                        if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
     104                                        && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
     105                                                optstring[idx] = ':';
     106                                                idx++;
     107                                        }
     108                                }
     109                        }
     110                        optstring[idx+0] = 'h';
     111                        optstring[idx+1] = '\0';
     112                }
     113
     114                struct option optarr[opt_count + 2];
     115                {
     116                        int idx = 0;
     117                        for(i; opt_count) {
     118                                if(options[i].long_name) {
     119                                        // we don't have the mutable keyword here, which is really what we would want
     120                                        int & val_ref = (int &)(const int &)options[i].val;
     121                                        val_ref = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
     122
     123                                        optarr[idx].name = options[i].long_name;
     124                                        optarr[idx].flag = 0p;
     125                                        optarr[idx].val  = options[i].val;
     126                                        if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
     127                                        || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
     128                                                optarr[idx].has_arg = no_argument;
     129                                        } else {
     130                                                optarr[idx].has_arg = required_argument;
     131                                        }
    104132                                        idx++;
    105133                                }
    106134                        }
    107                 }
    108                 optstring[idx+0] = 'h';
    109                 optstring[idx+1] = '\0';
    110         }
    111 
    112         struct option optarr[opt_count + 2];
    113         {
    114                 int idx = 0;
    115                 for(i; opt_count) {
    116                         if(options[i].long_name) {
    117                                 options[i].val = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
    118                                 optarr[idx].name = options[i].long_name;
    119                                 optarr[idx].flag = 0p;
    120                                 optarr[idx].val  = options[i].val;
    121                                 if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
    122                                     || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
    123                                         optarr[idx].has_arg = no_argument;
    124                                 } else {
    125                                         optarr[idx].has_arg = required_argument;
    126                                 }
    127                                 idx++;
     135                        optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
     136                        optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
     137                }
     138
     139                FILE * out = stderr;
     140                NEXT_ARG:
     141                for() {
     142                        int idx = 0;
     143                        int opt = getopt_long(argc, argv, optstring, optarr, &idx);
     144                        switch(opt) {
     145                                case -1:
     146                                        if(&left != 0p) left = argv + optind;
     147                                        return;
     148                                case 'h':
     149                                        out = stdout;
     150                                case '?':
     151                                        usage(argv[0], options, usage, out);
     152                                default:
     153                                        for(i; opt_count) {
     154                                                if(opt == options[i].val) {
     155                                                        const char * arg = optarg ? optarg : "";
     156                                                        if( arg[0] == '=' ) { arg++; }
     157                                                        // work around for some weird bug
     158                                                        void * variable = options[i].variable;
     159                                                        bool (*parse_func)(const char *, void * ) = options[i].parse;
     160                                                        bool success = parse_func( arg, variable );
     161                                                        if(success) continue NEXT_ARG;
     162
     163                                                        fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
     164                                                        usage(argv[0], options, usage, out);
     165                                                }
     166                                        }
     167                                        abort("Internal parse arg error\n");
    128168                        }
    129                 }
    130                 optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
    131                 optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
    132         }
    133 
    134         FILE * out = stderr;
    135         NEXT_ARG:
    136         for() {
    137                 int idx = 0;
    138                 int opt = getopt_long(argc, argv, optstring, optarr, &idx);
    139                 switch(opt) {
    140                         case -1:
    141                                 if(&left != 0p) left = argv + optind;
    142                                 return;
    143                         case 'h':
    144                                 out = stdout;
    145                         case '?':
    146                                 usage(argv[0], options, opt_count, usage, out);
    147                         default:
    148                                 for(i; opt_count) {
    149                                         if(opt == options[i].val) {
    150                                                 const char * arg = optarg ? optarg : "";
    151                                                 if( arg[0] == '=' ) { arg++; }
    152                                                 bool success = options[i].parse( arg, options[i].variable );
    153                                                 if(success) continue NEXT_ARG;
    154 
    155                                                 fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
    156                                                 usage(argv[0], options, opt_count, usage, out);
    157                                         }
    158                                 }
    159                                 abort("Internal parse arg error\n");
    160                 }
    161 
     169
     170                }
    162171        }
    163172}
     
    222231
    223232void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    224         usage(cfa_args_argv[0], options, opt_count, usage, error ? stderr : stdout);
     233        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
     234        usage(cfa_args_argv[0], arr, usage, error ? stderr : stdout);
    225235}
    226236
    227237void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    228         usage(argv[0], options, opt_count, usage, error ? stderr : stdout);
    229 }
    230 
    231 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * help, FILE * out) __attribute__((noreturn)) {
     238        const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
     239        usage(argv[0], arr, usage, error ? stderr : stdout);
     240}
     241
     242forall( [N] ) {
     243        void print_args_usage( const array(cfa_option, N ) & options, const char * usage, bool error) {
     244                usage(cfa_args_argv[0], options, usage, error ? stderr : stdout);
     245        }
     246
     247        void print_args_usage(int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, bool error) {
     248                usage(argv[0], options, usage, error ? stderr : stdout);
     249        }
     250}
     251
     252forall([N])
     253static void usage(char * cmd, const array( cfa_option, N ) & options, const char * help, FILE * out) __attribute__((noreturn)) {
    232254        int width = 0;
    233255        {
    234                 for(i; opt_count) {
     256                for(i; N) {
    235257                        if(options[i].long_name) {
    236258                                int w = strlen(options[i].long_name);
     
    251273        fprintf(out, "Usage:\n  %s %s\n", cmd, help);
    252274
    253         for(i; opt_count) {
     275        for(i; N) {
    254276                printopt(out, width, max_width, options[i].short_name, options[i].long_name, options[i].help);
    255277        }
  • libcfa/src/parseargs.hfa

    re874605 r93d2219  
    1616#pragma once
    1717
     18#include <array.hfa>
     19
    1820struct cfa_option {
    19       int val; // reserved
    20       char short_name;
    21       const char * long_name;
    22       const char * help;
    23       void * variable;
    24       bool (*parse)(const char *, void * );
     21        int val; // reserved
     22        char short_name;
     23        const char * long_name;
     24        const char * help;
     25        void * variable;
     26        bool (*parse)(const char *, void * );
    2527};
    2628
     
    3133forall(T & | { bool parse(const char *, T & ); })
    3234static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable ) {
    33       this.val        = 0;
    34       this.short_name = short_name;
    35       this.long_name  = long_name;
    36       this.help       = help;
    37       this.variable   = (void*)&variable;
    38       this.parse      = (bool (*)(const char *, void * ))parse;
     35        this.val        = 0;
     36        this.short_name = short_name;
     37        this.long_name  = long_name;
     38        this.help       = help;
     39        this.variable   = (void*)&variable;
     40        this.parse      = (bool (*)(const char *, void * ))parse;
    3941}
    4042
    4143forall(T &)
    4244static inline void ?{}( cfa_option & this, char short_name, const char * long_name, const char * help, T & variable, bool (*parse)(const char *, T & )) {
    43       this.val        = 0;
    44       this.short_name = short_name;
    45       this.long_name  = long_name;
    46       this.help       = help;
    47       this.variable   = (void*)&variable;
    48       this.parse      = (bool (*)(const char *, void * ))parse;
     45        this.val        = 0;
     46        this.short_name = short_name;
     47        this.long_name  = long_name;
     48        this.help       = help;
     49        this.variable   = (void*)&variable;
     50        this.parse      = (bool (*)(const char *, void * ))parse;
    4951}
    5052
     
    5254void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left );
    5355
     56forall( [N] ) {
     57        void parse_args( const array( cfa_option, N ) & options, const char * usage, char ** & left );
     58        void parse_args( int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, char ** & left );
     59}
     60
    5461void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
    5562void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn));
     63
     64forall( [N] ) {
     65        void print_args_usage( const array(cfa_option, N ) & options, const char * usage, bool error)  __attribute__ ((noreturn));
     66        void print_args_usage(int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, bool error)  __attribute__ ((noreturn));
     67}
    5668
    5769bool parse_yesno    (const char *, bool & );
Note: See TracChangeset for help on using the changeset viewer.