Changeset d3a804f5 for src/libcfa/concurrency
- Timestamp:
- Feb 14, 2017, 1:19:28 PM (9 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:
- 97d246d
- Parents:
- f923b5f (diff), eafb094 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src/libcfa/concurrency
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/coroutines
rf923b5f rd3a804f5 36 36 void ?{}(coStack_t * this); 37 37 void ?{}(coroutine * this); 38 void ?{}(coroutine * this, const char * name); 38 39 void ^?{}(coStack_t * this); 39 40 void ^?{}(coroutine * this); … … 76 77 "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", 77 78 src->name, src ); 78 assertf( src->last-> notHalted,79 assertf( src->last->state != Halted, 79 80 "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n" 80 81 "Possible cause is terminated coroutine's main routine has already returned.", … … 97 98 // not resuming self ? 98 99 if ( src != dst ) { 99 assertf( dst-> notHalted ,100 assertf( dst->state != Halted , 100 101 "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n" 101 102 "Possible cause is terminated coroutine's main routine has already returned.", … … 115 116 // not resuming self ? 116 117 if ( src != dst ) { 117 assertf( dst-> notHalted ,118 assertf( dst->state != Halted , 118 119 "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n" 119 120 "Possible cause is terminated coroutine's main routine has already returned.", -
src/libcfa/concurrency/coroutines.c
rf923b5f rd3a804f5 61 61 62 62 void ?{}(coroutine* this) { 63 this->name = "Anonymous Coroutine"; 63 this{ "Anonymous Coroutine" }; 64 } 65 66 void ?{}(coroutine* this, const char * name) { 67 this->name = name; 64 68 this->errno_ = 0; 65 69 this->state = Start; 66 this->notHalted = true;67 70 this->starter = NULL; 68 71 this->last = NULL; -
src/libcfa/concurrency/invoke.c
rf923b5f rd3a804f5 48 48 main( this ); 49 49 50 cor->state = Halt; 51 cor->notHalted = false; 50 cor->state = Halted; 52 51 53 52 //Final suspend, should never return -
src/libcfa/concurrency/invoke.h
rf923b5f rd3a804f5 30 30 #define SCHEDULER_CAPACITY 10 31 31 32 struct spinlock { 33 volatile int lock; 34 }; 35 32 36 struct simple_thread_list { 33 37 struct thread * head; 34 38 struct thread ** tail; 39 }; 40 41 struct signal_once { 42 volatile bool condition; 43 struct spinlock lock; 44 struct simple_thread_list blocked; 35 45 }; 36 46 … … 40 50 void append( struct simple_thread_list *, struct thread * ); 41 51 struct thread * pop_head( struct simple_thread_list * ); 52 53 void ?{}(spinlock * this); 54 void ^?{}(spinlock * this); 55 56 void ?{}(signal_once * this); 57 void ^?{}(signal_once * this); 42 58 } 43 59 #endif … … 53 69 }; 54 70 55 enum coroutine_state { Start, Inactive, Active, Halt, Primed };71 enum coroutine_state { Halted, Start, Inactive, Active, Primed }; 56 72 57 73 struct coroutine { … … 60 76 int errno_; // copy of global UNIX variable errno 61 77 enum coroutine_state state; // current execution status for coroutine 62 bool notHalted; // indicate if execuation state is not halted63 64 78 struct coroutine *starter; // first coroutine to resume this one 65 79 struct coroutine *last; // last coroutine to resume this one 66 80 }; 67 81 68 struct simple_lock {69 struct simple_thread_list blocked;70 };71 72 82 struct thread { 73 struct coroutine c; 74 struct si mple_lock lock;75 struct thread * next; 83 struct coroutine c; // coroutine body used to store context 84 struct signal_once terminated;// indicate if execuation state is not halted 85 struct thread * next; // instrusive link field for threads 76 86 }; 77 87 -
src/libcfa/concurrency/kernel
rf923b5f rd3a804f5 9 9 // 10 10 // Author : Thierry Delisle 11 // Created On : Tue Jan 17 12:27:26 201 611 // Created On : Tue Jan 17 12:27:26 2017 12 12 // Last Modified By : Thierry Delisle 13 13 // Last Modified On : -- … … 27 27 28 28 //----------------------------------------------------------------------------- 29 // Locks 30 void lock( spinlock * ); 31 void unlock( spinlock * ); 32 33 void wait( signal_once * ); 34 void signal( signal_once * ); 35 36 //----------------------------------------------------------------------------- 29 37 // Cluster 30 38 struct cluster { 31 39 simple_thread_list ready_queue; 32 pthread_spinlock_tlock;40 spinlock lock; 33 41 }; 34 42 … … 38 46 //----------------------------------------------------------------------------- 39 47 // Processor 48 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule }; 49 struct FinishAction { 50 FinishOpCode action_code; 51 thread * thrd; 52 spinlock * lock; 53 }; 54 static inline void ?{}(FinishAction * this) { 55 this->action_code = No_Action; 56 this->thrd = NULL; 57 this->lock = NULL; 58 } 59 static inline void ^?{}(FinishAction * this) {} 60 40 61 struct processor { 41 struct processorCtx_t * ctx;62 struct processorCtx_t * runner; 42 63 cluster * cltr; 43 64 coroutine * current_coroutine; 44 65 thread * current_thread; 45 66 pthread_t kernel_thread; 46 simple_lock lock; 47 volatile bool terminated; 67 68 signal_once terminated; 69 volatile bool is_terminated; 70 71 struct FinishAction finish; 48 72 }; 49 73 … … 51 75 void ?{}(processor * this, cluster * cltr); 52 76 void ^?{}(processor * this); 53 54 55 //-----------------------------------------------------------------------------56 // Locks57 58 void ?{}(simple_lock * this);59 void ^?{}(simple_lock * this);60 61 void lock( simple_lock * );62 void unlock( simple_lock * );63 64 struct pthread_spinlock_guard {65 pthread_spinlock_t * lock;66 };67 68 static inline void ?{}( pthread_spinlock_guard * this, pthread_spinlock_t * lock ) {69 this->lock = lock;70 pthread_spin_lock( this->lock );71 }72 73 static inline void ^?{}( pthread_spinlock_guard * this ) {74 pthread_spin_unlock( this->lock );75 }76 77 // //Simple spinlock implementation from78 // //http://stackoverflow.com/questions/1383363/is-my-spin-lock-implementation-correct-and-optimal79 // //Not optimal but correct80 // #define VOL81 82 // struct simple_spinlock {83 // VOL int lock;84 // };85 86 // extern VOL int __sync_lock_test_and_set( VOL int *, VOL int);87 // extern void __sync_synchronize();88 89 // static inline void lock( simple_spinlock * this ) {90 // while (__sync_lock_test_and_set(&this->lock, 1)) {91 // // Do nothing. This GCC builtin instruction92 // // ensures memory barrier.93 // }94 // }95 96 // static inline void unlock( simple_spinlock * this ) {97 // __sync_synchronize(); // Memory barrier.98 // this->lock = 0;99 // }100 77 101 78 #endif //KERNEL_H -
src/libcfa/concurrency/kernel.c
rf923b5f rd3a804f5 9 9 // 10 10 // Author : Thierry Delisle 11 // Created On : Tue Jan 17 12:27:26 201 611 // Created On : Tue Jan 17 12:27:26 2017 12 12 // Last Modified By : Thierry Delisle 13 13 // Last Modified On : -- … … 20 20 21 21 //Header 22 #include "kernel "22 #include "kernel_private.h" 23 23 24 24 //C Includes 25 25 #include <stddef.h> 26 26 extern "C" { 27 #include <fenv.h> 27 28 #include <sys/resource.h> 28 29 } … … 30 31 //CFA Includes 31 32 #include "libhdr.h" 32 #include "threads"33 33 34 34 //Private includes … … 38 38 //----------------------------------------------------------------------------- 39 39 // Kernel storage 40 struct processorCtx_t {41 processor * proc;42 coroutine c;43 };44 45 DECL_COROUTINE(processorCtx_t);46 47 40 #define KERNEL_STORAGE(T,X) static char X##_storage[sizeof(T)] 48 41 … … 92 85 93 86 rlimit r; 94 int ret =getrlimit( RLIMIT_STACK, &r);87 getrlimit( RLIMIT_STACK, &r); 95 88 this->size = r.rlim_cur; 96 89 … … 114 107 this->name = "Main Thread"; 115 108 this->errno_ = 0; 116 this->state = Inactive; 117 this->notHalted = true; 109 this->state = Start; 118 110 } 119 111 … … 127 119 (&this->c){}; 128 120 this->proc = proc; 129 proc-> ctx= this;121 proc->runner = this; 130 122 } 131 123 … … 133 125 (&this->c){ info }; 134 126 this->proc = proc; 135 proc->ctx = this; 136 } 137 138 void start(processor * this); 127 proc->runner = this; 128 } 139 129 140 130 void ?{}(processor * this) { … … 146 136 this->current_coroutine = NULL; 147 137 this->current_thread = NULL; 148 (&this-> lock){};149 this-> terminated = false;138 (&this->terminated){}; 139 this->is_terminated = false; 150 140 151 141 start( this ); 152 142 } 153 143 154 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) {144 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) { 155 145 this->cltr = cltr; 156 146 this->current_coroutine = NULL; 157 147 this->current_thread = NULL; 158 (&this-> lock){};159 this-> terminated = false;160 161 this-> ctx = ctx;162 LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx);163 ctx{ this };148 (&this->terminated){}; 149 this->is_terminated = false; 150 151 this->runner = runner; 152 LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", runner); 153 runner{ this }; 164 154 } 165 155 166 156 void ^?{}(processor * this) { 167 if( ! this-> terminated ) {157 if( ! this->is_terminated ) { 168 158 LIB_DEBUG_PRINTF("Kernel : core %p signaling termination\n", this); 169 this-> terminated = true;170 lock( &this->lock);159 this->is_terminated = true; 160 wait( &this->terminated ); 171 161 } 172 162 } … … 174 164 void ?{}(cluster * this) { 175 165 ( &this->ready_queue ){}; 176 pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE );166 ( &this->lock ){}; 177 167 } 178 168 179 169 void ^?{}(cluster * this) { 180 pthread_spin_destroy( &this->lock ); 181 } 182 183 //----------------------------------------------------------------------------- 184 // Processor running routines 185 void main(processorCtx_t * ctx); 186 thread * nextThread(cluster * this); 187 void scheduleInternal(processor * this, thread * dst); 188 void spin(processor * this, unsigned int * spin_count); 189 190 void main(processorCtx_t * ctx) { 191 processor * this = ctx->proc; 170 171 } 172 173 //============================================================================================= 174 // Kernel Scheduling logic 175 //============================================================================================= 176 //Main of the processor contexts 177 void main(processorCtx_t * runner) { 178 processor * this = runner->proc; 192 179 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this); 193 180 194 181 thread * readyThread = NULL; 195 for( unsigned int spin_count = 0; ! this-> terminated; spin_count++ ) {196 182 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 183 { 197 184 readyThread = nextThread( this->cltr ); 198 185 199 if(readyThread) { 200 scheduleInternal(this, readyThread); 186 if(readyThread) 187 { 188 runThread(this, readyThread); 189 190 //Some actions need to be taken from the kernel 191 finishRunning(this); 192 201 193 spin_count = 0; 202 } else { 194 } 195 else 196 { 203 197 spin(this, &spin_count); 204 198 } … … 206 200 207 201 LIB_DEBUG_PRINTF("Kernel : core %p unlocking thread\n", this); 208 unlock( &this->lock);202 signal( &this->terminated ); 209 203 LIB_DEBUG_PRINTF("Kernel : core %p terminated\n", this); 210 204 } 211 205 212 //Declarations for scheduleInternal 213 extern void ThreadCtxSwitch(coroutine * src, coroutine * dst); 214 215 // scheduleInternal runs a thread by context switching 206 // runThread runs a thread by context switching 216 207 // from the processor coroutine to the target thread 217 void scheduleInternal(processor * this, thread * dst) { 218 // coroutine * proc_ctx = get_coroutine(this->ctx); 219 // coroutine * thrd_ctx = get_coroutine(dst); 220 221 // //Update global state 222 // this->current_thread = dst; 223 224 // // Context Switch to the thread 225 // ThreadCtxSwitch(proc_ctx, thrd_ctx); 226 // // when ThreadCtxSwitch returns we are back in the processor coroutine 227 228 coroutine * proc_ctx = get_coroutine(this->ctx); 229 coroutine * thrd_ctx = get_coroutine(dst); 230 thrd_ctx->last = proc_ctx; 231 232 // context switch to specified coroutine 233 // Which is now the current_coroutine 234 LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine); 235 this->current_thread = dst; 236 this->current_coroutine = thrd_ctx; 237 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context ); 238 this->current_coroutine = proc_ctx; 239 LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine); 240 241 // when CtxSwitch returns we are back in the processor coroutine 208 void runThread(processor * this, thread * dst) { 209 coroutine * proc_cor = get_coroutine(this->runner); 210 coroutine * thrd_cor = get_coroutine(dst); 211 212 //Reset the terminating actions here 213 this->finish.action_code = No_Action; 214 215 //Update global state 216 this->current_thread = dst; 217 218 // Context Switch to the thread 219 ThreadCtxSwitch(proc_cor, thrd_cor); 220 // when ThreadCtxSwitch returns we are back in the processor coroutine 221 } 222 223 // Once a thread has finished running, some of 224 // its final actions must be executed from the kernel 225 void finishRunning(processor * this) { 226 if( this->finish.action_code == Release ) { 227 unlock( this->finish.lock ); 228 } 229 else if( this->finish.action_code == Schedule ) { 230 ScheduleThread( this->finish.thrd ); 231 } 232 else if( this->finish.action_code == Release_Schedule ) { 233 unlock( this->finish.lock ); 234 ScheduleThread( this->finish.thrd ); 235 } 236 else { 237 assert(this->finish.action_code == No_Action); 238 } 242 239 } 243 240 … … 262 259 processorCtx_t proc_cor_storage = { proc, &info }; 263 260 261 LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage.c.stack.base); 262 264 263 //Set global state 265 proc->current_coroutine = &proc-> ctx->c;264 proc->current_coroutine = &proc->runner->c; 266 265 proc->current_thread = NULL; 267 266 268 267 //We now have a proper context from which to schedule threads 269 LIB_DEBUG_PRINTF("Kernel : core %p created (%p )\n", proc, proc->ctx);268 LIB_DEBUG_PRINTF("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx); 270 269 271 270 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't … … 275 274 proc_cor_storage.c.state = Active; 276 275 main( &proc_cor_storage ); 277 proc_cor_storage.c.state = Halt; 278 proc_cor_storage.c.notHalted = false; 276 proc_cor_storage.c.state = Halted; 279 277 280 278 // Main routine of the core returned, the core is now fully terminated 281 LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc-> ctx);279 LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->runner); 282 280 283 281 return NULL; … … 287 285 LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this); 288 286 289 pthread_attr_t attributes;290 pthread_attr_init( &attributes );291 292 pthread_create( &this->kernel_thread, &attributes, CtxInvokeProcessor, (void*)this );293 294 pthread_attr_destroy( &attributes );287 // pthread_attr_t attributes; 288 // pthread_attr_init( &attributes ); 289 290 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 291 292 // pthread_attr_destroy( &attributes ); 295 293 296 294 LIB_DEBUG_PRINTF("Kernel : core %p started\n", this); … … 299 297 //----------------------------------------------------------------------------- 300 298 // Scheduler routines 301 void thread_schedule( thread * thrd ) {299 void ScheduleThread( thread * thrd ) { 302 300 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 303 301 304 pthread_spinlock_guard guard = { &systemProcessor->cltr->lock };302 lock( &systemProcessor->cltr->lock ); 305 303 append( &systemProcessor->cltr->ready_queue, thrd ); 304 unlock( &systemProcessor->cltr->lock ); 306 305 } 307 306 308 307 thread * nextThread(cluster * this) { 309 pthread_spinlock_guard guard = { &this->lock }; 310 return pop_head( &this->ready_queue ); 308 lock( &this->lock ); 309 thread * head = pop_head( &this->ready_queue ); 310 unlock( &this->lock ); 311 return head; 312 } 313 314 void ScheduleInternal() { 315 suspend(); 316 } 317 318 void ScheduleInternal( spinlock * lock ) { 319 get_this_processor()->finish.action_code = Release; 320 get_this_processor()->finish.lock = lock; 321 suspend(); 322 } 323 324 void ScheduleInternal( thread * thrd ) { 325 get_this_processor()->finish.action_code = Schedule; 326 get_this_processor()->finish.thrd = thrd; 327 suspend(); 328 } 329 330 void ScheduleInternal( spinlock * lock, thread * thrd ) { 331 get_this_processor()->finish.action_code = Release_Schedule; 332 get_this_processor()->finish.lock = lock; 333 get_this_processor()->finish.thrd = thrd; 334 suspend(); 311 335 } 312 336 … … 314 338 // Kernel boot procedures 315 339 void kernel_startup(void) { 316 340 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 341 342 // Start by initializing the main thread 317 343 // SKULLDUGGERY: the mainThread steals the process main thread 318 344 // which will then be scheduled by the systemProcessor normally 319 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 320 345 mainThread = (thread *)&mainThread_storage; 321 346 current_stack_info_t info; 322 323 // LIB_DEBUG_PRINTF("Kernel : core base : %p \n", info.base );324 // LIB_DEBUG_PRINTF("Kernel : core storage : %p \n", info.storage );325 // LIB_DEBUG_PRINTF("Kernel : core size : %x \n", info.size );326 // LIB_DEBUG_PRINTF("Kernel : core limit : %p \n", info.limit );327 // LIB_DEBUG_PRINTF("Kernel : core context : %p \n", info.context );328 // LIB_DEBUG_PRINTF("Kernel : core top : %p \n", info.top );329 330 // Start by initializing the main thread331 mainThread = (thread *)&mainThread_storage;332 347 mainThread{ &info }; 333 348 … … 343 358 // Add the main thread to the ready queue 344 359 // once resume is called on systemProcessor->ctx the mainThread needs to be scheduled like any normal thread 345 thread_schedule(mainThread);360 ScheduleThread(mainThread); 346 361 347 362 //initialize the global state variables … … 353 368 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 354 369 // mainThread is on the ready queue when this call is made. 355 resume(systemProcessor-> ctx);370 resume(systemProcessor->runner); 356 371 357 372 358 373 359 374 // THE SYSTEM IS NOW COMPLETELY RUNNING 360 361 362 363 375 LIB_DEBUG_PRINTF("Kernel : Started\n--------------------------------------------------\n\n"); 364 376 } … … 370 382 // When its coroutine terminates, it return control to the mainThread 371 383 // which is currently here 372 systemProcessor-> terminated = true;384 systemProcessor->is_terminated = true; 373 385 suspend(); 374 386 … … 377 389 // Destroy the system processor and its context in reverse order of construction 378 390 // These were manually constructed so we need manually destroy them 379 ^(systemProcessor-> ctx){};391 ^(systemProcessor->runner){}; 380 392 ^(systemProcessor){}; 381 393 … … 389 401 //----------------------------------------------------------------------------- 390 402 // Locks 391 void ?{}( simple_lock * this ) { 392 ( &this->blocked ){}; 393 } 394 395 void ^?{}( simple_lock * this ) { 396 397 } 398 399 void lock( simple_lock * this ) { 403 void ?{}( spinlock * this ) { 404 this->lock = 0; 405 } 406 void ^?{}( spinlock * this ) { 407 408 } 409 410 void lock( spinlock * this ) { 411 for ( unsigned int i = 1;; i += 1 ) { 412 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break; 413 } 414 } 415 416 void unlock( spinlock * this ) { 417 __sync_lock_release_4( &this->lock ); 418 } 419 420 void ?{}( signal_once * this ) { 421 this->condition = false; 422 } 423 void ^?{}( signal_once * this ) { 424 425 } 426 427 void wait( signal_once * this ) { 428 lock( &this->lock ); 429 if( !this->condition ) { 430 append( &this->blocked, this_thread() ); 431 ScheduleInternal( &this->lock ); 432 lock( &this->lock ); 433 } 434 unlock( &this->lock ); 435 } 436 437 void signal( signal_once * this ) { 438 lock( &this->lock ); 400 439 { 401 pthread_spinlock_guard guard = { &systemCluster->lock }; //HUGE TEMP HACK which only works if we have a single cluster and is stupid 402 append( &this->blocked, this_thread() ); 403 } 404 suspend(); 405 } 406 407 void unlock( simple_lock * this ) { 408 thread * it; 409 while( it = pop_head( &this->blocked) ) { 410 thread_schedule( it ); 411 } 440 this->condition = true; 441 442 thread * it; 443 while( it = pop_head( &this->blocked) ) { 444 ScheduleThread( it ); 445 } 446 } 447 unlock( &this->lock ); 412 448 } 413 449 -
src/libcfa/concurrency/threads.c
rf923b5f rd3a804f5 17 17 #include "threads" 18 18 19 #include "kernel "19 #include "kernel_private.h" 20 20 #include "libhdr.h" 21 21 … … 24 24 25 25 extern "C" { 26 #include <fenv.h> 26 27 #include <stddef.h> 27 28 } … … 43 44 (&this->c){}; 44 45 this->c.name = "Anonymous Coroutine"; 45 (&this-> lock){};46 (&this->terminated){}; 46 47 this->next = NULL; 47 48 } … … 71 72 //----------------------------------------------------------------------------- 72 73 // Starting and stopping threads 73 extern "C" {74 forall(dtype T | is_thread(T))75 void CtxInvokeThread(T * this);76 }77 78 extern void thread_schedule( thread * );79 80 74 forall( dtype T | is_thread(T) ) 81 75 void start( T* this ) { … … 91 85 CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context ); 92 86 93 LIB_DEBUG_PRINTF("Thread started : %p (t %p, c %p)\n", this, thrd_c, thrd_h); 94 95 thread_schedule(thrd_h); 87 ScheduleThread(thrd_h); 96 88 } 97 89 98 90 forall( dtype T | is_thread(T) ) 99 91 void stop( T* this ) { 100 thread* thrd = get_thread(this); 101 if( thrd->c.notHalted ) { 102 lock( &thrd->lock ); 103 } 92 wait( & get_thread(this)->terminated ); 104 93 } 105 94 106 95 void yield( void ) { 107 thread_schedule( this_thread() ); 108 suspend(); 96 ScheduleInternal( get_this_processor()->current_thread ); 109 97 } 110 98 111 99 void ThreadCtxSwitch(coroutine* src, coroutine* dst) { 100 // set state of current coroutine to inactive 101 src->state = Inactive; 102 dst->state = Active; 103 104 //update the last resumer 112 105 dst->last = src; 113 106 114 // set state of current coroutine to inactive 115 src->state = Inactive; 116 117 // set new coroutine that task is executing 107 // set new coroutine that the processor is executing 108 // and context switch to it 118 109 get_this_processor()->current_coroutine = dst; 119 120 // context switch to specified coroutine121 110 CtxSwitch( src->stack.context, dst->stack.context ); 122 // when CtxSwitch returns we are back in the src coroutine111 get_this_processor()->current_coroutine = src; 123 112 124 113 // set state of new coroutine to active 114 dst->state = Inactive; 125 115 src->state = Active; 126 116 } … … 130 120 extern "C" { 131 121 void __thread_signal_termination( thread * this ) { 132 this->c.state = Halt ;133 this->c.notHalted = false;134 unlock( &this->lock );122 this->c.state = Halted; 123 LIB_DEBUG_PRINTF("Thread end : %p\n", this); 124 signal( &this->terminated ); 135 125 } 136 126 }
Note:
See TracChangeset
for help on using the changeset viewer.