Changeset c81ebf9 for src/libcfa
- Timestamp:
- Jun 6, 2017, 11:45:13 AM (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:
- c5ac6d5
- Parents:
- 7b13aeb
- Location:
- src/libcfa/concurrency
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/libcfa/concurrency/alarm.c ¶
r7b13aeb rc81ebf9 15 15 // 16 16 17 extern "C" { 18 #include <time.h> 19 #include <sys/time.h> 20 } 21 17 22 #include "alarm.h" 18 23 #include "kernel_private.h" 24 #include "preemption.h" 19 25 20 static void register_self( alarm_node_t * this ) { 21 lock( &systemProcessor->alarm_lock ); 22 insert( &systemProcessor->alarms, this ); 23 unlock( &systemProcessor->alarm_lock ); 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; 24 34 } 25 35 26 void ?{}( alarm_node_t * this, thread_desc * thrd, cfa_time_t alarm, cfa_time_t period = 0 ) { 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 ) { 27 50 this->thrd = thrd; 28 51 this->alarm = alarm; 29 52 this->period = period; 30 53 this->next = 0; 31 32 register_self( this );54 this->set = false; 55 this->kernel_alarm = false; 33 56 } 34 57 35 void ?{}( alarm_node_t * this, processor * proc, cfa_time_t alarm,cfa_time_t period = 0 ) {58 void ?{}( alarm_node_t * this, processor * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ) { 36 59 this->proc = proc; 37 60 this->alarm = alarm; 38 61 this->period = period; 39 62 this->next = 0; 63 this->set = false; 64 this->kernel_alarm = true; 65 } 40 66 41 register_self( this ); 67 void ^?{}( alarm_node_t * this ) { 68 if( this->set ) { 69 unregister_self( this ); 70 } 42 71 } 43 72 … … 62 91 } 63 92 64 voidpop( alarm_list_t * this ) {93 alarm_node_t * pop( alarm_list_t * this ) { 65 94 alarm_node_t * head = this->head; 66 95 if( head ) { … … 73 102 return head; 74 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 } -
TabularUnified src/libcfa/concurrency/alarm.h ¶
r7b13aeb rc81ebf9 18 18 #define ALARM_H 19 19 20 #include <stdbool.h> 21 20 22 #include "assert" 21 23 22 typedef unsigned long int cfa_time_t;24 typedef unsigned long int __cfa_time_t; 23 25 24 26 struct thread_desc; 25 27 struct processor; 26 28 29 //============================================================================================= 30 // Clock logic 31 //============================================================================================= 32 33 #define TIMEGRAN 1_000_000_000L // nanosecond granularity, except for timeval 34 35 __cfa_time_t __kernel_get_time(); 36 void __kernel_set_timer( __cfa_time_t alarm ); 37 38 //============================================================================================= 39 // Alarm logic 40 //============================================================================================= 41 27 42 struct alarm_node_t { 28 cfa_time_t alarm; // time when alarm goes off29 cfa_time_t period;// if > 0 => period of alarm30 alarm_node_t * next; // intrusive link list field43 __cfa_time_t alarm; // time when alarm goes off 44 __cfa_time_t period; // if > 0 => period of alarm 45 alarm_node_t * next; // intrusive link list field 31 46 32 47 union { … … 34 49 processor * proc; // proc who created event 35 50 }; 51 52 bool set :1; // whether or not the alarm has be registered 53 bool kernel_alarm :1; // true if this is not a user defined alarm 36 54 }; 37 55 38 56 typedef alarm_node_t ** __alarm_it_t; 39 57 40 void ?{}( alarm_node_t * this, thread_desc * thrd, cfa_time_t alarm, cfa_time_t period = 0 ); 41 void ?{}( alarm_node_t * this, processor * proc, cfa_time_t alarm, cfa_time_t period = 0 ); 58 void ?{}( alarm_node_t * this, thread_desc * thrd, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ); 59 void ?{}( alarm_node_t * this, processor * proc, __cfa_time_t alarm = 0, __cfa_time_t period = 0 ); 60 void ^?{}( alarm_node_t * this ); 42 61 43 62 struct alarm_list_t { … … 54 73 alarm_node_t * pop( alarm_list_t * this ); 55 74 75 void register_self ( alarm_node_t * this ); 76 void unregister_self( alarm_node_t * this ); 77 56 78 #endif 57 79 -
TabularUnified src/libcfa/concurrency/kernel ¶
r7b13aeb rc81ebf9 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 -
TabularUnified src/libcfa/concurrency/kernel.c ¶
r7b13aeb rc81ebf9 36 36 //CFA Includes 37 37 #include "libhdr.h" 38 #include "preemption.h" 38 39 39 40 //Private includes … … 81 82 82 83 void ?{}( current_stack_info_t * this ) { 83 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 1\n");84 84 CtxGet( &this->ctx ); 85 85 this->base = this->ctx.FP; … … 96 96 97 97 void ?{}( coStack_t * this, current_stack_info_t * info) { 98 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 2\n");99 98 this->size = info->size; 100 99 this->storage = info->storage; … … 107 106 108 107 void ?{}( coroutine_desc * this, current_stack_info_t * info) { 109 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 3\n");110 108 (&this->stack){ info }; 111 109 this->name = "Main Thread"; … … 115 113 116 114 void ?{}( thread_desc * this, current_stack_info_t * info) { 117 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 4\n");118 115 (&this->cor){ info }; 119 116 } … … 122 119 // Processor coroutine 123 120 void ?{}(processorCtx_t * this, processor * proc) { 124 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 5\n");125 121 (&this->__cor){ "Processor" }; 126 122 this->proc = proc; … … 129 125 130 126 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) { 131 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 6\n");132 127 (&this->__cor){ info }; 133 128 this->proc = proc; … … 136 131 137 132 void ?{}(processor * this) { 138 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 7\n");139 133 this{ systemCluster }; 140 134 } 141 135 142 136 void ?{}(processor * this, cluster * cltr) { 143 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 8\n");144 137 this->cltr = cltr; 145 138 this->current_coroutine = NULL; … … 147 140 (&this->terminated){}; 148 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; 149 146 150 147 start( this ); … … 157 154 (&this->terminated){}; 158 155 this->is_terminated = false; 156 this->disable_preempt_count = 0; 157 this->pending_preemption = false; 159 158 160 159 this->runner = runner; … … 164 163 165 164 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) { 166 LIB_DEBUG_PRINT_SAFE("Kernel : Ctor 9\n");167 165 (&this->alarms){}; 168 166 (&this->alarm_lock){}; 167 this->pending_alarm = false; 169 168 170 169 (&this->proc){ cltr, runner }; … … 194 193 void main(processorCtx_t * runner) { 195 194 processor * this = runner->proc; 195 196 196 LIB_DEBUG_PRINT_SAFE("Kernel : core %p starting\n", this); 197 197 198 thread_desc * readyThread = NULL;199 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )200 198 { 201 readyThread = nextThread( this->cltr ); 202 203 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++ ) 204 206 { 205 runThread(this, readyThread); 206 207 //Some actions need to be taken from the kernel 208 finishRunning(this); 209 210 spin_count = 0; 211 } 212 else 213 { 214 spin(this, &spin_count); 215 } 216 } 217 218 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 219 227 signal( &this->terminated ); 220 228 LIB_DEBUG_PRINT_SAFE("Kernel : core %p terminated\n", this); … … 315 323 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 316 324 317 // pthread_attr_t attributes;318 // pthread_attr_init( &attributes );319 320 325 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 321 322 // pthread_attr_destroy( &attributes );323 326 324 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); … … 381 384 this_processor->finish.thrd_count = thrd_count; 382 385 suspend(); 383 }384 385 //=============================================================================================386 // Kernel Preemption logic387 //=============================================================================================388 389 #define __CFA_DEFAULT_PREEMPTION__ 10390 391 unsigned int default_preemption() {392 return __CFA_DEFAULT_PREEMPTION__;393 }394 395 void kernel_start_preemption() {396 397 386 } 398 387 … … 536 525 } 537 526 527 bool try_lock( spinlock * this ) { 528 return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 529 } 530 538 531 void lock( spinlock * this ) { 539 532 for ( unsigned int i = 1;; i += 1 ) { -
TabularUnified src/libcfa/concurrency/kernel_private.h ¶
r7b13aeb rc81ebf9 52 52 alarm_list_t alarms; 53 53 spinlock alarm_lock; 54 55 bool pending_alarm; 54 56 }; 55 57 56 58 extern cluster * systemCluster; 57 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 } 58 80 59 81 //----------------------------------------------------------------------------- -
TabularUnified src/libcfa/concurrency/monitor ¶
r7b13aeb rc81ebf9 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 -
TabularUnified src/libcfa/concurrency/monitor.c ¶
r7b13aeb rc81ebf9 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 -
TabularUnified src/libcfa/concurrency/signal.c ¶
r7b13aeb rc81ebf9 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 // signal.c -- 9 // 10 // Author : Thierry Delisle 11 // Created On : Mon Jun 5 14:20:42 2017 12 // Last Modified By : Thierry Delisle 13 // Last Modified On : -- 14 // Update Count : 0 15 // 16 17 #include "preemption.h" 18 19 extern "C" { 20 #include <signal.h> 21 } 22 23 #define __CFA_DEFAULT_PREEMPTION__ 10 24 25 __attribute__((weak)) unsigned int default_preemption() { 26 return __CFA_DEFAULT_PREEMPTION__; 27 } 28 29 static void preempt( processor * this ); 30 static void timeout( thread_desc * this ); 31 32 //============================================================================================= 33 // Kernel Preemption logic 34 //============================================================================================= 35 36 void kernel_start_preemption() { 37 38 } 39 40 void tick_preemption() { 41 alarm_list_t * alarms = &systemProcessor->alarms; 42 __cfa_time_t currtime = __kernel_get_time(); 43 while( alarms->head && alarms->head->alarm < currtime ) { 44 alarm_node_t * node = pop(alarms); 45 if( node->kernel_alarm ) { 46 preempt( node->proc ); 47 } 48 else { 49 timeout( node->thrd ); 50 } 51 52 if( node->period > 0 ) { 53 node->alarm += node->period; 54 insert( alarms, node ); 55 } 56 else { 57 node->set = false; 58 } 59 } 60 61 if( alarms->head ) { 62 __kernel_set_timer( alarms->head->alarm - currtime ); 63 } 64 } 65 66 void update_preemption( processor * this, __cfa_time_t duration ) { 67 // assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 ); 68 alarm_node_t * alarm = this->preemption_alarm; 69 70 // Alarms need to be enabled 71 if ( duration > 0 && !alarm->set ) { 72 alarm->alarm = __kernel_get_time() + duration; 73 alarm->period = duration; 74 register_self( alarm ); 75 } 76 // Zero duraction but alarm is set 77 else if ( duration == 0 && alarm->set ) { 78 unregister_self( alarm ); 79 alarm->alarm = 0; 80 alarm->period = 0; 81 } 82 // If alarm is different from previous, change it 83 else if ( duration > 0 && alarm->period != duration ) { 84 unregister_self( alarm ); 85 alarm->alarm = __kernel_get_time() + duration; 86 alarm->period = duration; 87 register_self( alarm ); 88 } 89 } 90 91 void ?{}( preemption_scope * this, processor * proc ) { 92 (&this->alarm){ proc }; 93 this->proc = proc; 94 this->proc->preemption_alarm = &this->alarm; 95 update_preemption( this->proc, this->proc->preemption ); 96 } 97 98 void ^?{}( preemption_scope * this ) { 99 update_preemption( this->proc, 0 ); 100 } 101 102 //============================================================================================= 103 // Kernel Signal logic 104 //============================================================================================= 105 106 static inline bool preemption_ready() { 107 return this_processor->disable_preempt_count == 0; 108 } 109 110 static inline void defer_ctxSwitch() { 111 this_processor->pending_preemption = true; 112 } 113 114 static inline void defer_alarm() { 115 systemProcessor->pending_alarm = true; 116 } 117 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 119 if( preemption_ready() ) { 120 ScheduleInternal( this_processor->current_thread ); 121 } 122 else { 123 defer_ctxSwitch(); 124 } 125 } 126 127 void sigHandler_alarm( __attribute__((unused)) int sig ) { 128 if( try_lock( &systemProcessor->alarm_lock ) ) { 129 tick_preemption(); 130 unlock( &systemProcessor->alarm_lock ); 131 } 132 else { 133 defer_alarm(); 134 } 135 } 136 137 static void preempt( processor * this ) { 138 pthread_kill( this->kernel_thread, SIGUSR1 ); 139 } 140 141 static void timeout( thread_desc * this ) { 142 //TODO : implement waking threads 143 }
Note: See TracChangeset
for help on using the changeset viewer.