Changes in / [121ac13:9f4524b]
- Location:
- src
- Files:
-
- 1 added
- 19 edited
-
benchmark/Makefile.am (modified) (3 diffs)
-
benchmark/Makefile.in (modified) (3 diffs)
-
benchmark/SchedInt.c (added)
-
benchmark/csv-data.c (modified) (4 diffs)
-
benchmark/schedint/cfa1.c (modified) (2 diffs)
-
benchmark/schedint/cfa2.c (modified) (2 diffs)
-
benchmark/schedint/cfa4.c (modified) (2 diffs)
-
libcfa/concurrency/invoke.h (modified) (2 diffs)
-
libcfa/concurrency/kernel (modified) (4 diffs)
-
libcfa/concurrency/kernel.c (modified) (11 diffs)
-
libcfa/concurrency/kernel_private.h (modified) (1 diff)
-
libcfa/concurrency/monitor (modified) (5 diffs)
-
libcfa/concurrency/monitor.c (modified) (39 diffs)
-
tests/boundedBuffer.c (modified) (3 diffs)
-
tests/datingService.c (modified) (5 diffs)
-
tests/sched-int-barge.c (modified) (2 diffs)
-
tests/sched-int-block.c (modified) (2 diffs)
-
tests/sched-int-disjoint.c (modified) (3 diffs)
-
tests/sched-int-wait.c (modified) (6 diffs)
-
tests/thread.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/benchmark/Makefile.am
r121ac13 r9f4524b 27 27 28 28 noinst_PROGRAMS = 29 30 all : ctxswitch$(EXEEXT) mutex$(EXEEXT) signal$(EXEEXT) waitfor$(EXEEXT) creation$(EXEEXT)31 29 32 30 bench$(EXEEXT) : … … 65 63 ctxswitch-pthread$(EXEEXT): 66 64 @BACKEND_CC@ ctxswitch/pthreads.c -DBENCH_N=50000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags} 65 66 ## ========================================================================================================= 67 creation$(EXEEXT) :\ 68 creation-pthread.run \ 69 creation-cfa_coroutine.run \ 70 creation-cfa_thread.run \ 71 creation-upp_coroutine.run \ 72 creation-upp_thread.run 73 74 creation-cfa_coroutine$(EXEEXT): 75 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 76 77 creation-cfa_thread$(EXEEXT): 78 ${CC} creation/cfa_thrd.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 79 80 creation-upp_coroutine$(EXEEXT): 81 u++ creation/upp_cor.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags} 82 83 creation-upp_thread$(EXEEXT): 84 u++ creation/upp_thrd.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags} 85 86 creation-pthread$(EXEEXT): 87 @BACKEND_CC@ creation/pthreads.c -DBENCH_N=250000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags} 67 88 68 89 ## ========================================================================================================= … … 132 153 133 154 ## ========================================================================================================= 134 creation$(EXEEXT) :\135 creation-pthread.run \136 creation-cfa_coroutine.run \137 creation-cfa_thread.run \138 creation-upp_coroutine.run \139 creation-upp_thread.run140 141 creation-cfa_coroutine$(EXEEXT):142 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}143 144 creation-cfa_thread$(EXEEXT):145 ${CC} creation/cfa_thrd.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}146 147 creation-upp_coroutine$(EXEEXT):148 u++ creation/upp_cor.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags}149 150 creation-upp_thread$(EXEEXT):151 u++ creation/upp_thrd.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags}152 153 creation-pthread$(EXEEXT):154 @BACKEND_CC@ creation/pthreads.c -DBENCH_N=250000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}155 156 ## =========================================================================================================157 155 158 156 %.run : %$(EXEEXT) ${REPEAT} -
src/benchmark/Makefile.in
r121ac13 r9f4524b 444 444 .NOTPARALLEL: 445 445 446 all : ctxswitch$(EXEEXT) mutex$(EXEEXT) signal$(EXEEXT) waitfor$(EXEEXT) creation$(EXEEXT)447 448 446 bench$(EXEEXT) : 449 447 @for ccflags in "-debug" "-nodebug"; do \ … … 481 479 @BACKEND_CC@ ctxswitch/pthreads.c -DBENCH_N=50000000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags} 482 480 481 creation$(EXEEXT) :\ 482 creation-pthread.run \ 483 creation-cfa_coroutine.run \ 484 creation-cfa_thread.run \ 485 creation-upp_coroutine.run \ 486 creation-upp_thread.run 487 488 creation-cfa_coroutine$(EXEEXT): 489 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 490 491 creation-cfa_thread$(EXEEXT): 492 ${CC} creation/cfa_thrd.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 493 494 creation-upp_coroutine$(EXEEXT): 495 u++ creation/upp_cor.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags} 496 497 creation-upp_thread$(EXEEXT): 498 u++ creation/upp_thrd.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags} 499 500 creation-pthread$(EXEEXT): 501 @BACKEND_CC@ creation/pthreads.c -DBENCH_N=250000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags} 502 483 503 mutex$(EXEEXT) :\ 484 504 mutex-function.run \ … … 542 562 waitfor-cfa4$(EXEEXT): 543 563 ${CC} schedext/cfa4.c -DBENCH_N=500000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 544 545 creation$(EXEEXT) :\546 creation-pthread.run \547 creation-cfa_coroutine.run \548 creation-cfa_thread.run \549 creation-upp_coroutine.run \550 creation-upp_thread.run551 552 creation-cfa_coroutine$(EXEEXT):553 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}554 555 creation-cfa_thread$(EXEEXT):556 ${CC} creation/cfa_thrd.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}557 558 creation-upp_coroutine$(EXEEXT):559 u++ creation/upp_cor.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags}560 561 creation-upp_thread$(EXEEXT):562 u++ creation/upp_thrd.cc -DBENCH_N=50000000 -I. -nodebug -lrt -quiet ${AM_CFLAGS} ${CFLAGS} ${ccflags}563 564 creation-pthread$(EXEEXT):565 @BACKEND_CC@ creation/pthreads.c -DBENCH_N=250000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags}566 564 567 565 %.run : %$(EXEEXT) ${REPEAT} -
src/benchmark/csv-data.c
r121ac13 r9f4524b 111 111 StartTime = Time(); 112 112 for( int i = 0;; i++ ) { 113 signal( cond1a);114 if( i > N ) break; 115 wait( cond1b);113 signal(&cond1a); 114 if( i > N ) break; 115 wait(&cond1b); 116 116 } 117 117 EndTime = Time(); … … 122 122 void side1B( mon_t & mutex a ) { 123 123 for( int i = 0;; i++ ) { 124 signal( cond1b);125 if( i > N ) break; 126 wait( cond1a);124 signal(&cond1b); 125 if( i > N ) break; 126 wait(&cond1a); 127 127 } 128 128 } … … 159 159 StartTime = Time(); 160 160 for( int i = 0;; i++ ) { 161 signal( cond2a);162 if( i > N ) break; 163 wait( cond2b);161 signal(&cond2a); 162 if( i > N ) break; 163 wait(&cond2b); 164 164 } 165 165 EndTime = Time(); … … 170 170 void side2B( mon_t & mutex a, mon_t & mutex b ) { 171 171 for( int i = 0;; i++ ) { 172 signal( cond2b);173 if( i > N ) break; 174 wait( cond2a);172 signal(&cond2b); 173 if( i > N ) break; 174 wait(&cond2a); 175 175 } 176 176 } -
src/benchmark/schedint/cfa1.c
r121ac13 r9f4524b 15 15 16 16 void __attribute__((noinline)) call( M & mutex a1 ) { 17 signal( c);17 signal(&c); 18 18 } 19 19 … … 22 22 BENCH( 23 23 for (size_t i = 0; i < n; i++) { 24 wait( c);24 wait(&c); 25 25 }, 26 26 result -
src/benchmark/schedint/cfa2.c
r121ac13 r9f4524b 15 15 16 16 void __attribute__((noinline)) call( M & mutex a1, M & mutex a2 ) { 17 signal( c);17 signal(&c); 18 18 } 19 19 … … 22 22 BENCH( 23 23 for (size_t i = 0; i < n; i++) { 24 wait( c);24 wait(&c); 25 25 }, 26 26 result -
src/benchmark/schedint/cfa4.c
r121ac13 r9f4524b 15 15 16 16 void __attribute__((noinline)) call( M & mutex a1, M & mutex a2, M & mutex a3, M & mutex a4 ) { 17 signal( c);17 signal(&c); 18 18 } 19 19 … … 22 22 BENCH( 23 23 for (size_t i = 0; i < n; i++) { 24 wait( c);24 wait(&c); 25 25 }, 26 26 result -
src/libcfa/concurrency/invoke.h
r121ac13 r9f4524b 25 25 #define _INVOKE_H_ 26 26 27 #define unlikely(x) __builtin_expect(!!(x), 0)28 #define thread_local _Thread_local27 #define unlikely(x) __builtin_expect(!!(x), 0) 28 #define thread_local _Thread_local 29 29 30 typedef void (*fptr_t)(); 31 typedef int_fast16_t __lock_size_t; 30 typedef void (*fptr_t)(); 32 31 33 struct spinlock {34 volatile int lock;35 #ifdef __CFA_DEBUG__36 const char * prev_name;37 void* prev_thrd;38 #endif39 };32 struct spinlock { 33 volatile int lock; 34 #ifdef __CFA_DEBUG__ 35 const char * prev_name; 36 void* prev_thrd; 37 #endif 38 }; 40 39 41 struct __thread_queue_t {42 struct thread_desc * head;43 struct thread_desc ** tail;44 };40 struct __thread_queue_t { 41 struct thread_desc * head; 42 struct thread_desc ** tail; 43 }; 45 44 46 struct __condition_stack_t {47 struct __condition_criterion_t * top;48 };45 struct __condition_stack_t { 46 struct __condition_criterion_t * top; 47 }; 49 48 50 #ifdef __CFORALL__51 extern "Cforall" {52 void ?{}( struct __thread_queue_t & );53 void append( struct __thread_queue_t &, struct thread_desc * );54 struct thread_desc * pop_head( struct __thread_queue_t &);55 struct thread_desc * remove( struct __thread_queue_t &, struct thread_desc ** );49 #ifdef __CFORALL__ 50 extern "Cforall" { 51 void ?{}( struct __thread_queue_t & ); 52 void append( struct __thread_queue_t *, struct thread_desc * ); 53 struct thread_desc * pop_head( struct __thread_queue_t * ); 54 struct thread_desc * remove( struct __thread_queue_t *, struct thread_desc ** ); 56 55 57 void ?{}( struct __condition_stack_t & );58 void push( struct __condition_stack_t &, struct __condition_criterion_t * );59 struct __condition_criterion_t * pop( struct __condition_stack_t &);56 void ?{}( struct __condition_stack_t & ); 57 void push( struct __condition_stack_t *, struct __condition_criterion_t * ); 58 struct __condition_criterion_t * pop( struct __condition_stack_t * ); 60 59 61 void?{}(spinlock & this);62 void ^?{}(spinlock & this);63 }64 #endif60 void ?{}(spinlock & this); 61 void ^?{}(spinlock & this); 62 } 63 #endif 65 64 66 struct coStack_t { 67 // size of stack 68 size_t size; 65 struct coStack_t { 66 unsigned int size; // size of stack 67 void *storage; // pointer to stack 68 void *limit; // stack grows towards stack limit 69 void *base; // base of stack 70 void *context; // address of cfa_context_t 71 void *top; // address of top of storage 72 bool userStack; // whether or not the user allocated the stack 73 }; 69 74 70 // pointer to stack 71 void *storage; 75 enum coroutine_state { Halted, Start, Inactive, Active, Primed }; 72 76 73 // stack grows towards stack limit 74 void *limit; 77 struct coroutine_desc { 78 struct coStack_t stack; // stack information of the coroutine 79 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 80 int errno_; // copy of global UNIX variable errno 81 enum coroutine_state state; // current execution status for coroutine 82 struct coroutine_desc * starter; // first coroutine to resume this one 83 struct coroutine_desc * last; // last coroutine to resume this one 84 }; 75 85 76 // base of stack 77 void *base; 86 struct __waitfor_mask_t { 87 short * accepted; // the index of the accepted function, -1 if none 88 struct __acceptable_t * clauses; // list of acceptable functions, null if any 89 short size; // number of acceptable functions 90 }; 78 91 79 // address of cfa_context_t 80 void *context; 92 struct monitor_desc { 93 struct spinlock lock; // spinlock to protect internal data 94 struct thread_desc * owner; // current owner of the monitor 95 struct __thread_queue_t entry_queue; // queue of threads that are blocked waiting for the monitor 96 struct __condition_stack_t signal_stack; // stack of conditions to run next once we exit the monitor 97 unsigned int recursion; // monitor routines can be called recursively, we need to keep track of that 98 struct __waitfor_mask_t mask; // mask used to know if some thread is waiting for something while holding the monitor 99 struct __condition_node_t * dtor_node; // node used to signal the dtor in a waitfor dtor 100 }; 81 101 82 // address of top of storage 83 void *top; 102 struct __monitor_group_t { 103 struct monitor_desc ** list; // currently held monitors 104 short size; // number of currently held monitors 105 fptr_t func; // last function that acquired monitors 106 }; 84 107 85 // whether or not the user allocated the stack 86 bool userStack; 87 }; 108 struct thread_desc { 109 // Core threading fields 110 struct coroutine_desc self_cor; // coroutine body used to store context 111 struct monitor_desc self_mon; // monitor body used for mutual exclusion 112 struct monitor_desc * self_mon_p; // pointer to monitor with sufficient lifetime for current monitors 113 struct __monitor_group_t monitors; // monitors currently held by this thread 88 114 89 enum coroutine_state { Halted, Start, Inactive, Active, Primed }; 115 // Link lists fields 116 struct thread_desc * next; // instrusive link field for threads 90 117 91 struct coroutine_desc {92 // stack information of the coroutine93 struct coStack_t stack;94 118 95 // textual name for coroutine/task, initialized by uC++ generated code96 const char *name;97 98 // copy of global UNIX variable errno99 int errno_;100 101 // current execution status for coroutine102 enum coroutine_state state;103 104 // first coroutine to resume this one105 struct coroutine_desc * starter;106 107 // last coroutine to resume this one108 struct coroutine_desc * last;109 };110 111 struct __waitfor_mask_t {112 // the index of the accepted function, -1 if none113 short * accepted;114 115 // list of acceptable functions, null if any116 struct __acceptable_t * clauses;117 118 // number of acceptable functions119 __lock_size_t size;120 };121 122 struct monitor_desc {123 // spinlock to protect internal data124 struct spinlock lock;125 126 // current owner of the monitor127 struct thread_desc * owner;128 129 // queue of threads that are blocked waiting for the monitor130 struct __thread_queue_t entry_queue;131 132 // stack of conditions to run next once we exit the monitor133 struct __condition_stack_t signal_stack;134 135 // monitor routines can be called recursively, we need to keep track of that136 unsigned int recursion;137 138 // mask used to know if some thread is waiting for something while holding the monitor139 struct __waitfor_mask_t mask;140 141 // node used to signal the dtor in a waitfor dtor142 struct __condition_node_t * dtor_node;143 };144 145 struct __monitor_group_t {146 // currently held monitors147 struct monitor_desc ** list;148 149 // number of currently held monitors150 __lock_size_t size;151 152 // last function that acquired monitors153 fptr_t func;154 };155 156 struct thread_desc {157 // Core threading fields158 // coroutine body used to store context159 struct coroutine_desc self_cor;160 161 // monitor body used for mutual exclusion162 struct monitor_desc self_mon;163 164 // pointer to monitor with sufficient lifetime for current monitors165 struct monitor_desc * self_mon_p;166 167 // monitors currently held by this thread168 struct __monitor_group_t monitors;169 170 // Link lists fields171 // instrusive link field for threads172 struct thread_desc * next;173 119 }; 174 120 175 121 #ifdef __CFORALL__ 176 122 extern "Cforall" { 177 static inline monitor_desc * ?[?]( const __monitor_group_t & this, ptrdiff_t index ) {178 return this.list[index];179 }123 static inline monitor_desc * ?[?]( const __monitor_group_t & this, ptrdiff_t index ) { 124 return this.list[index]; 125 } 180 126 181 static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {182 if( (lhs.list != 0) != (rhs.list != 0) ) return false;183 if( lhs.size != rhs.size ) return false;184 if( lhs.func != rhs.func ) return false;127 static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) { 128 if( (lhs.list != 0) != (rhs.list != 0) ) return false; 129 if( lhs.size != rhs.size ) return false; 130 if( lhs.func != rhs.func ) return false; 185 131 186 // Check that all the monitors match187 for( int i = 0; i < lhs.size; i++ ) {188 // If not a match, check next function189 if( lhs[i] != rhs[i] ) return false;190 }132 // Check that all the monitors match 133 for( int i = 0; i < lhs.size; i++ ) { 134 // If not a match, check next function 135 if( lhs[i] != rhs[i] ) return false; 136 } 191 137 192 return true;193 }194 }195 #endif138 return true; 139 } 140 } 141 #endif 196 142 197 143 #endif //_INVOKE_H_ … … 200 146 #define _INVOKE_PRIVATE_H_ 201 147 202 struct machine_context_t {203 void *SP;204 void *FP;205 void *PC;206 };148 struct machine_context_t { 149 void *SP; 150 void *FP; 151 void *PC; 152 }; 207 153 208 // assembler routines that performs the context switch209 extern void CtxInvokeStub( void );210 void CtxSwitch( void * from, void * to ) asm ("CtxSwitch");154 // assembler routines that performs the context switch 155 extern void CtxInvokeStub( void ); 156 void CtxSwitch( void * from, void * to ) asm ("CtxSwitch"); 211 157 212 #if defined( __x86_64__ )213 #define CtxGet( ctx ) __asm__ ( \214 "movq %%rsp,%0\n" \215 "movq %%rbp,%1\n" \216 : "=rm" (ctx.SP), "=rm" (ctx.FP) )217 #elif defined( __i386__ )218 #define CtxGet( ctx ) __asm__ ( \219 "movl %%esp,%0\n" \220 "movl %%ebp,%1\n" \221 : "=rm" (ctx.SP), "=rm" (ctx.FP) )222 #endif158 #if defined( __x86_64__ ) 159 #define CtxGet( ctx ) __asm__ ( \ 160 "movq %%rsp,%0\n" \ 161 "movq %%rbp,%1\n" \ 162 : "=rm" (ctx.SP), "=rm" (ctx.FP) ) 163 #elif defined( __i386__ ) 164 #define CtxGet( ctx ) __asm__ ( \ 165 "movl %%esp,%0\n" \ 166 "movl %%ebp,%1\n" \ 167 : "=rm" (ctx.SP), "=rm" (ctx.FP) ) 168 #endif 223 169 224 170 #endif //_INVOKE_PRIVATE_H_ -
src/libcfa/concurrency/kernel
r121ac13 r9f4524b 26 26 //----------------------------------------------------------------------------- 27 27 // Locks 28 // Lock the spinlock, spin if already acquired 29 void lock ( spinlock * DEBUG_CTX_PARAM2 ); 30 31 // Lock the spinlock, yield repeatedly if already acquired 32 void lock_yield( spinlock * DEBUG_CTX_PARAM2 ); 33 34 // Lock the spinlock, return false if already acquired 35 bool try_lock ( spinlock * DEBUG_CTX_PARAM2 ); 36 37 // Unlock the spinlock 38 void unlock ( spinlock * ); 28 void lock ( spinlock * DEBUG_CTX_PARAM2 ); // Lock the spinlock, spin if already acquired 29 void lock_yield( spinlock * DEBUG_CTX_PARAM2 ); // Lock the spinlock, yield repeatedly if already acquired 30 bool try_lock ( spinlock * DEBUG_CTX_PARAM2 ); // Lock the spinlock, return false if already acquired 31 void unlock ( spinlock * ); // Unlock the spinlock 39 32 40 33 struct semaphore { … … 46 39 void ?{}(semaphore & this, int count = 1); 47 40 void ^?{}(semaphore & this); 48 void P (semaphore &this);49 void V (semaphore &this);41 void P(semaphore * this); 42 void V(semaphore * this); 50 43 51 44 … … 53 46 // Cluster 54 47 struct cluster { 55 // Ready queue locks 56 spinlock ready_queue_lock; 57 58 // Ready queue for threads 59 __thread_queue_t ready_queue; 60 61 // Preemption rate on this cluster 62 unsigned long long int preemption; 48 spinlock ready_queue_lock; // Ready queue locks 49 __thread_queue_t ready_queue; // Ready queue for threads 50 unsigned long long int preemption; // Preemption rate on this cluster 63 51 }; 64 52 65 void ?{} (cluster & this);53 void ?{}(cluster & this); 66 54 void ^?{}(cluster & this); 67 55 … … 91 79 struct processor { 92 80 // Main state 93 // Coroutine ctx who does keeps the state of the processor 94 struct processorCtx_t * runner; 95 96 // Cluster from which to get threads 97 cluster * cltr; 98 99 // Handle to pthreads 100 pthread_t kernel_thread; 81 struct processorCtx_t * runner; // Coroutine ctx who does keeps the state of the processor 82 cluster * cltr; // Cluster from which to get threads 83 pthread_t kernel_thread; // Handle to pthreads 101 84 102 85 // Termination 103 // Set to true to notify the processor should terminate 104 volatile bool do_terminate; 105 106 // Termination synchronisation 107 semaphore terminated; 86 volatile bool do_terminate; // Set to true to notify the processor should terminate 87 semaphore terminated; // Termination synchronisation 108 88 109 89 // RunThread data 110 // Action to do after a thread is ran 111 struct FinishAction finish; 90 struct FinishAction finish; // Action to do after a thread is ran 112 91 113 92 // Preemption data 114 // Node which is added in the discrete event simulaiton 115 struct alarm_node_t * preemption_alarm; 116 117 // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible 118 bool pending_preemption; 93 struct alarm_node_t * preemption_alarm; // Node which is added in the discrete event simulaiton 94 bool pending_preemption; // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible 119 95 120 96 #ifdef __CFA_DEBUG__ 121 // Last function to enable preemption on this processor 122 char * last_enable; 97 char * last_enable; // Last function to enable preemption on this processor 123 98 #endif 124 99 }; 125 100 126 void ?{}(processor & this);127 void ?{}(processor & this, cluster * cltr);101 void ?{}(processor & this); 102 void ?{}(processor & this, cluster * cltr); 128 103 void ^?{}(processor & this); 129 104 -
src/libcfa/concurrency/kernel.c
r121ac13 r9f4524b 158 158 LIB_DEBUG_PRINT_SAFE("Kernel : core %p signaling termination\n", &this); 159 159 this.do_terminate = true; 160 P( this.terminated );160 P( &this.terminated ); 161 161 pthread_join( this.kernel_thread, NULL ); 162 162 } … … 216 216 } 217 217 218 V( this->terminated );218 V( &this->terminated ); 219 219 220 220 LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this); … … 335 335 336 336 lock( &this_processor->cltr->ready_queue_lock DEBUG_CTX2 ); 337 append( this_processor->cltr->ready_queue, thrd );337 append( &this_processor->cltr->ready_queue, thrd ); 338 338 unlock( &this_processor->cltr->ready_queue_lock ); 339 339 … … 344 344 verify( disable_preempt_count > 0 ); 345 345 lock( &this->ready_queue_lock DEBUG_CTX2 ); 346 thread_desc * head = pop_head( this->ready_queue );346 thread_desc * head = pop_head( &this->ready_queue ); 347 347 unlock( &this->ready_queue_lock ); 348 348 verify( disable_preempt_count > 0 ); … … 398 398 } 399 399 400 void BlockInternal(spinlock * locks [], unsigned short count) {400 void BlockInternal(spinlock ** locks, unsigned short count) { 401 401 disable_interrupts(); 402 402 this_processor->finish.action_code = Release_Multi; … … 411 411 } 412 412 413 void BlockInternal(spinlock * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {413 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 414 414 disable_interrupts(); 415 415 this_processor->finish.action_code = Release_Multi_Schedule; … … 618 618 void ^?{}(semaphore & this) {} 619 619 620 void P(semaphore &this) {621 lock( &this .lock DEBUG_CTX2 );622 this .count -= 1;623 if ( this .count < 0 ) {620 void P(semaphore * this) { 621 lock( &this->lock DEBUG_CTX2 ); 622 this->count -= 1; 623 if ( this->count < 0 ) { 624 624 // queue current task 625 append( this.waiting, (thread_desc *)this_thread );625 append( &this->waiting, (thread_desc *)this_thread ); 626 626 627 627 // atomically release spin lock and block 628 BlockInternal( &this .lock );628 BlockInternal( &this->lock ); 629 629 } 630 630 else { 631 unlock( &this .lock );632 } 633 } 634 635 void V(semaphore &this) {631 unlock( &this->lock ); 632 } 633 } 634 635 void V(semaphore * this) { 636 636 thread_desc * thrd = NULL; 637 lock( &this .lock DEBUG_CTX2 );638 this .count += 1;639 if ( this .count <= 0 ) {637 lock( &this->lock DEBUG_CTX2 ); 638 this->count += 1; 639 if ( this->count <= 0 ) { 640 640 // remove task at head of waiting list 641 thrd = pop_head( this.waiting );642 } 643 644 unlock( &this .lock );641 thrd = pop_head( &this->waiting ); 642 } 643 644 unlock( &this->lock ); 645 645 646 646 // make new owner … … 655 655 } 656 656 657 void append( __thread_queue_t &this, thread_desc * t ) {658 verify(this .tail != NULL);659 *this .tail = t;660 this .tail = &t->next;661 } 662 663 thread_desc * pop_head( __thread_queue_t &this ) {664 thread_desc * head = this .head;657 void append( __thread_queue_t * this, thread_desc * t ) { 658 verify(this->tail != NULL); 659 *this->tail = t; 660 this->tail = &t->next; 661 } 662 663 thread_desc * pop_head( __thread_queue_t * this ) { 664 thread_desc * head = this->head; 665 665 if( head ) { 666 this .head = head->next;666 this->head = head->next; 667 667 if( !head->next ) { 668 this .tail = &this.head;668 this->tail = &this->head; 669 669 } 670 670 head->next = NULL; … … 673 673 } 674 674 675 thread_desc * remove( __thread_queue_t &this, thread_desc ** it ) {675 thread_desc * remove( __thread_queue_t * this, thread_desc ** it ) { 676 676 thread_desc * thrd = *it; 677 677 verify( thrd ); … … 679 679 (*it) = thrd->next; 680 680 681 if( this .tail == &thrd->next ) {682 this .tail = it;681 if( this->tail == &thrd->next ) { 682 this->tail = it; 683 683 } 684 684 685 685 thrd->next = NULL; 686 686 687 verify( (this .head == NULL) == (&this.head == this.tail) );688 verify( *this .tail == NULL );687 verify( (this->head == NULL) == (&this->head == this->tail) ); 688 verify( *this->tail == NULL ); 689 689 return thrd; 690 690 } … … 694 694 } 695 695 696 void push( __condition_stack_t &this, __condition_criterion_t * t ) {696 void push( __condition_stack_t * this, __condition_criterion_t * t ) { 697 697 verify( !t->next ); 698 t->next = this .top;699 this .top = t;700 } 701 702 __condition_criterion_t * pop( __condition_stack_t &this ) {703 __condition_criterion_t * top = this .top;698 t->next = this->top; 699 this->top = t; 700 } 701 702 __condition_criterion_t * pop( __condition_stack_t * this ) { 703 __condition_criterion_t * top = this->top; 704 704 if( top ) { 705 this .top = top->next;705 this->top = top->next; 706 706 top->next = NULL; 707 707 } -
src/libcfa/concurrency/kernel_private.h
r121ac13 r9f4524b 48 48 void BlockInternal(thread_desc * thrd); 49 49 void BlockInternal(spinlock * lock, thread_desc * thrd); 50 void BlockInternal(spinlock * locks [], unsigned short count);51 void BlockInternal(spinlock * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);50 void BlockInternal(spinlock ** locks, unsigned short count); 51 void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count); 52 52 void LeaveThread(spinlock * lock, thread_desc * thrd); 53 53 -
src/libcfa/concurrency/monitor
r121ac13 r9f4524b 39 39 } 40 40 41 // static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) { 42 // return ((intptr_t)lhs) < ((intptr_t)rhs); 43 // } 44 41 45 struct monitor_guard_t { 42 46 monitor_desc ** m; 43 __lock_size_tcount;47 int count; 44 48 monitor_desc ** prev_mntrs; 45 __lock_size_tprev_count;49 unsigned short prev_count; 46 50 fptr_t prev_func; 47 51 }; 48 52 49 void ?{}( monitor_guard_t & this, monitor_desc ** m, __lock_size_t count, void (*func)() );53 void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, void (*func)() ); 50 54 void ^?{}( monitor_guard_t & this ); 51 55 … … 53 57 monitor_desc * m; 54 58 monitor_desc ** prev_mntrs; 55 __lock_size_tprev_count;59 unsigned short prev_count; 56 60 fptr_t prev_func; 57 61 }; … … 70 74 71 75 struct __condition_criterion_t { 72 // Whether or not the criterion is met (True if met) 73 bool ready; 74 75 // The monitor this criterion concerns 76 monitor_desc * target; 77 78 // The parent node to which this criterion belongs 79 struct __condition_node_t * owner; 80 81 // Intrusive linked list Next field 82 __condition_criterion_t * next; 76 bool ready; //Whether or not the criterion is met (True if met) 77 monitor_desc * target; //The monitor this criterion concerns 78 struct __condition_node_t * owner; //The parent node to which this criterion belongs 79 __condition_criterion_t * next; //Intrusive linked list Next field 83 80 }; 84 81 85 82 struct __condition_node_t { 86 // Thread that needs to be woken when all criteria are met 87 thread_desc * waiting_thread; 88 89 // Array of criteria (Criterions are contiguous in memory) 90 __condition_criterion_t * criteria; 91 92 // Number of criterions in the criteria 93 __lock_size_t count; 94 95 // Intrusive linked list Next field 96 __condition_node_t * next; 97 98 // Custom user info accessible before signalling 99 uintptr_t user_info; 83 thread_desc * waiting_thread; //Thread that needs to be woken when all criteria are met 84 __condition_criterion_t * criteria; //Array of criteria (Criterions are contiguous in memory) 85 unsigned short count; //Number of criterions in the criteria 86 __condition_node_t * next; //Intrusive linked list Next field 87 uintptr_t user_info; //Custom user info accessible before signalling 100 88 }; 101 89 … … 105 93 }; 106 94 107 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info );95 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ); 108 96 void ?{}(__condition_criterion_t & this ); 109 97 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner ); 110 98 111 99 void ?{}( __condition_blocked_queue_t & ); 112 void append( __condition_blocked_queue_t &, __condition_node_t * );113 __condition_node_t * pop_head( __condition_blocked_queue_t &);100 void append( __condition_blocked_queue_t *, __condition_node_t * ); 101 __condition_node_t * pop_head( __condition_blocked_queue_t * ); 114 102 115 103 struct condition { 116 // Link list which contains the blocked threads as-well as the information needed to unblock them 117 __condition_blocked_queue_t blocked; 118 119 // Array of monitor pointers (Monitors are NOT contiguous in memory) 120 monitor_desc ** monitors; 121 122 // Number of monitors in the array 123 __lock_size_t monitor_count; 104 __condition_blocked_queue_t blocked; //Link list which contains the blocked threads as-well as the information needed to unblock them 105 monitor_desc ** monitors; //Array of monitor pointers (Monitors are NOT contiguous in memory) 106 unsigned short monitor_count; //Number of monitors in the array 124 107 }; 125 108 … … 133 116 } 134 117 135 void wait ( condition &this, uintptr_t user_info = 0 );136 bool signal ( condition &this );137 bool signal_block( condition &this );138 static inline bool is_empty ( condition & this ) { return !this.blocked.head; }139 uintptr_t front ( condition &this );118 void wait( condition * this, uintptr_t user_info = 0 ); 119 bool signal( condition * this ); 120 bool signal_block( condition * this ); 121 static inline bool is_empty( condition * this ) { return !this->blocked.head; } 122 uintptr_t front( condition * this ); 140 123 141 124 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/monitor.c
r121ac13 r9f4524b 26 26 // Forward declarations 27 27 static inline void set_owner ( monitor_desc * this, thread_desc * owner ); 28 static inline void set_owner ( monitor_desc * storage [], __lock_size_t count, thread_desc * owner );29 static inline void set_mask ( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask );28 static inline void set_owner ( monitor_desc ** storage, short count, thread_desc * owner ); 29 static inline void set_mask ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ); 30 30 static inline void reset_mask( monitor_desc * this ); 31 31 … … 33 33 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors ); 34 34 35 static inline void lock_all ( spinlock * locks [], __lock_size_t count );36 static inline void lock_all ( monitor_desc * source [], spinlock * /*out*/ locks [], __lock_size_t count );37 static inline void unlock_all( spinlock * locks [], __lock_size_t count );38 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count );39 40 static inline void save ( monitor_desc * ctx [], __lock_size_t count, spinlock * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks []);41 static inline void restore( monitor_desc * ctx [], __lock_size_t count, spinlock * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks []);42 43 static inline void init ( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []);44 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []);35 static inline void lock_all( spinlock ** locks, unsigned short count ); 36 static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count ); 37 static inline void unlock_all( spinlock ** locks, unsigned short count ); 38 static inline void unlock_all( monitor_desc ** locks, unsigned short count ); 39 40 static inline void save ( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ); 41 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*in */ recursions, __waitfor_mask_t * /*in */ masks ); 42 43 static inline void init ( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 44 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 45 45 46 46 static inline thread_desc * check_condition ( __condition_criterion_t * ); 47 static inline void brand_condition ( condition &);48 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc * monitors [], __lock_size_t count );47 static inline void brand_condition ( condition * ); 48 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc ** monitors, int count ); 49 49 50 50 forall(dtype T | sized( T )) 51 static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val );52 static inline __lock_size_t count_max ( const __waitfor_mask_t & mask );53 static inline __lock_size_t aggregate ( monitor_desc * storage [], const __waitfor_mask_t & mask );51 static inline short insert_unique( T ** array, short & size, T * val ); 52 static inline short count_max ( const __waitfor_mask_t & mask ); 53 static inline short aggregate ( monitor_desc ** storage, const __waitfor_mask_t & mask ); 54 54 55 55 //----------------------------------------------------------------------------- … … 58 58 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 59 59 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 60 init( count, monitors, waiter, criteria );/* Link everything together */ \60 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 61 61 62 62 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 63 63 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 64 64 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 65 init_push( count, monitors, waiter, criteria );/* Link everything together and push it to the AS-Stack */ \65 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 66 66 67 67 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 68 68 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 69 __lock_size_t count = cnt;/* Save the count to a local variable */ \69 unsigned short count = cnt; /* Save the count to a local variable */ \ 70 70 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 71 __waitfor_mask_t masks [ count ];/* Save the current waitfor masks to restore them later */ \71 __waitfor_mask_t masks[ count ]; /* Save the current waitfor masks to restore them later */ \ 72 72 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 73 73 … … 114 114 115 115 // Some one else has the monitor, wait in line for it 116 append( this->entry_queue, thrd );116 append( &this->entry_queue, thrd ); 117 117 BlockInternal( &this->lock ); 118 118 … … 153 153 } 154 154 155 __lock_size_t count = 1;155 int count = 1; 156 156 monitor_desc ** monitors = &this; 157 157 __monitor_group_t group = { &this, 1, func }; … … 160 160 161 161 // Wake the thread that is waiting for this 162 __condition_criterion_t * urgent = pop( this->signal_stack );162 __condition_criterion_t * urgent = pop( &this->signal_stack ); 163 163 verify( urgent ); 164 164 … … 182 182 183 183 // Some one else has the monitor, wait in line for it 184 append( this->entry_queue, thrd );184 append( &this->entry_queue, thrd ); 185 185 BlockInternal( &this->lock ); 186 186 … … 272 272 // relies on the monitor array being sorted 273 273 static inline void enter( __monitor_group_t monitors ) { 274 for( __lock_size_t i = 0; i < monitors.size; i++) {274 for(int i = 0; i < monitors.size; i++) { 275 275 __enter_monitor_desc( monitors.list[i], monitors ); 276 276 } … … 279 279 // Leave multiple monitor 280 280 // relies on the monitor array being sorted 281 static inline void leave(monitor_desc * monitors [], __lock_size_t count) {282 for( __lock_size_t i = count - 1; i >= 0; i--) {281 static inline void leave(monitor_desc ** monitors, int count) { 282 for(int i = count - 1; i >= 0; i--) { 283 283 __leave_monitor_desc( monitors[i] ); 284 284 } … … 287 287 // Ctor for monitor guard 288 288 // Sorts monitors before entering 289 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {289 void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, fptr_t func ) { 290 290 // Store current array 291 291 this.m = m; … … 296 296 297 297 // Save previous thread context 298 this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func]; 298 this.prev_mntrs = this_thread->monitors.list; 299 this.prev_count = this_thread->monitors.size; 300 this.prev_func = this_thread->monitors.func; 299 301 300 302 // Update thread context (needed for conditions) 301 this_thread->monitors.[list, size, func] = [m, count, func]; 303 this_thread->monitors.list = m; 304 this_thread->monitors.size = count; 305 this_thread->monitors.func = func; 302 306 303 307 // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count); … … 321 325 322 326 // Restore thread context 323 this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func]; 324 } 327 this_thread->monitors.list = this.prev_mntrs; 328 this_thread->monitors.size = this.prev_count; 329 this_thread->monitors.func = this.prev_func; 330 } 331 325 332 326 333 // Ctor for monitor guard 327 334 // Sorts monitors before entering 328 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {335 void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, fptr_t func ) { 329 336 // Store current array 330 337 this.m = *m; 331 338 332 339 // Save previous thread context 333 this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func]; 340 this.prev_mntrs = this_thread->monitors.list; 341 this.prev_count = this_thread->monitors.size; 342 this.prev_func = this_thread->monitors.func; 334 343 335 344 // Update thread context (needed for conditions) 336 this_thread->monitors.[list, size, func] = [m, 1, func]; 345 this_thread->monitors.list = m; 346 this_thread->monitors.size = 1; 347 this_thread->monitors.func = func; 337 348 338 349 __enter_monitor_dtor( this.m, func ); 339 350 } 351 340 352 341 353 // Dtor for monitor guard … … 345 357 346 358 // Restore thread context 347 this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func]; 359 this_thread->monitors.list = this.prev_mntrs; 360 this_thread->monitors.size = this.prev_count; 361 this_thread->monitors.func = this.prev_func; 348 362 } 349 363 350 364 //----------------------------------------------------------------------------- 351 365 // Internal scheduling types 352 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info ) {366 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) { 353 367 this.waiting_thread = waiting_thread; 354 368 this.count = count; … … 364 378 } 365 379 366 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t &owner ) {380 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner ) { 367 381 this.ready = false; 368 382 this.target = target; 369 this.owner = &owner;383 this.owner = owner; 370 384 this.next = NULL; 371 385 } … … 373 387 //----------------------------------------------------------------------------- 374 388 // Internal scheduling 375 void wait( condition &this, uintptr_t user_info = 0 ) {389 void wait( condition * this, uintptr_t user_info = 0 ) { 376 390 brand_condition( this ); 377 391 378 392 // Check that everything is as expected 379 assertf( this .monitors != NULL, "Waiting with no monitors (%p)", this.monitors );380 verifyf( this .monitor_count != 0, "Waiting with 0 monitors (%i)", this.monitor_count );381 verifyf( this .monitor_count < 32u, "Excessive monitor count (%i)", this.monitor_count );393 assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 394 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 395 verifyf( this->monitor_count < 32u, "Excessive monitor count (%i)", this->monitor_count ); 382 396 383 397 // Create storage for monitor context 384 monitor_ctx( this .monitors, this.monitor_count );398 monitor_ctx( this->monitors, this->monitor_count ); 385 399 386 400 // Create the node specific to this wait operation … … 389 403 // Append the current wait operation to the ones already queued on the condition 390 404 // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion 391 append( this.blocked, &waiter );405 append( &this->blocked, &waiter ); 392 406 393 407 // Lock all monitors (aggregates the locks as well) … … 395 409 396 410 // Find the next thread(s) to run 397 __lock_size_t thread_count = 0;411 short thread_count = 0; 398 412 thread_desc * threads[ count ]; 399 413 __builtin_memset( threads, 0, sizeof( threads ) ); … … 403 417 404 418 // Remove any duplicate threads 405 for( __lock_size_t i = 0; i < count; i++) {419 for( int i = 0; i < count; i++) { 406 420 thread_desc * new_owner = next_thread( monitors[i] ); 407 421 insert_unique( threads, thread_count, new_owner ); … … 415 429 } 416 430 417 bool signal( condition &this ) {431 bool signal( condition * this ) { 418 432 if( is_empty( this ) ) { return false; } 419 433 420 434 //Check that everything is as expected 421 verify( this .monitors );422 verify( this .monitor_count != 0 );435 verify( this->monitors ); 436 verify( this->monitor_count != 0 ); 423 437 424 438 //Some more checking in debug 425 439 LIB_DEBUG_DO( 426 440 thread_desc * this_thrd = this_thread; 427 if ( this .monitor_count != this_thrd->monitors.size ) {428 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );429 } 430 431 for(int i = 0; i < this .monitor_count; i++) {432 if ( this .monitors[i] != this_thrd->monitors.list[i] ) {433 abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors.list[i] );441 if ( this->monitor_count != this_thrd->monitors.size ) { 442 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->monitors.size ); 443 } 444 445 for(int i = 0; i < this->monitor_count; i++) { 446 if ( this->monitors[i] != this_thrd->monitors.list[i] ) { 447 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->monitors.list[i] ); 434 448 } 435 449 } 436 450 ); 437 451 438 __lock_size_t count = this.monitor_count;452 unsigned short count = this->monitor_count; 439 453 440 454 // Lock all monitors 441 lock_all( this .monitors, NULL, count );455 lock_all( this->monitors, NULL, count ); 442 456 443 457 //Pop the head of the waiting queue 444 __condition_node_t * node = pop_head( this.blocked );458 __condition_node_t * node = pop_head( &this->blocked ); 445 459 446 460 //Add the thread to the proper AS stack … … 448 462 __condition_criterion_t * crit = &node->criteria[i]; 449 463 assert( !crit->ready ); 450 push( crit->target->signal_stack, crit );464 push( &crit->target->signal_stack, crit ); 451 465 } 452 466 453 467 //Release 454 unlock_all( this .monitors, count );468 unlock_all( this->monitors, count ); 455 469 456 470 return true; 457 471 } 458 472 459 bool signal_block( condition &this ) {460 if( !this .blocked.head ) { return false; }473 bool signal_block( condition * this ) { 474 if( !this->blocked.head ) { return false; } 461 475 462 476 //Check that everything is as expected 463 verifyf( this .monitors != NULL, "Waiting with no monitors (%p)", this.monitors );464 verifyf( this .monitor_count != 0, "Waiting with 0 monitors (%i)", this.monitor_count );477 verifyf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors ); 478 verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count ); 465 479 466 480 // Create storage for monitor context 467 monitor_ctx( this .monitors, this.monitor_count );481 monitor_ctx( this->monitors, this->monitor_count ); 468 482 469 483 // Lock all monitors (aggregates the locks them as well) … … 477 491 478 492 //Find the thread to run 479 thread_desc * signallee = pop_head( this.blocked )->waiting_thread;493 thread_desc * signallee = pop_head( &this->blocked )->waiting_thread; 480 494 set_owner( monitors, count, signallee ); 481 495 482 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );496 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : signal_block condition %p (s: %p)\n", this, signallee ); 483 497 484 498 //Everything is ready to go to sleep … … 498 512 499 513 // Access the user_info of the thread waiting at the front of the queue 500 uintptr_t front( condition &this ) {514 uintptr_t front( condition * this ) { 501 515 verifyf( !is_empty(this), 502 516 "Attempt to access user data on an empty condition.\n" 503 517 "Possible cause is not checking if the condition is empty before reading stored data." 504 518 ); 505 return this .blocked.head->user_info;519 return this->blocked.head->user_info; 506 520 } 507 521 … … 523 537 // This statment doesn't have a contiguous list of monitors... 524 538 // Create one! 525 __lock_size_t max = count_max( mask );539 short max = count_max( mask ); 526 540 monitor_desc * mon_storage[max]; 527 541 __builtin_memset( mon_storage, 0, sizeof( mon_storage ) ); 528 __lock_size_t actual_count = aggregate( mon_storage, mask );529 530 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : waitfor %d (s: %d, m: %d)\n", actual_count, mask.size, ( __lock_size_t)max);542 short actual_count = aggregate( mon_storage, mask ); 543 544 LIB_DEBUG_PRINT_BUFFER_DECL( "Kernel : waitfor %d (s: %d, m: %d)\n", actual_count, mask.size, (short)max); 531 545 532 546 if(actual_count == 0) return; … … 555 569 556 570 __condition_criterion_t * dtor_crit = mon2dtor->dtor_node->criteria; 557 push( mon2dtor->signal_stack, dtor_crit );571 push( &mon2dtor->signal_stack, dtor_crit ); 558 572 559 573 unlock_all( locks, count ); … … 615 629 set_mask( monitors, count, mask ); 616 630 617 for( __lock_size_t i = 0; i < count; i++) {631 for(int i = 0; i < count; i++) { 618 632 verify( monitors[i]->owner == this_thread ); 619 633 } … … 647 661 } 648 662 649 static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {663 static inline void set_owner( monitor_desc ** monitors, short count, thread_desc * owner ) { 650 664 monitors[0]->owner = owner; 651 665 monitors[0]->recursion = 1; 652 for( __lock_size_t i = 1; i < count; i++ ) {666 for( int i = 1; i < count; i++ ) { 653 667 monitors[i]->owner = owner; 654 668 monitors[i]->recursion = 0; … … 656 670 } 657 671 658 static inline void set_mask( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {659 for( __lock_size_t i = 0; i < count; i++) {672 static inline void set_mask( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ) { 673 for(int i = 0; i < count; i++) { 660 674 storage[i]->mask = mask; 661 675 } … … 671 685 //Check the signaller stack 672 686 LIB_DEBUG_PRINT_SAFE("Kernel : mon %p AS-stack top %p\n", this, this->signal_stack.top); 673 __condition_criterion_t * urgent = pop( this->signal_stack );687 __condition_criterion_t * urgent = pop( &this->signal_stack ); 674 688 if( urgent ) { 675 689 //The signaller stack is not empty, … … 683 697 // No signaller thread 684 698 // Get the next thread in the entry_queue 685 thread_desc * new_owner = pop_head( this->entry_queue );699 thread_desc * new_owner = pop_head( &this->entry_queue ); 686 700 set_owner( this, new_owner ); 687 701 … … 691 705 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) { 692 706 __acceptable_t * it = this->mask.clauses; // Optim 693 __lock_size_t count = this->mask.size;707 int count = this->mask.size; 694 708 695 709 // Check if there are any acceptable functions … … 700 714 701 715 // For all acceptable functions check if this is the current function. 702 for( __lock_size_t i = 0; i < count; i++, it++ ) {716 for( short i = 0; i < count; i++, it++ ) { 703 717 if( *it == group ) { 704 718 *this->mask.accepted = i; … … 711 725 } 712 726 713 static inline void init( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []) {714 for( __lock_size_t i = 0; i < count; i++) {727 static inline void init( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 728 for(int i = 0; i < count; i++) { 715 729 (criteria[i]){ monitors[i], waiter }; 716 730 } 717 731 718 waiter .criteria = criteria;719 } 720 721 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria []) {722 for( __lock_size_t i = 0; i < count; i++) {732 waiter->criteria = criteria; 733 } 734 735 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ) { 736 for(int i = 0; i < count; i++) { 723 737 (criteria[i]){ monitors[i], waiter }; 724 738 LIB_DEBUG_PRINT_SAFE( "Kernel : target %p = %p\n", criteria[i].target, &criteria[i] ); 725 push( criteria[i].target->signal_stack, &criteria[i] );726 } 727 728 waiter .criteria = criteria;729 } 730 731 static inline void lock_all( spinlock * locks [], __lock_size_t count ) {732 for( __lock_size_t i = 0; i < count; i++ ) {739 push( &criteria[i].target->signal_stack, &criteria[i] ); 740 } 741 742 waiter->criteria = criteria; 743 } 744 745 static inline void lock_all( spinlock ** locks, unsigned short count ) { 746 for( int i = 0; i < count; i++ ) { 733 747 lock_yield( locks[i] DEBUG_CTX2 ); 734 748 } 735 749 } 736 750 737 static inline void lock_all( monitor_desc * source [], spinlock * /*out*/ locks [], __lock_size_t count ) {738 for( __lock_size_t i = 0; i < count; i++ ) {751 static inline void lock_all( monitor_desc ** source, spinlock ** /*out*/ locks, unsigned short count ) { 752 for( int i = 0; i < count; i++ ) { 739 753 spinlock * l = &source[i]->lock; 740 754 lock_yield( l DEBUG_CTX2 ); … … 743 757 } 744 758 745 static inline void unlock_all( spinlock * locks [], __lock_size_t count ) {746 for( __lock_size_t i = 0; i < count; i++ ) {759 static inline void unlock_all( spinlock ** locks, unsigned short count ) { 760 for( int i = 0; i < count; i++ ) { 747 761 unlock( locks[i] ); 748 762 } 749 763 } 750 764 751 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) {752 for( __lock_size_t i = 0; i < count; i++ ) {765 static inline void unlock_all( monitor_desc ** locks, unsigned short count ) { 766 for( int i = 0; i < count; i++ ) { 753 767 unlock( &locks[i]->lock ); 754 768 } 755 769 } 756 770 757 static inline void save( 758 monitor_desc * ctx [], 759 __lock_size_t count, 760 __attribute((unused)) spinlock * locks [], 761 unsigned int /*out*/ recursions [], 762 __waitfor_mask_t /*out*/ masks [] 763 ) { 764 for( __lock_size_t i = 0; i < count; i++ ) { 771 static inline void save( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 772 for( int i = 0; i < count; i++ ) { 765 773 recursions[i] = ctx[i]->recursion; 766 774 masks[i] = ctx[i]->mask; … … 768 776 } 769 777 770 static inline void restore( 771 monitor_desc * ctx [], 772 __lock_size_t count, 773 spinlock * locks [], 774 unsigned int /*out*/ recursions [], 775 __waitfor_mask_t /*out*/ masks [] 776 ) { 778 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 777 779 lock_all( locks, count ); 778 for( __lock_size_t i = 0; i < count; i++ ) {780 for( int i = 0; i < count; i++ ) { 779 781 ctx[i]->recursion = recursions[i]; 780 782 ctx[i]->mask = masks[i]; … … 809 811 } 810 812 811 static inline void brand_condition( condition &this ) {813 static inline void brand_condition( condition * this ) { 812 814 thread_desc * thrd = this_thread; 813 if( !this .monitors ) {815 if( !this->monitors ) { 814 816 // LIB_DEBUG_PRINT_SAFE("Branding\n"); 815 817 assertf( thrd->monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list ); 816 this .monitor_count = thrd->monitors.size;817 818 this .monitors = malloc( this.monitor_count * sizeof( *this.monitors ) );819 for( int i = 0; i < this .monitor_count; i++ ) {820 this .monitors[i] = thrd->monitors.list[i];821 } 822 } 823 } 824 825 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {826 827 __thread_queue_t & entry_queue =monitors[0]->entry_queue;818 this->monitor_count = thrd->monitors.size; 819 820 this->monitors = malloc( this->monitor_count * sizeof( *this->monitors ) ); 821 for( int i = 0; i < this->monitor_count; i++ ) { 822 this->monitors[i] = thrd->monitors.list[i]; 823 } 824 } 825 } 826 827 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc ** monitors, int count ) { 828 829 __thread_queue_t * entry_queue = &monitors[0]->entry_queue; 828 830 829 831 // For each thread in the entry-queue 830 for( thread_desc ** thrd_it = &entry_queue .head;832 for( thread_desc ** thrd_it = &entry_queue->head; 831 833 *thrd_it; 832 834 thrd_it = &(*thrd_it)->next … … 850 852 851 853 forall(dtype T | sized( T )) 852 static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val ) {854 static inline short insert_unique( T ** array, short & size, T * val ) { 853 855 if( !val ) return size; 854 856 855 for( __lock_size_t i = 0; i <= size; i++) {857 for(int i = 0; i <= size; i++) { 856 858 if( array[i] == val ) return size; 857 859 } … … 862 864 } 863 865 864 static inline __lock_size_t count_max( const __waitfor_mask_t & mask ) {865 __lock_size_t max = 0;866 for( __lock_size_t i = 0; i < mask.size; i++ ) {866 static inline short count_max( const __waitfor_mask_t & mask ) { 867 short max = 0; 868 for( int i = 0; i < mask.size; i++ ) { 867 869 max += mask.clauses[i].size; 868 870 } … … 870 872 } 871 873 872 static inline __lock_size_t aggregate( monitor_desc * storage [], const __waitfor_mask_t & mask ) {873 __lock_size_t size = 0;874 for( __lock_size_t i = 0; i < mask.size; i++ ) {874 static inline short aggregate( monitor_desc ** storage, const __waitfor_mask_t & mask ) { 875 short size = 0; 876 for( int i = 0; i < mask.size; i++ ) { 875 877 __libcfa_small_sort( mask.clauses[i].list, mask.clauses[i].size ); 876 for( __lock_size_t j = 0; j < mask.clauses[i].size; j++) {878 for( int j = 0; j < mask.clauses[i].size; j++) { 877 879 insert_unique( storage, size, mask.clauses[i].list[j] ); 878 880 } … … 888 890 } 889 891 890 void append( __condition_blocked_queue_t &this, __condition_node_t * c ) {891 verify(this .tail != NULL);892 *this .tail = c;893 this .tail = &c->next;894 } 895 896 __condition_node_t * pop_head( __condition_blocked_queue_t &this ) {897 __condition_node_t * head = this .head;892 void append( __condition_blocked_queue_t * this, __condition_node_t * c ) { 893 verify(this->tail != NULL); 894 *this->tail = c; 895 this->tail = &c->next; 896 } 897 898 __condition_node_t * pop_head( __condition_blocked_queue_t * this ) { 899 __condition_node_t * head = this->head; 898 900 if( head ) { 899 this .head = head->next;901 this->head = head->next; 900 902 if( !head->next ) { 901 this .tail = &this.head;903 this->tail = &this->head; 902 904 } 903 905 head->next = NULL; -
src/tests/boundedBuffer.c
r121ac13 r9f4524b 1 // 1 // 2 2 // The contents of this file are covered under the licence agreement in the 3 3 // file "LICENCE" distributed with Cforall. 4 // 5 // boundedBuffer.c -- 6 // 4 // 5 // boundedBuffer.c -- 6 // 7 7 // Author : Peter A. Buhr 8 8 // Created On : Mon Oct 30 12:45:13 2017 … … 10 10 // Last Modified On : Mon Oct 30 23:02:46 2017 11 11 // Update Count : 9 12 // 12 // 13 13 14 14 #include <stdlib> … … 31 31 32 32 void insert( Buffer & mutex buffer, int elem ) { 33 if ( buffer.count == 20 ) wait( buffer.empty );33 if ( buffer.count == 20 ) wait( &buffer.empty ); 34 34 buffer.elements[buffer.back] = elem; 35 35 buffer.back = ( buffer.back + 1 ) % 20; 36 36 buffer.count += 1; 37 signal( buffer.full );37 signal( &buffer.full ); 38 38 } 39 39 int remove( Buffer & mutex buffer ) { 40 if ( buffer.count == 0 ) wait( buffer.full );40 if ( buffer.count == 0 ) wait( &buffer.full ); 41 41 int elem = buffer.elements[buffer.front]; 42 42 buffer.front = ( buffer.front + 1 ) % 20; 43 43 buffer.count -= 1; 44 signal( buffer.empty );44 signal( &buffer.empty ); 45 45 return elem; 46 46 } -
src/tests/datingService.c
r121ac13 r9f4524b 1 // -*- Mode: C -*- 2 // 1 // -*- Mode: C -*- 2 // 3 3 // The contents of this file are covered under the licence agreement in the 4 4 // file "LICENCE" distributed with Cforall. 5 // 6 // datingService.c -- 7 // 5 // 6 // datingService.c -- 7 // 8 8 // Author : Peter A. Buhr 9 9 // Created On : Mon Oct 30 12:56:20 2017 … … 11 11 // Last Modified On : Mon Oct 30 23:02:11 2017 12 12 // Update Count : 15 13 // 13 // 14 14 15 15 #include <stdlib> // random … … 18 18 #include <thread> 19 19 #include <unistd.h> // getpid 20 21 bool empty( condition & c ) { 22 return c.blocked.head == NULL; 23 } 20 24 21 25 enum { NoOfPairs = 20 }; … … 27 31 28 32 unsigned int girl( DatingService & mutex ds, unsigned int PhoneNo, unsigned int ccode ) { 29 if ( is_empty( ds.Boys[ccode] ) ) {30 wait( ds.Girls[ccode] );33 if ( empty( ds.Boys[ccode] ) ) { 34 wait( &ds.Girls[ccode] ); 31 35 ds.GirlPhoneNo = PhoneNo; 32 36 } else { 33 37 ds.GirlPhoneNo = PhoneNo; 34 signal_block( ds.Boys[ccode] );38 signal_block( &ds.Boys[ccode] ); 35 39 } // if 36 40 return ds.BoyPhoneNo; … … 38 42 39 43 unsigned int boy( DatingService & mutex ds, unsigned int PhoneNo, unsigned int ccode ) { 40 if ( is_empty( ds.Girls[ccode] ) ) {41 wait( ds.Boys[ccode] );44 if ( empty( ds.Girls[ccode] ) ) { 45 wait( &ds.Boys[ccode] ); 42 46 ds.BoyPhoneNo = PhoneNo; 43 47 } else { 44 48 ds.BoyPhoneNo = PhoneNo; 45 signal_block( ds.Girls[ccode] );49 signal_block( &ds.Girls[ccode] ); 46 50 } // if 47 51 return ds.GirlPhoneNo; -
src/tests/sched-int-barge.c
r121ac13 r9f4524b 73 73 if( action == c.do_wait1 || action == c.do_wait2 ) { 74 74 c.state = WAIT; 75 wait( cond );75 wait( &cond ); 76 76 77 77 if(c.state != SIGNAL) { … … 83 83 c.state = SIGNAL; 84 84 85 signal( cond );86 signal( cond );85 signal( &cond ); 86 signal( &cond ); 87 87 } 88 88 else { -
src/tests/sched-int-block.c
r121ac13 r9f4524b 47 47 //------------------------------------------------------------------------------ 48 48 void wait_op( global_data_t & mutex a, global_data_t & mutex b, unsigned i ) { 49 wait( cond, (uintptr_t)this_thread );49 wait( &cond, (uintptr_t)this_thread ); 50 50 51 51 yield( random( 10 ) ); … … 74 74 [a.last_thread, b.last_thread, a.last_signaller, b.last_signaller] = this_thread; 75 75 76 if( !is_empty( cond ) ) {76 if( !is_empty( &cond ) ) { 77 77 78 thread_desc * next = front( cond );78 thread_desc * next = front( &cond ); 79 79 80 if( ! signal_block( cond ) ) {80 if( ! signal_block( &cond ) ) { 81 81 sout | "ERROR expected to be able to signal" | endl; 82 82 abort(); -
src/tests/sched-int-disjoint.c
r121ac13 r9f4524b 59 59 // Waiting logic 60 60 bool wait( global_t & mutex m, global_data_t & mutex d ) { 61 wait( cond );61 wait( &cond ); 62 62 if( d.state != SIGNAL ) { 63 63 sout | "ERROR barging!" | endl; … … 80 80 //------------------------------------------------------------------------------ 81 81 // Signalling logic 82 void signal( condition &cond, global_t & mutex a, global_data_t & mutex b ) {82 void signal( condition * cond, global_t & mutex a, global_data_t & mutex b ) { 83 83 b.state = SIGNAL; 84 84 signal( cond ); … … 86 86 87 87 void logic( global_t & mutex a ) { 88 signal( cond, a, data );88 signal( &cond, a, data ); 89 89 90 90 yield( random( 10 ) ); -
src/tests/sched-int-wait.c
r121ac13 r9f4524b 41 41 //---------------------------------------------------------------------------------------------------- 42 42 // Tools 43 void signal( condition &cond, global_t & mutex a, global_t & mutex b ) {43 void signal( condition * cond, global_t & mutex a, global_t & mutex b ) { 44 44 signal( cond ); 45 45 } 46 46 47 void signal( condition &cond, global_t & mutex a, global_t & mutex b, global_t & mutex c ) {47 void signal( condition * cond, global_t & mutex a, global_t & mutex b, global_t & mutex c ) { 48 48 signal( cond ); 49 49 } 50 50 51 void wait( condition &cond, global_t & mutex a, global_t & mutex b ) {51 void wait( condition * cond, global_t & mutex a, global_t & mutex b ) { 52 52 wait( cond ); 53 53 } 54 54 55 void wait( condition &cond, global_t & mutex a, global_t & mutex b, global_t & mutex c ) {55 void wait( condition * cond, global_t & mutex a, global_t & mutex b, global_t & mutex c ) { 56 56 wait( cond ); 57 57 } … … 65 65 switch( action ) { 66 66 case 0: 67 signal( condABC, globalA, globalB, globalC );67 signal( &condABC, globalA, globalB, globalC ); 68 68 break; 69 69 case 1: 70 signal( condAB , globalA, globalB );70 signal( &condAB , globalA, globalB ); 71 71 break; 72 72 case 2: 73 signal( condBC , globalB, globalC );73 signal( &condBC , globalB, globalC ); 74 74 break; 75 75 case 3: 76 signal( condAC , globalA, globalC );76 signal( &condAC , globalA, globalC ); 77 77 break; 78 78 default: … … 88 88 void main( WaiterABC & this ) { 89 89 for( int i = 0; i < N; i++ ) { 90 wait( condABC, globalA, globalB, globalC );90 wait( &condABC, globalA, globalB, globalC ); 91 91 } 92 92 … … 98 98 void main( WaiterAB & this ) { 99 99 for( int i = 0; i < N; i++ ) { 100 wait( condAB , globalA, globalB );100 wait( &condAB , globalA, globalB ); 101 101 } 102 102 … … 108 108 void main( WaiterAC & this ) { 109 109 for( int i = 0; i < N; i++ ) { 110 wait( condAC , globalA, globalC );110 wait( &condAC , globalA, globalC ); 111 111 } 112 112 … … 118 118 void main( WaiterBC & this ) { 119 119 for( int i = 0; i < N; i++ ) { 120 wait( condBC , globalB, globalC );120 wait( &condBC , globalB, globalC ); 121 121 } 122 122 -
src/tests/thread.c
r121ac13 r9f4524b 15 15 yield(); 16 16 } 17 V( *this.lock);17 V(this.lock); 18 18 } 19 19 20 20 void main(Second& this) { 21 P( *this.lock);21 P(this.lock); 22 22 for(int i = 0; i < 10; i++) { 23 23 sout | "Second : Suspend No." | i + 1 | endl;
Note:
See TracChangeset
for help on using the changeset viewer.