Ignore:
File:
1 edited

Legend:

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

    r34b8cb7 r5f5a729  
    124124static void __wake_one(cluster * cltr);
    125125
    126 static void mark_idle (__cluster_proc_list & idles, processor & proc);
     126static bool mark_idle (__cluster_proc_list & idles, processor & proc);
    127127static void mark_awake(__cluster_proc_list & idles, processor & proc);
     128static [unsigned idle, unsigned total, * processor] query_idles( & __cluster_proc_list idles );
    128129
    129130extern void __cfa_io_start( processor * );
     
    212213
    213214                                // Push self to idle stack
    214                                 mark_idle(this->cltr->procs, * this);
     215                                if(!mark_idle(this->cltr->procs, * this)) continue MAIN_LOOP;
    215216
    216217                                // Confirm the ready-queue is empty
     
    330331                                // Push self to idle stack
    331332                                ready_schedule_unlock();
    332                                 mark_idle(this->cltr->procs, * this);
     333                                if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;
    333334                                ready_schedule_lock();
    334335
     
    765766
    766767        // Check if there is a sleeping processor
    767         int fd = __atomic_load_n(&this->procs.fd, __ATOMIC_SEQ_CST);
     768        processor * p;
     769        unsigned idle;
     770        unsigned total;
     771        [idle, total, p] = query_idles(this->procs);
    768772
    769773        // If no one is sleeping, we are done
    770         if( fd == 0 ) return;
     774        if( idle == 0 ) return;
    771775
    772776        // We found a processor, wake it up
    773777        eventfd_t val;
    774778        val = 1;
    775         eventfd_write( fd, val );
     779        eventfd_write( p->idle, val );
    776780
    777781        #if !defined(__CFA_NO_STATISTICS__)
     
    802806}
    803807
    804 static void mark_idle(__cluster_proc_list & this, processor & proc) {
    805         /* paranoid */ verify( ! __preemption_enabled() );
    806         lock( this );
     808static bool mark_idle(__cluster_proc_list & this, processor & proc) {
     809        /* paranoid */ verify( ! __preemption_enabled() );
     810        if(!try_lock( this )) return false;
    807811                this.idle++;
    808812                /* paranoid */ verify( this.idle <= this.total );
    809813                remove(proc);
    810814                insert_first(this.idles, proc);
    811 
    812                 __atomic_store_n(&this.fd, proc.idle, __ATOMIC_SEQ_CST);
    813815        unlock( this );
    814816        /* paranoid */ verify( ! __preemption_enabled() );
     817
     818        return true;
    815819}
    816820
     
    822826                remove(proc);
    823827                insert_last(this.actives, proc);
    824 
    825                 __atomic_store_n(&this.fd, this.idles`first.idle, __ATOMIC_SEQ_CST);
    826828        unlock( this );
     829        /* paranoid */ verify( ! __preemption_enabled() );
     830}
     831
     832static [unsigned idle, unsigned total, * processor] query_idles( & __cluster_proc_list this ) {
     833        /* paranoid */ verify( ! __preemption_enabled() );
     834        /* paranoid */ verify( ready_schedule_islocked() );
     835
     836        for() {
     837                uint64_t l = __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST);
     838                if( 1 == (l % 2) ) { Pause(); continue; }
     839                unsigned idle    = this.idle;
     840                unsigned total   = this.total;
     841                processor * proc = &this.idles`first;
     842                // Compiler fence is unnecessary, but gcc-8 and older incorrectly reorder code without it
     843                asm volatile("": : :"memory");
     844                if(l != __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST)) { Pause(); continue; }
     845                return [idle, total, proc];
     846        }
     847
     848        /* paranoid */ verify( ready_schedule_islocked() );
    827849        /* paranoid */ verify( ! __preemption_enabled() );
    828850}
     
    886908                if(head == tail) return false;
    887909                #if OLD_MAIN
    888                         ready_schedule_lock();
    889                         ret = __cfa_io_drain( proc );
    890                         ready_schedule_unlock();
     910                ready_schedule_lock();
     911                ret = __cfa_io_drain( proc );
     912                ready_schedule_unlock();
    891913                #else
    892914                        ret = __cfa_io_drain( proc );
    893                 #endif
     915        #endif
    894916        #endif
    895917        return ret;
Note: See TracChangeset for help on using the changeset viewer.