Changes in / [a505021:c744563a]


Ignore:
Files:
4 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/containers.hfa

    ra505021 rc744563a  
    146146        static inline forall( dtype T | is_node(T) ) {
    147147                void ?{}( __queue(T) & this ) with( this ) {
    148                         head{ 1p };
     148                        head{ 0p };
    149149                        tail{ &head };
    150                         verify(*tail == 1p);
    151150                }
    152151
    153152                void append( __queue(T) & this, T * val ) with( this ) {
    154153                        verify(tail != 0p);
    155                         verify(*tail == 1p);
    156154                        *tail = val;
    157155                        tail = &get_next( *val );
    158                         *tail = 1p;
    159156                }
    160157
    161158                T * pop_head( __queue(T) & this ) {
    162                         verify(*this.tail == 1p);
    163159                        T * head = this.head;
    164                         if( head != 1p ) {
     160                        if( head ) {
    165161                                this.head = get_next( *head );
    166                                 if( get_next( *head ) == 1p ) {
     162                                if( !get_next( *head ) ) {
    167163                                        this.tail = &this.head;
    168164                                }
    169165                                get_next( *head ) = 0p;
    170                                 verify(*this.tail == 1p);
    171                                 return head;
    172                         }
    173                         verify(*this.tail == 1p);
    174                         return 0p;
     166                        }
     167                        return head;
    175168                }
    176169
     
    187180                        get_next( *val ) = 0p;
    188181
    189                         verify( (head == 1p) == (&head == tail) );
    190                         verify( *tail == 1p );
     182                        verify( (head == 0p) == (&head == tail) );
     183                        verify( *tail == 0p );
    191184                        return val;
    192185                }
  • libcfa/src/bits/locks.hfa

    ra505021 rc744563a  
    6060        }
    6161
     62        extern void yield( unsigned int );
     63
    6264        static inline void ?{}( __spinlock_t & this ) {
    6365                this.lock = 0;
     
    6668        // Lock the spinlock, return false if already acquired
    6769        static inline bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
    68                 disable_interrupts();
    6970                bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
    7071                if( result ) {
     72                        disable_interrupts();
    7173                        __cfaabi_dbg_record( this, caller );
    72                 } else {
    73                         enable_interrupts_noPoll();
    7474                }
    7575                return result;
     
    8383                #endif
    8484
    85                 disable_interrupts();
    8685                for ( unsigned int i = 1;; i += 1 ) {
    8786                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
     
    9998                        #endif
    10099                }
     100                disable_interrupts();
    101101                __cfaabi_dbg_record( this, caller );
    102102        }
    103103
    104104        static inline void unlock( __spinlock_t & this ) {
     105                enable_interrupts_noPoll();
    105106                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    106                 enable_interrupts_noPoll();
    107107        }
    108108
  • libcfa/src/concurrency/coroutine.hfa

    ra505021 rc744563a  
    5454void prime(T & cor);
    5555
    56 static inline struct coroutine_desc * active_coroutine() __attribute__((const)) { return TL_GET( this_thread )->curr_cor; }
     56static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
    5757
    5858//-----------------------------------------------------------------------------
     
    7373// Private wrappers for context switch and stack creation
    7474// Wrapper for co
    75 static inline void CoroutineCtxSwitch( coroutine_desc * src, coroutine_desc * dst ) __attribute__((nonnull (1, 2))) {
     75static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    7676        // set state of current coroutine to inactive
    7777        src->state = src->state == Halted ? Halted : Inactive;
     
    152152}
    153153
    154 static inline void resume( coroutine_desc * dst ) __attribute__((nonnull (1))) {
     154static inline void resume(coroutine_desc * dst) {
    155155        // optimization : read TLS once and reuse it
    156156        // Safety note: this is preemption safe since if
  • libcfa/src/concurrency/invoke.h

    ra505021 rc744563a  
    9292        };
    9393
    94         enum coroutine_state { Halted, Start, Primed, Inactive, Active, Rerun };
    95         enum __Preemption_Reason { __NO_PREEMPTION, __ALARM_PREEMPTION, __POLL_PREEMPTION, __MANUAL_PREEMPTION };
     94        enum coroutine_state { Halted, Start, Inactive, Active, Primed };
    9695
    9796        struct coroutine_desc {
     
    165164
    166165                // current execution status for coroutine
    167                 volatile int state;
    168                 enum __Preemption_Reason preempted;
     166                enum coroutine_state state;
    169167
    170168                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
     
    200198        #ifdef __cforall
    201199        extern "Cforall" {
    202                 static inline thread_desc *& get_next( thread_desc & this ) __attribute__((const)) {
     200                static inline thread_desc *& get_next( thread_desc & this ) {
    203201                        return this.next;
    204202                }
    205203
    206                 static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) /*__attribute__((const))*/ {
     204                static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) {
    207205                        return this.node.[next, prev];
    208206                }
     
    220218                }
    221219
    222                 static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) __attribute__((const)) {
     220                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {
    223221                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
    224222                        if( lhs.size != rhs.size ) return false;
  • libcfa/src/concurrency/kernel.cfa

    ra505021 rc744563a  
    110110//-----------------------------------------------------------------------------
    111111//Start and stop routine for the kernel, declared first to make sure they run first
    112 static void __kernel_startup (void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
    113 static void __kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     112static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     113static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
    114114
    115115//-----------------------------------------------------------------------------
     
    208208}
    209209
    210 static void * CtxInvokeProcessor(void * arg);
    211 
     210static void start(processor * this);
    212211void ?{}(processor & this, const char name[], cluster & cltr) with( this ) {
    213212        this.name = name;
    214213        this.cltr = &cltr;
    215214        terminated{ 0 };
    216         destroyer = 0p;
    217215        do_terminate = false;
    218216        preemption_alarm = 0p;
     
    222220        idleLock{};
    223221
    224         __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", &this);
    225 
    226         this.stack = __create_pthread( &this.kernel_thread, CtxInvokeProcessor, (void *)&this );
    227 
    228         __cfaabi_dbg_print_safe("Kernel : core %p started\n", &this);
     222        start( &this );
    229223}
    230224
     
    264258// Kernel Scheduling logic
    265259//=============================================================================================
    266 static thread_desc * __next_thread(cluster * this);
    267 static void __run_thread(processor * this, thread_desc * dst);
    268 static void __halt(processor * this);
     260static void runThread(processor * this, thread_desc * dst);
     261static void finishRunning(processor * this);
     262static void halt(processor * this);
    269263
    270264//Main of the processor contexts
     
    289283                thread_desc * readyThread = 0p;
    290284                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) {
    291                         readyThread = __next_thread( this->cltr );
     285                        readyThread = nextThread( this->cltr );
    292286
    293287                        if(readyThread) {
    294                                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    295                                 /* paranoid */ verifyf( readyThread->state == Inactive || readyThread->state == Start || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);
    296                                 /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next );
    297 
    298                                 __run_thread(this, readyThread);
    299 
    300                                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     288                                verify( ! kernelTLS.preemption_state.enabled );
     289
     290                                runThread(this, readyThread);
     291
     292                                verify( ! kernelTLS.preemption_state.enabled );
     293
     294                                //Some actions need to be taken from the kernel
     295                                finishRunning(this);
    301296
    302297                                spin_count = 0;
    303298                        } else {
    304299                                // spin(this, &spin_count);
    305                                 __halt(this);
     300                                halt(this);
    306301                        }
    307302                }
     
    323318// runThread runs a thread by context switching
    324319// from the processor coroutine to the target thread
    325 static void __run_thread(processor * this, thread_desc * thrd_dst) {
     320static void runThread(processor * this, thread_desc * thrd_dst) {
    326321        coroutine_desc * proc_cor = get_coroutine(this->runner);
     322
     323        // Reset the terminating actions here
     324        this->finish.action_code = No_Action;
    327325
    328326        // Update global state
    329327        kernelTLS.this_thread = thrd_dst;
    330328
    331         // set state of processor coroutine to inactive
    332         verify(proc_cor->state == Active);
    333         proc_cor->state = Inactive;
    334 
    335         // Actually run the thread
    336         RUNNING:  while(true) {
    337                 if(unlikely(thrd_dst->preempted)) {
    338                         thrd_dst->preempted = __NO_PREEMPTION;
    339                         verify(thrd_dst->state == Active || thrd_dst->state == Rerun);
    340                 } else {
    341                         verify(thrd_dst->state == Start || thrd_dst->state == Primed || thrd_dst->state == Inactive);
    342                         thrd_dst->state = Active;
    343                 }
    344 
    345                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    346 
    347                 // set context switch to the thread that the processor is executing
    348                 verify( thrd_dst->context.SP );
    349                 CtxSwitch( &proc_cor->context, &thrd_dst->context );
    350                 // when CtxSwitch returns we are back in the processor coroutine
    351 
    352                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    353 
    354 
    355                 // We just finished running a thread, there are a few things that could have happened.
    356                 // 1 - Regular case : the thread has blocked and now one has scheduled it yet.
    357                 // 2 - Racy case    : the thread has blocked but someone has already tried to schedule it.
    358                 // 3 - Polite Racy case : the thread has blocked, someone has already tried to schedule it, but the thread is nice and wants to go through the ready-queue any way
    359                 // 4 - Preempted
    360                 // In case 1, we may have won a race so we can't write to the state again.
    361                 // In case 2, we lost the race so we now own the thread.
    362                 // In case 3, we lost the race but can just reschedule the thread.
    363 
    364                 if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
    365                         // The thread was preempted, reschedule it and reset the flag
    366                         __schedule_thread( thrd_dst );
    367                         break RUNNING;
    368                 }
    369 
    370                 // set state of processor coroutine to active and the thread to inactive
    371                 static_assert(sizeof(thrd_dst->state) == sizeof(int));
    372                 enum coroutine_state old_state = __atomic_exchange_n(&thrd_dst->state, Inactive, __ATOMIC_SEQ_CST);
    373                 switch(old_state) {
    374                         case Halted:
    375                                 // The thread has halted, it should never be scheduled/run again, leave it back to Halted and move on
    376                                 thrd_dst->state = Halted;
    377 
    378                                 // We may need to wake someone up here since
    379                                 unpark( this->destroyer );
    380                                 this->destroyer = 0p;
    381                                 break RUNNING;
    382                         case Active:
    383                                 // This is case 1, the regular case, nothing more is needed
    384                                 break RUNNING;
    385                         case Rerun:
    386                                 // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    387                                 // In this case, just run it again.
    388                                 continue RUNNING;
    389                         default:
    390                                 // This makes no sense, something is wrong abort
    391                                 abort("Finished running a thread that was Inactive/Start/Primed %d\n", old_state);
    392                 }
    393         }
    394 
    395         // Just before returning to the processor, set the processor coroutine to active
     329        // set state of processor coroutine to inactive and the thread to active
     330        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     331        thrd_dst->state = Active;
     332
     333        // set context switch to the thread that the processor is executing
     334        verify( thrd_dst->context.SP );
     335        CtxSwitch( &proc_cor->context, &thrd_dst->context );
     336        // when CtxSwitch returns we are back in the processor coroutine
     337
     338        // set state of processor coroutine to active and the thread to inactive
     339        thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
    396340        proc_cor->state = Active;
    397341}
    398342
    399343// KERNEL_ONLY
    400 void returnToKernel() {
    401         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     344static void returnToKernel() {
    402345        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    403346        thread_desc * thrd_src = kernelTLS.this_thread;
    404347
    405         // Run the thread on this processor
    406         {
    407                 int local_errno = *__volatile_errno();
    408                 #if defined( __i386 ) || defined( __x86_64 )
    409                         __x87_store;
    410                 #endif
    411                 verify( proc_cor->context.SP );
    412                 CtxSwitch( &thrd_src->context, &proc_cor->context );
    413                 #if defined( __i386 ) || defined( __x86_64 )
    414                         __x87_load;
    415                 #endif
    416                 *__volatile_errno() = local_errno;
    417         }
    418 
    419         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     348        // set state of current coroutine to inactive
     349        thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
     350        proc_cor->state = Active;
     351        int local_errno = *__volatile_errno();
     352        #if defined( __i386 ) || defined( __x86_64 )
     353                __x87_store;
     354        #endif
     355
     356        // set new coroutine that the processor is executing
     357        // and context switch to it
     358        verify( proc_cor->context.SP );
     359        CtxSwitch( &thrd_src->context, &proc_cor->context );
     360
     361        // set state of new coroutine to active
     362        proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
     363        thrd_src->state = Active;
     364
     365        #if defined( __i386 ) || defined( __x86_64 )
     366                __x87_load;
     367        #endif
     368        *__volatile_errno() = local_errno;
     369}
     370
     371// KERNEL_ONLY
     372// Once a thread has finished running, some of
     373// its final actions must be executed from the kernel
     374static void finishRunning(processor * this) with( this->finish ) {
     375        verify( ! kernelTLS.preemption_state.enabled );
     376        choose( action_code ) {
     377        case No_Action:
     378                break;
     379        case Release:
     380                unlock( *lock );
     381        case Schedule:
     382                ScheduleThread( thrd );
     383        case Release_Schedule:
     384                unlock( *lock );
     385                ScheduleThread( thrd );
     386        case Release_Multi:
     387                for(int i = 0; i < lock_count; i++) {
     388                        unlock( *locks[i] );
     389                }
     390        case Release_Multi_Schedule:
     391                for(int i = 0; i < lock_count; i++) {
     392                        unlock( *locks[i] );
     393                }
     394                for(int i = 0; i < thrd_count; i++) {
     395                        ScheduleThread( thrds[i] );
     396                }
     397        case Callback:
     398                callback();
     399        default:
     400                abort("KERNEL ERROR: Unexpected action to run after thread");
     401        }
    420402}
    421403
     
    465447} // Abort
    466448
    467 void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
     449void * create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
    468450        pthread_attr_t attr;
    469451
     
    493475}
    494476
     477static void start(processor * this) {
     478        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);
     479
     480        this->stack = create_pthread( &this->kernel_thread, CtxInvokeProcessor, (void *)this );
     481
     482        __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
     483}
     484
    495485// KERNEL_ONLY
    496 static void __kernel_first_resume( processor * this ) {
     486void kernel_first_resume( processor * this ) {
    497487        thread_desc * src = mainThread;
    498488        coroutine_desc * dst = get_coroutine(this->runner);
     
    526516
    527517// KERNEL_ONLY
    528 static void __kernel_last_resume( processor * this ) {
     518void kernel_last_resume( processor * this ) {
    529519        coroutine_desc * src = &mainThread->self_cor;
    530520        coroutine_desc * dst = get_coroutine(this->runner);
     
    540530//-----------------------------------------------------------------------------
    541531// Scheduler routines
     532
    542533// KERNEL ONLY
    543 void __schedule_thread( thread_desc * thrd ) with( *thrd->curr_cluster ) {
    544         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    545         /* paranoid */ #if defined( __CFA_WITH_VERIFY__ )
    546         /* paranoid */ if( thrd->state == Inactive || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
    547                           "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );
    548         /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,
    549                           "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );
    550         /* paranoid */ #endif
    551         /* paranoid */ verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
    552 
    553         lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
    554         bool was_empty = !(ready_queue != 0);
    555         append( ready_queue, thrd );
    556         unlock( ready_queue_lock );
    557 
    558         if(was_empty) {
    559                 lock      (proc_list_lock __cfaabi_dbg_ctx2);
    560                 if(idles) {
    561                         wake_fast(idles.head);
     534void ScheduleThread( thread_desc * thrd ) {
     535        verify( thrd );
     536        verify( thrd->state != Halted );
     537
     538        verify( ! kernelTLS.preemption_state.enabled );
     539
     540        verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
     541
     542        with( *thrd->curr_cluster ) {
     543                lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
     544                bool was_empty = !(ready_queue != 0);
     545                append( ready_queue, thrd );
     546                unlock( ready_queue_lock );
     547
     548                if(was_empty) {
     549                        lock      (proc_list_lock __cfaabi_dbg_ctx2);
     550                        if(idles) {
     551                                wake_fast(idles.head);
     552                        }
     553                        unlock    (proc_list_lock);
    562554                }
    563                 unlock    (proc_list_lock);
    564         }
    565         else if( struct processor * idle = idles.head ) {
    566                 wake_fast(idle);
    567         }
    568 
    569         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     555                else if( struct processor * idle = idles.head ) {
     556                        wake_fast(idle);
     557                }
     558
     559        }
     560
     561        verify( ! kernelTLS.preemption_state.enabled );
    570562}
    571563
    572564// KERNEL ONLY
    573 static thread_desc * __next_thread(cluster * this) with( *this ) {
    574         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    575 
     565thread_desc * nextThread(cluster * this) with( *this ) {
     566        verify( ! kernelTLS.preemption_state.enabled );
    576567        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    577568        thread_desc * head = pop_head( ready_queue );
    578569        unlock( ready_queue_lock );
    579 
    580         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     570        verify( ! kernelTLS.preemption_state.enabled );
    581571        return head;
    582572}
    583573
    584 void unpark( thread_desc * thrd ) {
    585         if( !thrd ) return;
    586 
     574void BlockInternal() {
    587575        disable_interrupts();
    588         static_assert(sizeof(thrd->state) == sizeof(int));
    589         enum coroutine_state old_state = __atomic_exchange_n(&thrd->state, Rerun, __ATOMIC_SEQ_CST);
    590         switch(old_state) {
    591                 case Active:
    592                         // Wake won the race, the thread will reschedule/rerun itself
    593                         break;
    594                 case Inactive:
    595                         /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
    596 
    597                         // Wake lost the race,
    598                         thrd->state = Inactive;
    599                         __schedule_thread( thrd );
    600                         break;
    601                 case Rerun:
    602                         abort("More than one thread attempted to schedule thread %p\n", thrd);
    603                         break;
    604                 case Halted:
    605                 case Start:
    606                 case Primed:
    607                 default:
    608                         // This makes no sense, something is wrong abort
    609                         abort();
    610         }
     576        verify( ! kernelTLS.preemption_state.enabled );
     577        returnToKernel();
     578        verify( ! kernelTLS.preemption_state.enabled );
    611579        enable_interrupts( __cfaabi_dbg_ctx );
    612580}
    613581
    614 void park( void ) {
    615         /* paranoid */ verify( kernelTLS.preemption_state.enabled );
     582void BlockInternal( __spinlock_t * lock ) {
    616583        disable_interrupts();
    617         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    618         /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION );
    619 
     584        with( *kernelTLS.this_processor ) {
     585                finish.action_code = Release;
     586                finish.lock        = lock;
     587        }
     588
     589        verify( ! kernelTLS.preemption_state.enabled );
    620590        returnToKernel();
    621 
    622         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     591        verify( ! kernelTLS.preemption_state.enabled );
     592
    623593        enable_interrupts( __cfaabi_dbg_ctx );
    624         /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    625 
     594}
     595
     596void BlockInternal( thread_desc * thrd ) {
     597        disable_interrupts();
     598        with( * kernelTLS.this_processor ) {
     599                finish.action_code = Schedule;
     600                finish.thrd        = thrd;
     601        }
     602
     603        verify( ! kernelTLS.preemption_state.enabled );
     604        returnToKernel();
     605        verify( ! kernelTLS.preemption_state.enabled );
     606
     607        enable_interrupts( __cfaabi_dbg_ctx );
     608}
     609
     610void BlockInternal( __spinlock_t * lock, thread_desc * thrd ) {
     611        assert(thrd);
     612        disable_interrupts();
     613        with( * kernelTLS.this_processor ) {
     614                finish.action_code = Release_Schedule;
     615                finish.lock        = lock;
     616                finish.thrd        = thrd;
     617        }
     618
     619        verify( ! kernelTLS.preemption_state.enabled );
     620        returnToKernel();
     621        verify( ! kernelTLS.preemption_state.enabled );
     622
     623        enable_interrupts( __cfaabi_dbg_ctx );
     624}
     625
     626void BlockInternal(__spinlock_t * locks [], unsigned short count) {
     627        disable_interrupts();
     628        with( * kernelTLS.this_processor ) {
     629                finish.action_code = Release_Multi;
     630                finish.locks       = locks;
     631                finish.lock_count  = count;
     632        }
     633
     634        verify( ! kernelTLS.preemption_state.enabled );
     635        returnToKernel();
     636        verify( ! kernelTLS.preemption_state.enabled );
     637
     638        enable_interrupts( __cfaabi_dbg_ctx );
     639}
     640
     641void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
     642        disable_interrupts();
     643        with( *kernelTLS.this_processor ) {
     644                finish.action_code = Release_Multi_Schedule;
     645                finish.locks       = locks;
     646                finish.lock_count  = lock_count;
     647                finish.thrds       = thrds;
     648                finish.thrd_count  = thrd_count;
     649        }
     650
     651        verify( ! kernelTLS.preemption_state.enabled );
     652        returnToKernel();
     653        verify( ! kernelTLS.preemption_state.enabled );
     654
     655        enable_interrupts( __cfaabi_dbg_ctx );
     656}
     657
     658void BlockInternal(__finish_callback_fptr_t callback) {
     659        disable_interrupts();
     660        with( *kernelTLS.this_processor ) {
     661                finish.action_code = Callback;
     662                finish.callback    = callback;
     663        }
     664
     665        verify( ! kernelTLS.preemption_state.enabled );
     666        returnToKernel();
     667        verify( ! kernelTLS.preemption_state.enabled );
     668
     669        enable_interrupts( __cfaabi_dbg_ctx );
    626670}
    627671
    628672// KERNEL ONLY
    629 void __leave_thread() {
    630         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     673void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
     674        verify( ! kernelTLS.preemption_state.enabled );
     675        with( * kernelTLS.this_processor ) {
     676                finish.action_code = thrd ? Release_Schedule : Release;
     677                finish.lock        = lock;
     678                finish.thrd        = thrd;
     679        }
     680
    631681        returnToKernel();
    632         abort();
    633 }
    634 
    635 // KERNEL ONLY
    636 bool force_yield( __Preemption_Reason reason ) {
    637         /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    638         disable_interrupts();
    639         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    640 
    641         thread_desc * thrd = kernelTLS.this_thread;
    642         /* paranoid */ verify(thrd->state == Active || thrd->state == Rerun);
    643 
    644         // SKULLDUGGERY: It is possible that we are preempting this thread just before
    645         // it was going to park itself. If that is the case and it is already using the
    646         // intrusive fields then we can't use them to preempt the thread
    647         // If that is the case, abandon the preemption.
    648         bool preempted = false;
    649         if(thrd->next == 0p) {
    650                 preempted = true;
    651                 thrd->preempted = reason;
    652                 returnToKernel();
    653         }
    654 
    655         /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    656         enable_interrupts_noPoll();
    657         /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    658 
    659         return preempted;
    660682}
    661683
     
    665687//-----------------------------------------------------------------------------
    666688// Kernel boot procedures
    667 static void __kernel_startup(void) {
     689static void kernel_startup(void) {
    668690        verify( ! kernelTLS.preemption_state.enabled );
    669691        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     
    726748        // Add the main thread to the ready queue
    727749        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    728         __schedule_thread(mainThread);
     750        ScheduleThread(mainThread);
    729751
    730752        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
    731753        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    732754        // mainThread is on the ready queue when this call is made.
    733         __kernel_first_resume( kernelTLS.this_processor );
     755        kernel_first_resume( kernelTLS.this_processor );
    734756
    735757
     
    743765}
    744766
    745 static void __kernel_shutdown(void) {
     767static void kernel_shutdown(void) {
    746768        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    747769
     
    754776        // which is currently here
    755777        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    756         __kernel_last_resume( kernelTLS.this_processor );
     778        kernel_last_resume( kernelTLS.this_processor );
    757779        mainThread->self_cor.state = Halted;
    758780
     
    780802// Kernel Quiescing
    781803//=============================================================================================
    782 static void __halt(processor * this) with( *this ) {
     804static void halt(processor * this) with( *this ) {
    783805        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    784806
     
    891913
    892914                // atomically release spin lock and block
    893                 unlock( lock );
    894                 park();
     915                BlockInternal( &lock );
    895916        }
    896917        else {
     
    911932
    912933        // make new owner
    913         unpark( thrd );
     934        WakeThread( thrd );
    914935}
    915936
     
    969990//-----------------------------------------------------------------------------
    970991// Debug
    971 bool threading_enabled(void) __attribute__((const)) {
     992bool threading_enabled(void) {
    972993        return true;
    973994}
  • libcfa/src/concurrency/kernel.hfa

    ra505021 rc744563a  
    4545extern struct cluster * mainCluster;
    4646
     47enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
     48
     49typedef void (*__finish_callback_fptr_t)(void);
     50
     51//TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
     52struct FinishAction {
     53        FinishOpCode action_code;
     54        /*
     55        // Union of possible actions
     56        union {
     57                // Option 1 : locks and threads
     58                struct {
     59                        // 1 thread or N thread
     60                        union {
     61                                thread_desc * thrd;
     62                                struct {
     63                                        thread_desc ** thrds;
     64                                        unsigned short thrd_count;
     65                                };
     66                        };
     67                        // 1 lock or N lock
     68                        union {
     69                                __spinlock_t * lock;
     70                                struct {
     71                                        __spinlock_t ** locks;
     72                                        unsigned short lock_count;
     73                                };
     74                        };
     75                };
     76                // Option 2 : action pointer
     77                __finish_callback_fptr_t callback;
     78        };
     79        /*/
     80        thread_desc * thrd;
     81        thread_desc ** thrds;
     82        unsigned short thrd_count;
     83        __spinlock_t * lock;
     84        __spinlock_t ** locks;
     85        unsigned short lock_count;
     86        __finish_callback_fptr_t callback;
     87        //*/
     88};
     89static inline void ?{}(FinishAction & this) {
     90        this.action_code = No_Action;
     91        this.thrd = 0p;
     92        this.lock = 0p;
     93}
     94static inline void ^?{}(FinishAction &) {}
     95
    4796// Processor
    4897coroutine processorCtx_t {
     
    67116        // RunThread data
    68117        // Action to do after a thread is ran
    69         thread_desc * destroyer;
     118        struct FinishAction finish;
    70119
    71120        // Preemption data
     
    108157static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
    109158
    110 static inline [processor *&, processor *& ] __get( processor & this ) /*__attribute__((const))*/ { return this.node.[next, prev]; }
     159static inline [processor *&, processor *& ] __get( processor & this ) {
     160        return this.node.[next, prev];
     161}
    111162
    112163//-----------------------------------------------------------------------------
     
    151202static inline void ?{} (cluster & this, const char name[])        { this{name, default_preemption()}; }
    152203
    153 static inline [cluster *&, cluster *& ] __get( cluster & this ) /*__attribute__((const))*/ { return this.node.[next, prev]; }
    154 
    155 static inline struct processor * active_processor() __attribute__((const)) { return TL_GET( this_processor ); } // UNSAFE
    156 static inline struct cluster   * active_cluster  () __attribute__((const)) { return TL_GET( this_processor )->cltr; }
     204static inline [cluster *&, cluster *& ] __get( cluster & this ) {
     205        return this.node.[next, prev];
     206}
     207
     208static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE
     209static inline struct cluster   * active_cluster  () { return TL_GET( this_processor )->cltr; }
    157210
    158211// Local Variables: //
  • libcfa/src/concurrency/kernel_private.hfa

    ra505021 rc744563a  
    3131}
    3232
    33 void __schedule_thread( thread_desc * ) __attribute__((nonnull (1)));
     33void ScheduleThread( thread_desc * );
     34static inline void WakeThread( thread_desc * thrd ) {
     35        if( !thrd ) return;
     36
     37        verify(thrd->state == Inactive);
     38
     39        disable_interrupts();
     40        ScheduleThread( thrd );
     41        enable_interrupts( __cfaabi_dbg_ctx );
     42}
     43thread_desc * nextThread(cluster * this);
    3444
    3545//Block current thread and release/wake-up the following resources
    36 void __leave_thread() __attribute__((noreturn));
     46void BlockInternal(void);
     47void BlockInternal(__spinlock_t * lock);
     48void BlockInternal(thread_desc * thrd);
     49void BlockInternal(__spinlock_t * lock, thread_desc * thrd);
     50void BlockInternal(__spinlock_t * locks [], unsigned short count);
     51void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
     52void BlockInternal(__finish_callback_fptr_t callback);
     53void LeaveThread(__spinlock_t * lock, thread_desc * thrd);
    3754
    3855//-----------------------------------------------------------------------------
     
    4057void main(processorCtx_t *);
    4158
    42 void * __create_pthread( pthread_t *, void * (*)(void *), void * );
     59void * create_pthread( pthread_t *, void * (*)(void *), void * );
    4360
    4461static inline void wake_fast(processor * this) {
     
    85102#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    86103
    87 static inline uint32_t __tls_rand() {
     104static inline uint32_t tls_rand() {
    88105        kernelTLS.rand_seed ^= kernelTLS.rand_seed << 6;
    89106        kernelTLS.rand_seed ^= kernelTLS.rand_seed >> 21;
  • libcfa/src/concurrency/monitor.cfa

    ra505021 rc744563a  
    117117
    118118                        // Some one else has the monitor, wait in line for it
    119                         /* paranoid */ verify( thrd->next == 0p );
    120119                        append( this->entry_queue, thrd );
    121                         /* paranoid */ verify( thrd->next == 1p );
    122 
    123                         unlock( this->lock );
    124                         park();
     120
     121                        BlockInternal( &this->lock );
    125122
    126123                        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    127124
    128                         /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     125                        // BlockInternal will unlock spinlock, no need to unlock ourselves
    129126                        return;
    130127                }
    131128
    132129                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    133 
    134                 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    135                 /* paranoid */ verify( this->lock.lock );
    136130
    137131                // Release the lock and leave
     
    155149                        set_owner( this, thrd );
    156150
    157                         verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    158 
    159151                        unlock( this->lock );
    160152                        return;
     
    174166                        // Wake the thread that is waiting for this
    175167                        __condition_criterion_t * urgent = pop( this->signal_stack );
    176                         /* paranoid */ verify( urgent );
     168                        verify( urgent );
    177169
    178170                        // Reset mask
     
    183175
    184176                        // Some one else has the monitor, wait for him to finish and then run
    185                         unlock( this->lock );
    186 
    187                         // Release the next thread
    188                         /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    189                         unpark( urgent->owner->waiting_thread );
    190 
    191                         // Park current thread waiting
    192                         park();
     177                        BlockInternal( &this->lock, urgent->owner->waiting_thread );
    193178
    194179                        // Some one was waiting for us, enter
    195                         /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     180                        set_owner( this, thrd );
    196181                }
    197182                else {
     
    202187
    203188                        // Some one else has the monitor, wait in line for it
    204                         /* paranoid */ verify( thrd->next == 0p );
    205189                        append( this->entry_queue, thrd );
    206                         /* paranoid */ verify( thrd->next == 1p );
    207                         unlock( this->lock );
    208 
    209                         // Park current thread waiting
    210                         park();
    211 
    212                         /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     190                        BlockInternal( &this->lock );
     191
     192                        // BlockInternal will unlock spinlock, no need to unlock ourselves
    213193                        return;
    214194                }
     
    225205                __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
    226206
    227                 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     207                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    228208
    229209                // Leaving a recursion level, decrement the counter
     
    241221                thread_desc * new_owner = next_thread( this );
    242222
    243                 // Check the new owner is consistent with who we wake-up
    244                 // new_owner might be null even if someone owns the monitor when the owner is still waiting for another monitor
    245                 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    246 
    247223                // We can now let other threads in safely
    248224                unlock( this->lock );
    249225
    250226                //We need to wake-up the thread
    251                 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    252                 unpark( new_owner );
     227                WakeThread( new_owner );
    253228        }
    254229
     
    277252                disable_interrupts();
    278253
    279                 thrd->state = Halted;
    280 
    281                 /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
     254                thrd->self_cor.state = Halted;
     255
     256                verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    282257
    283258                // Leaving a recursion level, decrement the counter
     
    291266                thread_desc * new_owner = next_thread( this );
    292267
    293                 // Release the monitor lock
    294                 unlock( this->lock );
    295 
    296                 // Unpark the next owner if needed
    297                 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    298                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    299                 /* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
    300                 /* paranoid */ verify( thrd->state == Halted );
    301 
    302                 kernelTLS.this_processor->destroyer = new_owner;
    303 
    304                 // Leave the thread
    305                 __leave_thread();
     268                // Leave the thread, this will unlock the spinlock
     269                // Use leave thread instead of BlockInternal which is
     270                // specialized for this case and supports null new_owner
     271                LeaveThread( &this->lock, new_owner );
    306272
    307273                // Control flow should never reach here!
     
    434400        // Append the current wait operation to the ones already queued on the condition
    435401        // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion
    436         /* paranoid */ verify( waiter.next == 0p );
    437402        append( this.blocked, &waiter );
    438         /* paranoid */ verify( waiter.next == 1p );
    439403
    440404        // Lock all monitors (aggregates the locks as well)
     
    455419        }
    456420
    457         // Unlock the locks, we don't need them anymore
    458         for(int i = 0; i < count; i++) {
    459                 unlock( *locks[i] );
    460         }
    461 
    462         // Wake the threads
    463         for(int i = 0; i < thread_count; i++) {
    464                 unpark( threads[i] );
    465         }
    466 
    467421        // Everything is ready to go to sleep
    468         park();
     422        BlockInternal( locks, count, threads, thread_count );
    469423
    470424        // We are back, restore the owners and recursions
     
    536490        //Find the thread to run
    537491        thread_desc * signallee = pop_head( this.blocked )->waiting_thread;
    538         /* paranoid */ verify( signallee->next == 0p );
    539492        set_owner( monitors, count, signallee );
    540493
    541494        __cfaabi_dbg_print_buffer_decl( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );
    542495
    543         // unlock all the monitors
    544         unlock_all( locks, count );
    545 
    546         // unpark the thread we signalled
    547         unpark( signallee );
    548 
    549496        //Everything is ready to go to sleep
    550         park();
     497        BlockInternal( locks, count, &signallee, 1 );
    551498
    552499
     
    645592                                set_owner( monitors, count, next );
    646593
    647                                 // unlock all the monitors
    648                                 unlock_all( locks, count );
    649 
    650                                 // unpark the thread we signalled
    651                                 unpark( next );
    652 
    653                                 //Everything is ready to go to sleep
    654                                 park();
     594                                // Everything is ready to go to sleep
     595                                BlockInternal( locks, count, &next, 1 );
    655596
    656597                                // We are back, restore the owners and recursions
     
    690631        }
    691632
    692         // unlock all the monitors
    693         unlock_all( locks, count );
    694 
    695633        //Everything is ready to go to sleep
    696         park();
     634        BlockInternal( locks, count );
    697635
    698636
     
    712650
    713651static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
    714         /* paranoid */ verify( this->lock.lock );
     652        // __cfaabi_dbg_print_safe( "Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
    715653
    716654        //Pass the monitor appropriately
     
    722660
    723661static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {
    724         /* paranoid */ verify ( monitors[0]->lock.lock );
    725         /* paranoid */ verifyf( monitors[0]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[0]->owner, monitors[0]->recursion, monitors[0] );
    726         monitors[0]->owner        = owner;
    727         monitors[0]->recursion    = 1;
     662        monitors[0]->owner     = owner;
     663        monitors[0]->recursion = 1;
    728664        for( __lock_size_t i = 1; i < count; i++ ) {
    729                 /* paranoid */ verify ( monitors[i]->lock.lock );
    730                 /* paranoid */ verifyf( monitors[i]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[i]->owner, monitors[i]->recursion, monitors[i] );
    731                 monitors[i]->owner        = owner;
    732                 monitors[i]->recursion    = 0;
     665                monitors[i]->owner     = owner;
     666                monitors[i]->recursion = 0;
    733667        }
    734668}
     
    754688                //regardless of if we are ready to baton pass,
    755689                //we need to set the monitor as in use
    756                 /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    757690                set_owner( this,  urgent->owner->waiting_thread );
    758691
     
    763696        // Get the next thread in the entry_queue
    764697        thread_desc * new_owner = pop_head( this->entry_queue );
    765         /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    766         /* paranoid */ verify( !new_owner || new_owner->next == 0p );
    767698        set_owner( this, new_owner );
    768699
     
    910841        // For each thread in the entry-queue
    911842        for(    thread_desc ** thrd_it = &entry_queue.head;
    912                 *thrd_it != 1p;
     843                *thrd_it;
    913844                thrd_it = &(*thrd_it)->next
    914845        ) {
  • libcfa/src/concurrency/monitor.hfa

    ra505021 rc744563a  
    133133              bool signal      ( condition & this );
    134134              bool signal_block( condition & this );
    135 static inline bool is_empty    ( condition & this ) { return this.blocked.head == 1p; }
     135static inline bool is_empty    ( condition & this ) { return !this.blocked.head; }
    136136         uintptr_t front       ( condition & this );
    137137
  • libcfa/src/concurrency/mutex.cfa

    ra505021 rc744563a  
    4040        if( is_locked ) {
    4141                append( blocked_threads, kernelTLS.this_thread );
    42                 unlock( lock );
    43                 park();
     42                BlockInternal( &lock );
    4443        }
    4544        else {
     
    6362        lock( this.lock __cfaabi_dbg_ctx2 );
    6463        this.is_locked = (this.blocked_threads != 0);
    65         unpark(
     64        WakeThread(
    6665                pop_head( this.blocked_threads )
    6766        );
     
    9594        else {
    9695                append( blocked_threads, kernelTLS.this_thread );
    97                 unlock( lock );
    98                 park();
     96                BlockInternal( &lock );
    9997        }
    10098}
     
    123121                owner = thrd;
    124122                recursion_count = (thrd ? 1 : 0);
    125                 unpark( thrd );
     123                WakeThread( thrd );
    126124        }
    127125        unlock( lock );
     
    140138void notify_one(condition_variable & this) with(this) {
    141139        lock( lock __cfaabi_dbg_ctx2 );
    142         unpark(
     140        WakeThread(
    143141                pop_head( this.blocked_threads )
    144142        );
     
    149147        lock( lock __cfaabi_dbg_ctx2 );
    150148        while(this.blocked_threads) {
    151                 unpark(
     149                WakeThread(
    152150                        pop_head( this.blocked_threads )
    153151                );
     
    159157        lock( this.lock __cfaabi_dbg_ctx2 );
    160158        append( this.blocked_threads, kernelTLS.this_thread );
    161         unlock( this.lock );
    162         park();
     159        BlockInternal( &this.lock );
    163160}
    164161
     
    167164        lock( this.lock __cfaabi_dbg_ctx2 );
    168165        append( this.blocked_threads, kernelTLS.this_thread );
    169         unlock(l);
    170         unlock(this.lock);
    171         park();
     166        void __unlock(void) {
     167                unlock(l);
     168                unlock(this.lock);
     169        }
     170        BlockInternal( __unlock );
    172171        lock(l);
    173172}
  • libcfa/src/concurrency/preemption.cfa

    ra505021 rc744563a  
    187187        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    188188                processor   * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
     189                thread_desc * thrd = kernelTLS.this_thread;       // Cache the thread now since interrupts can start happening after the atomic store
    189190
    190191                with( kernelTLS.preemption_state ){
     
    208209                                if( proc->pending_preemption ) {
    209210                                        proc->pending_preemption = false;
    210                                         force_yield( __POLL_PREEMPTION );
     211                                        BlockInternal( thrd );
    211212                                }
    212213                        }
     
    306307        signal_block( SIGALRM );
    307308
    308         alarm_stack = __create_pthread( &alarm_thread, alarm_loop, 0p );
     309        alarm_stack = create_pthread( &alarm_thread, alarm_loop, 0p );
    309310}
    310311
     
    393394        // Preemption can occur here
    394395
    395         force_yield( __ALARM_PREEMPTION ); // Do the actual CtxSwitch
     396        BlockInternal( kernelTLS.this_thread ); // Do the actual CtxSwitch
    396397}
    397398
  • libcfa/src/concurrency/thread.cfa

    ra505021 rc744563a  
    2323#include "invoke.h"
    2424
     25extern "C" {
     26        #include <fenv.h>
     27        #include <stddef.h>
     28}
     29
     30//extern volatile thread_local processor * this_processor;
     31
    2532//-----------------------------------------------------------------------------
    2633// Thread ctors and dtors
     
    2936        self_cor{ name, storage, storageSize };
    3037        state = Start;
    31         preempted = __NO_PREEMPTION;
    3238        curr_cor = &self_cor;
    3339        self_mon.owner = &this;
     
    4955}
    5056
    51 //-----------------------------------------------------------------------------
    52 // Starting and stopping threads
    53 forall( dtype T | is_thread(T) )
    54 void __thrd_start( T & this, void (*main_p)(T &) ) {
    55         thread_desc * this_thrd = get_thread(this);
    56 
    57         disable_interrupts();
    58         CtxStart(main_p, get_coroutine(this), this, CtxInvokeThread);
    59 
    60         this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
    61         verify( this_thrd->context.SP );
    62 
    63         __schedule_thread(this_thrd);
    64         enable_interrupts( __cfaabi_dbg_ctx );
    65 }
    66 
    67 //-----------------------------------------------------------------------------
    68 // Support for threads that don't ues the thread keyword
    6957forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T&); } )
    7058void ?{}( scoped(T)& this ) with( this ) {
     
    8472}
    8573
     74//-----------------------------------------------------------------------------
     75// Starting and stopping threads
     76forall( dtype T | is_thread(T) )
     77void __thrd_start( T & this, void (*main_p)(T &) ) {
     78        thread_desc * this_thrd = get_thread(this);
     79
     80        disable_interrupts();
     81        CtxStart(main_p, get_coroutine(this), this, CtxInvokeThread);
     82
     83        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
     84        verify( this_thrd->context.SP );
     85
     86        ScheduleThread(this_thrd);
     87        enable_interrupts( __cfaabi_dbg_ctx );
     88}
     89
     90void yield( void ) {
     91        // Safety note : This could cause some false positives due to preemption
     92      verify( TL_GET( preemption_state.enabled ) );
     93        BlockInternal( TL_GET( this_thread ) );
     94        // Safety note : This could cause some false positives due to preemption
     95      verify( TL_GET( preemption_state.enabled ) );
     96}
     97
     98void yield( unsigned times ) {
     99        for( unsigned i = 0; i < times; i++ ) {
     100                yield();
     101        }
     102}
     103
    86104// Local Variables: //
    87105// mode: c //
  • libcfa/src/concurrency/thread.hfa

    ra505021 rc744563a  
    3131};
    3232
    33 // define that satisfies the trait without using the thread keyword
    34 #define DECL_THREAD(X) thread_desc* get_thread(X& this) __attribute__((const)) { return &this.__thrd; } void main(X& this)
    35 
    36 // Inline getters for threads/coroutines/monitors
    37 forall( dtype T | is_thread(T) )
    38 static inline coroutine_desc* get_coroutine(T & this) __attribute__((const)) { return &get_thread(this)->self_cor; }
     33#define DECL_THREAD(X) thread_desc* get_thread(X& this) { return &this.__thrd; } void main(X& this)
    3934
    4035forall( dtype T | is_thread(T) )
    41 static inline monitor_desc  * get_monitor  (T & this) __attribute__((const)) { return &get_thread(this)->self_mon; }
     36static inline coroutine_desc* get_coroutine(T & this) {
     37        return &get_thread(this)->self_cor;
     38}
    4239
    43 static inline coroutine_desc* get_coroutine(thread_desc * this) __attribute__((const)) { return &this->self_cor; }
    44 static inline monitor_desc  * get_monitor  (thread_desc * this) __attribute__((const)) { return &this->self_mon; }
     40forall( dtype T | is_thread(T) )
     41static inline monitor_desc* get_monitor(T & this) {
     42        return &get_thread(this)->self_mon;
     43}
    4544
    46 //-----------------------------------------------------------------------------
    47 // forward declarations needed for threads
     45static inline coroutine_desc* get_coroutine(thread_desc * this) {
     46        return &this->self_cor;
     47}
     48
     49static inline monitor_desc* get_monitor(thread_desc * this) {
     50        return &this->self_mon;
     51}
     52
    4853extern struct cluster * mainCluster;
    4954
     
    8388void ^?{}( scoped(T)& this );
    8489
    85 //-----------------------------------------------------------------------------
    86 // Thread getters
     90void yield();
     91void yield( unsigned times );
     92
    8793static inline struct thread_desc * active_thread () { return TL_GET( this_thread ); }
    88 
    89 //-----------------------------------------------------------------------------
    90 // Scheduler API
    91 
    92 //----------
    93 // Park thread: block until corresponding call to unpark, won't block if unpark is already called
    94 void park( void );
    95 
    96 //----------
    97 // Unpark a thread, if the thread is already blocked, schedule it
    98 //                  if the thread is not yet block, signal that it should rerun immediately
    99 void unpark( thread_desc * this );
    100 
    101 forall( dtype T | is_thread(T) )
    102 static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
    103 
    104 //----------
    105 // Yield: force thread to block and be rescheduled
    106 bool force_yield( enum __Preemption_Reason );
    107 
    108 static inline void yield() {
    109         force_yield(__MANUAL_PREEMPTION);
    110 }
    111 
    112 // Yield: yield N times
    113 static inline void yield( unsigned times ) {
    114         for( times ) {
    115                 yield();
    116         }
    117 }
    11894
    11995// Local Variables: //
  • tests/concurrent/examples/.expect/datingService.txt

    ra505021 rc744563a  
     1Girl:17 is dating Boy at 2 with ccode 17
     2 Boy:2 is dating Girl 17 with ccode 17
     3 Boy:14 is dating Girl 5 with ccode 5
     4Girl:5 is dating Boy at 14 with ccode 5
     5 Boy:9 is dating Girl 10 with ccode 10
     6Girl:10 is dating Boy at 9 with ccode 10
     7 Boy:1 is dating Girl 18 with ccode 18
     8Girl:18 is dating Boy at 1 with ccode 18
     9 Boy:16 is dating Girl 3 with ccode 3
     10Girl:3 is dating Boy at 16 with ccode 3
     11 Boy:5 is dating Girl 14 with ccode 14
     12Girl:14 is dating Boy at 5 with ccode 14
     13 Boy:15 is dating Girl 4 with ccode 4
     14Girl:4 is dating Boy at 15 with ccode 4
     15Girl:0 is dating Boy at 19 with ccode 0
     16 Boy:19 is dating Girl 0 with ccode 0
     17Girl:9 is dating Boy at 10 with ccode 9
     18 Boy:10 is dating Girl 9 with ccode 9
     19Girl:11 is dating Boy at 8 with ccode 11
     20 Boy:8 is dating Girl 11 with ccode 11
     21 Boy:12 is dating Girl 7 with ccode 7
     22Girl:7 is dating Boy at 12 with ccode 7
     23 Boy:11 is dating Girl 8 with ccode 8
     24Girl:8 is dating Boy at 11 with ccode 8
     25Girl:16 is dating Boy at 3 with ccode 16
     26 Boy:3 is dating Girl 16 with ccode 16
     27Girl:15 is dating Boy at 4 with ccode 15
     28 Boy:4 is dating Girl 15 with ccode 15
     29Girl:19 is dating Boy at 0 with ccode 19
     30 Boy:0 is dating Girl 19 with ccode 19
     31Girl:2 is dating Boy at 17 with ccode 2
     32 Boy:17 is dating Girl 2 with ccode 2
     33 Boy:13 is dating Girl 6 with ccode 6
     34Girl:6 is dating Boy at 13 with ccode 6
     35 Boy:7 is dating Girl 12 with ccode 12
     36Girl:12 is dating Boy at 7 with ccode 12
     37Girl:13 is dating Boy at 6 with ccode 13
     38 Boy:6 is dating Girl 13 with ccode 13
     39Girl:1 is dating Boy at 18 with ccode 1
     40 Boy:18 is dating Girl 1 with ccode 1
  • tests/concurrent/examples/datingService.cfa

    ra505021 rc744563a  
    11//
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    3 //
     3// 
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
     
    3535                signal_block( Boys[ccode] );                                    // restart boy to set phone number
    3636        } // if
    37         //sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode;
     37        sout | "Girl:" | PhoneNo | "is dating Boy at" | BoyPhoneNo | "with ccode" | ccode;
    3838        return BoyPhoneNo;
    3939} // DatingService girl
     
    4747                signal_block( Girls[ccode] );                                   // restart girl to set phone number
    4848        } // if
    49         //sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
     49        sout | " Boy:" | PhoneNo | "is dating Girl" | GirlPhoneNo | "with ccode" | ccode;
    5050        return GirlPhoneNo;
    5151} // DatingService boy
  • tests/concurrent/multi-monitor.cfa

    ra505021 rc744563a  
    1111
    1212void increment( monitor_t & mutex p1, monitor_t & mutex p2, int & value ) {
    13         assert(active_thread() == get_monitor(p1)->owner);
    14         assert(active_thread() == get_monitor(p2)->owner);
    1513        value += 1;
    16         assert(active_thread() == get_monitor(p1)->owner);
    17         assert(active_thread() == get_monitor(p2)->owner);
    1814}
    1915
Note: See TracChangeset for help on using the changeset viewer.