Changeset f5a51db for libcfa


Ignore:
Timestamp:
Feb 8, 2022, 11:53:13 AM (2 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
cc7bbe6
Parents:
97c215f (diff), 1cf8a9f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
libcfa/src
Files:
12 edited

Legend:

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

    r97c215f rf5a51db  
    306306                ctx->proc->io.pending = true;
    307307                ctx->proc->io.dirty   = true;
    308                 if(sq.to_submit > 30 || !lazy) {
     308                if(sq.to_submit > 30) {
     309                        __tls_stats()->io.flush.full++;
     310                        __cfa_io_flush( ctx->proc, 0 );
     311                }
     312                if(!lazy) {
     313                        __tls_stats()->io.flush.eager++;
    309314                        __cfa_io_flush( ctx->proc, 0 );
    310315                }
  • libcfa/src/concurrency/kernel.cfa

    r97c215f rf5a51db  
    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
     
    206216                                if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
    207217
    208                                 #if !defined(__CFA_NO_STATISTICS__)
    209                                         __tls_stats()->ready.sleep.halts++;
    210                                 #endif
    211 
    212218                                // Push self to idle stack
    213219                                if(!mark_idle(this->cltr->procs, * this)) continue MAIN_LOOP;
    214220
    215221                                // Confirm the ready-queue is empty
    216                                 readyThread = __next_thread_slow( this->cltr );
     222                                readyThread = __next_thread_search( this->cltr );
    217223                                if( readyThread ) {
    218224                                        // A thread was found, cancel the halt
    219225                                        mark_awake(this->cltr->procs, * this);
    220226
    221                                         #if !defined(__CFA_NO_STATISTICS__)
    222                                                 __tls_stats()->ready.sleep.cancels++;
    223                                         #endif
     227                                        __STATS__(true, ready.sleep.cancels++; )
    224228
    225229                                        // continue the mai loop
     
    248252
    249253                        if(this->io.pending && !this->io.dirty) {
     254                                __IO_STATS__(true, io.flush.dirty++; )
    250255                                __cfa_io_flush( this, 0 );
    251256                        }
    252 
    253                         #else
    254                                 #warning new kernel loop
    255                         SEARCH: {
    256                                 /* paranoid */ verify( ! __preemption_enabled() );
    257 
    258                                 // First, lock the scheduler since we are searching for a thread
    259                                 ready_schedule_lock();
    260 
    261                                 // Try to get the next thread
    262                                 readyThread = pop_fast( this->cltr );
    263                                 if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    264 
    265                                 // If we can't find a thread, might as well flush any outstanding I/O
    266                                 if(this->io.pending) { __cfa_io_flush( this, 0 ); }
    267 
    268                                 // Spin a little on I/O, just in case
    269                                 for(5) {
    270                                         __maybe_io_drain( this );
    271                                         readyThread = pop_fast( this->cltr );
    272                                         if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    273                                 }
    274 
    275                                 // no luck, try stealing a few times
    276                                 for(5) {
    277                                         if( __maybe_io_drain( this ) ) {
    278                                                 readyThread = pop_fast( this->cltr );
    279                                         } else {
    280                                                 readyThread = pop_slow( this->cltr );
    281                                         }
    282                                         if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    283                                 }
    284 
    285                                 // still no luck, search for a thread
    286                                 readyThread = pop_search( this->cltr );
    287                                 if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    288 
    289                                 // Don't block if we are done
    290                                 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) {
    291                                         ready_schedule_unlock();
    292                                         break MAIN_LOOP;
    293                                 }
    294 
    295                                 __STATS( __tls_stats()->ready.sleep.halts++; )
    296 
    297                                 // Push self to idle stack
    298                                 ready_schedule_unlock();
    299                                 if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;
    300                                 ready_schedule_lock();
    301 
    302                                 // Confirm the ready-queue is empty
    303                                 __maybe_io_drain( this );
    304                                 readyThread = pop_search( this->cltr );
    305                                 ready_schedule_unlock();
    306 
    307                                 if( readyThread ) {
    308                                         // A thread was found, cancel the halt
    309                                         mark_awake(this->cltr->procs, * this);
    310 
    311                                         __STATS( __tls_stats()->ready.sleep.cancels++; )
    312 
    313                                         // continue the main loop
    314                                         break SEARCH;
    315                                 }
    316 
    317                                 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )
    318                                 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd);
    319 
    320                                 {
    321                                         eventfd_t val;
    322                                         ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
    323                                         if(ret < 0) {
    324                                                 switch((int)errno) {
    325                                                 case EAGAIN:
    326                                                 #if EAGAIN != EWOULDBLOCK
    327                                                         case EWOULDBLOCK:
    328                                                 #endif
    329                                                 case EINTR:
    330                                                         // No need to do anything special here, just assume it's a legitimate wake-up
    331                                                         break;
    332                                                 default:
    333                                                         abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) );
    334                                                 }
    335                                         }
    336                                 }
    337 
    338                                         __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); )
    339 
    340                                 // We were woken up, remove self from idle
    341                                 mark_awake(this->cltr->procs, * this);
    342 
    343                                 // DON'T just proceed, start looking again
    344                                 continue MAIN_LOOP;
    345                         }
    346 
    347                 RUN_THREAD:
    348                         /* paranoid */ verify( ! __preemption_enabled() );
    349                         /* paranoid */ verify( readyThread );
    350 
    351                         // Reset io dirty bit
    352                         this->io.dirty = false;
    353 
    354                         // We found a thread run it
    355                         __run_thread(this, readyThread);
    356 
    357                         // Are we done?
    358                         if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
    359 
    360                         if(this->io.pending && !this->io.dirty) {
    361                                 __cfa_io_flush( this, 0 );
    362                         }
    363 
    364                         ready_schedule_lock();
    365                         __maybe_io_drain( this );
    366                         ready_schedule_unlock();
    367                         #endif
    368257                }
    369258
     
    476365                                break RUNNING;
    477366                        case TICKET_UNBLOCK:
    478                                 #if !defined(__CFA_NO_STATISTICS__)
    479                                         __tls_stats()->ready.threads.threads++;
    480                                 #endif
     367                                __STATS__(true, ready.threads.threads++; )
    481368                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
    482369                                // In this case, just run it again.
     
    493380        __cfadbg_print_safe(runtime_core, "Kernel : core %p finished running thread %p\n", this, thrd_dst);
    494381
    495         #if !defined(__CFA_NO_STATISTICS__)
    496                 __tls_stats()->ready.threads.threads--;
    497         #endif
     382        __STATS__(true, ready.threads.threads--; )
    498383
    499384        /* paranoid */ verify( ! __preemption_enabled() );
     
    506391        thread$ * thrd_src = kernelTLS().this_thread;
    507392
    508         __STATS( thrd_src->last_proc = kernelTLS().this_processor; )
     393        __STATS_DEF( thrd_src->last_proc = kernelTLS().this_processor; )
    509394
    510395        // Run the thread on this processor
     
    558443        // Dereference the thread now because once we push it, there is not guaranteed it's still valid.
    559444        struct cluster * cl = thrd->curr_cluster;
    560         __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; )
    561446
    562447        // push the thread to the cluster ready-queue
     
    609494
    610495        ready_schedule_lock();
    611                 thread$ * thrd;
    612                 for(25) {
    613                         thrd = pop_slow( this );
    614                         if(thrd) goto RET;
    615                 }
    616                 thrd = pop_search( this );
    617 
    618                 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 );
    619509        ready_schedule_unlock();
    620510
     
    732622// Wake a thread from the front if there are any
    733623static void __wake_one(cluster * this) {
     624        eventfd_t val;
     625
    734626        /* paranoid */ verify( ! __preemption_enabled() );
    735627        /* paranoid */ verify( ready_schedule_islocked() );
    736628
    737629        // Check if there is a sleeping processor
    738         // int fd = __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST);
    739         int fd = 0;
    740         if( __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST) != 0 ) {
    741                 fd = __atomic_exchange_n(&this->procs.fd, 0, __ATOMIC_RELAXED);
    742         }
    743 
    744         // If no one is sleeping, we are done
    745         if( fd == 0 ) return;
    746 
    747         // We found a processor, wake it up
    748         eventfd_t val;
    749         val = 1;
    750         eventfd_write( fd, val );
    751 
    752         #if !defined(__CFA_NO_STATISTICS__)
    753                 if( kernelTLS().this_stats ) {
    754                         __tls_stats()->ready.sleep.wakes++;
    755                 }
    756                 else {
    757                         __atomic_fetch_add(&this->stats->ready.sleep.wakes, 1, __ATOMIC_RELAXED);
    758                 }
    759         #endif
     630        struct __fd_waitctx * fdp = __atomic_load_n(&this->procs.fdw, __ATOMIC_SEQ_CST);
     631
     632        // If no one is sleeping: we are done
     633        if( fdp == 0p ) return;
     634
     635        int fd = 1;
     636        if( __atomic_load_n(&fdp->fd, __ATOMIC_SEQ_CST) != 1 ) {
     637                fd = __atomic_exchange_n(&fdp->fd, 1, __ATOMIC_RELAXED);
     638        }
     639
     640        switch(fd) {
     641        case 0:
     642                // If the processor isn't ready to sleep then the exchange will already wake it up
     643                #if !defined(__CFA_NO_STATISTICS__)
     644                        if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.early++;
     645                        } else { __atomic_fetch_add(&this->stats->ready.sleep.early, 1, __ATOMIC_RELAXED); }
     646                #endif
     647                break;
     648        case 1:
     649                // If someone else already said they will wake them: we are done
     650                #if !defined(__CFA_NO_STATISTICS__)
     651                        if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.seen++;
     652                        } else { __atomic_fetch_add(&this->stats->ready.sleep.seen, 1, __ATOMIC_RELAXED); }
     653                #endif
     654                break;
     655        default:
     656                // If the processor was ready to sleep, we need to wake it up with an actual write
     657                val = 1;
     658                eventfd_write( fd, val );
     659
     660                #if !defined(__CFA_NO_STATISTICS__)
     661                        if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.wakes++;
     662                        } else { __atomic_fetch_add(&this->stats->ready.sleep.wakes, 1, __ATOMIC_RELAXED); }
     663                #endif
     664                break;
     665        }
    760666
    761667        /* paranoid */ verify( ready_schedule_islocked() );
     
    770676
    771677        __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
     678
     679        this->idle_wctx.fd = 1;
    772680
    773681        eventfd_t val;
     
    779687
    780688static void idle_sleep(processor * this, io_future_t & future, iovec & iov) {
     689        // Tell everyone we are ready to go do sleep
     690        for() {
     691                int expected = this->idle_wctx.fd;
     692
     693                // Someone already told us to wake-up! No time for a nap.
     694                if(expected == 1) { return; }
     695
     696                // Try to mark that we are going to sleep
     697                if(__atomic_compare_exchange_n(&this->idle_wctx.fd, &expected, this->idle_fd, false,  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
     698                        // Every one agreed, taking a nap
     699                        break;
     700                }
     701        }
     702
     703
    781704        #if !defined(CFA_WITH_IO_URING_IDLE)
    782705                #if !defined(__CFA_NO_STATISTICS__)
     
    825748
    826749static bool mark_idle(__cluster_proc_list & this, processor & proc) {
     750        __STATS__(true, ready.sleep.halts++; )
     751
     752        proc.idle_wctx.fd = 0;
     753
    827754        /* paranoid */ verify( ! __preemption_enabled() );
    828755        if(!try_lock( this )) return false;
     
    832759                insert_first(this.idles, proc);
    833760
    834                 __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST);
     761                __atomic_store_n(&this.fdw, &proc.idle_wctx, __ATOMIC_SEQ_CST);
    835762        unlock( this );
    836763        /* paranoid */ verify( ! __preemption_enabled() );
     
    848775
    849776                {
    850                         int fd = 0;
    851                         if(!this.idles`isEmpty) fd = this.idles`first.idle_fd;
    852                         __atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST);
     777                        struct __fd_waitctx * wctx = 0;
     778                        if(!this.idles`isEmpty) wctx = &this.idles`first.idle_wctx;
     779                        __atomic_store_n(&this.fdw, wctx, __ATOMIC_SEQ_CST);
    853780                }
    854781
     
    914841                unsigned tail = *ctx->cq.tail;
    915842                if(head == tail) return false;
    916                 #if OLD_MAIN
    917                         ready_schedule_lock();
    918                         ret = __cfa_io_drain( proc );
    919                         ready_schedule_unlock();
    920                 #else
    921                         ret = __cfa_io_drain( proc );
    922                 #endif
     843                ready_schedule_lock();
     844                ret = __cfa_io_drain( proc );
     845                ready_schedule_unlock();
    923846        #endif
    924847        return ret;
  • libcfa/src/concurrency/kernel.hfa

    r97c215f rf5a51db  
    5353coroutine processorCtx_t {
    5454        struct processor * proc;
     55};
     56
     57
     58struct __fd_waitctx {
     59        volatile int fd;
    5560};
    5661
     
    101106        int idle_fd;
    102107
     108        // Idle waitctx
     109        struct __fd_waitctx idle_wctx;
     110
    103111        // Termination synchronisation (user semaphore)
    104112        oneshot terminated;
     
    207215
    208216        // FD to use to wake a processor
    209         volatile int fd;
     217        struct __fd_waitctx * volatile fdw;
    210218
    211219        // Total number of processors
  • libcfa/src/concurrency/kernel/fwd.hfa

    r97c215f rf5a51db  
    396396                                if( !(in_kernel) ) enable_interrupts(); \
    397397                        }
     398                        #if defined(CFA_HAVE_LINUX_IO_URING_H)
     399                                #define __IO_STATS__(in_kernel, ...) { \
     400                                        if( !(in_kernel) ) disable_interrupts(); \
     401                                        with( *__tls_stats() ) { \
     402                                                __VA_ARGS__ \
     403                                        } \
     404                                        if( !(in_kernel) ) enable_interrupts(); \
     405                                }
     406                        #else
     407                                #define __IO_STATS__(in_kernel, ...)
     408                        #endif
    398409                #else
    399410                        #define __STATS__(in_kernel, ...)
     411                        #define __IO_STATS__(in_kernel, ...)
    400412                #endif
    401413        }
  • libcfa/src/concurrency/kernel/startup.cfa

    r97c215f rf5a51db  
    537537        }
    538538
     539        this.idle_wctx.fd = 0;
     540
     541        // I'm assuming these two are reserved for standard input and output
     542        // so I'm using them as sentinels with idle_wctx.
     543        /* paranoid */ verify( this.idle_fd != 0 );
     544        /* paranoid */ verify( this.idle_fd != 1 );
     545
    539546        #if !defined(__CFA_NO_STATISTICS__)
    540547                print_stats = 0;
     
    590597// Cluster
    591598static void ?{}(__cluster_proc_list & this) {
    592         this.fd    = 0;
     599        this.fdw   = 0p;
    593600        this.idle  = 0;
    594601        this.total = 0;
  • libcfa/src/concurrency/mutex_stmt.hfa

    r97c215f rf5a51db  
    3838    }
    3939
     40    struct scoped_lock {
     41        L * internal_lock;
     42    };
     43
     44    static inline void ?{}( scoped_lock(L) & this, L & internal_lock ) {
     45        this.internal_lock = &internal_lock;
     46        lock(internal_lock);
     47    }
     48   
     49    static inline void ^?{}( scoped_lock(L) & this ) with(this) {
     50        unlock(*internal_lock);
     51    }
     52
    4053    static inline L * __get_ptr( L & this ) {
    4154        return &this;
  • libcfa/src/concurrency/preemption.cfa

    r97c215f rf5a51db  
    251251        bool enabled = __cfaabi_tls.preemption_state.enabled;
    252252
     253        // Check if there is a pending preemption
     254        processor   * proc = __cfaabi_tls.this_processor;
     255        bool pending = proc ? proc->pending_preemption : false;
     256        if( enabled && pending ) proc->pending_preemption = false;
     257
    253258        // create a assembler label after
    254259        // marked as clobber all to avoid movement
    255260        __cfaasm_label(check, after);
     261
     262        // If we can preempt and there is a pending one
     263        // this is a good time to yield
     264        if( enabled && pending ) {
     265                force_yield( __POLL_PREEMPTION );
     266        }
    256267        return enabled;
    257268}
     
    282293        // marked as clobber all to avoid movement
    283294        __cfaasm_label(get, after);
     295
     296        // This is used everywhere, to avoid cost, we DO NOT poll pending preemption
    284297        return val;
    285298}
     
    358371        if(!ready) { abort("Preemption should be ready"); }
    359372
    360         __cfaasm_label(debug, before);
    361 
    362                 sigset_t oldset;
    363                 int ret;
    364                 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
    365                 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    366 
    367                 ret = sigismember(&oldset, SIGUSR1);
    368                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    369                 if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); }
    370 
    371                 ret = sigismember(&oldset, SIGALRM);
    372                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    373                 if(ret == 0) { abort("ERROR SIGALRM is enabled"); }
    374 
    375                 ret = sigismember(&oldset, SIGTERM);
    376                 if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
    377                 if(ret == 1) { abort("ERROR SIGTERM is disabled"); }
    378 
    379         __cfaasm_label(debug, after);
     373        sigset_t oldset;
     374        int ret;
     375        ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset);  // workaround trac#208: cast should be unnecessary
     376        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
     377
     378        ret = sigismember(&oldset, SIGUSR1);
     379        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     380        if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); }
     381
     382        ret = sigismember(&oldset, SIGALRM);
     383        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     384        if(ret == 0) { abort("ERROR SIGALRM is enabled"); }
     385
     386        ret = sigismember(&oldset, SIGTERM);
     387        if(ret <  0) { abort("ERROR sigismember returned %d", ret); }
     388        if(ret == 1) { abort("ERROR SIGTERM is disabled"); }
    380389}
    381390
     
    548557        __cfaasm_label( check  );
    549558        __cfaasm_label( dsable );
    550         __cfaasm_label( debug  );
     559        // __cfaasm_label( debug  );
    551560
    552561        // Check if preemption is safe
     
    555564        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
    556565        if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; };
    557         if( __cfaasm_in( ip, debug  ) ) { ready = false; goto EXIT; };
     566        // if( __cfaasm_in( ip, debug  ) ) { ready = false; goto EXIT; };
    558567        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
    559568        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     
    661670
    662671        // Check if it is safe to preempt here
    663         if( !preemption_ready( ip ) ) { return; }
     672        if( !preemption_ready( ip ) ) {
     673                #if !defined(__CFA_NO_STATISTICS__)
     674                        __cfaabi_tls.this_stats->ready.threads.preempt.rllfwd++;
     675                #endif
     676                return;
     677        }
    664678
    665679        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", __cfaabi_tls.this_processor, __cfaabi_tls.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) );
     
    680694
    681695        // Preemption can occur here
     696
     697        #if !defined(__CFA_NO_STATISTICS__)
     698                __cfaabi_tls.this_stats->ready.threads.preempt.yield++;
     699        #endif
    682700
    683701        force_yield( __ALARM_PREEMPTION ); // Do the actual __cfactx_switch
  • libcfa/src/concurrency/ready_queue.cfa

    r97c215f rf5a51db  
    201201uint_fast32_t ready_mutate_lock( void ) with(*__scheduler_lock) {
    202202        /* paranoid */ verify( ! __preemption_enabled() );
    203         /* paranoid */ verify( ! kernelTLS().sched_lock );
    204203
    205204        // Step 1 : lock global lock
     
    207206        //   to simply lock their own lock and enter.
    208207        __atomic_acquire( &write_lock );
     208
     209        // Make sure we won't deadlock ourself
     210        // Checking before acquiring the writer lock isn't safe
     211        // because someone else could have locked us.
     212        /* paranoid */ verify( ! kernelTLS().sched_lock );
    209213
    210214        // Step 2 : lock per-proc lock
  • libcfa/src/concurrency/stats.cfa

    r97c215f rf5a51db  
    2929                stats->ready.threads.threads   = 0;
    3030                stats->ready.threads.cthreads  = 0;
     31                stats->ready.threads.preempt.yield  = 0;
     32                stats->ready.threads.preempt.rllfwd = 0;
    3133                stats->ready.sleep.halts   = 0;
    3234                stats->ready.sleep.cancels = 0;
     35                stats->ready.sleep.early   = 0;
    3336                stats->ready.sleep.wakes   = 0;
     37                stats->ready.sleep.seen    = 0;
    3438                stats->ready.sleep.exits   = 0;
    3539
     
    4347                        stats->io.submit.slow       = 0;
    4448                        stats->io.flush.external    = 0;
     49                        stats->io.flush.dirty       = 0;
     50                        stats->io.flush.full        = 0;
     51                        stats->io.flush.idle        = 0;
     52                        stats->io.flush.eager       = 0;
    4553                        stats->io.calls.flush       = 0;
    4654                        stats->io.calls.submitted   = 0;
     
    7179
    7280        void __tally_stats( struct __stats_t * cltr, struct __stats_t * proc ) {
    73                 tally_one( &cltr->ready.push.local.attempt, &proc->ready.push.local.attempt );
    74                 tally_one( &cltr->ready.push.local.success, &proc->ready.push.local.success );
    75                 tally_one( &cltr->ready.push.share.attempt, &proc->ready.push.share.attempt );
    76                 tally_one( &cltr->ready.push.share.success, &proc->ready.push.share.success );
    77                 tally_one( &cltr->ready.push.extrn.attempt, &proc->ready.push.extrn.attempt );
    78                 tally_one( &cltr->ready.push.extrn.success, &proc->ready.push.extrn.success );
    79                 tally_one( &cltr->ready.pop.local .attempt, &proc->ready.pop.local .attempt );
    80                 tally_one( &cltr->ready.pop.local .success, &proc->ready.pop.local .success );
    81                 tally_one( &cltr->ready.pop.help  .attempt, &proc->ready.pop.help  .attempt );
    82                 tally_one( &cltr->ready.pop.help  .success, &proc->ready.pop.help  .success );
    83                 tally_one( &cltr->ready.pop.steal .attempt, &proc->ready.pop.steal .attempt );
    84                 tally_one( &cltr->ready.pop.steal .success, &proc->ready.pop.steal .success );
    85                 tally_one( &cltr->ready.pop.search.attempt, &proc->ready.pop.search.attempt );
    86                 tally_one( &cltr->ready.pop.search.success, &proc->ready.pop.search.success );
    87                 tally_one( &cltr->ready.threads.migration , &proc->ready.threads.migration  );
    88                 tally_one( &cltr->ready.threads.extunpark , &proc->ready.threads.extunpark  );
    89                 tally_one( &cltr->ready.threads.threads   , &proc->ready.threads.threads    );
    90                 tally_one( &cltr->ready.threads.cthreads  , &proc->ready.threads.cthreads   );
    91                 tally_one( &cltr->ready.sleep.halts       , &proc->ready.sleep.halts        );
    92                 tally_one( &cltr->ready.sleep.cancels     , &proc->ready.sleep.cancels      );
    93                 tally_one( &cltr->ready.sleep.wakes       , &proc->ready.sleep.wakes        );
    94                 tally_one( &cltr->ready.sleep.exits       , &proc->ready.sleep.exits        );
     81                tally_one( &cltr->ready.push.local.attempt    , &proc->ready.push.local.attempt     );
     82                tally_one( &cltr->ready.push.local.success    , &proc->ready.push.local.success     );
     83                tally_one( &cltr->ready.push.share.attempt    , &proc->ready.push.share.attempt     );
     84                tally_one( &cltr->ready.push.share.success    , &proc->ready.push.share.success     );
     85                tally_one( &cltr->ready.push.extrn.attempt    , &proc->ready.push.extrn.attempt     );
     86                tally_one( &cltr->ready.push.extrn.success    , &proc->ready.push.extrn.success     );
     87                tally_one( &cltr->ready.pop.local .attempt    , &proc->ready.pop.local .attempt     );
     88                tally_one( &cltr->ready.pop.local .success    , &proc->ready.pop.local .success     );
     89                tally_one( &cltr->ready.pop.help  .attempt    , &proc->ready.pop.help  .attempt     );
     90                tally_one( &cltr->ready.pop.help  .success    , &proc->ready.pop.help  .success     );
     91                tally_one( &cltr->ready.pop.steal .attempt    , &proc->ready.pop.steal .attempt     );
     92                tally_one( &cltr->ready.pop.steal .success    , &proc->ready.pop.steal .success     );
     93                tally_one( &cltr->ready.pop.search.attempt    , &proc->ready.pop.search.attempt     );
     94                tally_one( &cltr->ready.pop.search.success    , &proc->ready.pop.search.success     );
     95                tally_one( &cltr->ready.threads.migration     , &proc->ready.threads.migration      );
     96                tally_one( &cltr->ready.threads.extunpark     , &proc->ready.threads.extunpark      );
     97                tally_one( &cltr->ready.threads.threads       , &proc->ready.threads.threads        );
     98                tally_one( &cltr->ready.threads.cthreads      , &proc->ready.threads.cthreads       );
     99                tally_one( &cltr->ready.threads.preempt.yield , &proc->ready.threads.preempt.yield  );
     100                tally_one( &cltr->ready.threads.preempt.rllfwd, &proc->ready.threads.preempt.rllfwd );
     101                tally_one( &cltr->ready.sleep.halts           , &proc->ready.sleep.halts            );
     102                tally_one( &cltr->ready.sleep.cancels         , &proc->ready.sleep.cancels          );
     103                tally_one( &cltr->ready.sleep.early           , &proc->ready.sleep.early            );
     104                tally_one( &cltr->ready.sleep.wakes           , &proc->ready.sleep.wakes            );
     105                tally_one( &cltr->ready.sleep.seen            , &proc->ready.sleep.wakes            );
     106                tally_one( &cltr->ready.sleep.exits           , &proc->ready.sleep.exits            );
    95107
    96108                #if defined(CFA_HAVE_LINUX_IO_URING_H)
     
    103115                        tally_one( &cltr->io.submit.slow      , &proc->io.submit.slow       );
    104116                        tally_one( &cltr->io.flush.external   , &proc->io.flush.external    );
     117                        tally_one( &cltr->io.flush.dirty      , &proc->io.flush.dirty       );
     118                        tally_one( &cltr->io.flush.full       , &proc->io.flush.full        );
     119                        tally_one( &cltr->io.flush.idle       , &proc->io.flush.idle        );
     120                        tally_one( &cltr->io.flush.eager      , &proc->io.flush.eager       );
    105121                        tally_one( &cltr->io.calls.flush      , &proc->io.calls.flush       );
    106122                        tally_one( &cltr->io.calls.submitted  , &proc->io.calls.submitted   );
     
    153169                             | " (" | eng3(ready.pop.search.attempt) | " try)";
    154170
    155                         sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel," | eng3(ready.sleep.wakes) | "wake," | eng3(ready.sleep.exits) | "exit";
     171                        sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel,"
     172                             | eng3(ready.sleep.wakes + ready.sleep.early) | '(' | eng3(ready.sleep.early) | ',' | eng3(ready.sleep.seen) | ')' | " wake(early, seen),"
     173                             | eng3(ready.sleep.exits) | "exit";
     174                        sstr | "- Preemption : " | eng3(ready.threads.preempt.yield) | "yields," | eng3(ready.threads.preempt.rllfwd) | "delayed";
    156175                        sstr | nl;
    157176                }
     
    178197                                if(io.alloc.fail || io.alloc.revoke || io.alloc.block)
    179198                                        sstr | "-     failures      : " | eng3(io.alloc.fail) | "oom, " | eng3(io.alloc.revoke) | "rvk, " | eng3(io.alloc.block) | "blk";
    180                                 if(io.flush.external)
    181                                         sstr | "- flush external    : " | eng3(io.flush.external);
     199                                // if(io.flush.external)
     200                                //      sstr | "- flush external    : " | eng3(io.flush.external);
    182201
    183202                                double avgsubs = ((double)io.calls.submitted) / io.calls.flush;
    184203                                double avgcomp = ((double)io.calls.completed) / io.calls.drain;
    185204                                sstr | "- syscll : "
    186                                      |   " sub " | eng3(io.calls.flush) | "/" | eng3(io.calls.submitted) | "(" | ws(3, 3, avgsubs) | "/flush)"
    187                                      | " - cmp " | eng3(io.calls.drain) | "/" | eng3(io.calls.completed) | "(" | ws(3, 3, avgcomp) | "/drain)"
     205                                     |   " sub " | eng3(io.calls.submitted) | "/" | eng3(io.calls.flush) | "(" | ws(3, 3, avgsubs) | "/flush)"
     206                                     | " - cmp " | eng3(io.calls.completed) | "/" | eng3(io.calls.drain) | "(" | ws(3, 3, avgcomp) | "/drain)"
    188207                                     | " - " | eng3(io.calls.errors.busy) | " EBUSY";
     208                                sstr | " - sub: " | eng3(io.flush.full) | "full, " | eng3(io.flush.dirty) | "drty, " | eng3(io.flush.idle) | "idle, " | eng3(io.flush.eager) | "eagr, " | eng3(io.flush.external) | "ext";
    189209                                sstr | "- ops blk: "
    190210                                     |   " sk rd: " | eng3(io.ops.sockread)  | "epll: " | eng3(io.ops.epllread)
  • libcfa/src/concurrency/stats.hfa

    r97c215f rf5a51db  
    6565                        volatile  int64_t threads;  // number of threads in the system, includes only local change
    6666                        volatile  int64_t cthreads; // number of threads in the system, includes only local change
     67                        struct {
     68                                volatile uint64_t yield;
     69                                volatile uint64_t rllfwd;
     70                        } preempt;
    6771                } threads;
    6872                struct {
    6973                        volatile uint64_t halts;
    7074                        volatile uint64_t cancels;
     75                        volatile uint64_t early;
    7176                        volatile uint64_t wakes;
     77                        volatile uint64_t seen;
    7278                        volatile uint64_t exits;
    7379                } sleep;
     
    8995                        struct {
    9096                                volatile uint64_t external;
     97                                volatile uint64_t dirty;
     98                                volatile uint64_t full;
     99                                volatile uint64_t idle;
     100                                volatile uint64_t eager;
    91101                        } flush;
    92102                        struct {
  • libcfa/src/stdhdr/pthread.h

    r97c215f rf5a51db  
    1010// Created On       : Wed Jun 16 13:39:06 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 16 13:39:42 2021
    13 // Update Count     : 1
     12// Last Modified On : Thu Feb  3 21:53:26 2022
     13// Update Count     : 13
    1414//
    1515
     16// pthread.h and setjmp.h cannot agree on the type of __sigsetjmp:
     17//
     18//   extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__));
     19//   extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__));
     20//
     21// With -Wall, gcc-11 warns about the disagreement unless the CPP directive
     22//
     23//    # 1 "/usr/include/pthread.h" 1 3 4
     24//
     25// appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the
     26// batchtest fails because of the spurious warning message. Hence, the warning is elided.
     27
    1628extern "C" {
     29#if defined(__GNUC__) && __GNUC__ == 11
     30        #pragma GCC diagnostic push
     31        #pragma GCC diagnostic ignored "-Warray-parameter"
     32#endif // defined(__GNUC__) && __GNUC__ == 11
     33
    1734#include_next <pthread.h>                                                               // has internal check for multiple expansion
     35
     36#if defined(__GNUC__) && __GNUC__ == 11
     37        #pragma GCC diagnostic pop
     38#endif // defined(__GNUC__) && __GNUC__ == 11
    1839} // extern "C"
    1940
    2041// Local Variables: //
    21 // tab-width: 4 //
    2242// mode: c++ //
    23 // compile-command: "make install" //
    2443// End: //
  • libcfa/src/stdhdr/setjmp.h

    r97c215f rf5a51db  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul  5 20:38:33 2016
    13 // Update Count     : 12
     12// Last Modified On : Thu Feb  3 21:53:28 2022
     13// Update Count     : 18
    1414//
    1515
     16// pthread.h and setjmp.h cannot agree on the type of __sigsetjmp:
     17//
     18//   extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__));
     19//   extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__));
     20//
     21// With -Wall, gcc-11 warns about the disagreement unless the CPP directive
     22//
     23//    # 1 "/usr/include/pthread.h" 1 3 4
     24//
     25// appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the
     26// batchtest fails because of the spurious warning message. Hence, the warning is elided.
     27
    1628extern "C" {
     29#if defined(__GNUC__) && __GNUC__ == 11
     30        #pragma GCC diagnostic push
     31        #pragma GCC diagnostic ignored "-Warray-parameter"
     32#endif // defined(__GNUC__) && __GNUC__ == 11
     33
    1734#include_next <setjmp.h>                                                                // has internal check for multiple expansion
     35
     36#if defined(__GNUC__) && __GNUC__ == 11
     37        #pragma GCC diagnostic pop
     38#endif // defined(__GNUC__) && __GNUC__ == 11
    1839} // extern "C"
    1940
    2041// Local Variables: //
    21 // tab-width: 4 //
    2242// mode: c++ //
    23 // compile-command: "make install" //
    2443// End: //
Note: See TracChangeset for help on using the changeset viewer.