Changes in / [8c680e9:b751c8e]
- Location:
- src
- Files:
-
- 1 added
- 18 edited
-
benchmark/CorCtxSwitch.c (modified) (1 diff)
-
benchmark/csv-data.c (modified) (1 diff)
-
benchmark/interrupt_linux.c (added)
-
libcfa/concurrency/alarm.c (modified) (7 diffs)
-
libcfa/concurrency/coroutine (modified) (4 diffs)
-
libcfa/concurrency/coroutine.c (modified) (2 diffs)
-
libcfa/concurrency/invoke.c (modified) (5 diffs)
-
libcfa/concurrency/invoke.h (modified) (3 diffs)
-
libcfa/concurrency/kernel (modified) (4 diffs)
-
libcfa/concurrency/kernel.c (modified) (35 diffs)
-
libcfa/concurrency/kernel_private.h (modified) (3 diffs)
-
libcfa/concurrency/monitor (modified) (1 diff)
-
libcfa/concurrency/monitor.c (modified) (23 diffs)
-
libcfa/concurrency/preemption.c (modified) (9 diffs)
-
libcfa/concurrency/thread (modified) (1 diff)
-
libcfa/concurrency/thread.c (modified) (4 diffs)
-
libcfa/libhdr/libalign.h (modified) (3 diffs)
-
libcfa/libhdr/libdebug.h (modified) (2 diffs)
-
tests/sched-int-block.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/benchmark/CorCtxSwitch.c
r8c680e9 rb751c8e 31 31 32 32 StartTime = Time(); 33 // for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) {34 // resume( this_coroutine() );35 // // resume( &s );36 // }37 33 resumer( &s, NoOfTimes ); 38 34 EndTime = Time(); -
src/benchmark/csv-data.c
r8c680e9 rb751c8e 38 38 39 39 StartTime = Time(); 40 // for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) {41 // resume( this_coroutine() );42 // // resume( &s );43 // }44 40 resumer( &s, NoOfTimes ); 45 41 EndTime = Time(); -
src/libcfa/concurrency/alarm.c
r8c680e9 rb751c8e 16 16 17 17 extern "C" { 18 #include <errno.h> 19 #include <stdio.h> 20 #include <string.h> 18 21 #include <time.h> 22 #include <unistd.h> 19 23 #include <sys/time.h> 20 24 } 25 26 #include "libhdr.h" 21 27 22 28 #include "alarm.h" … … 31 37 timespec curr; 32 38 clock_gettime( CLOCK_REALTIME, &curr ); 33 return ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec; 39 __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec; 40 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : current time is %lu\n", curr_time ); 41 return curr_time; 34 42 } 35 43 36 44 void __kernel_set_timer( __cfa_time_t alarm ) { 45 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm ); 37 46 itimerval val; 38 47 val.it_value.tv_sec = alarm / TIMEGRAN; // seconds … … 71 80 } 72 81 82 LIB_DEBUG_DO( bool validate( alarm_list_t * this ) { 83 alarm_node_t ** it = &this->head; 84 while( (*it) ) { 85 it = &(*it)->next; 86 } 87 88 return it == this->tail; 89 }) 90 73 91 static inline void insert_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t p ) { 74 assert( !n->next );92 verify( !n->next ); 75 93 if( p == this->tail ) { 76 94 this->tail = &n->next; … … 80 98 } 81 99 *p = n; 100 101 verify( validate( this ) ); 82 102 } 83 103 … … 89 109 90 110 insert_at( this, n, it ); 111 112 verify( validate( this ) ); 91 113 } 92 114 … … 100 122 head->next = NULL; 101 123 } 124 verify( validate( this ) ); 102 125 return head; 103 126 } … … 105 128 static inline void remove_at( alarm_list_t * this, alarm_node_t * n, __alarm_it_t it ) { 106 129 verify( it ); 107 verify( (*it) ->next== n );130 verify( (*it) == n ); 108 131 109 (*it) ->next= n->next;132 (*it) = n->next; 110 133 if( !n-> next ) { 111 134 this->tail = it; 112 135 } 113 136 n->next = NULL; 137 138 verify( validate( this ) ); 114 139 } 115 140 116 141 static inline void remove( alarm_list_t * this, alarm_node_t * n ) { 117 142 alarm_node_t ** it = &this->head; 118 while( (*it) && (*it) ->next!= n ) {143 while( (*it) && (*it) != n ) { 119 144 it = &(*it)->next; 120 145 } 121 146 147 verify( validate( this ) ); 148 122 149 if( *it ) { remove_at( this, n, it ); } 150 151 verify( validate( this ) ); 123 152 } 124 153 125 154 void register_self( alarm_node_t * this ) { 126 155 disable_interrupts(); 127 assert( !systemProcessor->pending_alarm );128 lock( &systemProcessor->alarm_lock );156 verify( !systemProcessor->pending_alarm ); 157 lock( &systemProcessor->alarm_lock DEBUG_CTX2 ); 129 158 { 159 verify( validate( &systemProcessor->alarms ) ); 160 bool first = !systemProcessor->alarms.head; 161 130 162 insert( &systemProcessor->alarms, this ); 131 163 if( systemProcessor->pending_alarm ) { 132 164 tick_preemption(); 133 165 } 166 if( first ) { 167 __kernel_set_timer( systemProcessor->alarms.head->alarm - __kernel_get_time() ); 168 } 134 169 } 135 170 unlock( &systemProcessor->alarm_lock ); 136 171 this->set = true; 137 enable_interrupts( );172 enable_interrupts( DEBUG_CTX ); 138 173 } 139 174 140 175 void unregister_self( alarm_node_t * this ) { 176 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : unregister %p start\n", this ); 141 177 disable_interrupts(); 142 lock( &systemProcessor->alarm_lock ); 143 remove( &systemProcessor->alarms, this ); 178 lock( &systemProcessor->alarm_lock DEBUG_CTX2 ); 179 { 180 verify( validate( &systemProcessor->alarms ) ); 181 remove( &systemProcessor->alarms, this ); 182 } 144 183 unlock( &systemProcessor->alarm_lock ); 145 disable_interrupts();184 enable_interrupts( DEBUG_CTX ); 146 185 this->set = false; 186 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Kernel : unregister %p end\n", this ); 147 187 } -
src/libcfa/concurrency/coroutine
r8c680e9 rb751c8e 63 63 64 64 // Get current coroutine 65 coroutine_desc * this_coroutine(void);65 extern volatile thread_local coroutine_desc * this_coroutine; 66 66 67 67 // Private wrappers for context switch and stack creation … … 71 71 // Suspend implementation inlined for performance 72 72 static inline void suspend() { 73 coroutine_desc * src = this_coroutine (); // optimization73 coroutine_desc * src = this_coroutine; // optimization 74 74 75 75 assertf( src->last != 0, … … 88 88 forall(dtype T | is_coroutine(T)) 89 89 static inline void resume(T * cor) { 90 coroutine_desc * src = this_coroutine (); // optimization90 coroutine_desc * src = this_coroutine; // optimization 91 91 coroutine_desc * dst = get_coroutine(cor); 92 92 … … 112 112 113 113 static inline void resume(coroutine_desc * dst) { 114 coroutine_desc * src = this_coroutine (); // optimization114 coroutine_desc * src = this_coroutine; // optimization 115 115 116 116 // not resuming self ? -
src/libcfa/concurrency/coroutine.c
r8c680e9 rb751c8e 32 32 #include "invoke.h" 33 33 34 extern thread_local processor * this_processor;34 extern volatile thread_local processor * this_processor; 35 35 36 36 //----------------------------------------------------------------------------- … … 106 106 107 107 // set state of current coroutine to inactive 108 src->state = Inactive;108 src->state = src->state == Halted ? Halted : Inactive; 109 109 110 110 // set new coroutine that task is executing 111 this_ processor->current_coroutine = dst;111 this_coroutine = dst; 112 112 113 113 // context switch to specified coroutine 114 assert( src->stack.context ); 114 115 CtxSwitch( src->stack.context, dst->stack.context ); 115 116 // when CtxSwitch returns we are back in the src coroutine -
src/libcfa/concurrency/invoke.c
r8c680e9 rb751c8e 29 29 30 30 extern void __suspend_internal(void); 31 extern void __leave_monitor_desc( struct monitor_desc * this ); 31 extern void __leave_thread_monitor( struct thread_desc * this ); 32 extern void disable_interrupts(); 33 extern void enable_interrupts( DEBUG_CTX_PARAM ); 32 34 33 35 void CtxInvokeCoroutine( 34 void (*main)(void *), 35 struct coroutine_desc *(*get_coroutine)(void *), 36 void (*main)(void *), 37 struct coroutine_desc *(*get_coroutine)(void *), 36 38 void *this 37 39 ) { … … 56 58 57 59 void CtxInvokeThread( 58 void (*dtor)(void *), 59 void (*main)(void *), 60 struct thread_desc *(*get_thread)(void *), 60 void (*dtor)(void *), 61 void (*main)(void *), 62 struct thread_desc *(*get_thread)(void *), 61 63 void *this 62 64 ) { 65 // First suspend, once the thread arrives here, 66 // the function pointer to main can be invalidated without risk 63 67 __suspend_internal(); 64 68 69 // Fetch the thread handle from the user defined thread structure 65 70 struct thread_desc* thrd = get_thread( this ); 66 struct coroutine_desc* cor = &thrd->cor;67 struct monitor_desc* mon = &thrd->mon;68 cor->state = Active;69 71 70 // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this); 72 // Officially start the thread by enabling preemption 73 enable_interrupts( DEBUG_CTX ); 74 75 // Call the main of the thread 71 76 main( this ); 72 77 73 __leave_monitor_desc( mon ); 78 // To exit a thread we must : 79 // 1 - Mark it as halted 80 // 2 - Leave its monitor 81 // 3 - Disable the interupts 82 // The order of these 3 operations is very important 83 __leave_thread_monitor( thrd ); 74 84 75 85 //Final suspend, should never return … … 80 90 81 91 void CtxStart( 82 void (*main)(void *), 83 struct coroutine_desc *(*get_coroutine)(void *), 84 void *this, 92 void (*main)(void *), 93 struct coroutine_desc *(*get_coroutine)(void *), 94 void *this, 85 95 void (*invoke)(void *) 86 96 ) { … … 108 118 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke; 109 119 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520 110 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7 120 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7 111 121 112 122 #elif defined( __x86_64__ ) … … 128 138 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke; 129 139 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520 130 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7 140 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7 131 141 #else 132 142 #error Only __i386__ and __x86_64__ is supported for threads in cfa -
src/libcfa/concurrency/invoke.h
r8c680e9 rb751c8e 31 31 struct spinlock { 32 32 volatile int lock; 33 #ifdef __CFA_DEBUG__ 34 const char * prev_name; 35 void* prev_thrd; 36 #endif 33 37 }; 34 38 … … 83 87 struct __thread_queue_t entry_queue; // queue of threads that are blocked waiting for the monitor 84 88 struct __condition_stack_t signal_stack; // stack of conditions 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 monitor86 89 unsigned int recursion; // monitor routines can be called recursively, we need to keep track of that 87 90 }; … … 99 102 #ifndef _INVOKE_PRIVATE_H_ 100 103 #define _INVOKE_PRIVATE_H_ 101 104 102 105 struct machine_context_t { 103 106 void *SP; -
src/libcfa/concurrency/kernel
r8c680e9 rb751c8e 28 28 //----------------------------------------------------------------------------- 29 29 // Locks 30 bool try_lock( spinlock * ); 31 void lock( spinlock * ); 32 void unlock( spinlock * ); 30 bool try_lock ( spinlock * DEBUG_CTX_PARAM2 ); 31 void lock ( spinlock * DEBUG_CTX_PARAM2 ); 32 void lock_yield( spinlock * DEBUG_CTX_PARAM2 ); 33 void unlock ( spinlock * ); 33 34 34 35 struct signal_once { … … 68 69 unsigned short thrd_count; 69 70 }; 70 static inline void ?{}(FinishAction * this) { 71 static inline void ?{}(FinishAction * this) { 71 72 this->action_code = No_Action; 72 73 this->thrd = NULL; … … 78 79 struct processorCtx_t * runner; 79 80 cluster * cltr; 80 coroutine_desc * current_coroutine;81 thread_desc * current_thread;82 81 pthread_t kernel_thread; 83 82 84 83 signal_once terminated; 85 84 volatile bool is_terminated; … … 90 89 unsigned int preemption; 91 90 92 unsigned short disable_preempt_count;91 bool pending_preemption; 93 92 94 bool pending_preemption;93 char * last_enable; 95 94 }; 96 95 -
src/libcfa/concurrency/kernel.c
r8c680e9 rb751c8e 15 15 // 16 16 17 #include "startup.h" 18 19 //Start and stop routine for the kernel, declared first to make sure they run first 20 void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 21 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 22 23 //Header 24 #include "kernel_private.h" 17 #include "libhdr.h" 25 18 26 19 //C Includes … … 35 28 36 29 //CFA Includes 37 #include " libhdr.h"30 #include "kernel_private.h" 38 31 #include "preemption.h" 32 #include "startup.h" 39 33 40 34 //Private includes 41 35 #define __CFA_INVOKE_PRIVATE__ 42 36 #include "invoke.h" 37 38 //Start and stop routine for the kernel, declared first to make sure they run first 39 void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) )); 40 void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) )); 43 41 44 42 //----------------------------------------------------------------------------- … … 59 57 // Global state 60 58 61 thread_local processor * this_processor; 62 63 coroutine_desc * this_coroutine(void) { 64 return this_processor->current_coroutine; 65 } 66 67 thread_desc * this_thread(void) { 68 return this_processor->current_thread; 69 } 59 volatile thread_local processor * this_processor; 60 volatile thread_local coroutine_desc * this_coroutine; 61 volatile thread_local thread_desc * this_thread; 62 volatile thread_local unsigned short disable_preempt_count = 1; 70 63 71 64 //----------------------------------------------------------------------------- 72 65 // Main thread construction 73 66 struct current_stack_info_t { 74 machine_context_t ctx; 67 machine_context_t ctx; 75 68 unsigned int size; // size of stack 76 69 void *base; // base of stack … … 106 99 107 100 void ?{}( coroutine_desc * this, current_stack_info_t * info) { 108 (&this->stack){ info }; 101 (&this->stack){ info }; 109 102 this->name = "Main Thread"; 110 103 this->errno_ = 0; … … 136 129 void ?{}(processor * this, cluster * cltr) { 137 130 this->cltr = cltr; 138 this->current_coroutine = NULL;139 this->current_thread = NULL;140 131 (&this->terminated){}; 141 132 this->is_terminated = false; 142 133 this->preemption_alarm = NULL; 143 134 this->preemption = default_preemption(); 144 this->disable_preempt_count = 1; //Start with interrupts disabled145 135 this->pending_preemption = false; 146 136 … … 150 140 void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) { 151 141 this->cltr = cltr; 152 this->current_coroutine = NULL;153 this->current_thread = NULL;154 142 (&this->terminated){}; 155 143 this->is_terminated = false; 156 this->disable_preempt_count = 0; 144 this->preemption_alarm = NULL; 145 this->preemption = default_preemption(); 157 146 this->pending_preemption = false; 147 this->kernel_thread = pthread_self(); 158 148 159 149 this->runner = runner; 160 LIB_DEBUG_PRINT_SAFE("Kernel : constructing processor context %p\n", runner);150 LIB_DEBUG_PRINT_SAFE("Kernel : constructing system processor context %p\n", runner); 161 151 runner{ this }; 162 152 } 153 154 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 163 155 164 156 void ?{}(system_proc_t * this, cluster * cltr, processorCtx_t * runner) { … … 168 160 169 161 (&this->proc){ cltr, runner }; 162 163 verify( validate( &this->alarms ) ); 170 164 } 171 165 … … 184 178 185 179 void ^?{}(cluster * this) { 186 180 187 181 } 188 182 … … 203 197 204 198 thread_desc * readyThread = NULL; 205 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 199 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 206 200 { 207 201 readyThread = nextThread( this->cltr ); … … 209 203 if(readyThread) 210 204 { 205 verify( disable_preempt_count > 0 ); 206 211 207 runThread(this, readyThread); 208 209 verify( disable_preempt_count > 0 ); 212 210 213 211 //Some actions need to be taken from the kernel … … 229 227 } 230 228 231 // runThread runs a thread by context switching 232 // from the processor coroutine to the target thread 229 // runThread runs a thread by context switching 230 // from the processor coroutine to the target thread 233 231 void runThread(processor * this, thread_desc * dst) { 234 232 coroutine_desc * proc_cor = get_coroutine(this->runner); 235 233 coroutine_desc * thrd_cor = get_coroutine(dst); 236 234 237 235 //Reset the terminating actions here 238 236 this->finish.action_code = No_Action; 239 237 240 238 //Update global state 241 this ->current_thread = dst;239 this_thread = dst; 242 240 243 241 // Context Switch to the thread … … 246 244 } 247 245 248 // Once a thread has finished running, some of 246 // Once a thread has finished running, some of 249 247 // its final actions must be executed from the kernel 250 248 void finishRunning(processor * this) { … … 256 254 } 257 255 else if( this->finish.action_code == Release_Schedule ) { 258 unlock( this->finish.lock ); 256 unlock( this->finish.lock ); 259 257 ScheduleThread( this->finish.thrd ); 260 258 } … … 289 287 processor * proc = (processor *) arg; 290 288 this_processor = proc; 289 this_coroutine = NULL; 290 this_thread = NULL; 291 disable_preempt_count = 1; 291 292 // SKULLDUGGERY: We want to create a context for the processor coroutine 292 293 // which is needed for the 2-step context switch. However, there is no reason 293 // to waste the perfectly valid stack create by pthread. 294 // to waste the perfectly valid stack create by pthread. 294 295 current_stack_info_t info; 295 296 machine_context_t ctx; … … 300 301 301 302 //Set global state 302 proc->current_coroutine = &proc->runner->__cor;303 proc->current_thread = NULL;303 this_coroutine = &proc->runner->__cor; 304 this_thread = NULL; 304 305 305 306 //We now have a proper context from which to schedule threads 306 307 LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx); 307 308 308 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 309 // resume it to start it like it normally would, it will just context switch 310 // back to here. Instead directly call the main since we already are on the 309 // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 310 // resume it to start it like it normally would, it will just context switch 311 // back to here. Instead directly call the main since we already are on the 311 312 // appropriate stack. 312 313 proc_cor_storage.__cor.state = Active; … … 315 316 316 317 // Main routine of the core returned, the core is now fully terminated 317 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 318 LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 318 319 319 320 return NULL; … … 322 323 void start(processor * this) { 323 324 LIB_DEBUG_PRINT_SAFE("Kernel : Starting core %p\n", this); 324 325 326 // SIGALRM must only be caught by the system processor 327 sigset_t old_mask; 328 bool is_system_proc = this_processor == &systemProcessor->proc; 329 if ( is_system_proc ) { 330 // Child kernel-thread inherits the signal mask from the parent kernel-thread. So one special case for the 331 // system processor creating the user processor => toggle the blocking SIGALRM on system processor, create user 332 // processor, and toggle back (below) previous signal mask of the system processor. 333 334 sigset_t new_mask; 335 sigemptyset( &new_mask ); 336 sigemptyset( &old_mask ); 337 sigaddset( &new_mask, SIGALRM ); 338 339 if ( sigprocmask( SIG_BLOCK, &new_mask, &old_mask ) == -1 ) { 340 abortf( "internal error, sigprocmask" ); 341 } 342 343 assert( ! sigismember( &old_mask, SIGALRM ) ); 344 } 345 325 346 pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this ); 326 347 327 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 348 // Toggle back previous signal mask of system processor. 349 if ( is_system_proc ) { 350 if ( sigprocmask( SIG_SETMASK, &old_mask, NULL ) == -1 ) { 351 abortf( "internal error, sigprocmask" ); 352 } // if 353 } // if 354 355 LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this); 328 356 } 329 357 … … 331 359 // Scheduler routines 332 360 void ScheduleThread( thread_desc * thrd ) { 333 if( !thrd ) return; 361 // if( !thrd ) return; 362 assert( thrd ); 363 assert( thrd->cor.state != Halted ); 364 365 verify( disable_preempt_count > 0 ); 334 366 335 367 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 336 337 lock( &systemProcessor->proc.cltr->lock );368 369 lock( &systemProcessor->proc.cltr->lock DEBUG_CTX2 ); 338 370 append( &systemProcessor->proc.cltr->ready_queue, thrd ); 339 371 unlock( &systemProcessor->proc.cltr->lock ); 372 373 verify( disable_preempt_count > 0 ); 340 374 } 341 375 342 376 thread_desc * nextThread(cluster * this) { 343 lock( &this->lock ); 377 verify( disable_preempt_count > 0 ); 378 lock( &this->lock DEBUG_CTX2 ); 344 379 thread_desc * head = pop_head( &this->ready_queue ); 345 380 unlock( &this->lock ); 381 verify( disable_preempt_count > 0 ); 346 382 return head; 347 383 } 348 384 349 void ScheduleInternal() { 385 void BlockInternal() { 386 disable_interrupts(); 387 verify( disable_preempt_count > 0 ); 350 388 suspend(); 351 } 352 353 void ScheduleInternal( spinlock * lock ) { 389 verify( disable_preempt_count > 0 ); 390 enable_interrupts( DEBUG_CTX ); 391 } 392 393 void BlockInternal( spinlock * lock ) { 394 disable_interrupts(); 354 395 this_processor->finish.action_code = Release; 355 396 this_processor->finish.lock = lock; 397 398 verify( disable_preempt_count > 0 ); 356 399 suspend(); 357 } 358 359 void ScheduleInternal( thread_desc * thrd ) { 400 verify( disable_preempt_count > 0 ); 401 402 enable_interrupts( DEBUG_CTX ); 403 } 404 405 void BlockInternal( thread_desc * thrd ) { 406 disable_interrupts(); 407 assert( thrd->cor.state != Halted ); 360 408 this_processor->finish.action_code = Schedule; 361 409 this_processor->finish.thrd = thrd; 410 411 verify( disable_preempt_count > 0 ); 362 412 suspend(); 363 } 364 365 void ScheduleInternal( spinlock * lock, thread_desc * thrd ) { 413 verify( disable_preempt_count > 0 ); 414 415 enable_interrupts( DEBUG_CTX ); 416 } 417 418 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 419 disable_interrupts(); 366 420 this_processor->finish.action_code = Release_Schedule; 367 421 this_processor->finish.lock = lock; 368 422 this_processor->finish.thrd = thrd; 423 424 verify( disable_preempt_count > 0 ); 369 425 suspend(); 370 } 371 372 void ScheduleInternal(spinlock ** locks, unsigned short count) { 426 verify( disable_preempt_count > 0 ); 427 428 enable_interrupts( DEBUG_CTX ); 429 } 430 431 void BlockInternal(spinlock ** locks, unsigned short count) { 432 disable_interrupts(); 373 433 this_processor->finish.action_code = Release_Multi; 374 434 this_processor->finish.locks = locks; 375 435 this_processor->finish.lock_count = count; 436 437 verify( disable_preempt_count > 0 ); 376 438 suspend(); 377 } 378 379 void ScheduleInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 439 verify( disable_preempt_count > 0 ); 440 441 enable_interrupts( DEBUG_CTX ); 442 } 443 444 void BlockInternal(spinlock ** locks, unsigned short lock_count, thread_desc ** thrds, unsigned short thrd_count) { 445 disable_interrupts(); 380 446 this_processor->finish.action_code = Release_Multi_Schedule; 381 447 this_processor->finish.locks = locks; … … 383 449 this_processor->finish.thrds = thrds; 384 450 this_processor->finish.thrd_count = thrd_count; 451 452 verify( disable_preempt_count > 0 ); 385 453 suspend(); 454 verify( disable_preempt_count > 0 ); 455 456 enable_interrupts( DEBUG_CTX ); 386 457 } 387 458 … … 392 463 // Kernel boot procedures 393 464 void kernel_startup(void) { 394 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 465 LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n"); 395 466 396 467 // Start by initializing the main thread 397 // SKULLDUGGERY: the mainThread steals the process main thread 468 // SKULLDUGGERY: the mainThread steals the process main thread 398 469 // which will then be scheduled by the systemProcessor normally 399 470 mainThread = (thread_desc *)&mainThread_storage; … … 403 474 LIB_DEBUG_PRINT_SAFE("Kernel : Main thread ready\n"); 404 475 405 // Enable preemption406 kernel_start_preemption();407 408 476 // Initialize the system cluster 409 477 systemCluster = (cluster *)&systemCluster_storage; … … 417 485 systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage }; 418 486 419 // Add the main thread to the ready queue 487 // Add the main thread to the ready queue 420 488 // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread 421 489 ScheduleThread(mainThread); … … 423 491 //initialize the global state variables 424 492 this_processor = &systemProcessor->proc; 425 this_processor->current_thread = mainThread; 426 this_processor->current_coroutine = &mainThread->cor; 493 this_thread = mainThread; 494 this_coroutine = &mainThread->cor; 495 disable_preempt_count = 1; 496 497 // Enable preemption 498 kernel_start_preemption(); 427 499 428 500 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX 429 501 // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that 430 // mainThread is on the ready queue when this call is made. 502 // mainThread is on the ready queue when this call is made. 431 503 resume( systemProcessor->proc.runner ); 432 504 … … 435 507 // THE SYSTEM IS NOW COMPLETELY RUNNING 436 508 LIB_DEBUG_PRINT_SAFE("Kernel : Started\n--------------------------------------------------\n\n"); 509 510 enable_interrupts( DEBUG_CTX ); 437 511 } 438 512 439 513 void kernel_shutdown(void) { 440 514 LIB_DEBUG_PRINT_SAFE("\n--------------------------------------------------\nKernel : Shutting down\n"); 515 516 disable_interrupts(); 441 517 442 518 // SKULLDUGGERY: Notify the systemProcessor it needs to terminates. … … 448 524 // THE SYSTEM IS NOW COMPLETELY STOPPED 449 525 526 // Disable preemption 527 kernel_stop_preemption(); 528 450 529 // Destroy the system processor and its context in reverse order of construction 451 530 // These were manually constructed so we need manually destroy them … … 457 536 ^(mainThread){}; 458 537 459 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 538 LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n"); 460 539 } 461 540 … … 467 546 // abort cannot be recursively entered by the same or different processors because all signal handlers return when 468 547 // the globalAbort flag is true. 469 lock( &kernel_abort_lock );548 lock( &kernel_abort_lock DEBUG_CTX2 ); 470 549 471 550 // first task to abort ? … … 473 552 kernel_abort_called = true; 474 553 unlock( &kernel_abort_lock ); 475 } 554 } 476 555 else { 477 556 unlock( &kernel_abort_lock ); 478 557 479 558 sigset_t mask; 480 559 sigemptyset( &mask ); … … 482 561 sigaddset( &mask, SIGUSR1 ); // block SIGUSR1 signals 483 562 sigsuspend( &mask ); // block the processor to prevent further damage during abort 484 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 485 } 486 487 return this_thread ();563 _exit( EXIT_FAILURE ); // if processor unblocks before it is killed, terminate it 564 } 565 566 return this_thread; 488 567 } 489 568 … … 494 573 __lib_debug_write( STDERR_FILENO, abort_text, len ); 495 574 496 if ( thrd != this_coroutine ()) {497 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine ()->name, this_coroutine());575 if ( thrd != this_coroutine ) { 576 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine ); 498 577 __lib_debug_write( STDERR_FILENO, abort_text, len ); 499 } 578 } 500 579 else { 501 580 __lib_debug_write( STDERR_FILENO, ".\n", 2 ); … … 505 584 extern "C" { 506 585 void __lib_debug_acquire() { 507 lock( &kernel_debug_lock);586 lock( &kernel_debug_lock DEBUG_CTX2 ); 508 587 } 509 588 510 589 void __lib_debug_release() { 511 unlock( &kernel_debug_lock);590 unlock( &kernel_debug_lock ); 512 591 } 513 592 } … … 525 604 } 526 605 527 bool try_lock( spinlock * this ) {606 bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) { 528 607 return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 529 608 } 530 609 531 void lock( spinlock * this ) {610 void lock( spinlock * this DEBUG_CTX_PARAM2 ) { 532 611 for ( unsigned int i = 1;; i += 1 ) { 533 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break; 534 } 535 } 612 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; } 613 } 614 LIB_DEBUG_DO( 615 this->prev_name = caller; 616 this->prev_thrd = this_thread; 617 ) 618 } 619 620 void lock_yield( spinlock * this DEBUG_CTX_PARAM2 ) { 621 for ( unsigned int i = 1;; i += 1 ) { 622 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; } 623 yield(); 624 } 625 LIB_DEBUG_DO( 626 this->prev_name = caller; 627 this->prev_thrd = this_thread; 628 ) 629 } 630 536 631 537 632 void unlock( spinlock * this ) { … … 547 642 548 643 void wait( signal_once * this ) { 549 lock( &this->lock );644 lock( &this->lock DEBUG_CTX2 ); 550 645 if( !this->cond ) { 551 append( &this->blocked, this_thread() ); 552 ScheduleInternal( &this->lock ); 553 lock( &this->lock ); 554 } 555 unlock( &this->lock ); 646 append( &this->blocked, (thread_desc*)this_thread ); 647 BlockInternal( &this->lock ); 648 } 649 else { 650 unlock( &this->lock ); 651 } 556 652 } 557 653 558 654 void signal( signal_once * this ) { 559 lock( &this->lock );655 lock( &this->lock DEBUG_CTX2 ); 560 656 { 561 657 this->cond = true; 562 658 659 disable_interrupts(); 563 660 thread_desc * it; 564 661 while( it = pop_head( &this->blocked) ) { 565 662 ScheduleThread( it ); 566 663 } 664 enable_interrupts( DEBUG_CTX ); 567 665 } 568 666 unlock( &this->lock ); … … 590 688 } 591 689 head->next = NULL; 592 } 690 } 593 691 return head; 594 692 } … … 609 707 this->top = top->next; 610 708 top->next = NULL; 611 } 709 } 612 710 return top; 613 711 } -
src/libcfa/concurrency/kernel_private.h
r8c680e9 rb751c8e 18 18 #define KERNEL_PRIVATE_H 19 19 20 #include "libhdr.h" 21 20 22 #include "kernel" 21 23 #include "thread" … … 23 25 #include "alarm.h" 24 26 25 #include "libhdr.h"26 27 27 28 //----------------------------------------------------------------------------- 28 29 // Scheduler 30 31 extern "C" { 32 void disable_interrupts(); 33 void enable_interrupts_noRF(); 34 void enable_interrupts( DEBUG_CTX_PARAM ); 35 } 36 29 37 void ScheduleThread( thread_desc * ); 38 static inline void WakeThread( thread_desc * thrd ) { 39 if( !thrd ) return; 40 41 disable_interrupts(); 42 ScheduleThread( thrd ); 43 enable_interrupts( DEBUG_CTX ); 44 } 30 45 thread_desc * nextThread(cluster * this); 31 46 32 void ScheduleInternal(void);33 void ScheduleInternal(spinlock * lock);34 void ScheduleInternal(thread_desc * thrd);35 void ScheduleInternal(spinlock * lock, thread_desc * thrd);36 void ScheduleInternal(spinlock ** locks, unsigned short count);37 void ScheduleInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count);47 void BlockInternal(void); 48 void BlockInternal(spinlock * lock); 49 void BlockInternal(thread_desc * thrd); 50 void BlockInternal(spinlock * lock, thread_desc * thrd); 51 void BlockInternal(spinlock ** locks, unsigned short count); 52 void BlockInternal(spinlock ** locks, unsigned short count, thread_desc ** thrds, unsigned short thrd_count); 38 53 39 54 //----------------------------------------------------------------------------- … … 60 75 extern cluster * systemCluster; 61 76 extern system_proc_t * systemProcessor; 62 extern thread_local processor * this_processor; 63 64 static inline void disable_interrupts() { 65 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 66 assert( prev != (unsigned short) -1 ); 67 } 68 69 static inline void enable_interrupts_noRF() { 70 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 71 verify( prev != (unsigned short) 0 ); 72 } 73 74 static inline void enable_interrupts() { 75 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &this_processor->disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 76 verify( prev != (unsigned short) 0 ); 77 if( prev == 1 && this_processor->pending_preemption ) { 78 ScheduleInternal( this_processor->current_thread ); 79 this_processor->pending_preemption = false; 80 } 81 } 77 extern volatile thread_local processor * this_processor; 78 extern volatile thread_local coroutine_desc * this_coroutine; 79 extern volatile thread_local thread_desc * this_thread; 80 extern volatile thread_local unsigned short disable_preempt_count; 82 81 83 82 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/monitor
r8c680e9 rb751c8e 26 26 static inline void ?{}(monitor_desc * this) { 27 27 this->owner = NULL; 28 this->stack_owner = NULL;29 28 this->recursion = 0; 30 29 } -
src/libcfa/concurrency/monitor.c
r8c680e9 rb751c8e 19 19 #include <stdlib> 20 20 21 #include "libhdr.h" 21 22 #include "kernel_private.h" 22 #include "libhdr.h"23 23 24 24 //----------------------------------------------------------------------------- … … 44 44 45 45 extern "C" { 46 void __enter_monitor_desc( monitor_desc * this) {47 lock ( &this->lock);48 thread_desc * thrd = this_thread ();49 50 LIB_DEBUG_PRINT_SAFE("%p Entering %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);46 void __enter_monitor_desc( monitor_desc * this ) { 47 lock_yield( &this->lock DEBUG_CTX2 ); 48 thread_desc * thrd = this_thread; 49 50 // LIB_DEBUG_PRINT_SAFE("%p Entering %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion); 51 51 52 52 if( !this->owner ) { … … 62 62 //Some one else has the monitor, wait in line for it 63 63 append( &this->entry_queue, thrd ); 64 LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);65 ScheduleInternal( &this->lock );66 67 // ScheduleInternal will unlock spinlock, no need to unlock ourselves68 return; 64 // LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd); 65 BlockInternal( &this->lock ); 66 67 //BlockInternal will unlock spinlock, no need to unlock ourselves 68 return; 69 69 } 70 70 … … 75 75 // leave pseudo code : 76 76 // TODO 77 void __leave_monitor_desc( monitor_desc * this) {78 lock ( &this->lock);79 80 LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);81 verifyf( this_thread () == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread(), this->owner, this->recursion );77 void __leave_monitor_desc( monitor_desc * this ) { 78 lock_yield( &this->lock DEBUG_CTX2 ); 79 80 // LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i). ", this_thread, this, this->owner, this->recursion); 81 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread, this->owner, this->recursion ); 82 82 83 83 //Leaving a recursion level, decrement the counter … … 96 96 unlock( &this->lock ); 97 97 98 LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner);98 // LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner); 99 99 100 100 //We need to wake-up the thread 101 ScheduleThread( new_owner ); 101 WakeThread( new_owner ); 102 } 103 104 void __leave_thread_monitor( thread_desc * thrd ) { 105 monitor_desc * this = &thrd->mon; 106 lock_yield( &this->lock DEBUG_CTX2 ); 107 108 disable_interrupts(); 109 110 thrd->cor.state = Halted; 111 112 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion ); 113 114 //Leaving a recursion level, decrement the counter 115 this->recursion -= 1; 116 117 //If we haven't left the last level of recursion 118 //it means we don't need to do anything 119 if( this->recursion != 0) { 120 unlock( &this->lock ); 121 return; 122 } 123 124 thread_desc * new_owner = next_thread( this ); 125 126 //We can now let other threads in safely 127 unlock( &this->lock ); 128 129 //We need to wake-up the thread 130 if( new_owner) ScheduleThread( new_owner ); 102 131 } 103 132 } … … 121 150 enter( this->m, this->count ); 122 151 123 this->prev_mntrs = this_thread ()->current_monitors;124 this->prev_count = this_thread ()->current_monitor_count;125 126 this_thread ()->current_monitors = m;127 this_thread ()->current_monitor_count = count;152 this->prev_mntrs = this_thread->current_monitors; 153 this->prev_count = this_thread->current_monitor_count; 154 155 this_thread->current_monitors = m; 156 this_thread->current_monitor_count = count; 128 157 } 129 158 … … 131 160 leave( this->m, this->count ); 132 161 133 this_thread ()->current_monitors = this->prev_mntrs;134 this_thread ()->current_monitor_count = this->prev_count;162 this_thread->current_monitors = this->prev_mntrs; 163 this_thread->current_monitor_count = this->prev_count; 135 164 } 136 165 … … 159 188 // Internal scheduling 160 189 void wait( condition * this, uintptr_t user_info = 0 ) { 161 LIB_DEBUG_PRINT_SAFE("Waiting\n");190 // LIB_DEBUG_PRINT_SAFE("Waiting\n"); 162 191 163 192 brand_condition( this ); … … 170 199 unsigned short count = this->monitor_count; 171 200 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 172 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal173 174 LIB_DEBUG_PRINT_SAFE("count %i\n", count);175 176 __condition_node_t waiter = { this_thread(), count, user_info };201 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 202 203 // LIB_DEBUG_PRINT_SAFE("count %i\n", count); 204 205 __condition_node_t waiter = { (thread_desc*)this_thread, count, user_info }; 177 206 178 207 __condition_criterion_t criteria[count]; 179 208 for(int i = 0; i < count; i++) { 180 209 (&criteria[i]){ this->monitors[i], &waiter }; 181 LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );210 // LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] ); 182 211 } 183 212 … … 201 230 } 202 231 203 LIB_DEBUG_PRINT_SAFE("Will unblock: ");232 // LIB_DEBUG_PRINT_SAFE("Will unblock: "); 204 233 for(int i = 0; i < thread_count; i++) { 205 LIB_DEBUG_PRINT_SAFE("%p ", threads[i]);206 } 207 LIB_DEBUG_PRINT_SAFE("\n");234 // LIB_DEBUG_PRINT_SAFE("%p ", threads[i]); 235 } 236 // LIB_DEBUG_PRINT_SAFE("\n"); 208 237 209 238 // Everything is ready to go to sleep 210 ScheduleInternal( locks, count, threads, thread_count );239 BlockInternal( locks, count, threads, thread_count ); 211 240 212 241 … … 222 251 bool signal( condition * this ) { 223 252 if( is_empty( this ) ) { 224 LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");253 // LIB_DEBUG_PRINT_SAFE("Nothing to signal\n"); 225 254 return false; 226 255 } … … 231 260 232 261 unsigned short count = this->monitor_count; 233 262 234 263 //Some more checking in debug 235 264 LIB_DEBUG_DO( 236 thread_desc * this_thrd = this_thread ();265 thread_desc * this_thrd = this_thread; 237 266 if ( this->monitor_count != this_thrd->current_monitor_count ) { 238 267 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->current_monitor_count ); … … 248 277 //Lock all the monitors 249 278 lock_all( this->monitors, NULL, count ); 250 LIB_DEBUG_PRINT_SAFE("Signalling");279 // LIB_DEBUG_PRINT_SAFE("Signalling"); 251 280 252 281 //Pop the head of the waiting queue … … 256 285 for(int i = 0; i < count; i++) { 257 286 __condition_criterion_t * crit = &node->criteria[i]; 258 LIB_DEBUG_PRINT_SAFE(" %p", crit->target);287 // LIB_DEBUG_PRINT_SAFE(" %p", crit->target); 259 288 assert( !crit->ready ); 260 289 push( &crit->target->signal_stack, crit ); 261 290 } 262 291 263 LIB_DEBUG_PRINT_SAFE("\n");292 // LIB_DEBUG_PRINT_SAFE("\n"); 264 293 265 294 //Release … … 281 310 unsigned short count = this->monitor_count; 282 311 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 283 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal312 spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 284 313 285 314 lock_all( this->monitors, locks, count ); 286 315 287 316 //create creteria 288 __condition_node_t waiter = { this_thread(), count, 0 };317 __condition_node_t waiter = { (thread_desc*)this_thread, count, 0 }; 289 318 290 319 __condition_criterion_t criteria[count]; 291 320 for(int i = 0; i < count; i++) { 292 321 (&criteria[i]){ this->monitors[i], &waiter }; 293 LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );322 // LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] ); 294 323 push( &criteria[i].target->signal_stack, &criteria[i] ); 295 324 } … … 309 338 310 339 //Everything is ready to go to sleep 311 ScheduleInternal( locks, count, &signallee, 1 );340 BlockInternal( locks, count, &signallee, 1 ); 312 341 313 342 … … 325 354 326 355 uintptr_t front( condition * this ) { 327 verifyf( !is_empty(this), 356 verifyf( !is_empty(this), 328 357 "Attempt to access user data on an empty condition.\n" 329 358 "Possible cause is not checking if the condition is empty before reading stored data." … … 335 364 // Internal scheduling 336 365 void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) { 337 // thread_desc * this = this_thread ();366 // thread_desc * this = this_thread; 338 367 339 368 // unsigned short count = this->current_monitor_count; 340 369 // unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 341 // spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal370 // spinlock * locks [ count ]; //We need to pass-in an array of locks to BlockInternal 342 371 343 372 // lock_all( this->current_monitors, locks, count ); … … 348 377 349 378 // // // Everything is ready to go to sleep 350 // // ScheduleInternal( locks, count, threads, thread_count );379 // // BlockInternal( locks, count, threads, thread_count ); 351 380 352 381 … … 393 422 static inline void lock_all( spinlock ** locks, unsigned short count ) { 394 423 for( int i = 0; i < count; i++ ) { 395 lock ( locks[i]);424 lock_yield( locks[i] DEBUG_CTX2 ); 396 425 } 397 426 } … … 400 429 for( int i = 0; i < count; i++ ) { 401 430 spinlock * l = &source[i]->lock; 402 lock ( l);431 lock_yield( l DEBUG_CTX2 ); 403 432 if(locks) locks[i] = l; 404 433 } … … 443 472 for( int i = 0; i < count; i++ ) { 444 473 445 LIB_DEBUG_PRINT_SAFE( "Checking %p for %p\n", &criteria[i], target );474 // LIB_DEBUG_PRINT_SAFE( "Checking %p for %p\n", &criteria[i], target ); 446 475 if( &criteria[i] == target ) { 447 476 criteria[i].ready = true; 448 LIB_DEBUG_PRINT_SAFE( "True\n" );477 // LIB_DEBUG_PRINT_SAFE( "True\n" ); 449 478 } 450 479 … … 452 481 } 453 482 454 LIB_DEBUG_PRINT_SAFE( "Runing %i\n", ready2run );483 // LIB_DEBUG_PRINT_SAFE( "Runing %i\n", ready2run ); 455 484 return ready2run ? node->waiting_thread : NULL; 456 485 } 457 486 458 487 static inline void brand_condition( condition * this ) { 459 thread_desc * thrd = this_thread ();488 thread_desc * thrd = this_thread; 460 489 if( !this->monitors ) { 461 LIB_DEBUG_PRINT_SAFE("Branding\n");490 // LIB_DEBUG_PRINT_SAFE("Branding\n"); 462 491 assertf( thrd->current_monitors != NULL, "No current monitor to brand condition", thrd->current_monitors ); 463 492 this->monitor_count = thrd->current_monitor_count; -
src/libcfa/concurrency/preemption.c
r8c680e9 rb751c8e 15 15 // 16 16 17 #include "libhdr.h" 17 18 #include "preemption.h" 18 19 19 20 extern "C" { 21 #include <errno.h> 22 #include <execinfo.h> 23 #define __USE_GNU 20 24 #include <signal.h> 21 } 22 23 #define __CFA_DEFAULT_PREEMPTION__ 10 25 #undef __USE_GNU 26 #include <stdio.h> 27 #include <string.h> 28 #include <unistd.h> 29 } 30 31 32 #ifdef __USE_STREAM__ 33 #include "fstream" 34 #endif 35 36 #define __CFA_DEFAULT_PREEMPTION__ 10000 24 37 25 38 __attribute__((weak)) unsigned int default_preemption() { … … 27 40 } 28 41 42 #define __CFA_SIGCXT__ ucontext_t * 43 #define __CFA_SIGPARMS__ __attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *sfp, __attribute__((unused)) __CFA_SIGCXT__ cxt 44 29 45 static void preempt( processor * this ); 30 46 static void timeout( thread_desc * this ); 31 47 48 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ); 49 void sigHandler_alarm ( __CFA_SIGPARMS__ ); 50 void sigHandler_segv ( __CFA_SIGPARMS__ ); 51 void sigHandler_abort ( __CFA_SIGPARMS__ ); 52 53 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ); 54 32 55 //============================================================================================= 33 56 // Kernel Preemption logic … … 35 58 36 59 void kernel_start_preemption() { 37 38 } 60 LIB_DEBUG_PRINT_SAFE("Kernel : Starting preemption\n"); 61 __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO ); 62 __kernel_sigaction( SIGALRM, sigHandler_alarm , SA_SIGINFO ); 63 __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); 64 __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); 65 // __kernel_sigaction( SIGABRT, sigHandler_abort , SA_SIGINFO ); 66 } 67 68 void kernel_stop_preemption() { 69 //Block all signals, we are no longer in a position to handle them 70 sigset_t mask; 71 sigfillset( &mask ); 72 sigprocmask( SIG_BLOCK, &mask, NULL ); 73 LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n"); 74 75 // assert( !systemProcessor->alarms.head ); 76 // assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head ); 77 } 78 79 LIB_DEBUG_DO( bool validate( alarm_list_t * this ); ) 39 80 40 81 void tick_preemption() { 82 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" ); 83 41 84 alarm_list_t * alarms = &systemProcessor->alarms; 42 85 __cfa_time_t currtime = __kernel_get_time(); 43 86 while( alarms->head && alarms->head->alarm < currtime ) { 44 87 alarm_node_t * node = pop(alarms); 88 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node ); 89 45 90 if( node->kernel_alarm ) { 46 91 preempt( node->proc ); … … 50 95 } 51 96 97 verify( validate( alarms ) ); 98 52 99 if( node->period > 0 ) { 53 node->alarm +=node->period;100 node->alarm = currtime + node->period; 54 101 insert( alarms, node ); 55 102 } … … 62 109 __kernel_set_timer( alarms->head->alarm - currtime ); 63 110 } 111 112 verify( validate( alarms ) ); 113 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" ); 64 114 } 65 115 66 116 void update_preemption( processor * this, __cfa_time_t duration ) { 67 // assert( THREAD_GETMEM( disableInt ) && THREAD_GETMEM( disableIntCnt ) == 1 ); 117 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration ); 118 68 119 alarm_node_t * alarm = this->preemption_alarm; 120 duration *= 1000; 69 121 70 122 // Alarms need to be enabled … … 97 149 98 150 void ^?{}( preemption_scope * this ) { 151 disable_interrupts(); 152 99 153 update_preemption( this->proc, 0 ); 100 154 } … … 104 158 //============================================================================================= 105 159 160 LIB_DEBUG_DO( static thread_local void * last_interrupt = 0; ) 161 162 extern "C" { 163 void disable_interrupts() { 164 __attribute__((unused)) unsigned short new_val = __atomic_add_fetch_2( &disable_preempt_count, 1, __ATOMIC_SEQ_CST ); 165 verify( new_val < (unsigned short)65_000 ); 166 verify( new_val != (unsigned short) 0 ); 167 } 168 169 void enable_interrupts_noRF() { 170 __attribute__((unused)) unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 171 verify( prev != (unsigned short) 0 ); 172 } 173 174 void enable_interrupts( DEBUG_CTX_PARAM ) { 175 processor * proc = this_processor; 176 thread_desc * thrd = this_thread; 177 unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST ); 178 verify( prev != (unsigned short) 0 ); 179 if( prev == 1 && proc->pending_preemption ) { 180 proc->pending_preemption = false; 181 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Executing deferred CtxSwitch on %p\n", this_processor ); 182 BlockInternal( thrd ); 183 LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Executing deferred back\n" ); 184 } 185 186 LIB_DEBUG_DO( proc->last_enable = caller; ) 187 } 188 } 189 190 static inline void signal_unblock( int sig ) { 191 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p unblocking sig %i\n", this_processor, sig ); 192 193 // LIB_DEBUG_DO( 194 // sigset_t waiting; 195 // sigemptyset(&waiting); 196 // sigpending(&waiting); 197 // verify( !sigismember(&waiting, sig) ); 198 // ) 199 200 sigset_t mask; 201 sigemptyset( &mask ); 202 sigaddset( &mask, sig ); 203 204 if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) { 205 abortf( "internal error, sigprocmask" ); 206 } // if 207 } 208 106 209 static inline bool preemption_ready() { 107 return this_processor->disable_preempt_count == 0;210 return disable_preempt_count == 0; 108 211 } 109 212 … … 116 219 } 117 220 118 void sigHandler_ctxSwitch( __attribute__((unused)) int sig ) { 221 extern "C" { 222 __attribute__((noinline)) void __debug_break() { 223 pthread_kill( pthread_self(), SIGTRAP ); 224 } 225 } 226 227 void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) { 228 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "CtxSw IRH %10p running %10p @ %10p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 229 LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[REG_RIP]); ) 230 119 231 if( preemption_ready() ) { 120 ScheduleInternal( this_processor->current_thread ); 232 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 233 signal_unblock( SIGUSR1 ); 234 BlockInternal( (thread_desc*)this_thread ); 235 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Back\n\n"); 236 } 237 else { 238 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Defering\n" ); 239 defer_ctxSwitch(); 240 signal_unblock( SIGUSR1 ); 241 } 242 } 243 244 void sigHandler_alarm( __CFA_SIGPARMS__ ) { 245 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "\nAlarm IRH %10p running %10p @ %10p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) ); 246 LIB_DEBUG_DO( last_interrupt = (void *)(cxt->uc_mcontext.gregs[REG_RIP]); ) 247 248 if( try_lock( &systemProcessor->alarm_lock DEBUG_CTX2 ) ) { 249 tick_preemption(); 250 unlock( &systemProcessor->alarm_lock ); 251 } 252 else { 253 defer_alarm(); 254 } 255 256 signal_unblock( SIGALRM ); 257 258 if( preemption_ready() && this_processor->pending_preemption ) { 259 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm IRH : Blocking thread %p on %p\n", this_thread, this_processor ); 260 this_processor->pending_preemption = false; 261 BlockInternal( (thread_desc*)this_thread ); 262 // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm Switch IRH : Back\n\n"); 263 } 264 } 265 266 static void preempt( processor * this ) { 267 // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : signalling %p\n", this ); 268 269 if( this != systemProcessor ) { 270 pthread_kill( this->kernel_thread, SIGUSR1 ); 121 271 } 122 272 else { … … 125 275 } 126 276 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 277 static void timeout( thread_desc * this ) { 142 278 //TODO : implement waking threads 143 279 } 280 281 static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags ) { 282 struct sigaction act; 283 284 act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler; 285 act.sa_flags = flags; 286 287 // disabled during signal handler 288 sigemptyset( &act.sa_mask ); 289 sigaddset( &act.sa_mask, sig ); 290 291 if ( sigaction( sig, &act, NULL ) == -1 ) { 292 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 293 " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n", 294 sig, handler, flags, errno, strerror( errno ) 295 ); 296 _exit( EXIT_FAILURE ); 297 } 298 } 299 300 typedef void (*sa_handler_t)(int); 301 302 static void __kernel_sigdefault( int sig ) { 303 struct sigaction act; 304 305 // act.sa_handler = SIG_DFL; 306 act.sa_flags = 0; 307 sigemptyset( &act.sa_mask ); 308 309 if ( sigaction( sig, &act, NULL ) == -1 ) { 310 LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, 311 " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n", 312 sig, errno, strerror( errno ) 313 ); 314 _exit( EXIT_FAILURE ); 315 } 316 } 317 318 //============================================================================================= 319 // Terminating Signals logic 320 //============================================================================================= 321 322 LIB_DEBUG_DO( 323 static void __kernel_backtrace( int start ) { 324 // skip first N stack frames 325 326 enum { Frames = 50 }; 327 void * array[Frames]; 328 int size = backtrace( array, Frames ); 329 char ** messages = backtrace_symbols( array, size ); 330 331 // find executable name 332 *index( messages[0], '(' ) = '\0'; 333 #ifdef __USE_STREAM__ 334 serr | "Stack back trace for:" | messages[0] | endl; 335 #else 336 fprintf( stderr, "Stack back trace for: %s\n", messages[0]); 337 #endif 338 339 // skip last 2 stack frames after main 340 for ( int i = start; i < size && messages != NULL; i += 1 ) { 341 char * name = NULL; 342 char * offset_begin = NULL; 343 char * offset_end = NULL; 344 345 for ( char *p = messages[i]; *p; ++p ) { 346 // find parantheses and +offset 347 if ( *p == '(' ) { 348 name = p; 349 } 350 else if ( *p == '+' ) { 351 offset_begin = p; 352 } 353 else if ( *p == ')' ) { 354 offset_end = p; 355 break; 356 } 357 } 358 359 // if line contains symbol print it 360 int frameNo = i - start; 361 if ( name && offset_begin && offset_end && name < offset_begin ) { 362 // delimit strings 363 *name++ = '\0'; 364 *offset_begin++ = '\0'; 365 *offset_end++ = '\0'; 366 367 #ifdef __USE_STREAM__ 368 serr | "(" | frameNo | ")" | messages[i] | ":" 369 | name | "+" | offset_begin | offset_end | endl; 370 #else 371 fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end); 372 #endif 373 } 374 // otherwise, print the whole line 375 else { 376 #ifdef __USE_STREAM__ 377 serr | "(" | frameNo | ")" | messages[i] | endl; 378 #else 379 fprintf( stderr, "(%i) %s\n", frameNo, messages[i] ); 380 #endif 381 } 382 } 383 384 free( messages ); 385 } 386 ) 387 388 void sigHandler_segv( __CFA_SIGPARMS__ ) { 389 LIB_DEBUG_DO( 390 #ifdef __USE_STREAM__ 391 serr | "*CFA runtime error* program cfa-cpp terminated with" 392 | (sig == SIGSEGV ? "segment fault." : "bus error.") 393 | endl; 394 #else 395 fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." ); 396 #endif 397 398 // skip first 2 stack frames 399 __kernel_backtrace( 1 ); 400 ) 401 exit( EXIT_FAILURE ); 402 } 403 404 // void sigHandler_abort( __CFA_SIGPARMS__ ) { 405 // // skip first 6 stack frames 406 // LIB_DEBUG_DO( __kernel_backtrace( 6 ); ) 407 408 // // reset default signal handler 409 // __kernel_sigdefault( SIGABRT ); 410 411 // raise( SIGABRT ); 412 // } -
src/libcfa/concurrency/thread
r8c680e9 rb751c8e 54 54 } 55 55 56 thread_desc * this_thread(void);56 extern volatile thread_local thread_desc * this_thread; 57 57 58 58 forall( dtype T | is_thread(T) ) -
src/libcfa/concurrency/thread.c
r8c680e9 rb751c8e 28 28 } 29 29 30 extern thread_local processor * this_processor;30 extern volatile thread_local processor * this_processor; 31 31 32 32 //----------------------------------------------------------------------------- … … 71 71 coroutine_desc* thrd_c = get_coroutine(this); 72 72 thread_desc* thrd_h = get_thread (this); 73 thrd_c->last = this_coroutine(); 74 this_processor->current_coroutine = thrd_c; 73 thrd_c->last = this_coroutine; 75 74 76 LIB_DEBUG_PRINT_SAFE("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h);75 // LIB_DEBUG_PRINT_SAFE("Thread start : %p (t %p, c %p)\n", this, thrd_c, thrd_h); 77 76 77 disable_interrupts(); 78 78 create_stack(&thrd_c->stack, thrd_c->stack.size); 79 this_coroutine = thrd_c; 79 80 CtxStart(this, CtxInvokeThread); 81 assert( thrd_c->last->stack.context ); 80 82 CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context ); 81 83 82 84 ScheduleThread(thrd_h); 85 enable_interrupts( DEBUG_CTX ); 83 86 } 84 87 85 88 void yield( void ) { 86 ScheduleInternal( this_processor->current_thread );89 BlockInternal( (thread_desc *)this_thread ); 87 90 } 88 91 … … 95 98 void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) { 96 99 // set state of current coroutine to inactive 97 src->state = Inactive;100 src->state = src->state == Halted ? Halted : Inactive; 98 101 dst->state = Active; 99 102 … … 103 106 // set new coroutine that the processor is executing 104 107 // and context switch to it 105 this_processor->current_coroutine = dst; 108 this_coroutine = dst; 109 assert( src->stack.context ); 106 110 CtxSwitch( src->stack.context, dst->stack.context ); 107 this_ processor->current_coroutine = src;111 this_coroutine = src; 108 112 109 113 // set state of new coroutine to active 110 dst->state = Inactive;114 dst->state = dst->state == Halted ? Halted : Inactive; 111 115 src->state = Active; 112 116 } -
src/libcfa/libhdr/libalign.h
r8c680e9 rb751c8e 1 // -*- Mode: C++ -*- 1 // -*- Mode: C++ -*- 2 2 // 3 3 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo … … 18 18 // Free Software Foundation; either version 2.1 of the License, or (at your 19 19 // option) any later version. 20 // 20 // 21 21 // This library is distributed in the hope that it will be useful, but WITHOUT 22 22 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 23 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 24 24 // for more details. 25 // 25 // 26 26 // You should have received a copy of the GNU Lesser General Public License 27 27 // along with this library. 28 // 28 // 29 29 30 30 … … 33 33 34 34 #include "assert" 35 #include <stdbool.h> 35 36 36 // Minimum size used to align memory boundaries for memory allocations. 37 // Minimum size used to align memory boundaries for memory allocations. 37 38 #define libAlign() (sizeof(double)) 38 39 -
src/libcfa/libhdr/libdebug.h
r8c680e9 rb751c8e 18 18 19 19 #ifdef __CFA_DEBUG__ 20 #define LIB_DEBUG_DO(x) x 21 #define LIB_NO_DEBUG_DO(x) ((void)0) 20 #define LIB_DEBUG_DO(...) __VA_ARGS__ 21 #define LIB_NO_DEBUG_DO(...) 22 #define DEBUG_CTX __PRETTY_FUNCTION__ 23 #define DEBUG_CTX2 , __PRETTY_FUNCTION__ 24 #define DEBUG_CTX_PARAM const char * caller 25 #define DEBUG_CTX_PARAM2 , const char * caller 22 26 #else 23 #define LIB_DEBUG_DO(x) ((void)0) 24 #define LIB_NO_DEBUG_DO(x) x 27 #define LIB_DEBUG_DO(...) 28 #define LIB_NO_DEBUG_DO(...) __VA_ARGS__ 29 #define DEBUG_CTX 30 #define DEBUG_CTX2 31 #define DEBUG_CTX_PARAM 32 #define DEBUG_CTX_PARAM2 25 33 #endif 26 34 … … 51 59 52 60 #ifdef __CFA_DEBUG_PRINT__ 53 #define LIB_DEBUG_WRITE( fd, buffer, len ) __lib_debug_write( fd, buffer, len ) 54 #define LIB_DEBUG_ACQUIRE() __lib_debug_acquire() 55 #define LIB_DEBUG_RELEASE() __lib_debug_release() 56 #define LIB_DEBUG_PRINT_SAFE(...) __lib_debug_print_safe (__VA_ARGS__) 57 #define LIB_DEBUG_PRINT_NOLOCK(...) __lib_debug_print_nolock (__VA_ARGS__) 58 #define LIB_DEBUG_PRINT_BUFFER(...) __lib_debug_print_buffer (__VA_ARGS__) 61 #define LIB_DEBUG_WRITE( fd, buffer, len ) __lib_debug_write( fd, buffer, len ) 62 #define LIB_DEBUG_ACQUIRE() __lib_debug_acquire() 63 #define LIB_DEBUG_RELEASE() __lib_debug_release() 64 #define LIB_DEBUG_PRINT_SAFE(...) __lib_debug_print_safe (__VA_ARGS__) 65 #define LIB_DEBUG_PRINT_NOLOCK(...) __lib_debug_print_nolock (__VA_ARGS__) 66 #define LIB_DEBUG_PRINT_BUFFER(...) __lib_debug_print_buffer (__VA_ARGS__) 67 #define LIB_DEBUG_PRINT_BUFFER_DECL(fd, ...) char text[256]; int len = snprintf( text, 256, __VA_ARGS__ ); __lib_debug_write( fd, text, len ); 68 #define LIB_DEBUG_PRINT_BUFFER_LOCAL(fd, ...) len = snprintf( text, 256, __VA_ARGS__ ); __lib_debug_write( fd, text, len ); 59 69 #else 60 #define LIB_DEBUG_WRITE(...) ((void)0) 61 #define LIB_DEBUG_ACQUIRE() ((void)0) 62 #define LIB_DEBUG_RELEASE() ((void)0) 63 #define LIB_DEBUG_PRINT_SAFE(...) ((void)0) 64 #define LIB_DEBUG_PRINT_NOLOCK(...) ((void)0) 65 #define LIB_DEBUG_PRINT_BUFFER(...) ((void)0) 70 #define LIB_DEBUG_WRITE(...) ((void)0) 71 #define LIB_DEBUG_ACQUIRE() ((void)0) 72 #define LIB_DEBUG_RELEASE() ((void)0) 73 #define LIB_DEBUG_PRINT_SAFE(...) ((void)0) 74 #define LIB_DEBUG_PRINT_NOLOCK(...) ((void)0) 75 #define LIB_DEBUG_PRINT_BUFFER(...) ((void)0) 76 #define LIB_DEBUG_PRINT_BUFFER_DECL(...) ((void)0) 77 #define LIB_DEBUG_PRINT_BUFFER_LOCAL(...) ((void)0) 66 78 #endif 67 79 -
src/tests/sched-int-block.c
r8c680e9 rb751c8e 31 31 //------------------------------------------------------------------------------ 32 32 void wait_op( global_data_t * mutex a, global_data_t * mutex b, unsigned i ) { 33 wait( &cond, (uintptr_t)this_thread ());33 wait( &cond, (uintptr_t)this_thread ); 34 34 35 35 yield( ((unsigned)rand48()) % 10 ); … … 40 40 } 41 41 42 a->last_thread = b->last_thread = this_thread ();42 a->last_thread = b->last_thread = this_thread; 43 43 44 44 yield( ((unsigned)rand48()) % 10 ); … … 56 56 yield( ((unsigned)rand48()) % 10 ); 57 57 58 a->last_thread = b->last_thread = a->last_signaller = b->last_signaller = this_thread ();58 a->last_thread = b->last_thread = a->last_signaller = b->last_signaller = this_thread; 59 59 60 60 if( !is_empty( &cond ) ) { … … 86 86 //------------------------------------------------------------------------------ 87 87 void barge_op( global_data_t * mutex a ) { 88 a->last_thread = this_thread ();88 a->last_thread = this_thread; 89 89 } 90 90
Note:
See TracChangeset
for help on using the changeset viewer.