Changes in / [f681823:c26b98c4]


Ignore:
Files:
8 edited

Legend:

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

    rf681823 rc26b98c4  
    205205                                // Don't block if we are done
    206206                                if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;
     207
     208                                #if !defined(__CFA_NO_STATISTICS__)
     209                                        __tls_stats()->ready.sleep.halts++;
     210                                #endif
    207211
    208212                                // Push self to idle stack
     
    728732// Wake a thread from the front if there are any
    729733static void __wake_one(cluster * this) {
     734        /* paranoid */ verify( ! __preemption_enabled() );
     735        /* paranoid */ verify( ready_schedule_islocked() );
     736
     737        // 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
    730748        eventfd_t val;
    731 
    732         /* paranoid */ verify( ! __preemption_enabled() );
    733         /* paranoid */ verify( ready_schedule_islocked() );
    734 
    735         // Check if there is a sleeping processor
    736         struct __fd_waitctx * fdp = __atomic_load_n(&this->procs.fdw, __ATOMIC_SEQ_CST);
    737 
    738         // If no one is sleeping: we are done
    739         if( fdp == 0p ) return;
    740 
    741         int fd = 1;
    742         if( __atomic_load_n(&fdp->fd, __ATOMIC_SEQ_CST) != 1 ) {
    743                 fd = __atomic_exchange_n(&fdp->fd, 1, __ATOMIC_RELAXED);
    744         }
    745 
    746         switch(fd) {
    747         case 0:
    748                 // If the processor isn't ready to sleep then the exchange will already wake it up
    749                 #if !defined(__CFA_NO_STATISTICS__)
    750                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.early++;
    751                         } else { __atomic_fetch_add(&this->stats->ready.sleep.early, 1, __ATOMIC_RELAXED); }
    752                 #endif
    753                 break;
    754         case 1:
    755                 // If someone else already said they will wake them: we are done
    756                 #if !defined(__CFA_NO_STATISTICS__)
    757                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.seen++;
    758                         } else { __atomic_fetch_add(&this->stats->ready.sleep.seen, 1, __ATOMIC_RELAXED); }
    759                 #endif
    760                 break;
    761         default:
    762                 // If the processor was ready to sleep, we need to wake it up with an actual write
    763                 val = 1;
    764                 eventfd_write( fd, val );
    765 
    766                 #if !defined(__CFA_NO_STATISTICS__)
    767                         if( kernelTLS().this_stats ) { __tls_stats()->ready.sleep.wakes++;
    768                         } else { __atomic_fetch_add(&this->stats->ready.sleep.wakes, 1, __ATOMIC_RELAXED); }
    769                 #endif
    770                 break;
    771         }
     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
    772760
    773761        /* paranoid */ verify( ready_schedule_islocked() );
     
    782770
    783771        __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
    784 
    785         this->idle_wctx.fd = 1;
    786772
    787773        eventfd_t val;
     
    793779
    794780static void idle_sleep(processor * this, io_future_t & future, iovec & iov) {
    795         // Tell everyone we are ready to go do sleep
    796         for() {
    797                 int expected = this->idle_wctx.fd;
    798 
    799                 // Someone already told us to wake-up! No time for a nap.
    800                 if(expected == 1) { return; }
    801 
    802                 // Try to mark that we are going to sleep
    803                 if(__atomic_compare_exchange_n(&this->idle_wctx.fd, &expected, this->idle_fd, false,  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
    804                         // Every one agreed, taking a nap
    805                         break;
    806                 }
    807         }
    808 
    809 
    810781        #if !defined(CFA_WITH_IO_URING_IDLE)
    811782                #if !defined(__CFA_NO_STATISTICS__)
     
    854825
    855826static bool mark_idle(__cluster_proc_list & this, processor & proc) {
    856         #if !defined(__CFA_NO_STATISTICS__)
    857                 __tls_stats()->ready.sleep.halts++;
    858         #endif
    859 
    860         proc.idle_wctx.fd = 0;
    861 
    862827        /* paranoid */ verify( ! __preemption_enabled() );
    863828        if(!try_lock( this )) return false;
     
    867832                insert_first(this.idles, proc);
    868833
    869                 __atomic_store_n(&this.fdw, &proc.idle_wctx, __ATOMIC_SEQ_CST);
     834                __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST);
    870835        unlock( this );
    871836        /* paranoid */ verify( ! __preemption_enabled() );
     
    883848
    884849                {
    885                         struct __fd_waitctx * wctx = 0;
    886                         if(!this.idles`isEmpty) wctx = &this.idles`first.idle_wctx;
    887                         __atomic_store_n(&this.fdw, wctx, __ATOMIC_SEQ_CST);
     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);
    888853                }
    889854
  • libcfa/src/concurrency/kernel.hfa

    rf681823 rc26b98c4  
    5353coroutine processorCtx_t {
    5454        struct processor * proc;
    55 };
    56 
    57 
    58 struct __fd_waitctx {
    59         volatile int fd;
    6055};
    6156
     
    106101        int idle_fd;
    107102
    108         // Idle waitctx
    109         struct __fd_waitctx idle_wctx;
    110 
    111103        // Termination synchronisation (user semaphore)
    112104        oneshot terminated;
     
    215207
    216208        // FD to use to wake a processor
    217         struct __fd_waitctx * volatile fdw;
     209        volatile int fd;
    218210
    219211        // Total number of processors
  • libcfa/src/concurrency/kernel/startup.cfa

    rf681823 rc26b98c4  
    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 
    546539        #if !defined(__CFA_NO_STATISTICS__)
    547540                print_stats = 0;
     
    597590// Cluster
    598591static void ?{}(__cluster_proc_list & this) {
    599         this.fdw   = 0p;
     592        this.fd    = 0;
    600593        this.idle  = 0;
    601594        this.total = 0;
  • libcfa/src/concurrency/mutex_stmt.hfa

    rf681823 rc26b98c4  
    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 
    5340    static inline L * __get_ptr( L & this ) {
    5441        return &this;
  • libcfa/src/concurrency/stats.cfa

    rf681823 rc26b98c4  
    3131                stats->ready.sleep.halts   = 0;
    3232                stats->ready.sleep.cancels = 0;
    33                 stats->ready.sleep.early   = 0;
    3433                stats->ready.sleep.wakes   = 0;
    35                 stats->ready.sleep.seen    = 0;
    3634                stats->ready.sleep.exits   = 0;
    3735
     
    9391                tally_one( &cltr->ready.sleep.halts       , &proc->ready.sleep.halts        );
    9492                tally_one( &cltr->ready.sleep.cancels     , &proc->ready.sleep.cancels      );
    95                 tally_one( &cltr->ready.sleep.early       , &proc->ready.sleep.early        );
    9693                tally_one( &cltr->ready.sleep.wakes       , &proc->ready.sleep.wakes        );
    97                 tally_one( &cltr->ready.sleep.seen        , &proc->ready.sleep.wakes        );
    9894                tally_one( &cltr->ready.sleep.exits       , &proc->ready.sleep.exits        );
    9995
     
    157153                             | " (" | eng3(ready.pop.search.attempt) | " try)";
    158154
    159                         sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel,"
    160                              | eng3(ready.sleep.wakes + ready.sleep.early) | '(' | eng3(ready.sleep.early) | ',' | eng3(ready.sleep.seen) | ')' | " wake(early, seen),"
    161                              | eng3(ready.sleep.exits) | "exit";
     155                        sstr | "- Idle Slp : " | eng3(ready.sleep.halts) | "halt," | eng3(ready.sleep.cancels) | "cancel," | eng3(ready.sleep.wakes) | "wake," | eng3(ready.sleep.exits) | "exit";
    162156                        sstr | nl;
    163157                }
  • libcfa/src/concurrency/stats.hfa

    rf681823 rc26b98c4  
    6969                        volatile uint64_t halts;
    7070                        volatile uint64_t cancels;
    71                         volatile uint64_t early;
    7271                        volatile uint64_t wakes;
    73                         volatile uint64_t seen;
    7472                        volatile uint64_t exits;
    7573                } sleep;
  • tests/concurrent/mutexstmt/.expect/locks.txt

    rf681823 rc26b98c4  
    33Start Test: multi lock deadlock/mutual exclusion
    44End Test: multi lock deadlock/mutual exclusion
    5 Start Test: single scoped lock mutual exclusion
    6 End Test: single scoped lock mutual exclusion
    7 Start Test: multi scoped lock deadlock/mutual exclusion
    8 End Test: multi scoped lock deadlock/mutual exclusion
  • tests/concurrent/mutexstmt/locks.cfa

    rf681823 rc26b98c4  
    5959}
    6060
    61 thread T_Mutex_Scoped {};
    6261
    63 void main( T_Mutex_Scoped & this ) {
    64         for (unsigned int i = 0; i < num_times; i++) {
    65                 {
    66                         scoped_lock(single_acquisition_lock) s{m1};
    67                         count++;
    68                 }
    69                 {
    70                         scoped_lock(single_acquisition_lock) s{m1};
    71                         assert(!insideFlag);
    72                         insideFlag = true;
    73                         assert(insideFlag);
    74                         insideFlag = false;
    75                 }
    76         }
    77 }
    78 
    79 thread T_Multi_Scoped {};
    80 
    81 void main( T_Multi_Scoped & this ) {
    82         for (unsigned int i = 0; i < num_times; i++) {
    83                 {
    84                         scoped_lock(single_acquisition_lock) s{m1};
    85                         assert(!insideFlag);
    86                         insideFlag = true;
    87                         assert(insideFlag);
    88                         insideFlag = false;
    89                 }
    90                 {
    91                         scoped_lock(single_acquisition_lock) s1{m1};
    92                         scoped_lock(single_acquisition_lock) s2{m2};
    93                         scoped_lock(single_acquisition_lock) s3{m3};
    94                         scoped_lock(single_acquisition_lock) s4{m4};
    95                         scoped_lock(single_acquisition_lock) s5{m5};
    96                         assert(!insideFlag);
    97                         insideFlag = true;
    98                         assert(insideFlag);
    99                         insideFlag = false;
    100                 }
    101                 {
    102                         scoped_lock(single_acquisition_lock) s1{m1};
    103                         scoped_lock(single_acquisition_lock) s3{m3};
    104                         assert(!insideFlag);
    105                         insideFlag = true;
    106                         assert(insideFlag);
    107                         insideFlag = false;
    108                 }
    109                 {
    110                         scoped_lock(single_acquisition_lock) s1{m1};
    111                         scoped_lock(single_acquisition_lock) s2{m2};
    112                         scoped_lock(single_acquisition_lock) s4{m4};
    113                         assert(!insideFlag);
    114                         insideFlag = true;
    115                         assert(insideFlag);
    116                         insideFlag = false;
    117                 }
    118                 {
    119                         scoped_lock(single_acquisition_lock) s1{m1};
    120                         scoped_lock(single_acquisition_lock) s3{m3};
    121                         scoped_lock(single_acquisition_lock) s4{m4};
    122                         scoped_lock(single_acquisition_lock) s5{m5};
    123                         assert(!insideFlag);
    124                         insideFlag = true;
    125                         assert(insideFlag);
    126                         insideFlag = false;
    127                 }
    128         }
    129 }
    130 
    131 int num_tasks = 10;
    13262int main() {
    13363        processor p[10];
     
    13767                T_Mutex t[10];
    13868        }
    139         assert(count == num_tasks * num_times);
    14069        printf("End Test: single lock mutual exclusion\n");
    14170        printf("Start Test: multi lock deadlock/mutual exclusion\n");
     
    14473        }
    14574        printf("End Test: multi lock deadlock/mutual exclusion\n");
    146        
    147         count = 0;
    148         printf("Start Test: single scoped lock mutual exclusion\n");
    149         {
    150                 T_Mutex_Scoped t[10];
    151         }
    152         assert(count == num_tasks * num_times);
    153         printf("End Test: single scoped lock mutual exclusion\n");
    154         printf("Start Test: multi scoped lock deadlock/mutual exclusion\n");
    155         {
    156                 T_Multi_Scoped t[10];
    157         }
    158         printf("End Test: multi scoped lock deadlock/mutual exclusion\n");     
    15975}
Note: See TracChangeset for help on using the changeset viewer.