Ignore:
Timestamp:
Feb 1, 2022, 10:10:46 AM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
Children:
7b2c8c3c
Parents:
f681823 (diff), 89a5a1f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel.cfa

    rf681823 r376c632a  
    4242
    4343#if !defined(__CFA_NO_STATISTICS__)
    44         #define __STATS( ...) __VA_ARGS__
     44        #define __STATS_DEF( ...) __VA_ARGS__
    4545#else
    46         #define __STATS( ...)
     46        #define __STATS_DEF( ...)
    4747#endif
    4848
     
    122122static thread$ * __next_thread(cluster * this);
    123123static thread$ * __next_thread_slow(cluster * this);
     124static thread$ * __next_thread_search(cluster * this);
    124125static inline bool __must_unpark( thread$ * thrd ) __attribute((nonnull(1)));
    125126static void __run_thread(processor * this, thread$ * dst);
     
    187188                MAIN_LOOP:
    188189                for() {
    189                         #define OLD_MAIN 1
    190                         #if OLD_MAIN
    191190                        // Check if there is pending io
    192191                        __maybe_io_drain( this );
     
    196195
    197196                        if( !readyThread ) {
     197                                __IO_STATS__(true, io.flush.idle++; )
    198198                                __cfa_io_flush( this, 0 );
    199199
     200                                readyThread = __next_thread( this->cltr );
     201                        }
     202
     203                        if( !readyThread ) for(5) {
     204                                __IO_STATS__(true, io.flush.idle++; )
     205
    200206                                readyThread = __next_thread_slow( this->cltr );
     207
     208                                if( readyThread ) break;
     209
     210                                __cfa_io_flush( this, 0 );
    201211                        }
    202212
     
    210220
    211221                                // Confirm the ready-queue is empty
    212                                 readyThread = __next_thread_slow( this->cltr );
     222                                readyThread = __next_thread_search( this->cltr );
    213223                                if( readyThread ) {
    214224                                        // A thread was found, cancel the halt
    215225                                        mark_awake(this->cltr->procs, * this);
    216226
    217                                         #if !defined(__CFA_NO_STATISTICS__)
    218                                                 __tls_stats()->ready.sleep.cancels++;
    219                                         #endif
     227                                        __STATS__(true, ready.sleep.cancels++; )
    220228
    221229                                        // continue the mai loop
     
    244252
    245253                        if(this->io.pending && !this->io.dirty) {
     254                                __IO_STATS__(true, io.flush.dirty++; )
    246255                                __cfa_io_flush( this, 0 );
    247256                        }
    248 
    249                         #else
    250                                 #warning new kernel loop
    251                         SEARCH: {
    252                                 /* paranoid */ verify( ! __preemption_enabled() );
    253 
    254                                 // First, lock the scheduler since we are searching for a thread
    255                                 ready_schedule_lock();
    256 
    257                                 // Try to get the next thread
    258                                 readyThread = pop_fast( this->cltr );
    259                                 if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    260 
    261                                 // If we can't find a thread, might as well flush any outstanding I/O
    262                                 if(this->io.pending) { __cfa_io_flush( this, 0 ); }
    263 
    264                                 // Spin a little on I/O, just in case
    265                                 for(5) {
    266                                         __maybe_io_drain( this );
    267                                         readyThread = pop_fast( this->cltr );
    268                                         if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    269                                 }
    270 
    271                                 // no luck, try stealing a few times
    272                                 for(5) {
    273                                         if( __maybe_io_drain( this ) ) {
    274                                                 readyThread = pop_fast( this->cltr );
    275                                         } else {
    276                                                 readyThread = pop_slow( this->cltr );
    277                                         }
    278                                         if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    279                                 }
    280 
    281                                 // still no luck, search for a thread
    282                                 readyThread = pop_search( this->cltr );
    283                                 if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    284 
    285                                 // Don't block if we are done
    286                                 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) {
    287                                         ready_schedule_unlock();
    288                                         break MAIN_LOOP;
    289                                 }
    290 
    291                                 __STATS( __tls_stats()->ready.sleep.halts++; )
    292 
    293                                 // Push self to idle stack
    294                                 ready_schedule_unlock();
    295                                 if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;
    296                                 ready_schedule_lock();
    297 
    298                                 // Confirm the ready-queue is empty
    299                                 __maybe_io_drain( this );
    300                                 readyThread = pop_search( this->cltr );
    301                                 ready_schedule_unlock();
    302 
    303                                 if( readyThread ) {
    304                                         // A thread was found, cancel the halt
    305                                         mark_awake(this->cltr->procs, * this);
    306 
    307                                         __STATS( __tls_stats()->ready.sleep.cancels++; )
    308 
    309                                         // continue the main loop
    310                                         break SEARCH;
    311                                 }
    312 
    313                                 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )
    314                                 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd);
    315 
    316                                 {
    317                                         eventfd_t val;
    318                                         ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
    319                                         if(ret < 0) {
    320                                                 switch((int)errno) {
    321                                                 case EAGAIN:
    322                                                 #if EAGAIN != EWOULDBLOCK
    323                                                         case EWOULDBLOCK:
    324                                                 #endif
    325                                                 case EINTR:
    326                                                         // No need to do anything special here, just assume it's a legitimate wake-up
    327                                                         break;
    328                                                 default:
    329                                                         abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    330                                                 }
    331                                         }
    332                                 }
    333 
    334                                         __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); )
    335 
    336                                 // We were woken up, remove self from idle
    337                                 mark_awake(this->cltr->procs, * this);
    338 
    339                                 // DON'T just proceed, start looking again
    340                                 continue MAIN_LOOP;
    341                         }
    342 
    343                 RUN_THREAD:
    344                         /* paranoid */ verify( ! __preemption_enabled() );
    345                         /* paranoid */ verify( readyThread );
    346 
    347                         // Reset io dirty bit
    348                         this->io.dirty = false;
    349 
    350                         // We found a thread run it
    351                         __run_thread(this, readyThread);
    352 
    353                         // Are we done?
    354                         if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
    355 
    356                         if(this->io.pending && !this->io.dirty) {
    357                                 __cfa_io_flush( this, 0 );
    358                         }
    359 
    360                         ready_schedule_lock();
    361                         __maybe_io_drain( this );
    362                         ready_schedule_unlock();
    363                         #endif
    364257                }
    365258
     
    472365                                break RUNNING;
    473366                        case TICKET_UNBLOCK:
    474                                 #if !defined(__CFA_NO_STATISTICS__)
    475                                         __tls_stats()->ready.threads.threads++;
    476                                 #endif
     367                                __STATS__(true, ready.threads.threads++; )
    477368                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    478369                                // In this case, just run it again.
     
    489380        __cfadbg_print_safe(runtime_core, "Kernel : core %p finished running thread %p\n", this, thrd_dst);
    490381
    491         #if !defined(__CFA_NO_STATISTICS__)
    492                 __tls_stats()->ready.threads.threads--;
    493         #endif
     382        __STATS__(true, ready.threads.threads--; )
    494383
    495384        /* paranoid */ verify( ! __preemption_enabled() );
     
    502391        thread$ * thrd_src = kernelTLS().this_thread;
    503392
    504         __STATS( thrd_src->last_proc = kernelTLS().this_processor; )
     393        __STATS_DEF( thrd_src->last_proc = kernelTLS().this_processor; )
    505394
    506395        // Run the thread on this processor
     
    554443        // Dereference the thread now because once we push it, there is not guaranteed it's still valid.
    555444        struct cluster * cl = thrd->curr_cluster;
    556         __STATS(bool outside = hint == UNPARK_LOCAL && thrd->last_proc && thrd->last_proc != kernelTLS().this_processor; )
     445        __STATS_DEF(bool outside = hint == UNPARK_LOCAL && thrd->last_proc && thrd->last_proc != kernelTLS().this_processor; )
    557446
    558447        // push the thread to the cluster ready-queue
     
    605494
    606495        ready_schedule_lock();
    607                 thread$ * thrd;
    608                 for(25) {
    609                         thrd = pop_slow( this );
    610                         if(thrd) goto RET;
    611                 }
    612                 thrd = pop_search( this );
    613 
    614                 RET:
     496                thread$ * thrd = pop_slow( this );
     497        ready_schedule_unlock();
     498
     499        /* paranoid */ verify( ! __preemption_enabled() );
     500        return thrd;
     501}
     502
     503// KERNEL ONLY
     504static inline thread$ * __next_thread_search(cluster * this) with( *this ) {
     505        /* paranoid */ verify( ! __preemption_enabled() );
     506
     507        ready_schedule_lock();
     508                thread$ * thrd = pop_search( this );
    615509        ready_schedule_unlock();
    616510
     
    854748
    855749static bool mark_idle(__cluster_proc_list & this, processor & proc) {
    856         #if !defined(__CFA_NO_STATISTICS__)
    857                 __tls_stats()->ready.sleep.halts++;
    858         #endif
     750        __STATS__(true, ready.sleep.halts++; )
    859751
    860752        proc.idle_wctx.fd = 0;
     
    949841                unsigned tail = *ctx->cq.tail;
    950842                if(head == tail) return false;
    951                 #if OLD_MAIN
    952                         ready_schedule_lock();
    953                         ret = __cfa_io_drain( proc );
    954                         ready_schedule_unlock();
    955                 #else
    956                         ret = __cfa_io_drain( proc );
    957                 #endif
     843                ready_schedule_lock();
     844                ret = __cfa_io_drain( proc );
     845                ready_schedule_unlock();
    958846        #endif
    959847        return ret;
Note: See TracChangeset for help on using the changeset viewer.