Ignore:
File:
1 edited

Legend:

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

    ra633f6f r5f5a729  
    126126static 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 * );
     
    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__)
     
    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() );
     
    824826                remove(proc);
    825827                insert_last(this.actives, proc);
    826 
    827                 {
    828                         int fd = 0;
    829                         if(!this.idles`isEmpty) fd = this.idles`first.idle;
    830                         __atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST);
    831                 }
    832 
    833828        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() );
    834849        /* paranoid */ verify( ! __preemption_enabled() );
    835850}
     
    893908                if(head == tail) return false;
    894909                #if OLD_MAIN
    895                         ready_schedule_lock();
    896                         ret = __cfa_io_drain( proc );
    897                         ready_schedule_unlock();
     910                ready_schedule_lock();
     911                ret = __cfa_io_drain( proc );
     912                ready_schedule_unlock();
    898913                #else
    899914                        ret = __cfa_io_drain( proc );
    900                 #endif
     915        #endif
    901916        #endif
    902917        return ret;
Note: See TracChangeset for help on using the changeset viewer.