Changeset 10e90cb for src/libcfa/concurrency
- Timestamp:
- Jun 6, 2017, 2:50:57 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:
- c6d2e93
- Parents:
- 8ca3a72 (diff), c5ac6d5 (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:
-
- 3 added
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/alarm.c
r8ca3a72 r10e90cb 1 // -*- Mode: CFA -*- 2 // 3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo 4 // 5 // The contents of this file are covered under the licence agreement in the 6 // file "LICENCE" distributed with Cforall. 7 // 8 // alarm.c -- 9 // 10 // Author : Thierry Delisle 11 // Created On : Fri Jun 2 11:31:25 2017 12 // Last Modified By : Thierry Delisle 13 // Last Modified On : -- 14 // Update Count : 0 15 // 16 17 extern "C" { 18 #include <time.h> 19 #include <sys/time.h> 20 } 21 22 #include "alarm.h" 23 #include "kernel_private.h" 24 #include "preemption.h" 25 26 //============================================================================================= 27 // Clock logic 28 //============================================================================================= 29 30 __cfa_time_t __kernel_get_time() { 31 timespec curr; 32 clock_gettime( CLOCK_REALTIME, &curr ); 33 return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec; 34 } 35 36 void __kernel_set_timer( __cfa_time_t alarm ) { 37 itimerval val; 38 val.it_value.tv_sec = alarm / TIMEGRAN; // seconds 39 val.it_value.tv_usec = (alarm % TIMEGRAN) / ( TIMEGRAN / 1_000_000L ); // microseconds 40 val.it_interval.tv_sec = 0; 41 val.it_interval.tv_usec = 0; 42 setitimer( ITIMER_REAL, &val, NULL ); 43 } 44 45 //============================================================================================= 46 // Alarm logic 47 //============================================================================================= 48 49 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) { 50 this->thrd = thrd; 51 this->alarm = alarm; 52 this->period = period; 53 this->next = 0; 54 this->set = false; 55 this->kernel_alarm = false; 56 } 57 58 void ?{}( alarm_node_t * this, processor * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) { 59 this->proc = proc; 60 this->alarm = alarm; 61 this->period = period; 62 this->next = 0; 63 this->set = false; 64 this->kernel_alarm = true; 65 } 66 67 void ^?{}( alarm_node_t * this ) { 68 if( this->set ) { 69 unregister_self( this ); 70 } 71 } 72 73 static inline void insert_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t p ) { 74 assert( !n->next ); 75 if( p == this->tail ) { 76 this->tail = &n->next; 77 } 78 else { 79 n->next = *p; 80 } 81 *p = n; 82 } 83 84 void insert( alarm_list_t * this, alarm_node_t * n ) { 85 alarm_node_t ** it = &this->head; 86 while( (*it) && (n->alarm > (*it)->alarm) ) { 87 it = &(*it)->next; 88 } 89 90 insert_at( this, n, it ); 91 } 92 93 alarm_node_t * pop( alarm_list_t * this ) { 94 alarm_node_t * head = this->head; 95 if( head ) { 96 this->head = head->next; 97 if( !head->next ) { 98 this->tail = &this->head; 99 } 100 head->next = NULL; 101 } 102 return head; 103 } 104 105 static inline void remove_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t it ) { 106 assert( it ); 107 assert( (*it)->next == n ); 108 109 (*it)->next = n->next; 110 if( !n-> next ) { 111 this->tail = it; 112 } 113 n->next = NULL; 114 } 115 116 static inline void remove( alarm_list_t * this, alarm_node_t * n ) { 117 alarm_node_t ** it = &this->head; 118 while( (*it) && (*it)->next != n ) { 119 it = &(*it)->next; 120 } 121 122 if( *it ) { remove_at( this, n, it ); } 123 } 124 125 void register_self( alarm_node_t * this ) { 126 disable_interrupts(); 127 assert( !systemProcessor->pending_alarm ); 128 lock( &systemProcessor->alarm_lock ); 129 { 130 insert( &systemProcessor->alarms, this ); 131 if( systemProcessor->pending_alarm ) { 132 tick_preemption(); 133 } 134 } 135 unlock( &systemProcessor->alarm_lock ); 136 this->set = true; 137 enable_interrupts(); 138 } 139 140 void unregister_self( alarm_node_t * this ) { 141 disable_interrupts(); 142 lock( &systemProcessor->alarm_lock ); 143 remove( &systemProcessor->alarms, this ); 144 unlock( &systemProcessor->alarm_lock ); 145 disable_interrupts(); 146 this->set = false; 147 } -
src/libcfa/concurrency/kernel
r8ca3a72 r10e90cb 28 28 //----------------------------------------------------------------------------- 29 29 // Locks 30 bool try_lock( spinlock * ); 30 31 void lock( spinlock * ); 31 32 void unlock( spinlock * ); … … 85 86 86 87 struct FinishAction finish; 88 89 struct alarm_node_t * preemption_alarm; 90 unsigned int preemption; 91 92 unsigned short disable_preempt_count; 93 94 bool pending_preemption; 87 95 }; 88 96 … … 94 102 95 103 // Local Variables: // 96 // mode: c//97 // tab-width: 4//104 // mode: CFA // 105 // tab-width: 6 // 98 106 // End: // -
src/libcfa/concurrency/kernel.c
r8ca3a72 r10e90cb 36 36 //CFA Includes 37 37 #include "libhdr.h" 38 #include "preemption.h" 38 39 39 40 //Private includes … … 47 48 KERNEL_STORAGE(processorCtx_t, systemProcessorCtx); 48 49 KERNEL_STORAGE(cluster, systemCluster); 49 KERNEL_STORAGE( processor, systemProcessor);50 KERNEL_STORAGE(system_proc_t, systemProcessor); 50 51 KERNEL_STORAGE(thread_desc, mainThread); 51 52 KERNEL_STORAGE(machine_context_t, mainThread_context); 52 53 53 54 cluster * systemCluster; 54 processor* systemProcessor;55 system_proc_t * systemProcessor; 55 56 thread_desc * mainThread; 56 57 … … 118 119 // Processor coroutine 119 120 void ?{}(processorCtx_t * this, processor * proc) { 120 (&this->__cor){ };121 (&this->__cor){ "Processor" }; 121 122 this->proc = proc; 122 123 proc->runner = this; … … 139 140 (&this->terminated){}; 140 141 this->is_terminated = false; 142 this->preemption_alarm = NULL; 143 this->preemption = default_preemption(); 144 this->disable_preempt_count = 1; //Start with interrupts disabled 145 this->pending_preemption = false; 141 146 142 147 start( this ); … … 149 154 (&this->terminated){}; 150 155 this->is_terminated = false; 156 this->disable_preempt_count = 0; 157 this->pending_preemption = false; 151 158 152 159 this->runner = runner; 153 160 LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner); 154 161 runner{ this }; 162 } 163 164 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) { 165 (&this->alarms){}; 166 (&this->alarm_lock){}; 167 this->pending_alarm = false; 168 169 (&this->proc){ cltr, runner }; 155 170 } 156 171 … … 178 193 void main(processorCtx_t * runner) { 179 194 processor * this = runner->proc; 195 180 196 LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this); 181 197 182 thread_desc * readyThread = NULL;183 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )184 198 { 185 readyThread = nextThread( this->cltr ); 186 187 if(readyThread) 199 // Setup preemption data 200 preemption_scope scope = { this }; 201 202 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 203 204 thread_desc * readyThread = NULL; 205 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 188 206 { 189 runThread(this, readyThread); 190 191 //Some actions need to be taken from the kernel 192 finishRunning(this); 193 194 spin_count = 0; 195 } 196 else 197 { 198 spin(this, &spin_count); 199 } 200 } 201 202 LIB_DEBUG_PRINT_SAFE("Kernel : core %p unlocking thread\n", this); 207 readyThread = nextThread( this->cltr ); 208 209 if(readyThread) 210 { 211 runThread(this, readyThread); 212 213 //Some actions need to be taken from the kernel 214 finishRunning(this); 215 216 spin_count = 0; 217 } 218 else 219 { 220 spin(this, &spin_count); 221 } 222 } 223 224 LIB_DEBUG_PRINT_SAFE("Kernel : core %p stopping\n", this); 225 } 226 203 227 signal( &this->terminated ); 204 228 LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this); … … 299 323 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 300 324 301 // pthread_attr_t attributes;302 // pthread_attr_init( &attributes );303 304 325 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 305 306 // pthread_attr_destroy( &attributes );307 326 308 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); … … 316 335 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 317 336 318 lock( &systemProcessor-> cltr->lock );319 append( &systemProcessor-> cltr->ready_queue, thrd );320 unlock( &systemProcessor-> cltr->lock );337 lock( &systemProcessor->proc.cltr->lock ); 338 append( &systemProcessor->proc.cltr->ready_queue, thrd ); 339 unlock( &systemProcessor->proc.cltr->lock ); 321 340 } 322 341 … … 367 386 } 368 387 388 //============================================================================================= 389 // Kernel Setup logic 390 //============================================================================================= 369 391 //----------------------------------------------------------------------------- 370 392 // Kernel boot procedures … … 379 401 mainThread{ &info }; 380 402 403 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 404 405 // Enable preemption 406 kernel_start_preemption(); 407 381 408 // Initialize the system cluster 382 409 systemCluster = (cluster *)&systemCluster_storage; 383 410 systemCluster{}; 384 411 412 LIB_DEBUG_PRINT_SAFE("Kernel : System cluster ready\n"); 413 385 414 // Initialize the system processor and the system processor ctx 386 415 // (the coroutine that contains the processing control flow) 387 systemProcessor = ( processor*)&systemProcessor_storage;416 systemProcessor = (system_proc_t *)&systemProcessor_storage; 388 417 systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage }; 389 418 390 419 // Add the main thread to the ready queue 391 // once resume is called on systemProcessor-> ctxthe mainThread needs to be scheduled like any normal thread420 // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread 392 421 ScheduleThread(mainThread); 393 422 394 423 //initialize the global state variables 395 this_processor = systemProcessor;424 this_processor = &systemProcessor->proc; 396 425 this_processor->current_thread = mainThread; 397 426 this_processor->current_coroutine = &mainThread->cor; … … 400 429 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 401 430 // mainThread is on the ready queue when this call is made. 402 resume( systemProcessor->runner);431 resume( systemProcessor->proc.runner ); 403 432 404 433 … … 414 443 // When its coroutine terminates, it return control to the mainThread 415 444 // which is currently here 416 systemProcessor-> is_terminated = true;445 systemProcessor->proc.is_terminated = true; 417 446 suspend(); 418 447 … … 421 450 // Destroy the system processor and its context in reverse order of construction 422 451 // These were manually constructed so we need manually destroy them 423 ^(systemProcessor-> runner){};452 ^(systemProcessor->proc.runner){}; 424 453 ^(systemProcessor){}; 425 454 … … 484 513 } 485 514 515 //============================================================================================= 516 // Kernel Utilities 517 //============================================================================================= 486 518 //----------------------------------------------------------------------------- 487 519 // Locks … … 491 523 void ^?{}( spinlock * this ) { 492 524 525 } 526 527 bool try_lock( spinlock * this ) { 528 return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 493 529 } 494 530 -
src/libcfa/concurrency/kernel_private.h
r8ca3a72 r10e90cb 21 21 #include "thread" 22 22 23 #include "alarm.h" 24 23 25 //----------------------------------------------------------------------------- 24 26 // Scheduler … … 35 37 //----------------------------------------------------------------------------- 36 38 // Processor 37 structprocessorCtx_t {39 coroutine processorCtx_t { 38 40 processor * proc; 39 coroutine_desc __cor;40 41 }; 41 42 DECL_COROUTINE(processorCtx_t);43 42 44 43 void main(processorCtx_t *); … … 47 46 void finishRunning(processor * this); 48 47 void spin(processor * this, unsigned int * spin_count); 48 49 struct system_proc_t { 50 processor proc; 51 52 alarm_list_t alarms; 53 spinlock alarm_lock; 54 55 bool pending_alarm; 56 }; 57 58 extern cluster * systemCluster; 59 extern system_proc_t * systemProcessor; 60 extern thread_local processor * this_processor; 61 62 static inline void disable_interrupts() { 63 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 64 assert( prev != (unsigned short) -1 ); 65 } 66 67 static inline void enable_interrupts_noRF() { 68 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 69 assert( prev != (unsigned short) 0 ); 70 } 71 72 static inline void enable_interrupts() { 73 unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 74 assert( prev != (unsigned short) 0 ); 75 if( prev == 1 && this_processor->pending_preemption ) { 76 ScheduleInternal( this_processor->current_thread ); 77 this_processor->pending_preemption = false; 78 } 79 } 49 80 50 81 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/monitor
r8ca3a72 r10e90cb 92 92 uintptr_t front( condition * this ); 93 93 94 struct __acceptable_t { 95 void (*func)(void); 96 unsigned short count; 97 monitor_desc * monitors[1]; 98 }; 99 100 void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ); 101 94 102 #endif //MONITOR_H -
src/libcfa/concurrency/monitor.c
r8ca3a72 r10e90cb 212 212 ScheduleInternal( locks, count, threads, thread_count ); 213 213 214 214 215 //WE WOKE UP 215 216 … … 312 313 ScheduleInternal( locks, count, &signallee, 1 ); 313 314 315 316 317 314 318 LIB_DEBUG_PRINT_SAFE( "Back from signal block\n" ); 315 319 … … 330 334 ); 331 335 return this->blocked.head->user_info; 336 } 337 338 //----------------------------------------------------------------------------- 339 // Internal scheduling 340 void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) { 341 // thread_desc * this = this_thread(); 342 343 // unsigned short count = this->current_monitor_count; 344 // unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 345 // spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal 346 347 // lock_all( this->current_monitors, locks, count ); 348 349 350 351 352 353 // // // Everything is ready to go to sleep 354 // // ScheduleInternal( locks, count, threads, thread_count ); 355 356 357 // //WE WOKE UP 358 359 360 // //We are back, restore the owners and recursions 361 // lock_all( locks, count ); 362 // restore_recursion( this->monitors, recursions, count ); 363 // unlock_all( locks, count ); 332 364 } 333 365
Note:
See TracChangeset
for help on using the changeset viewer.