Changes in / [5527759:9d5fb67]


Ignore:
Location:
src
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r5527759 r9d5fb67  
    492492                        }
    493493
    494                         if(clause.target.arguments.empty()) {
    495                                 SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
    496                         }
    497 
    498494                        // Find all alternatives for all arguments in canonical form
    499495                        std::vector< AlternativeFinder > argAlternatives;
     
    560556                                                        auto param_end = function->parameters.end();
    561557
    562                                                         int n_mutex_arg = 0;
    563 
    564558                                                        // For every arguments of its set, check if it matches one of the parameter
    565559                                                        // The order is important
     
    570564                                                                        // We ran out of parameters but still have arguments
    571565                                                                        // this function doesn't match
    572                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" ));
     566                                                                        SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
    573567                                                                }
    574568
    575                                                                 n_mutex_arg++;
    576 
    577569                                                                // Check if the argument matches the parameter type in the current scope
    578                                                                 if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     570                                                                if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    579571                                                                        // Type doesn't match
    580572                                                                        stringstream ss;
    581573                                                                        ss << "candidate function not viable: no known convertion from '";
     574                                                                        arg.expr->get_result()->print( ss );
     575                                                                        ss << "' to '";
    582576                                                                        (*param)->get_type()->print( ss );
    583                                                                         ss << "' to '";
    584                                                                         arg.expr->get_result()->print( ss );
    585577                                                                        ss << "'\n";
    586578                                                                        SemanticError( function, ss.str() );
     
    596588                                                                // We ran out of arguments but still have parameters left
    597589                                                                // this function doesn't match
    598                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" ));
     590                                                                SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
    599591                                                        }
    600592
  • src/SynTree/Statement.cc

    r5527759 r9d5fb67  
    453453void WaitForStmt::print( std::ostream &os, Indenter indent ) const {
    454454        os << "Waitfor Statement" << endl;
    455         indent += 1;
    456         for( auto & clause : clauses ) {
    457                 os << indent << "target function :";
    458                 if(clause.target.function) { clause.target.function->print(os, indent + 1); }
    459                 os << endl << indent << "with arguments :" << endl;
    460                 for( auto & thing : clause.target.arguments) {
    461                         if(thing) { thing->print(os, indent + 1); }
    462                 }
    463                 os << indent << " with statment :" << endl;
    464                 if(clause.statement) { clause.statement->print(os, indent + 1); }
    465 
    466                 os << indent << " with condition :" << endl;
    467                 if(clause.condition) { clause.condition->print(os, indent + 1); }
    468         }
    469 
    470         os << indent << " timeout of :" << endl;
    471         if(timeout.time) { timeout.time->print(os, indent + 1); }
    472 
    473         os << indent << " with statment :" << endl;
    474         if(timeout.statement) { timeout.statement->print(os, indent + 1); }
    475 
    476         os << indent << " with condition :" << endl;
    477         if(timeout.condition) { timeout.condition->print(os, indent + 1); }
    478 
    479 
    480         os << indent << " else :" << endl;
    481         if(orelse.statement) { orelse.statement->print(os, indent + 1); }
    482 
    483         os << indent << " with condition :" << endl;
    484         if(orelse.condition) { orelse.condition->print(os, indent + 1); }
     455        os << indent << "... with block:" << endl << indent+1;
     456        // block->print( os, indent + 4 );
    485457}
    486458
  • src/libcfa/bits/locks.h

    r5527759 r9d5fb67  
    6969        }
    7070
    71 
    72         #ifdef __CFA_DEBUG__
    73                 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
    74         #else
    75                 #define __cfaabi_dbg_record(x, y)
    76         #endif
    77 
    7871        // Lock the spinlock, return false if already acquired
    7972        static inline _Bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
     
    8174                if( result ) {
    8275                        disable_interrupts();
    83                         __cfaabi_dbg_record( this, caller );
     76                        // __cfaabi_dbg_debug_do(
     77                        //      this.prev_name = caller;
     78                        //      this.prev_thrd = TL_GET( this_thread );
     79                        // )
    8480                }
    8581                return result;
     
    109105                }
    110106                disable_interrupts();
    111                 __cfaabi_dbg_record( this, caller );
     107                // __cfaabi_dbg_debug_do(
     108                //      this.prev_name = caller;
     109                //      this.prev_thrd = TL_GET( this_thread );
     110                // )
    112111        }
    113112
  • src/libcfa/concurrency/coroutine

    r5527759 r9d5fb67  
    3232//-----------------------------------------------------------------------------
    3333// Ctors and dtors
    34 // void ?{}( coStack_t & this );
    35 // void ^?{}( coStack_t & this );
    36 
    37 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize );
    38 void ^?{}( coroutine_desc & this );
    39 
    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 }; }
    42 static 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 }; }
     34void ?{}(coStack_t & this);
     35void ?{}(coroutine_desc & this);
     36void ?{}(coroutine_desc & this, const char * name);
     37void ^?{}(coStack_t & this);
     38void ^?{}(coroutine_desc & this);
    4539
    4640//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/coroutine.c

    r5527759 r9d5fb67  
    3939//-----------------------------------------------------------------------------
    4040// Coroutine ctors and dtors
    41 void ?{}( coStack_t & this, void * storage, size_t storageSize ) with( this ) {
    42       size               = storageSize == 0 ? 65000 : storageSize; // size of stack
    43       this.storage = storage;                                // pointer to stack
    44       limit              = NULL;                                   // stack grows towards stack limit
    45       base               = NULL;                                   // base of stack
    46       context    = NULL;                                   // address of cfa_context_t
    47       top                = NULL;                                   // address of top of storage
    48       userStack  = storage != NULL;
     41void ?{}(coStack_t& this) with( this ) {
     42        size            = 65000;        // size of stack
     43        storage = NULL; // pointer to stack
     44        limit           = NULL; // stack grows towards stack limit
     45        base            = NULL; // base of stack
     46        context = NULL; // address of cfa_context_t
     47        top             = NULL; // address of top of storage
     48        userStack       = false;
     49}
     50
     51void ?{}(coStack_t& this, size_t size) {
     52        this{};
     53        this.size = size;
     54
     55        create_stack(&this, this.size);
     56}
     57
     58void ?{}(coroutine_desc& this) {
     59        this{ "Anonymous Coroutine" };
     60}
     61
     62void ?{}(coroutine_desc& this, const char * name) with( this ) {
     63        this.name = name;
     64        errno_ = 0;
     65        state = Start;
     66        starter = NULL;
     67        last = NULL;
     68}
     69
     70void ?{}(coroutine_desc& this, size_t size) {
     71        this{};
     72        (this.stack){size};
    4973}
    5074
    5175void ^?{}(coStack_t & this) {
    52       if ( ! this.userStack && this.storage ) {
    53             __cfaabi_dbg_debug_do(
    54                   if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
    55                         abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    56                   }
    57             );
    58             free( this.storage );
    59       }
    60 }
    61 
    62 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
    63       (this.stack){storage, storageSize};
    64       this.name = name;
    65       errno_ = 0;
    66       state = Start;
    67       starter = NULL;
    68       last = NULL;
     76        if ( ! this.userStack && this.storage ) {
     77                __cfaabi_dbg_debug_do(
     78                        if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
     79                                abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
     80                        }
     81                );
     82                free( this.storage );
     83        }
    6984}
    7085
     
    7590forall(dtype T | is_coroutine(T))
    7691void prime(T& cor) {
    77       coroutine_desc* this = get_coroutine(cor);
    78       assert(this->state == Start);
     92        coroutine_desc* this = get_coroutine(cor);
     93        assert(this->state == Start);
    7994
    80       this->state = Primed;
    81       resume(cor);
     95        this->state = Primed;
     96        resume(cor);
    8297}
    8398
    8499// Wrapper for co
    85100void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    86       verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
    87       disable_interrupts();
     101        verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     102        disable_interrupts();
    88103
    89       // set state of current coroutine to inactive
    90       src->state = src->state == Halted ? Halted : Inactive;
     104        // set state of current coroutine to inactive
     105        src->state = src->state == Halted ? Halted : Inactive;
    91106
    92       // set new coroutine that task is executing
    93       TL_SET( this_coroutine, dst );
     107        // set new coroutine that task is executing
     108        TL_SET( this_coroutine, dst );
    94109
    95       // context switch to specified coroutine
    96       assert( src->stack.context );
    97       CtxSwitch( src->stack.context, dst->stack.context );
    98       // when CtxSwitch returns we are back in the src coroutine
     110        // context switch to specified coroutine
     111        assert( src->stack.context );
     112        CtxSwitch( src->stack.context, dst->stack.context );
     113        // when CtxSwitch returns we are back in the src coroutine
    99114
    100       // set state of new coroutine to active
    101       src->state = Active;
     115        // set state of new coroutine to active
     116        src->state = Active;
    102117
    103       enable_interrupts( __cfaabi_dbg_ctx );
    104       verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     118        enable_interrupts( __cfaabi_dbg_ctx );
     119        verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
    105120} //ctxSwitchDirect
    106121
    107122void create_stack( coStack_t* this, unsigned int storageSize ) with( *this ) {
    108       //TEMP HACK do this on proper kernel startup
    109       if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
     123        //TEMP HACK do this on proper kernel startup
     124        if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
    110125
    111       size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
     126        size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
    112127
    113       if ( !storage ) {
    114             __cfaabi_dbg_print_safe("Kernel : Creating stack of size %zu for stack obj %p\n", cxtSize + size + 8, this);
     128        if ( (intptr_t)storage == 0 ) {
     129                userStack = false;
     130                size = libCeiling( storageSize, 16 );
     131                // use malloc/memalign because "new" raises an exception for out-of-memory
    115132
    116             userStack = false;
    117             size = libCeiling( storageSize, 16 );
    118             // use malloc/memalign because "new" raises an exception for out-of-memory
     133                // assume malloc has 8 byte alignment so add 8 to allow rounding up to 16 byte alignment
     134                __cfaabi_dbg_debug_do( storage = memalign( pageSize, cxtSize + size + pageSize ) );
     135                __cfaabi_dbg_no_debug_do( storage = malloc( cxtSize + size + 8 ) );
    119136
    120             // assume malloc has 8 byte alignment so add 8 to allow rounding up to 16 byte alignment
    121             __cfaabi_dbg_debug_do( storage = memalign( pageSize, cxtSize + size + pageSize ) );
    122             __cfaabi_dbg_no_debug_do( storage = malloc( cxtSize + size + 8 ) );
     137                __cfaabi_dbg_debug_do(
     138                        if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) {
     139                                abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
     140                        } // if
     141                );
    123142
    124             __cfaabi_dbg_debug_do(
    125                   if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) {
    126                         abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
    127                   } // if
    128             );
     143                if ( (intptr_t)storage == 0 ) {
     144                        abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
     145                } // if
    129146
    130             if ( (intptr_t)storage == 0 ) {
    131                   abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
    132             } // if
     147                __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
     148                __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
    133149
    134             __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
    135             __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
     150        } else {
     151                assertf( ((size_t)storage & (libAlign() - 1)) != 0ul, "Stack storage %p for task/coroutine must be aligned on %d byte boundary.", storage, (int)libAlign() );
     152                userStack = true;
     153                size = storageSize - cxtSize;
    136154
    137       } else {
    138             __cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%u bytes)\n", this, storage, storageSize);
     155                if ( size % 16 != 0u ) size -= 8;
    139156
    140             assertf( ((size_t)storage & (libAlign() - 1)) == 0ul, "Stack storage %p for task/coroutine must be aligned on %d byte boundary.", storage, (int)libAlign() );
    141             userStack = true;
    142             size = storageSize - cxtSize;
     157                limit = (char *)libCeiling( (unsigned long)storage, 16 ); // minimum alignment
     158        } // if
     159        assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
    143160
    144             if ( size % 16 != 0u ) size -= 8;
    145 
    146             limit = (char *)libCeiling( (unsigned long)storage, 16 ); // minimum alignment
    147       } // if
    148       assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %d bytes for a stack.", size, MinStackSize );
    149 
    150       base = (char *)limit + size;
    151       context = base;
    152       top = (char *)context + cxtSize;
     161        base = (char *)limit + size;
     162        context = base;
     163        top = (char *)context + cxtSize;
    153164}
    154165
     
    156167// is not inline (We can't inline Cforall in C)
    157168extern "C" {
    158       void __suspend_internal(void) {
    159             suspend();
    160       }
     169        void __suspend_internal(void) {
     170                suspend();
     171        }
    161172
    162       void __leave_coroutine(void) {
    163             coroutine_desc * src = TL_GET( this_coroutine ); // optimization
     173        void __leave_coroutine(void) {
     174                coroutine_desc * src = TL_GET( this_coroutine ); // optimization
    164175
    165             assertf( src->starter != 0,
    166                   "Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
    167                   "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    168                   src->name, src );
    169             assertf( src->starter->state != Halted,
    170                   "Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
    171                   "Possible cause is terminated coroutine's main routine has already returned.",
    172                   src->name, src, src->starter->name, src->starter );
     176                assertf( src->starter != 0,
     177                        "Attempt to suspend/leave coroutine \"%.256s\" (%p) that has never been resumed.\n"
     178                        "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
     179                        src->name, src );
     180                assertf( src->starter->state != Halted,
     181                        "Attempt by coroutine \"%.256s\" (%p) to suspend/leave back to terminated coroutine \"%.256s\" (%p).\n"
     182                        "Possible cause is terminated coroutine's main routine has already returned.",
     183                        src->name, src, src->starter->name, src->starter );
    173184
    174             CoroutineCtxSwitch( src, src->starter );
    175       }
     185                CoroutineCtxSwitch( src, src->starter );
     186        }
    176187}
    177188
  • src/libcfa/concurrency/invoke.h

    r5527759 r9d5fb67  
    125125                // pointer to monitor with sufficient lifetime for current monitors
    126126                struct monitor_desc *  self_mon_p;
    127 
    128                 // pointer to the cluster on which the thread is running
    129                 struct cluster * curr_cluster;
    130127
    131128                // monitors currently held by this thread
  • src/libcfa/concurrency/kernel

    r5527759 r9d5fb67  
    4848        __queue_t(thread_desc) ready_queue;
    4949
    50         // Name of the cluster
    51         const char * name;
    52 
    5350        // Preemption rate on this cluster
    5451        Duration preemption_rate;
    5552};
    5653
    57 extern struct cluster * mainCluster;
    5854extern Duration default_preemption();
    5955
    60 void ?{} (cluster & this, const char * name, Duration preemption_rate);
     56void ?{} (cluster & this);
    6157void ^?{}(cluster & this);
    62 
    63 static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    64 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
    65 static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
    6658
    6759//-----------------------------------------------------------------------------
     
    10092        cluster * cltr;
    10193
    102         // Name of the processor
    103         const char * name;
    104 
    10594        // Handle to pthreads
    10695        pthread_t kernel_thread;
     
    130119};
    131120
    132 void  ?{}(processor & this, const char * name, cluster & cltr);
     121void  ?{}(processor & this);
     122void  ?{}(processor & this, cluster * cltr);
    133123void ^?{}(processor & this);
    134 
    135 static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    136 static inline void  ?{}(processor & this, cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    137 static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
    138124
    139125// Local Variables: //
  • src/libcfa/concurrency/kernel.c

    r5527759 r9d5fb67  
    4242KERNEL_STORAGE(cluster,           mainCluster);
    4343KERNEL_STORAGE(processor,         mainProcessor);
     44KERNEL_STORAGE(processorCtx_t,    mainProcessorCtx);
    4445KERNEL_STORAGE(thread_desc,       mainThread);
    4546KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    4647
    47 cluster     * mainCluster;
    48 processor   * mainProcessor;
     48cluster *    mainCluster;
     49processor mainProcessor;
    4950thread_desc * mainThread;
    5051
     
    6465
    6566//-----------------------------------------------------------------------------
    66 // Struct to steal stack
     67// Main thread construction
    6768struct current_stack_info_t {
    6869        machine_context_t ctx;
     
    8990}
    9091
    91 //-----------------------------------------------------------------------------
    92 // Main thread construction
    9392void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) {
    9493        size      = info->size;
     
    112111        self_cor{ info };
    113112        curr_cor = &self_cor;
    114         curr_cluster = mainCluster;
    115113        self_mon.owner = &this;
    116114        self_mon.recursion = 1;
     
    128126//-----------------------------------------------------------------------------
    129127// Processor coroutine
    130 void ?{}(processorCtx_t & this) {
    131 
     128void ?{}(processorCtx_t & this) {}
     129
     130// Construct the processor context of the main processor
     131void ?{}(processorCtx_t & this, processor * proc) {
     132        (this.__cor){ "Processor" };
     133        this.__cor.starter = NULL;
     134        this.proc = proc;
    132135}
    133136
     
    138141}
    139142
    140 void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {
    141         this.name = name;
    142         this.cltr = &cltr;
     143void ?{}(processor & this) {
     144        this{ mainCluster };
     145}
     146
     147void ?{}(processor & this, cluster * cltr) with( this ) {
     148        this.cltr = cltr;
    143149        terminated{ 0 };
    144150        do_terminate = false;
     
    148154
    149155        start( &this );
     156}
     157
     158void ?{}(processor & this, cluster * cltr, processorCtx_t & runner) with( this ) {
     159        this.cltr = cltr;
     160        terminated{ 0 };
     161        do_terminate = false;
     162        preemption_alarm = NULL;
     163        pending_preemption = false;
     164        kernel_thread = pthread_self();
     165        runner.proc = &this;
     166
     167        __cfaabi_dbg_print_safe("Kernel : constructing main processor context %p\n", &runner);
     168        runner{ &this };
    150169}
    151170
     
    162181}
    163182
    164 void ?{}(cluster & this, const char * name, Duration preemption_rate) with( this ) {
    165         this.name = name;
    166         this.preemption_rate = preemption_rate;
     183void ?{}(cluster & this) with( this ) {
    167184        ready_queue{};
    168185        ready_queue_lock{};
     186
     187        preemption_rate = default_preemption();
    169188}
    170189
     
    293312        TL_SET( this_coroutine, NULL );
    294313        TL_SET( this_thread, NULL );
    295         TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];
     314        TL_GET( preemption_state ).enabled = false;
     315        TL_GET( preemption_state ).disable_count = 1;
    296316        // SKULLDUGGERY: We want to create a context for the processor coroutine
    297317        // which is needed for the 2-step context switch. However, there is no reason
     
    382402        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    383403
    384         with( *thrd->curr_cluster ) {
     404        with( *TL_GET( this_processor )->cltr ) {
    385405                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
    386406                append( ready_queue, thrd );
     
    410430void BlockInternal( __spinlock_t * lock ) {
    411431        disable_interrupts();
    412         with( *TL_GET( this_processor ) ) {
    413                 finish.action_code = Release;
    414                 finish.lock        = lock;
    415         }
     432        TL_GET( this_processor )->finish.action_code = Release;
     433        TL_GET( this_processor )->finish.lock        = lock;
    416434
    417435        verify( ! TL_GET( preemption_state ).enabled );
     
    424442void BlockInternal( thread_desc * thrd ) {
    425443        disable_interrupts();
    426         with( *TL_GET( this_processor ) ) {
    427                 finish.action_code = Schedule;
    428                 finish.thrd        = thrd;
    429         }
     444        TL_GET( this_processor )->finish.action_code = Schedule;
     445        TL_GET( this_processor )->finish.thrd        = thrd;
    430446
    431447        verify( ! TL_GET( preemption_state ).enabled );
     
    439455        assert(thrd);
    440456        disable_interrupts();
    441         with( *TL_GET( this_processor ) ) {
    442                 finish.action_code = Release_Schedule;
    443                 finish.lock        = lock;
    444                 finish.thrd        = thrd;
    445         }
     457        TL_GET( this_processor )->finish.action_code = Release_Schedule;
     458        TL_GET( this_processor )->finish.lock        = lock;
     459        TL_GET( this_processor )->finish.thrd        = thrd;
    446460
    447461        verify( ! TL_GET( preemption_state ).enabled );
     
    454468void BlockInternal(__spinlock_t * locks [], unsigned short count) {
    455469        disable_interrupts();
    456         with( *TL_GET( this_processor ) ) {
    457                 finish.action_code = Release_Multi;
    458                 finish.locks       = locks;
    459                 finish.lock_count  = count;
    460         }
     470        TL_GET( this_processor )->finish.action_code = Release_Multi;
     471        TL_GET( this_processor )->finish.locks       = locks;
     472        TL_GET( this_processor )->finish.lock_count  = count;
    461473
    462474        verify( ! TL_GET( preemption_state ).enabled );
     
    469481void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
    470482        disable_interrupts();
    471         with( *TL_GET( this_processor ) ) {
    472                 finish.action_code = Release_Multi_Schedule;
    473                 finish.locks       = locks;
    474                 finish.lock_count  = lock_count;
    475                 finish.thrds       = thrds;
    476                 finish.thrd_count  = thrd_count;
    477         }
     483        TL_GET( this_processor )->finish.action_code = Release_Multi_Schedule;
     484        TL_GET( this_processor )->finish.locks       = locks;
     485        TL_GET( this_processor )->finish.lock_count  = lock_count;
     486        TL_GET( this_processor )->finish.thrds       = thrds;
     487        TL_GET( this_processor )->finish.thrd_count  = thrd_count;
    478488
    479489        verify( ! TL_GET( preemption_state ).enabled );
     
    486496void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    487497        verify( ! TL_GET( preemption_state ).enabled );
    488         with( *TL_GET( this_processor ) ) {
    489                 finish.action_code = thrd ? Release_Schedule : Release;
    490                 finish.lock        = lock;
    491                 finish.thrd        = thrd;
    492         }
     498        TL_GET( this_processor )->finish.action_code = thrd ? Release_Schedule : Release;
     499        TL_GET( this_processor )->finish.lock        = lock;
     500        TL_GET( this_processor )->finish.thrd        = thrd;
    493501
    494502        returnToKernel();
     
    504512        __cfaabi_dbg_print_safe("Kernel : Starting\n");
    505513
    506         // Initialize the main cluster
    507         mainCluster = (cluster *)&storage_mainCluster;
    508         (*mainCluster){"Main Cluster"};
    509 
    510         __cfaabi_dbg_print_safe("Kernel : Main cluster ready\n");
    511 
    512514        // Start by initializing the main thread
    513515        // SKULLDUGGERY: the mainThread steals the process main thread
     
    519521        __cfaabi_dbg_print_safe("Kernel : Main thread ready\n");
    520522
    521 
    522 
    523         // Construct the processor context of the main processor
    524         void ?{}(processorCtx_t & this, processor * proc) {
    525                 (this.__cor){ "Processor" };
    526                 this.__cor.starter = NULL;
    527                 this.proc = proc;
    528         }
    529 
    530         void ?{}(processor & this) with( this ) {
    531                 name = "Main Processor";
    532                 cltr = mainCluster;
    533                 terminated{ 0 };
    534                 do_terminate = false;
    535                 preemption_alarm = NULL;
    536                 pending_preemption = false;
    537                 kernel_thread = pthread_self();
    538 
    539                 runner{ &this };
    540                 __cfaabi_dbg_print_safe("Kernel : constructed main processor context %p\n", &runner);
    541         }
     523        // Initialize the main cluster
     524        mainCluster = (cluster *)&storage_mainCluster;
     525        (*mainCluster){};
     526
     527        __cfaabi_dbg_print_safe("Kernel : main cluster ready\n");
    542528
    543529        // Initialize the main processor and the main processor ctx
    544530        // (the coroutine that contains the processing control flow)
    545531        mainProcessor = (processor *)&storage_mainProcessor;
    546         (*mainProcessor){};
     532        (*mainProcessor){ mainCluster, *(processorCtx_t *)&storage_mainProcessorCtx };
    547533
    548534        //initialize the global state variables
     
    739725                thrd->dbg_next = NULL;
    740726        }
    741 
    742         void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
    743                 this.prev_name = prev_name;
    744                 this.prev_thrd = TL_GET( this_thread );
    745         }
    746727)
    747728// Local Variables: //
  • src/libcfa/concurrency/preemption.c

    r5527759 r9d5fb67  
    149149        // Disable interrupts by incrementing the counter
    150150        void disable_interrupts() {
    151                 with( TL_GET( preemption_state ) ) {
    152                         enabled = false;
    153                         __attribute__((unused)) unsigned short new_val = disable_count + 1;
    154                         disable_count = new_val;
    155                         verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    156                 }
     151                TL_GET( preemption_state ).enabled = false;
     152                __attribute__((unused)) unsigned short new_val = TL_GET( preemption_state ).disable_count + 1;
     153                TL_GET( preemption_state ).disable_count = new_val;
     154                verify( new_val < 65_000u );              // If this triggers someone is disabling interrupts without enabling them
    157155        }
    158156
     
    163161                thread_desc * thrd = TL_GET( this_thread );       // Cache the thread now since interrupts can start happening after the atomic add
    164162
    165                 with( TL_GET( preemption_state ) ){
    166                         unsigned short prev = disable_count;
    167                         disable_count -= 1;
    168                         verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
    169 
    170                         // Check if we need to prempt the thread because an interrupt was missed
    171                         if( prev == 1 ) {
    172                                 enabled = true;
    173                                 if( proc->pending_preemption ) {
    174                                         proc->pending_preemption = false;
    175                                         BlockInternal( thrd );
    176                                 }
     163                unsigned short prev = TL_GET( preemption_state ).disable_count;
     164                TL_GET( preemption_state ).disable_count -= 1;
     165                verify( prev != 0u );                     // If this triggers someone is enabled already enabled interruptsverify( prev != 0u );
     166
     167                // Check if we need to prempt the thread because an interrupt was missed
     168                if( prev == 1 ) {
     169                        TL_GET( preemption_state ).enabled = true;
     170                        if( proc->pending_preemption ) {
     171                                proc->pending_preemption = false;
     172                                BlockInternal( thrd );
    177173                        }
    178174                }
     
    332328        if( !preemption_ready() ) { return; }
    333329
    334         __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", TL_GET( this_processor ), TL_GET( this_thread ) );
     330        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
    335331
    336332        TL_GET( preemption_state ).in_progress = true;  // Sync flag : prevent recursive calls to the signal handler
  • src/libcfa/concurrency/thread

    r5527759 r9d5fb67  
    2323
    2424//-----------------------------------------------------------------------------
    25 // thread trait
     25// Coroutine trait
     26// Anything that implements this trait can be resumed.
     27// Anything that is resumed is a coroutine.
    2628trait is_thread(dtype T) {
    2729      void ^?{}(T& mutex this);
     
    5052}
    5153
    52 extern struct cluster * mainCluster;
     54//extern thread_local thread_desc * volatile this_thread;
    5355
    5456forall( dtype T | is_thread(T) )
     
    5759//-----------------------------------------------------------------------------
    5860// Ctors and dtors
    59 void ?{}(thread_desc & this, const char * const name, struct cluster & cl, void * storage, size_t storageSize );
    60 void ^?{}(thread_desc & this);
    61 
    62 static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 0 }; }
    63 static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
    64 static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
    65 static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 0 }; }
    66 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0, stackSize }; }
    67 static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
    68 static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 0 }; }
    69 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 0 }; }
    70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
     61void ?{}(thread_desc& this);
     62void ^?{}(thread_desc& this);
    7163
    7264//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/thread.c

    r5527759 r9d5fb67  
    3030//-----------------------------------------------------------------------------
    3131// Thread ctors and dtors
    32 void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
    33         self_cor{ name, storage, storageSize };
    34         verify(&self_cor);
     32
     33void ?{}(thread_desc& this) with( this ) {
     34        self_cor{};
     35        self_cor.name = "Anonymous Coroutine";
    3536        curr_cor = &self_cor;
    3637        self_mon.owner = &this;
    3738        self_mon.recursion = 1;
    3839        self_mon_p = &self_mon;
    39         curr_cluster = &cl;
    4040        next = NULL;
    4141        __cfaabi_dbg_debug_do(
  • src/tests/concurrent/examples/.expect/boundedBufferEXT.txt

    r5527759 r9d5fb67  
    1 total:400000
     1concurrent/examples/boundedBufferEXT.c:39:1 error: No alternatives for function in call to waitfor
     2/u/pabuhr/software/cfa-cc/include/cfa/bits/containers.h:170:1 error: candidate function not viable: no mutex parameters
     3forall
     4  _6573_20_T: sized object type
     5  ... with assertions
     6    get_next: pointer to function
     7    ... with parameters
     8      reference to instance of type _6573_20_T (not function type)
     9    ... returning
     10      _retval_get_next: reference to pointer to instance of type _6573_20_T (not function type)
     11      ... with attributes:
     12        Attribute with name: unused
     13
     14
     15
     16  lvalue function
     17... with parameters
     18  this: reference to instance of struct __queue with body 1
     19  ... with parameters
     20    instance of type _6573_20_T (not function type)
     21
     22  it: pointer to pointer to instance of type _6573_20_T (not function type)
     23... returning
     24  _retval_remove: pointer to instance of type _6573_20_T (not function type)
     25  ... with attributes:
     26    Attribute with name: unused
     27
     28
     29/usr/include/stdio.h:178:1 error: candidate function not viable: no mutex parameters
     30lvalue function
     31... with parameters
     32  __filename: C pointer to const char
     33... returning
     34  _retval_remove: signed int
     35  ... with attributes:
     36    Attribute with name: unused
     37
     38
     39concurrent/examples/boundedBufferEXT.c:47:1 error: No alternatives for function in call to waitfor
     40concurrent/examples/boundedBufferEXT.c:37:1 error: candidate function not viable: too few mutex arguments
     41forall
     42  _6578_20_T: sized object type
     43  ... with assertions
     44    ?=?: pointer to function
     45    ... with parameters
     46      reference to instance of type _6578_20_T (not function type)
     47      instance of type _6578_20_T (not function type)
     48    ... returning
     49      _retval__operator_assign: instance of type _6578_20_T (not function type)
     50      ... with attributes:
     51        Attribute with name: unused
     52
     53
     54    ?{}: pointer to function
     55    ... with parameters
     56      reference to instance of type _6578_20_T (not function type)
     57    ... returning nothing
     58
     59    ?{}: pointer to function
     60    ... with parameters
     61      reference to instance of type _6578_20_T (not function type)
     62      instance of type _6578_20_T (not function type)
     63    ... returning nothing
     64
     65    ^?{}: pointer to function
     66    ... with parameters
     67      reference to instance of type _6578_20_T (not function type)
     68    ... returning nothing
     69
     70
     71  lvalue function
     72... with parameters
     73  buffer: mutex reference to instance of struct Buffer with body 1
     74  ... with parameters
     75    instance of type _6578_20_T (not function type)
     76
     77  elem: instance of type _6578_20_T (not function type)
     78... returning nothing
     79
  • src/tests/concurrent/examples/boundedBufferEXT.c

    r5527759 r9d5fb67  
    1 //
     1// 
    22// The contents of this file are covered under the licence agreement in the
    33// file "LICENCE" distributed with Cforall.
    4 //
    5 // boundedBufferEXT.c --
    6 //
     4// 
     5// boundedBufferEXT.c -- 
     6// 
    77// Author           : Peter A. Buhr
    88// Created On       : Wed Apr 18 22:52:12 2018
     
    1010// Last Modified On : Fri Apr 20 22:25:14 2018
    1111// Update Count     : 6
    12 //
     12// 
    1313
    1414#include <stdlib>                                                                               // random
     
    3939forall( otype T )
    4040void insert( Buffer(T) & mutex buffer, T elem ) with( buffer ) {
    41         if ( count == BufferSize ) waitfor( remove, buffer );
     41        if ( count == BufferSize ) waitfor( remove );
    4242        elements[back] = elem;
    4343        back = ( back + 1 ) % BufferSize;
     
    4747forall( otype T )
    4848T remove( Buffer(T) & mutex buffer ) with( buffer ) {
    49         if ( count == 0 ) waitfor( insert, buffer );
     49        if ( count == 0 ) waitfor( insert );
    5050        T elem = elements[front];
    5151        front = ( front + 1 ) % BufferSize;
  • src/tests/concurrent/thread.c

    r5527759 r9d5fb67  
    77thread Second { semaphore* lock; };
    88
    9 void ?{}( First  & this, semaphore & lock ) { ((thread&)this){"Thread 1"}; this.lock = &lock; }
    10 void ?{}( Second & this, semaphore & lock ) { ((thread&)this){"Thread 2"}; this.lock = &lock; }
     9void ?{}( First & this, semaphore & lock ) { this.lock = &lock; }
     10void ?{}( Second & this, semaphore & lock ) { this.lock = &lock; }
    1111
    1212void main(First& this) {
Note: See TracChangeset for help on using the changeset viewer.