Changeset 5ea06d6
- Timestamp:
- Mar 31, 2017, 1:04:21 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 23063ea
- Parents:
- 78d3dd5
- Location:
- src
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/invoke.h
r78d3dd5 r5ea06d6 33 33 }; 34 34 35 struct simple_thread_list {35 struct __thread_queue_t { 36 36 struct thread_desc * head; 37 37 struct thread_desc ** tail; 38 38 }; 39 39 40 struct simple_thread_stack{40 struct __thread_stack_t { 41 41 struct thread_desc * top; 42 42 }; … … 44 44 #ifdef __CFORALL__ 45 45 extern "Cforall" { 46 void ?{}( struct simple_thread_list * );47 void append( struct simple_thread_list *, struct thread_desc * );48 struct thread_desc * pop_head( struct simple_thread_list * );46 void ?{}( struct __thread_queue_t * ); 47 void append( struct __thread_queue_t *, struct thread_desc * ); 48 struct thread_desc * pop_head( struct __thread_queue_t * ); 49 49 50 void ?{}( struct simple_thread_stack* );51 void push( struct simple_thread_stack*, struct thread_desc * );52 struct thread_desc * pop( struct simple_thread_stack* );50 void ?{}( struct __thread_stack_t * ); 51 void push( struct __thread_stack_t *, struct thread_desc * ); 52 struct thread_desc * pop( struct __thread_stack_t * ); 53 53 54 54 void ?{}(spinlock * this); … … 58 58 59 59 struct coStack_t { 60 unsigned int size; // size of stack61 void *storage; // pointer to stack62 void *limit; // stack grows towards stack limit63 void *base; // base of stack64 void *context; // address of cfa_context_t65 void *top; // address of top of storage66 bool userStack; // whether or not the user allocated the stack60 unsigned int size; // size of stack 61 void *storage; // pointer to stack 62 void *limit; // stack grows towards stack limit 63 void *base; // base of stack 64 void *context; // address of cfa_context_t 65 void *top; // address of top of storage 66 bool userStack; // whether or not the user allocated the stack 67 67 }; 68 68 … … 70 70 71 71 struct coroutine_desc { 72 struct coStack_t stack; // stack information of the coroutine73 const char *name; // textual name for coroutine/task, initialized by uC++ generated code74 int errno_; // copy of global UNIX variable errno75 enum coroutine_state state; // current execution status for coroutine76 struct coroutine_desc *starter; // first coroutine to resume this one77 struct coroutine_desc *last; // last coroutine to resume this one72 struct coStack_t stack; // stack information of the coroutine 73 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 74 int errno_; // copy of global UNIX variable errno 75 enum coroutine_state state; // current execution status for coroutine 76 struct coroutine_desc *starter; // first coroutine to resume this one 77 struct coroutine_desc *last; // last coroutine to resume this one 78 78 }; 79 79 80 80 struct monitor_desc { 81 struct spinlock lock; 82 struct thread_desc * owner; 83 struct simple_thread_list entry_queue;84 struct simple_thread_stack signal_stack;85 struct monitor_desc * stack_owner; 86 unsigned int recursion; 81 struct spinlock lock; // spinlock to protect internal data 82 struct thread_desc * owner; // current owner of the monitor 83 struct __thread_queue_t entry_queue; // queue of threads that are blocked waiting for the monitor 84 struct __thread_stack_t signal_stack; // stack of threads to run next once we exit the monitor 85 struct monitor_desc * stack_owner; // if bulk acquiring was used we need to synchronize signals with an other monitor 86 unsigned int recursion; // monitor routines can be called recursively, we need to keep track of that 87 87 }; 88 88 89 89 struct thread_desc { 90 struct coroutine_desc cor; // coroutine body used to store context 91 struct monitor_desc mon; // monitor body used for mutual exclusion 92 struct thread_desc * next; // instrusive link field for threads 90 struct coroutine_desc cor; // coroutine body used to store context 91 struct monitor_desc mon; // monitor body used for mutual exclusion 92 struct thread_desc * next; // instrusive link field for threads 93 struct monitor_desc ** current_monitors; // currently held monitors 94 unsigned short current_monitor_count; // number of currently held monitors 93 95 }; 94 96 -
src/libcfa/concurrency/kernel
r78d3dd5 r5ea06d6 32 32 33 33 struct signal_once { 34 volatile bool cond ition;34 volatile bool cond; 35 35 struct spinlock lock; 36 struct simple_thread_list blocked;36 struct __thread_queue_t blocked; 37 37 }; 38 38 … … 46 46 // Cluster 47 47 struct cluster { 48 simple_thread_list ready_queue;48 __thread_queue_t ready_queue; 49 49 spinlock lock; 50 50 }; -
src/libcfa/concurrency/kernel.c
r78d3dd5 r5ea06d6 475 475 476 476 void ?{}( signal_once * this ) { 477 this->cond ition= false;477 this->cond = false; 478 478 } 479 479 void ^?{}( signal_once * this ) { … … 483 483 void wait( signal_once * this ) { 484 484 lock( &this->lock ); 485 if( !this->cond ition) {485 if( !this->cond ) { 486 486 append( &this->blocked, this_thread() ); 487 487 ScheduleInternal( &this->lock ); … … 494 494 lock( &this->lock ); 495 495 { 496 this->cond ition= true;496 this->cond = true; 497 497 498 498 thread_desc * it; … … 506 506 //----------------------------------------------------------------------------- 507 507 // Queues 508 void ?{}( simple_thread_list * this ) {508 void ?{}( __thread_queue_t * this ) { 509 509 this->head = NULL; 510 510 this->tail = &this->head; 511 511 } 512 512 513 void append( simple_thread_list * this, thread_desc * t ) {513 void append( __thread_queue_t * this, thread_desc * t ) { 514 514 assert(this->tail != NULL); 515 515 *this->tail = t; … … 517 517 } 518 518 519 thread_desc * pop_head( simple_thread_list * this ) {519 thread_desc * pop_head( __thread_queue_t * this ) { 520 520 thread_desc * head = this->head; 521 521 if( head ) { … … 529 529 } 530 530 531 void ?{}( simple_thread_stack* this ) {531 void ?{}( __thread_stack_t * this ) { 532 532 this->top = NULL; 533 533 } 534 534 535 void push( simple_thread_stack* this, thread_desc * t ) {535 void push( __thread_stack_t * this, thread_desc * t ) { 536 536 assert(t->next != NULL); 537 537 t->next = this->top; … … 539 539 } 540 540 541 thread_desc * pop( simple_thread_stack* this ) {541 thread_desc * pop( __thread_stack_t * this ) { 542 542 thread_desc * top = this->top; 543 543 if( top ) { -
src/libcfa/concurrency/monitor
r78d3dd5 r5ea06d6 30 30 } 31 31 32 //Array entering routine33 void enter(monitor_desc **, int count);34 void leave(monitor_desc **, int count);35 36 32 struct monitor_guard_t { 37 33 monitor_desc ** m; 38 34 int count; 35 monitor_desc ** prev_mntrs; 36 unsigned short prev_count; 39 37 }; 40 38 … … 43 41 } 44 42 45 static inline void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) { 46 this->m = m; 47 this->count = count; 48 qsort(this->m, count); 49 enter( this->m, this->count ); 43 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ); 44 void ^?{}( monitor_guard_t * this ); 45 46 //----------------------------------------------------------------------------- 47 // Internal scheduling 48 struct condition { 49 __thread_queue_t blocked; 50 monitor_desc ** monitors; 51 unsigned short monitor_count; 52 }; 53 54 static inline void ?{}( condition * this ) { 55 this->monitors = NULL; 56 this->monitor_count = 0; 50 57 } 51 58 52 static inline void ^?{}( monitor_guard_t * this ) { 53 leave( this->m, this->count ); 54 } 55 56 59 void wait( condition * this ); 60 void signal( condition * this ); 57 61 #endif //MONITOR_H -
src/libcfa/concurrency/monitor.c
r78d3dd5 r5ea06d6 18 18 19 19 #include "kernel_private.h" 20 #include "libhdr.h" 20 21 21 22 void set_owner( monitor_desc * this, thread_desc * owner ) { … … 28 29 29 30 extern "C" { 30 void __enter_monitor_desc(monitor_desc * this ) {31 void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) { 31 32 lock( &this->lock ); 32 33 thread_desc * thrd = this_thread(); 34 35 //Update the stack owner 36 this->stack_owner = leader; 33 37 34 38 if( !this->owner ) { … … 52 56 53 57 unlock( &this->lock ); 58 return; 54 59 } 55 60 … … 69 74 // context switch to him right away 70 75 // 71 void __leave_monitor_desc(monitor_desc * this ) {76 void __leave_monitor_desc(monitor_desc * this, monitor_desc * leader) { 72 77 lock( &this->lock ); 73 78 74 79 thread_desc * thrd = this_thread(); 75 assert( thrd == this->owner );80 assert( thrd == this->owner || this->stack_owner ); 76 81 77 82 //Leaving a recursion level, decrement the counter … … 81 86 //it means we don't need to do anything 82 87 if( this->recursion != 0) { 88 this->stack_owner = leader; 83 89 unlock( &this->lock ); 84 90 return; … … 87 93 //If we don't own the signal stack then just leave it to the owner 88 94 if( this->stack_owner ) { 89 assert( this->owner == this->stack_owner );95 this->stack_owner = leader; 90 96 unlock( &this->lock ); 91 97 return; … … 102 108 //transfer control immediately 103 109 set_owner( this, new_owner ); 110 this->stack_owner = leader; 104 111 ScheduleInternal( &this->lock, new_owner ); 105 112 return; … … 111 118 set_owner( this, new_owner ); 112 119 120 //Update the stack owner 121 this->stack_owner = leader; 122 113 123 //We can now let other threads in safely 114 124 unlock( &this->lock ); … … 119 129 } 120 130 121 void enter(monitor_desc ** monitors, int count) { 122 for(int i = 0; i < count; i++) { 123 __enter_monitor_desc( monitors[i] ); 124 } 125 } 126 127 void leave(monitor_desc ** monitors, int count) { 131 static inline void enter(monitor_desc ** monitors, int count) { 132 __enter_monitor_desc( monitors[0], NULL ); 133 for(int i = 1; i < count; i++) { 134 __enter_monitor_desc( monitors[i], monitors[0] ); 135 } 136 } 137 138 static inline void leave(monitor_desc ** monitors, int count) { 139 __leave_monitor_desc( monitors[0], NULL ); 128 140 for(int i = count - 1; i >= 0; i--) { 129 __leave_monitor_desc( monitors[i] ); 130 } 131 } 141 __leave_monitor_desc( monitors[i], monitors[0] ); 142 } 143 } 144 145 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) { 146 this->m = m; 147 this->count = count; 148 qsort(this->m, count); 149 enter( this->m, this->count ); 150 151 this->prev_mntrs = this_thread()->current_monitors; 152 this->prev_count = this_thread()->current_monitor_count; 153 154 this_thread()->current_monitors = m; 155 this_thread()->current_monitor_count = count; 156 } 157 158 void ^?{}( monitor_guard_t * this ) { 159 leave( this->m, this->count ); 160 161 this_thread()->current_monitors = this->prev_mntrs; 162 this_thread()->current_monitor_count = this->prev_count; 163 } 164 165 //----------------------------------------------------------------------------- 166 // Internal scheduling 167 void wait( condition * this ) { 168 // LIB_DEBUG_FPRINTF("Waiting\n"); 169 thread_desc * this_thrd = this_thread(); 170 171 if( !this->monitors ) { 172 this->monitors = this_thrd->current_monitors; 173 this->monitor_count = this_thrd->current_monitor_count; 174 } 175 176 unsigned short count = this->monitor_count; 177 178 //Check that everything is as expected 179 assert( this->monitors != NULL ); 180 assert( this->monitor_count != 0 ); 181 182 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 183 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal 184 185 // LIB_DEBUG_FPRINTF("Getting ready to wait\n"); 186 187 //Loop on all the monitors and release the owner 188 for( unsigned int i = 0; i < count; i++ ) { 189 monitor_desc * cur = this->monitors[i]; 190 191 assert( cur ); 192 193 // LIB_DEBUG_FPRINTF("cur %p lock %p\n", cur, &cur->lock); 194 195 //Store the locks for later 196 locks[i] = &cur->lock; 197 198 //Protect the monitors 199 lock( locks[i] ); 200 { 201 //Save the recursion levels 202 recursions[i] = cur->recursion; 203 204 //Release the owner 205 cur->recursion = 0; 206 cur->owner = NULL; 207 } 208 //Release the monitor 209 unlock( locks[i] ); 210 } 211 212 // LIB_DEBUG_FPRINTF("Waiting now\n"); 213 214 //Everything is ready to go to sleep 215 ScheduleInternal( locks, count ); 216 217 218 //WE WOKE UP 219 220 221 //We are back, restore the owners and recursions 222 for( unsigned int i = 0; i < count; i++ ) { 223 monitor_desc * cur = this->monitors[i]; 224 225 //Protect the monitors 226 lock( locks[i] ); 227 { 228 //Release the owner 229 cur->owner = this_thrd; 230 cur->recursion = recursions[i]; 231 } 232 //Release the monitor 233 unlock( locks[i] ); 234 } 235 } 236 237 static void __signal_internal( condition * this ) { 238 if( !this->blocked.head ) return; 239 240 //Check that everything is as expected 241 assert( this->monitors ); 242 assert( this->monitor_count != 0 ); 243 244 LIB_DEBUG_DO( 245 if ( this->monitors != this_thread()->current_monitors ) { 246 abortf( "Signal on condition %p made outside of the correct monitor(s)", this ); 247 } // if 248 ); 249 250 monitor_desc * owner = this->monitors[0]; 251 lock( &owner->lock ); 252 { 253 thread_desc * unblock = pop_head( &this->blocked ); 254 push( &owner->signal_stack, unblock ); 255 } 256 unlock( &owner->lock ); 257 } 258 259 void signal( condition * this ) { 260 __signal_internal( this ); 261 } -
src/libcfa/concurrency/thread.c
r78d3dd5 r5ea06d6 39 39 this->mon.recursion = 1; 40 40 this->next = NULL; 41 42 this->current_monitors = NULL; 43 this->current_monitor_count = 0; 41 44 } 42 45
Note: See TracChangeset
for help on using the changeset viewer.