Changeset 05cfa4d


Ignore:
Timestamp:
May 5, 2020, 4:53:14 PM (17 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
b1ac7dd
Parents:
6e33a2d
Message:
  • Added 'fix' of the deadlock on cluster destruction by taking preempted threads and pretending they were blocked.
  • Added statistics for when submition blocked to obtain an sqe.
File:
1 edited

Legend:

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

    r6e33a2d r05cfa4d  
    141141                        struct {
    142142                                struct {
    143                                         unsigned long long int val;
    144                                         unsigned long long int cnt;
     143                                        volatile unsigned long long int val;
     144                                        volatile unsigned long long int cnt;
     145                                        volatile unsigned long long int block;
    145146                                } submit_avg;
    146147                        } stats;
     
    303304                // Initialize statistics
    304305                #if !defined(__CFA_NO_STATISTICS__)
    305                         this.io->submit_q.stats.submit_avg.val = 0;
    306                         this.io->submit_q.stats.submit_avg.cnt = 0;
     306                        this.io->submit_q.stats.submit_avg.val   = 0;
     307                        this.io->submit_q.stats.submit_avg.cnt   = 0;
     308                        this.io->submit_q.stats.submit_avg.block = 0;
    307309                        this.io->completion_q.stats.completed_avg.val = 0;
    308310                        this.io->completion_q.stats.completed_avg.slow_cnt = 0;
     
    344346
    345347                if( this.io->cltr_flags & CFA_CLUSTER_IO_POLLER_USER_THREAD ) {
    346                         verify( this.io->poller.fast.waiting );
    347                         verify( this.io->poller.fast.thrd.state == Blocked );
    348 
    349                         this.io->poller.fast.thrd.curr_cluster = mainCluster;
     348                        with( this.io->poller.fast ) {
     349                                /* paranoid */ verify( waiting ); // The thread shouldn't be in a system call
     350                                /* paranoid */ verify( this.procs.head == 0p || &this == mainCluster );
     351                                /* paranoid */ verify( this.idles.head == 0p || &this == mainCluster );
     352
     353                                // We need to adjust the clean-up based on where the thread is
     354                                if( thrd.preempted != __NO_PREEMPTION ) {
     355
     356                                        // This is the tricky case
     357                                        // The thread was preempted and now it is on the ready queue
     358                                        /* paranoid */ verify( thrd.state == Active );           // The thread better be in this state
     359                                        /* paranoid */ verify( thrd.next == 1p );                // The thread should be the last on the list
     360                                        /* paranoid */ verify( this.ready_queue.head == &thrd ); // The thread should be the only thing on the list
     361
     362                                        // Remove the thread from the ready queue of this cluster
     363                                        this.ready_queue.head = 1p;
     364                                        thrd.next = 0p;
     365
     366                                        // Fixup the thread state
     367                                        thrd.state = Blocked;
     368                                        thrd.preempted = __NO_PREEMPTION;
     369
     370                                        // Pretend like the thread was blocked all along
     371                                }
     372                                // !!! This is not an else if !!!
     373                                if( thrd.state == Blocked ) {
     374
     375                                        // This is the "easy case"
     376                                        // The thread is parked and can easily be moved to active cluster
     377                                        verify( thrd.curr_cluster != active_cluster() || thrd.curr_cluster == mainCluster );
     378                                        thrd.curr_cluster = active_cluster();
    350379
    351380                        // unpark the fast io_poller
    352                         unpark( &this.io->poller.fast.thrd __cfaabi_dbg_ctx2 );
     381                                        unpark( &thrd __cfaabi_dbg_ctx2 );
     382                                }
     383                                else {
     384
     385                                        // The thread is in a weird state
     386                                        // I don't know what to do here
     387                                        abort("Fast poller thread is in unexpected state, cannot clean-up correctly\n");
     388                                }
     389
     390                        }
    353391
    354392                        ^(this.io->poller.fast){};
     
    369407                                        __cfaabi_bits_print_safe( STDERR_FILENO,
    370408                                                "----- I/O uRing Stats -----\n"
    371                                                 "- total submit calls  : %llu\n"
    372                                                 "- avg submit          : %lf\n"
    373                                                 "- total wait calls    : %llu (%llu slow, %llu fast)\n"
    374                                                 "- avg completion/wait : %lf\n",
     409                                                "- total submit calls  : %'llu\n"
     410                                                "- avg submit          : %'.2lf\n"
     411                                                "- pre-submit block %%  : %'.2lf\n"
     412                                                "- total wait calls    : %'llu (%'llu slow, %'llu fast)\n"
     413                                                "- avg completion/wait : %'.2lf\n",
    375414                                                submit_avg.cnt,
    376415                                                ((double)submit_avg.val) / submit_avg.cnt,
     416                                                (100.0 * submit_avg.block) / submit_avg.cnt,
    377417                                                completed_avg.slow_cnt + completed_avg.fast_cnt,
    378418                                                completed_avg.slow_cnt,  completed_avg.fast_cnt,
     
    584624        static inline [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring ) {
    585625                // Wait for a spot to be available
    586                 P(ring.submit);
     626                __attribute__((unused)) bool blocked = P(ring.submit);
     627                #if !defined(__CFA_NO_STATISTICS__)
     628                        __atomic_fetch_add( &ring.submit_q.stats.submit_avg.block, blocked ? 1ul64 : 0ul64, __ATOMIC_RELAXED );
     629                #endif
    587630
    588631                // Allocate the sqe
Note: See TracChangeset for help on using the changeset viewer.