Changes in / [9997fee:534d84e]


Ignore:
Location:
src
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r9997fee r534d84e  
    385385                void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) {
    386386                        DeclarationWithType * function = getFunction( appExpr );
    387                         if ( isAssignment( function ) ) {
     387                        if ( function->name == "?=?" ) { // doesn't use isAssignment, because ?+=?, etc. should not count as self-assignment
    388388                                if ( appExpr->args.size() == 2 ) {
    389389                                        // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits)
  • src/ResolvExpr/Resolver.cc

    r9997fee r534d84e  
    492492                        }
    493493
     494                        if(clause.target.arguments.empty()) {
     495                                SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
     496                        }
     497
    494498                        // Find all alternatives for all arguments in canonical form
    495499                        std::vector< AlternativeFinder > argAlternatives;
     
    556560                                                        auto param_end = function->parameters.end();
    557561
     562                                                        int n_mutex_arg = 0;
     563
    558564                                                        // For every arguments of its set, check if it matches one of the parameter
    559565                                                        // The order is important
     
    564570                                                                        // We ran out of parameters but still have arguments
    565571                                                                        // this function doesn't match
    566                                                                         SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
     572                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" ));
    567573                                                                }
    568574
     575                                                                n_mutex_arg++;
     576
    569577                                                                // Check if the argument matches the parameter type in the current scope
    570                                                                 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     578                                                                if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    571579                                                                        // Type doesn't match
    572580                                                                        stringstream ss;
    573581                                                                        ss << "candidate function not viable: no known convertion from '";
     582                                                                        (*param)->get_type()->print( ss );
     583                                                                        ss << "' to '";
    574584                                                                        arg.expr->get_result()->print( ss );
    575                                                                         ss << "' to '";
    576                                                                         (*param)->get_type()->print( ss );
    577585                                                                        ss << "'\n";
    578586                                                                        SemanticError( function, ss.str() );
     
    588596                                                                // We ran out of arguments but still have parameters left
    589597                                                                // this function doesn't match
    590                                                                 SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
     598                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" ));
    591599                                                        }
    592600
  • src/SynTree/Statement.cc

    r9997fee r534d84e  
    453453void WaitForStmt::print( std::ostream &os, Indenter indent ) const {
    454454        os << "Waitfor Statement" << endl;
    455         os << indent << "... with block:" << endl << indent+1;
    456         // block->print( os, indent + 4 );
     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); }
    457485}
    458486
  • src/libcfa/bits/locks.h

    r9997fee r534d84e  
    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
    7178        // Lock the spinlock, return false if already acquired
    7279        static inline _Bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
     
    7481                if( result ) {
    7582                        disable_interrupts();
    76                         // __cfaabi_dbg_debug_do(
    77                         //      this.prev_name = caller;
    78                         //      this.prev_thrd = TL_GET( this_thread );
    79                         // )
     83                        __cfaabi_dbg_record( this, caller );
    8084                }
    8185                return result;
     
    105109                }
    106110                disable_interrupts();
    107                 // __cfaabi_dbg_debug_do(
    108                 //      this.prev_name = caller;
    109                 //      this.prev_thrd = TL_GET( this_thread );
    110                 // )
     111                __cfaabi_dbg_record( this, caller );
    111112        }
    112113
  • src/libcfa/concurrency/coroutine

    r9997fee r534d84e  
    3232//-----------------------------------------------------------------------------
    3333// Ctors and dtors
    34 void ?{}(coStack_t & this);
    35 void ?{}(coroutine_desc & this);
    36 void ?{}(coroutine_desc & this, const char * name);
    37 void ^?{}(coStack_t & this);
    38 void ^?{}(coroutine_desc & this);
     34// void ?{}( coStack_t & this );
     35// void ^?{}( coStack_t & this );
     36
     37void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize );
     38void ^?{}( coroutine_desc & this );
     39
     40static inline void ?{}( coroutine_desc & this)                                       { this{ "Anonymous Coroutine", NULL, 0 }; }
     41static inline void ?{}( coroutine_desc & this, size_t stackSize)                     { this{ "Anonymous Coroutine", NULL, stackSize }; }
     42static inline void ?{}( coroutine_desc & this, void * storage, size_t storageSize )  { this{ "Anonymous Coroutine", storage, storageSize }; }
     43static inline void ?{}( coroutine_desc & this, const char * name)                    { this{ name, NULL, 0 }; }
     44static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, NULL, stackSize }; }
    3945
    4046//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/coroutine.c

    r9997fee r534d84e  
    3939//-----------------------------------------------------------------------------
    4040// Coroutine ctors and dtors
    41 void ?{}(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 
    51 void ?{}(coStack_t& this, size_t size) {
    52         this{};
    53         this.size = size;
    54 
    55         create_stack(&this, this.size);
    56 }
    57 
    58 void ?{}(coroutine_desc& this) {
    59         this{ "Anonymous Coroutine" };
    60 }
    61 
    62 void ?{}(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 
    70 void ?{}(coroutine_desc& this, size_t size) {
    71         this{};
    72         (this.stack){size};
     41void ?{}( 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;
    7349}
    7450
    7551void ^?{}(coStack_t & this) {
    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         }
     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
     62void ?{}( 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;
    8469}
    8570
     
    9075forall(dtype T | is_coroutine(T))
    9176void prime(T& cor) {
    92         coroutine_desc* this = get_coroutine(cor);
    93         assert(this->state == Start);
     77      coroutine_desc* this = get_coroutine(cor);
     78      assert(this->state == Start);
    9479
    95         this->state = Primed;
    96         resume(cor);
     80      this->state = Primed;
     81      resume(cor);
    9782}
    9883
    9984// Wrapper for co
    10085void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    101         verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
    102         disable_interrupts();
     86      verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     87      disable_interrupts();
    10388
    104         // set state of current coroutine to inactive
    105         src->state = src->state == Halted ? Halted : Inactive;
     89      // set state of current coroutine to inactive
     90      src->state = src->state == Halted ? Halted : Inactive;
    10691
    107         // set new coroutine that task is executing
    108         TL_SET( this_coroutine, dst );
     92      // set new coroutine that task is executing
     93      TL_SET( this_coroutine, dst );
    10994
    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
     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
    11499
    115         // set state of new coroutine to active
    116         src->state = Active;
     100      // set state of new coroutine to active
     101      src->state = Active;
    117102
    118         enable_interrupts( __cfaabi_dbg_ctx );
    119         verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     103      enable_interrupts( __cfaabi_dbg_ctx );
     104      verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
    120105} //ctxSwitchDirect
    121106
    122107void create_stack( coStack_t* this, unsigned int storageSize ) with( *this ) {
    123         //TEMP HACK do this on proper kernel startup
    124         if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
     108      //TEMP HACK do this on proper kernel startup
     109      if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE );
    125110
    126         size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
     111      size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment
    127112
    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
     113      if ( !storage ) {
     114            __cfaabi_dbg_print_safe("Kernel : Creating stack of size %zu for stack obj %p\n", cxtSize + size + 8, this);
    132115
    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 ) );
     116            userStack = false;
     117            size = libCeiling( storageSize, 16 );
     118            // use malloc/memalign because "new" raises an exception for out-of-memory
    136119
    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                 );
     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 ) );
    142123
    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
     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            );
    146129
    147                 __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
    148                 __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
     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
    149133
    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;
     134            __cfaabi_dbg_debug_do( limit = (char *)storage + pageSize );
     135            __cfaabi_dbg_no_debug_do( limit = (char *)libCeiling( (unsigned long)storage, 16 ) ); // minimum alignment
    154136
    155                 if ( size % 16 != 0u ) size -= 8;
     137      } else {
     138            __cfaabi_dbg_print_safe("Kernel : stack obj %p using user stack %p(%u bytes)\n", this, storage, storageSize);
    156139
    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 );
     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;
    160143
    161         base = (char *)limit + size;
    162         context = base;
    163         top = (char *)context + cxtSize;
     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;
    164153}
    165154
     
    167156// is not inline (We can't inline Cforall in C)
    168157extern "C" {
    169         void __suspend_internal(void) {
    170                 suspend();
    171         }
     158      void __suspend_internal(void) {
     159            suspend();
     160      }
    172161
    173         void __leave_coroutine(void) {
    174                 coroutine_desc * src = TL_GET( this_coroutine ); // optimization
     162      void __leave_coroutine(void) {
     163            coroutine_desc * src = TL_GET( this_coroutine ); // optimization
    175164
    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 );
     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 );
    184173
    185                 CoroutineCtxSwitch( src, src->starter );
    186         }
     174            CoroutineCtxSwitch( src, src->starter );
     175      }
    187176}
    188177
  • src/libcfa/concurrency/invoke.h

    r9997fee r534d84e  
    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;
    127130
    128131                // monitors currently held by this thread
  • src/libcfa/concurrency/kernel

    r9997fee r534d84e  
    4848        __queue_t(thread_desc) ready_queue;
    4949
     50        // Name of the cluster
     51        const char * name;
     52
    5053        // Preemption rate on this cluster
    5154        Duration preemption_rate;
    5255};
    5356
     57extern struct cluster * mainCluster;
    5458extern Duration default_preemption();
    5559
    56 void ?{} (cluster & this);
     60void ?{} (cluster & this, const char * name, Duration preemption_rate);
    5761void ^?{}(cluster & this);
     62
     63static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
     64static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
     65static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
    5866
    5967//-----------------------------------------------------------------------------
     
    92100        cluster * cltr;
    93101
     102        // Name of the processor
     103        const char * name;
     104
    94105        // Handle to pthreads
    95106        pthread_t kernel_thread;
     
    119130};
    120131
    121 void  ?{}(processor & this);
    122 void  ?{}(processor & this, cluster * cltr);
     132void  ?{}(processor & this, const char * name, cluster & cltr);
    123133void ^?{}(processor & this);
     134
     135static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
     136static inline void  ?{}(processor & this, cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
     137static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
    124138
    125139// Local Variables: //
  • src/libcfa/concurrency/kernel.c

    r9997fee r534d84e  
    4242KERNEL_STORAGE(cluster,           mainCluster);
    4343KERNEL_STORAGE(processor,         mainProcessor);
    44 KERNEL_STORAGE(processorCtx_t,    mainProcessorCtx);
    4544KERNEL_STORAGE(thread_desc,       mainThread);
    4645KERNEL_STORAGE(machine_context_t, mainThreadCtx);
    4746
    48 cluster *    mainCluster;
    49 processor mainProcessor;
     47cluster     * mainCluster;
     48processor   * mainProcessor;
    5049thread_desc * mainThread;
    5150
     
    6564
    6665//-----------------------------------------------------------------------------
    67 // Main thread construction
     66// Struct to steal stack
    6867struct current_stack_info_t {
    6968        machine_context_t ctx;
     
    9089}
    9190
     91//-----------------------------------------------------------------------------
     92// Main thread construction
    9293void ?{}( coStack_t & this, current_stack_info_t * info) with( this ) {
    9394        size      = info->size;
     
    111112        self_cor{ info };
    112113        curr_cor = &self_cor;
     114        curr_cluster = mainCluster;
    113115        self_mon.owner = &this;
    114116        self_mon.recursion = 1;
     
    126128//-----------------------------------------------------------------------------
    127129// Processor coroutine
    128 void ?{}(processorCtx_t & this) {}
    129 
    130 // Construct the processor context of the main processor
    131 void ?{}(processorCtx_t & this, processor * proc) {
    132         (this.__cor){ "Processor" };
    133         this.__cor.starter = NULL;
    134         this.proc = proc;
     130void ?{}(processorCtx_t & this) {
     131
    135132}
    136133
     
    141138}
    142139
    143 void ?{}(processor & this) {
    144         this{ mainCluster };
    145 }
    146 
    147 void ?{}(processor & this, cluster * cltr) with( this ) {
    148         this.cltr = cltr;
     140void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {
     141        this.name = name;
     142        this.cltr = &cltr;
    149143        terminated{ 0 };
    150144        do_terminate = false;
     
    154148
    155149        start( &this );
    156 }
    157 
    158 void ?{}(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 };
    169150}
    170151
     
    181162}
    182163
    183 void ?{}(cluster & this) with( this ) {
     164void ?{}(cluster & this, const char * name, Duration preemption_rate) with( this ) {
     165        this.name = name;
     166        this.preemption_rate = preemption_rate;
    184167        ready_queue{};
    185168        ready_queue_lock{};
    186 
    187         preemption_rate = default_preemption();
    188169}
    189170
     
    312293        TL_SET( this_coroutine, NULL );
    313294        TL_SET( this_thread, NULL );
    314         TL_GET( preemption_state ).enabled = false;
    315         TL_GET( preemption_state ).disable_count = 1;
     295        TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];
    316296        // SKULLDUGGERY: We want to create a context for the processor coroutine
    317297        // which is needed for the 2-step context switch. However, there is no reason
     
    402382        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    403383
    404         with( *TL_GET( this_processor )->cltr ) {
     384        with( *thrd->curr_cluster ) {
    405385                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
    406386                append( ready_queue, thrd );
     
    430410void BlockInternal( __spinlock_t * lock ) {
    431411        disable_interrupts();
    432         TL_GET( this_processor )->finish.action_code = Release;
    433         TL_GET( this_processor )->finish.lock        = lock;
     412        with( *TL_GET( this_processor ) ) {
     413                finish.action_code = Release;
     414                finish.lock        = lock;
     415        }
    434416
    435417        verify( ! TL_GET( preemption_state ).enabled );
     
    442424void BlockInternal( thread_desc * thrd ) {
    443425        disable_interrupts();
    444         TL_GET( this_processor )->finish.action_code = Schedule;
    445         TL_GET( this_processor )->finish.thrd        = thrd;
     426        with( *TL_GET( this_processor ) ) {
     427                finish.action_code = Schedule;
     428                finish.thrd        = thrd;
     429        }
    446430
    447431        verify( ! TL_GET( preemption_state ).enabled );
     
    455439        assert(thrd);
    456440        disable_interrupts();
    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;
     441        with( *TL_GET( this_processor ) ) {
     442                finish.action_code = Release_Schedule;
     443                finish.lock        = lock;
     444                finish.thrd        = thrd;
     445        }
    460446
    461447        verify( ! TL_GET( preemption_state ).enabled );
     
    468454void BlockInternal(__spinlock_t * locks [], unsigned short count) {
    469455        disable_interrupts();
    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;
     456        with( *TL_GET( this_processor ) ) {
     457                finish.action_code = Release_Multi;
     458                finish.locks       = locks;
     459                finish.lock_count  = count;
     460        }
    473461
    474462        verify( ! TL_GET( preemption_state ).enabled );
     
    481469void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
    482470        disable_interrupts();
    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;
     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        }
    488478
    489479        verify( ! TL_GET( preemption_state ).enabled );
     
    496486void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    497487        verify( ! TL_GET( preemption_state ).enabled );
    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;
     488        with( *TL_GET( this_processor ) ) {
     489                finish.action_code = thrd ? Release_Schedule : Release;
     490                finish.lock        = lock;
     491                finish.thrd        = thrd;
     492        }
    501493
    502494        returnToKernel();
     
    511503        verify( ! TL_GET( preemption_state ).enabled );
    512504        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     505
     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");
    513511
    514512        // Start by initializing the main thread
     
    521519        __cfaabi_dbg_print_safe("Kernel : Main thread ready\n");
    522520
    523         // Initialize the main cluster
    524         mainCluster = (cluster *)&storage_mainCluster;
    525         (*mainCluster){};
    526 
    527         __cfaabi_dbg_print_safe("Kernel : main cluster ready\n");
     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        }
    528542
    529543        // Initialize the main processor and the main processor ctx
    530544        // (the coroutine that contains the processing control flow)
    531545        mainProcessor = (processor *)&storage_mainProcessor;
    532         (*mainProcessor){ mainCluster, *(processorCtx_t *)&storage_mainProcessorCtx };
     546        (*mainProcessor){};
    533547
    534548        //initialize the global state variables
     
    725739                thrd->dbg_next = NULL;
    726740        }
     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        }
    727746)
    728747// Local Variables: //
  • src/libcfa/concurrency/preemption.c

    r9997fee r534d84e  
    149149        // Disable interrupts by incrementing the counter
    150150        void disable_interrupts() {
    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
     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                }
    155157        }
    156158
     
    161163                thread_desc * thrd = TL_GET( this_thread );       // Cache the thread now since interrupts can start happening after the atomic add
    162164
    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 );
     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                                }
    173177                        }
    174178                }
     
    328332        if( !preemption_ready() ) { return; }
    329333
    330         __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
     334        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", TL_GET( this_processor ), TL_GET( this_thread ) );
    331335
    332336        TL_GET( preemption_state ).in_progress = true;  // Sync flag : prevent recursive calls to the signal handler
  • src/libcfa/concurrency/thread

    r9997fee r534d84e  
    2323
    2424//-----------------------------------------------------------------------------
    25 // Coroutine trait
    26 // Anything that implements this trait can be resumed.
    27 // Anything that is resumed is a coroutine.
     25// thread trait
    2826trait is_thread(dtype T) {
    2927      void ^?{}(T& mutex this);
     
    5250}
    5351
    54 //extern thread_local thread_desc * volatile this_thread;
     52extern struct cluster * mainCluster;
    5553
    5654forall( dtype T | is_thread(T) )
     
    5957//-----------------------------------------------------------------------------
    6058// Ctors and dtors
    61 void ?{}(thread_desc& this);
    62 void ^?{}(thread_desc& this);
     59void ?{}(thread_desc & this, const char * const name, struct cluster & cl, void * storage, size_t storageSize );
     60void ^?{}(thread_desc & this);
     61
     62static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 0 }; }
     63static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
     64static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
     65static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 0 }; }
     66static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0, stackSize }; }
     67static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
     68static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 0 }; }
     69static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 0 }; }
     70static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
    6371
    6472//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/thread.c

    r9997fee r534d84e  
    3030//-----------------------------------------------------------------------------
    3131// Thread ctors and dtors
    32 
    33 void ?{}(thread_desc& this) with( this ) {
    34         self_cor{};
    35         self_cor.name = "Anonymous Coroutine";
     32void ?{}(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);
    3635        curr_cor = &self_cor;
    3736        self_mon.owner = &this;
    3837        self_mon.recursion = 1;
    3938        self_mon_p = &self_mon;
     39        curr_cluster = &cl;
    4040        next = NULL;
    4141        __cfaabi_dbg_debug_do(
  • src/tests/concurrent/examples/.expect/boundedBufferEXT.txt

    r9997fee r534d84e  
    1 concurrent/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
    3 forall
    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
    30 lvalue 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 
    39 concurrent/examples/boundedBufferEXT.c:47:1 error: No alternatives for function in call to waitfor
    40 concurrent/examples/boundedBufferEXT.c:37:1 error: candidate function not viable: too few mutex arguments
    41 forall
    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 
     1total:400000
  • src/tests/concurrent/examples/boundedBufferEXT.c

    r9997fee r534d84e  
    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 );
     41        if ( count == BufferSize ) waitfor( remove, buffer );
    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 );
     49        if ( count == 0 ) waitfor( insert, buffer );
    5050        T elem = elements[front];
    5151        front = ( front + 1 ) % BufferSize;
  • src/tests/concurrent/thread.c

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