Changes in / [a073d46:e994912]
- Location:
- src
- Files:
-
- 1 deleted
- 5 edited
-
examples/multicore.c (deleted)
-
libcfa/concurrency/coroutines (modified) (1 diff)
-
libcfa/concurrency/coroutines.c (modified) (2 diffs)
-
libcfa/concurrency/kernel (modified) (4 diffs)
-
libcfa/concurrency/kernel.c (modified) (18 diffs)
-
libcfa/concurrency/threads.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/coroutines
ra073d46 re994912 36 36 void ?{}(coStack_t * this); 37 37 void ?{}(coroutine * this); 38 void ?{}(coroutine * this, const char * name);39 38 void ^?{}(coStack_t * this); 40 39 void ^?{}(coroutine * this); -
src/libcfa/concurrency/coroutines.c
ra073d46 re994912 62 62 void ?{}(coroutine* this) { 63 63 this->name = "Anonymous Coroutine"; 64 this->errno_ = 0;65 this->state = Start;66 this->notHalted = true;67 this->starter = NULL;68 this->last = NULL;69 }70 71 void ?{}(coroutine* this, const char * name) {72 this->name = name;73 64 this->errno_ = 0; 74 65 this->state = Start; … … 169 160 this->context = this->base; 170 161 this->top = (char *)this->context + cxtSize; 171 172 LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", this->base);173 162 } 174 163 -
src/libcfa/concurrency/kernel
ra073d46 re994912 30 30 struct cluster { 31 31 simple_thread_list ready_queue; 32 //pthread_spinlock_t lock;32 pthread_spinlock_t lock; 33 33 }; 34 34 … … 38 38 //----------------------------------------------------------------------------- 39 39 // Processor 40 enum ProcessorAction {41 Reschedule,42 NoAction43 };44 45 40 struct processor { 46 struct processorCtx_t * runner;41 struct processorCtx_t * ctx; 47 42 cluster * cltr; 48 43 coroutine * current_coroutine; … … 51 46 simple_lock lock; 52 47 volatile bool terminated; 53 ProcessorAction thread_action;54 48 }; 55 49 … … 68 62 void unlock( simple_lock * ); 69 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 from 78 // //http://stackoverflow.com/questions/1383363/is-my-spin-lock-implementation-correct-and-optimal 79 // //Not optimal but correct 80 // #define VOL 81 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 instruction 92 // // 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 70 101 #endif //KERNEL_H 71 102 -
src/libcfa/concurrency/kernel.c
ra073d46 re994912 25 25 #include <stddef.h> 26 26 extern "C" { 27 #include <fenv.h>28 27 #include <sys/resource.h> 29 28 } … … 36 35 #define __CFA_INVOKE_PRIVATE__ 37 36 #include "invoke.h" 38 39 static volatile int lock;40 41 void spin_lock( volatile int *lock ) {42 for ( unsigned int i = 1;; i += 1 ) {43 if ( *lock == 0 && __sync_lock_test_and_set_4( lock, 1 ) == 0 ) break;44 }45 }46 47 void spin_unlock( volatile int *lock ) {48 __sync_lock_release_4( lock );49 }50 37 51 38 //----------------------------------------------------------------------------- … … 140 127 (&this->c){}; 141 128 this->proc = proc; 142 proc-> runner= this;129 proc->ctx = this; 143 130 } 144 131 … … 146 133 (&this->c){ info }; 147 134 this->proc = proc; 148 proc-> runner= this;135 proc->ctx = this; 149 136 } 150 137 … … 165 152 } 166 153 167 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {154 void ?{}(processor * this, cluster * cltr, processorCtx_t * ctx) { 168 155 this->cltr = cltr; 169 156 this->current_coroutine = NULL; … … 172 159 this->terminated = false; 173 160 174 this-> runner = runner;175 LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", runner);176 runner{ this };161 this->ctx = ctx; 162 LIB_DEBUG_PRINTF("Kernel : constructing processor context %p\n", ctx); 163 ctx{ this }; 177 164 } 178 165 … … 187 174 void ?{}(cluster * this) { 188 175 ( &this->ready_queue ){}; 189 lock = 0;176 pthread_spin_init( &this->lock, PTHREAD_PROCESS_PRIVATE ); 190 177 } 191 178 192 179 void ^?{}(cluster * this) { 193 180 pthread_spin_destroy( &this->lock ); 194 181 } 195 182 196 183 //----------------------------------------------------------------------------- 197 184 // Processor running routines 198 void main(processorCtx_t * );185 void main(processorCtx_t * ctx); 199 186 thread * nextThread(cluster * this); 200 187 void scheduleInternal(processor * this, thread * dst); 201 188 void spin(processor * this, unsigned int * spin_count); 202 void thread_schedule( thread * thrd ); 203 204 //Main of the processor contexts 205 void main(processorCtx_t * runner) { 206 processor * this = runner->proc; 189 190 void main(processorCtx_t * ctx) { 191 processor * this = ctx->proc; 207 192 LIB_DEBUG_PRINTF("Kernel : core %p starting\n", this); 208 209 fenv_t envp;210 fegetenv( &envp );211 LIB_DEBUG_PRINTF("Kernel : mxcsr %x\n", envp.__mxcsr);212 193 213 194 thread * readyThread = NULL; … … 235 216 // from the processor coroutine to the target thread 236 217 void scheduleInternal(processor * this, thread * dst) { 237 this->thread_action = NoAction;238 239 218 // coroutine * proc_ctx = get_coroutine(this->ctx); 240 219 // coroutine * thrd_ctx = get_coroutine(dst); … … 247 226 // // when ThreadCtxSwitch returns we are back in the processor coroutine 248 227 249 coroutine * proc_ctx = get_coroutine(this-> runner);228 coroutine * proc_ctx = get_coroutine(this->ctx); 250 229 coroutine * thrd_ctx = get_coroutine(dst); 251 230 thrd_ctx->last = proc_ctx; … … 253 232 // context switch to specified coroutine 254 233 // Which is now the current_coroutine 255 //LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);234 LIB_DEBUG_PRINTF("Kernel : switching to ctx %p (from %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine); 256 235 this->current_thread = dst; 257 236 this->current_coroutine = thrd_ctx; 258 237 CtxSwitch( proc_ctx->stack.context, thrd_ctx->stack.context ); 259 238 this->current_coroutine = proc_ctx; 260 //LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine);239 LIB_DEBUG_PRINTF("Kernel : returned from ctx %p (to %p, current %p)\n", thrd_ctx, proc_ctx, this->current_coroutine); 261 240 262 241 // when CtxSwitch returns we are back in the processor coroutine 263 if(this->thread_action == Reschedule) {264 thread_schedule( dst );265 }266 242 } 267 243 … … 286 262 processorCtx_t proc_cor_storage = { proc, &info }; 287 263 288 LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage.c.stack.base);289 290 264 //Set global state 291 proc->current_coroutine = &proc-> runner->c;265 proc->current_coroutine = &proc->ctx->c; 292 266 proc->current_thread = NULL; 293 267 294 268 //We now have a proper context from which to schedule threads 295 LIB_DEBUG_PRINTF("Kernel : core %p created (%p , %p)\n", proc, proc->runner, &ctx);269 LIB_DEBUG_PRINTF("Kernel : core %p created (%p)\n", proc, proc->ctx); 296 270 297 271 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't … … 305 279 306 280 // Main routine of the core returned, the core is now fully terminated 307 LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc-> runner);281 LIB_DEBUG_PRINTF("Kernel : core %p main ended (%p)\n", proc, proc->ctx); 308 282 309 283 return NULL; … … 313 287 LIB_DEBUG_PRINTF("Kernel : Starting core %p\n", this); 314 288 315 //pthread_attr_t attributes;316 //pthread_attr_init( &attributes );317 318 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );319 320 //pthread_attr_destroy( &attributes );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 ); 321 295 322 296 LIB_DEBUG_PRINTF("Kernel : core %p started\n", this); … … 328 302 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 329 303 330 spin_lock( &lock );304 pthread_spinlock_guard guard = { &systemProcessor->cltr->lock }; 331 305 append( &systemProcessor->cltr->ready_queue, thrd ); 332 spin_unlock( &lock );333 306 } 334 307 335 308 thread * nextThread(cluster * this) { 336 spin_lock( &lock ); 337 thread * head = pop_head( &this->ready_queue ); 338 spin_unlock( &lock ); 339 return head; 309 pthread_spinlock_guard guard = { &this->lock }; 310 return pop_head( &this->ready_queue ); 340 311 } 341 312 … … 343 314 // Kernel boot procedures 344 315 void kernel_startup(void) { 345 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 346 347 // Start by initializing the main thread 316 348 317 // SKULLDUGGERY: the mainThread steals the process main thread 349 318 // which will then be scheduled by the systemProcessor normally 319 LIB_DEBUG_PRINTF("Kernel : Starting\n"); 320 321 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 thread 350 331 mainThread = (thread *)&mainThread_storage; 351 current_stack_info_t info;352 332 mainThread{ &info }; 353 333 … … 373 353 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 374 354 // mainThread is on the ready queue when this call is made. 375 resume(systemProcessor-> runner);355 resume(systemProcessor->ctx); 376 356 377 357 378 358 379 359 // THE SYSTEM IS NOW COMPLETELY RUNNING 360 361 362 380 363 LIB_DEBUG_PRINTF("Kernel : Started\n--------------------------------------------------\n\n"); 381 364 } … … 394 377 // Destroy the system processor and its context in reverse order of construction 395 378 // These were manually constructed so we need manually destroy them 396 ^(systemProcessor-> runner){};379 ^(systemProcessor->ctx){}; 397 380 ^(systemProcessor){}; 398 381 … … 416 399 void lock( simple_lock * this ) { 417 400 { 418 spin_lock( &lock );401 pthread_spinlock_guard guard = { &systemCluster->lock }; //HUGE TEMP HACK which only works if we have a single cluster and is stupid 419 402 append( &this->blocked, this_thread() ); 420 spin_unlock( &lock );421 403 } 422 404 suspend(); -
src/libcfa/concurrency/threads.c
ra073d46 re994912 24 24 25 25 extern "C" { 26 #include <fenv.h>27 26 #include <stddef.h> 28 27 } … … 92 91 CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context ); 93 92 94 fenv_t envp;95 fegetenv( &envp );96 LIB_DEBUG_PRINTF("Thread : mxcsr %x\n", envp.__mxcsr);97 93 LIB_DEBUG_PRINTF("Thread started : %p (t %p, c %p)\n", this, thrd_c, thrd_h); 98 94 … … 109 105 110 106 void yield( void ) { 111 get_this_processor()->thread_action = Reschedule;107 thread_schedule( this_thread() ); 112 108 suspend(); 113 109 }
Note:
See TracChangeset
for help on using the changeset viewer.