Changes in / [f681823:c26b98c4]
- Files:
-
- 8 edited
-
libcfa/src/concurrency/kernel.cfa (modified) (7 diffs)
-
libcfa/src/concurrency/kernel.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/kernel/startup.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/mutex_stmt.hfa (modified) (1 diff)
-
libcfa/src/concurrency/stats.cfa (modified) (3 diffs)
-
libcfa/src/concurrency/stats.hfa (modified) (1 diff)
-
tests/concurrent/mutexstmt/.expect/locks.txt (modified) (1 diff)
-
tests/concurrent/mutexstmt/locks.cfa (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
rf681823 rc26b98c4 205 205 // Don't block if we are done 206 206 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 207 211 208 212 // Push self to idle stack … … 728 732 // Wake a thread from the front if there are any 729 733 static 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 730 748 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 772 760 773 761 /* paranoid */ verify( ready_schedule_islocked() ); … … 782 770 783 771 __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this); 784 785 this->idle_wctx.fd = 1;786 772 787 773 eventfd_t val; … … 793 779 794 780 static void idle_sleep(processor * this, io_future_t & future, iovec & iov) { 795 // Tell everyone we are ready to go do sleep796 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 sleep803 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 nap805 break;806 }807 }808 809 810 781 #if !defined(CFA_WITH_IO_URING_IDLE) 811 782 #if !defined(__CFA_NO_STATISTICS__) … … 854 825 855 826 static bool mark_idle(__cluster_proc_list & this, processor & proc) { 856 #if !defined(__CFA_NO_STATISTICS__)857 __tls_stats()->ready.sleep.halts++;858 #endif859 860 proc.idle_wctx.fd = 0;861 862 827 /* paranoid */ verify( ! __preemption_enabled() ); 863 828 if(!try_lock( this )) return false; … … 867 832 insert_first(this.idles, proc); 868 833 869 __atomic_store_n(&this.fd w, &proc.idle_wctx, __ATOMIC_SEQ_CST);834 __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST); 870 835 unlock( this ); 871 836 /* paranoid */ verify( ! __preemption_enabled() ); … … 883 848 884 849 { 885 struct __fd_waitctx * wctx= 0;886 if(!this.idles`isEmpty) wctx = &this.idles`first.idle_wctx;887 __atomic_store_n(&this.fd w, 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); 888 853 } 889 854 -
libcfa/src/concurrency/kernel.hfa
rf681823 rc26b98c4 53 53 coroutine processorCtx_t { 54 54 struct processor * proc; 55 };56 57 58 struct __fd_waitctx {59 volatile int fd;60 55 }; 61 56 … … 106 101 int idle_fd; 107 102 108 // Idle waitctx109 struct __fd_waitctx idle_wctx;110 111 103 // Termination synchronisation (user semaphore) 112 104 oneshot terminated; … … 215 207 216 208 // FD to use to wake a processor 217 struct __fd_waitctx * volatile fdw;209 volatile int fd; 218 210 219 211 // Total number of processors -
libcfa/src/concurrency/kernel/startup.cfa
rf681823 rc26b98c4 537 537 } 538 538 539 this.idle_wctx.fd = 0;540 541 // I'm assuming these two are reserved for standard input and output542 // 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 546 539 #if !defined(__CFA_NO_STATISTICS__) 547 540 print_stats = 0; … … 597 590 // Cluster 598 591 static void ?{}(__cluster_proc_list & this) { 599 this.fd w = 0p;592 this.fd = 0; 600 593 this.idle = 0; 601 594 this.total = 0; -
libcfa/src/concurrency/mutex_stmt.hfa
rf681823 rc26b98c4 38 38 } 39 39 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 53 40 static inline L * __get_ptr( L & this ) { 54 41 return &this; -
libcfa/src/concurrency/stats.cfa
rf681823 rc26b98c4 31 31 stats->ready.sleep.halts = 0; 32 32 stats->ready.sleep.cancels = 0; 33 stats->ready.sleep.early = 0;34 33 stats->ready.sleep.wakes = 0; 35 stats->ready.sleep.seen = 0;36 34 stats->ready.sleep.exits = 0; 37 35 … … 93 91 tally_one( &cltr->ready.sleep.halts , &proc->ready.sleep.halts ); 94 92 tally_one( &cltr->ready.sleep.cancels , &proc->ready.sleep.cancels ); 95 tally_one( &cltr->ready.sleep.early , &proc->ready.sleep.early );96 93 tally_one( &cltr->ready.sleep.wakes , &proc->ready.sleep.wakes ); 97 tally_one( &cltr->ready.sleep.seen , &proc->ready.sleep.wakes );98 94 tally_one( &cltr->ready.sleep.exits , &proc->ready.sleep.exits ); 99 95 … … 157 153 | " (" | eng3(ready.pop.search.attempt) | " try)"; 158 154 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"; 162 156 sstr | nl; 163 157 } -
libcfa/src/concurrency/stats.hfa
rf681823 rc26b98c4 69 69 volatile uint64_t halts; 70 70 volatile uint64_t cancels; 71 volatile uint64_t early;72 71 volatile uint64_t wakes; 73 volatile uint64_t seen;74 72 volatile uint64_t exits; 75 73 } sleep; -
tests/concurrent/mutexstmt/.expect/locks.txt
rf681823 rc26b98c4 3 3 Start Test: multi lock deadlock/mutual exclusion 4 4 End Test: multi lock deadlock/mutual exclusion 5 Start Test: single scoped lock mutual exclusion6 End Test: single scoped lock mutual exclusion7 Start Test: multi scoped lock deadlock/mutual exclusion8 End Test: multi scoped lock deadlock/mutual exclusion -
tests/concurrent/mutexstmt/locks.cfa
rf681823 rc26b98c4 59 59 } 60 60 61 thread T_Mutex_Scoped {};62 61 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;132 62 int main() { 133 63 processor p[10]; … … 137 67 T_Mutex t[10]; 138 68 } 139 assert(count == num_tasks * num_times);140 69 printf("End Test: single lock mutual exclusion\n"); 141 70 printf("Start Test: multi lock deadlock/mutual exclusion\n"); … … 144 73 } 145 74 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");159 75 }
Note:
See TracChangeset
for help on using the changeset viewer.