Changeset 1c273d0


Ignore:
Timestamp:
Jun 23, 2017, 10:12:04 AM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
d43cd01
Parents:
aa3d77b
Message:

preemption works for threads

Location:
src
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/alarm.c

    raa3d77b r1c273d0  
    3737        clock_gettime( CLOCK_REALTIME, &curr );
    3838        __cfa_time_t curr_time = ((__cfa_time_t)curr.tv_sec * TIMEGRAN) + curr.tv_nsec;
    39         LIB_DEBUG_DO(
    40                 char text[256];
    41                 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : current time is %lu\n", curr_time );
    42                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    43         );
     39        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : current time is %lu\n", curr_time );
    4440        return curr_time;
    4541}
    4642
    4743void __kernel_set_timer( __cfa_time_t alarm ) {
    48 
    49         LIB_DEBUG_DO(
    50                 char text[256];
    51                 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm );
    52                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    53         );
    54 
     44        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : set timer to %lu\n", (__cfa_time_t)alarm );
    5545        itimerval val;
    5646        val.it_value.tv_sec = alarm / TIMEGRAN;                 // seconds
     
    164154        disable_interrupts();
    165155        verify( !systemProcessor->pending_alarm );
    166         lock( &systemProcessor->alarm_lock );
     156        lock( &systemProcessor->alarm_lock, __PRETTY_FUNCTION__ );
    167157        {
    168158                verify( validate( &systemProcessor->alarms ) );
     
    183173
    184174void unregister_self( alarm_node_t * this ) {
    185         LIB_DEBUG_DO(
    186                 char text[256];
    187                 __attribute__((unused)) int len = snprintf( text, 256, "Kernel : unregister %p start\n", this );
    188                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    189         );
     175        // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Kernel : unregister %p start\n", this );
    190176        disable_interrupts();
    191         lock( &systemProcessor->alarm_lock );
     177        lock( &systemProcessor->alarm_lock, __PRETTY_FUNCTION__ );
    192178        {
    193179                verify( validate( &systemProcessor->alarms ) );
     
    197183        disable_interrupts();
    198184        this->set = false;
    199         LIB_DEBUG_DO(
    200                 len = snprintf( text, 256, "Kernel : unregister %p end\n", this );
    201                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    202         );
     185        // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Kernel : unregister %p end\n", this );
    203186}
  • src/libcfa/concurrency/coroutine

    raa3d77b r1c273d0  
    6363
    6464// Get current coroutine
    65 coroutine_desc * this_coroutine(void);
     65extern volatile thread_local coroutine_desc * this_coroutine;
    6666
    6767// Private wrappers for context switch and stack creation
     
    7171// Suspend implementation inlined for performance
    7272static inline void suspend() {
    73         coroutine_desc * src = this_coroutine();                // optimization
     73        coroutine_desc * src = this_coroutine;          // optimization
    7474
    7575        assertf( src->last != 0,
     
    8888forall(dtype T | is_coroutine(T))
    8989static inline void resume(T * cor) {
    90         coroutine_desc * src = this_coroutine();                // optimization
     90        coroutine_desc * src = this_coroutine;          // optimization
    9191        coroutine_desc * dst = get_coroutine(cor);
    9292
     
    112112
    113113static inline void resume(coroutine_desc * dst) {
    114         coroutine_desc * src = this_coroutine();                // optimization
     114        coroutine_desc * src = this_coroutine;          // optimization
    115115
    116116        // not resuming self ?
  • src/libcfa/concurrency/coroutine.c

    raa3d77b r1c273d0  
    106106
    107107        // set state of current coroutine to inactive
    108         src->state = Inactive;
     108        src->state = src->state == Halted ? Halted : Inactive;
    109109
    110110        // set new coroutine that task is executing
    111         this_processor->current_coroutine = dst;
     111        this_coroutine = dst;
    112112
    113113        // context switch to specified coroutine
     114        assert( src->stack.context );
    114115        CtxSwitch( src->stack.context, dst->stack.context );
    115116        // when CtxSwitch returns we are back in the src coroutine             
  • src/libcfa/concurrency/invoke.c

    raa3d77b r1c273d0  
    2929
    3030extern void __suspend_internal(void);
    31 extern void __leave_monitor_desc( struct monitor_desc * this );
     31extern void __leave_thread_monitor( struct thread_desc * this );
    3232extern void disable_interrupts();
    3333extern void enable_interrupts( const char * );
    3434
    3535void CtxInvokeCoroutine(
    36       void (*main)(void *), 
    37       struct coroutine_desc *(*get_coroutine)(void *), 
     36      void (*main)(void *),
     37      struct coroutine_desc *(*get_coroutine)(void *),
    3838      void *this
    3939) {
     
    5858
    5959void CtxInvokeThread(
    60       void (*dtor)(void *), 
    61       void (*main)(void *), 
    62       struct thread_desc *(*get_thread)(void *), 
     60      void (*dtor)(void *),
     61      void (*main)(void *),
     62      struct thread_desc *(*get_thread)(void *),
    6363      void *this
    6464) {
     65      // First suspend, once the thread arrives here,
     66      // the function pointer to main can be invalidated without risk
    6567      __suspend_internal();
    6668
     69      // Fetch the thread handle from the user defined thread structure
    6770      struct thread_desc* thrd = get_thread( this );
    68       struct coroutine_desc* cor = &thrd->cor;
    69       struct monitor_desc* mon = &thrd->mon;
    70       cor->state = Active;
     71
     72      // Officially start the thread by enabling preemption
    7173      enable_interrupts( __PRETTY_FUNCTION__ );
    7274
    73       // LIB_DEBUG_PRINTF("Invoke Thread : invoking main %p (args %p)\n", main, this);
     75      // Call the main of the thread
    7476      main( this );
    7577
    76       disable_interrupts();
    77       __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 );
    7884
    7985      //Final suspend, should never return
     
    8490
    8591void CtxStart(
    86       void (*main)(void *), 
    87       struct coroutine_desc *(*get_coroutine)(void *), 
    88       void *this, 
     92      void (*main)(void *),
     93      struct coroutine_desc *(*get_coroutine)(void *),
     94      void *this,
    8995      void (*invoke)(void *)
    9096) {
     
    112118        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke;
    113119      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    114       ((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
    115121
    116122#elif defined( __x86_64__ )
     
    132138      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fixedRegisters[1] = invoke;
    133139      ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520
    134       ((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
    135141#else
    136142      #error Only __i386__ and __x86_64__ is supported for threads in cfa
  • src/libcfa/concurrency/invoke.h

    raa3d77b r1c273d0  
    3131      struct spinlock {
    3232            volatile int lock;
     33            #ifdef __CFA_DEBUG__
     34                  const char * prev;
     35            #endif
    3336      };
    3437
     
    8386            struct __thread_queue_t entry_queue;      // queue of threads that are blocked waiting for the monitor
    8487            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 monitor
    8688            unsigned int recursion;                   // monitor routines can be called recursively, we need to keep track of that
    8789      };
  • src/libcfa/concurrency/kernel

    raa3d77b r1c273d0  
    2828//-----------------------------------------------------------------------------
    2929// Locks
    30 bool try_lock( spinlock * );
    31 void lock( spinlock * );
     30bool try_lock( spinlock *
     31        #ifdef __CFA_DEBUG__
     32                , const char * caller
     33        #endif
     34);
     35
     36void lock( spinlock *
     37        #ifdef __CFA_DEBUG__
     38                , const char * caller
     39        #endif
     40);
     41
    3242void unlock( spinlock * );
    3343
     
    7888        struct processorCtx_t * runner;
    7989        cluster * cltr;
    80         coroutine_desc * current_coroutine;
    81         thread_desc * current_thread;
    8290        pthread_t kernel_thread;
    8391       
  • src/libcfa/concurrency/kernel.c

    raa3d77b r1c273d0  
    6060
    6161volatile thread_local processor * this_processor;
    62 volatile thread_local unsigned short disable_preempt_count;
    63 
    64 coroutine_desc * this_coroutine(void) {
    65         return this_processor->current_coroutine;
    66 }
    67 
    68 thread_desc * this_thread(void) {
    69         return this_processor->current_thread;
    70 }
     62volatile thread_local coroutine_desc * this_coroutine;
     63volatile thread_local thread_desc * this_thread;
     64volatile thread_local unsigned short disable_preempt_count = 1;
    7165
    7266//-----------------------------------------------------------------------------
    7367// Main thread construction
    7468struct current_stack_info_t {
    75         machine_context_t ctx; 
     69        machine_context_t ctx;
    7670        unsigned int size;              // size of stack
    7771        void *base;                             // base of stack
     
    107101
    108102void ?{}( coroutine_desc * this, current_stack_info_t * info) {
    109         (&this->stack){ info }; 
     103        (&this->stack){ info };
    110104        this->name = "Main Thread";
    111105        this->errno_ = 0;
     
    137131void ?{}(processor * this, cluster * cltr) {
    138132        this->cltr = cltr;
    139         this->current_coroutine = NULL;
    140         this->current_thread = NULL;
    141133        (&this->terminated){};
    142134        this->is_terminated = false;
     
    150142void ?{}(processor * this, cluster * cltr, processorCtx_t * runner) {
    151143        this->cltr = cltr;
    152         this->current_coroutine = NULL;
    153         this->current_thread = NULL;
    154144        (&this->terminated){};
    155145        this->is_terminated = false;
     
    190180
    191181void ^?{}(cluster * this) {
    192        
     182
    193183}
    194184
     
    209199
    210200                thread_desc * readyThread = NULL;
    211                 for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ ) 
     201                for( unsigned int spin_count = 0; ! this->is_terminated; spin_count++ )
    212202                {
    213203                        readyThread = nextThread( this->cltr );
     
    239229}
    240230
    241 // runThread runs a thread by context switching 
    242 // from the processor coroutine to the target thread 
     231// runThread runs a thread by context switching
     232// from the processor coroutine to the target thread
    243233void runThread(processor * this, thread_desc * dst) {
    244234        coroutine_desc * proc_cor = get_coroutine(this->runner);
    245235        coroutine_desc * thrd_cor = get_coroutine(dst);
    246        
     236
    247237        //Reset the terminating actions here
    248238        this->finish.action_code = No_Action;
    249239
    250240        //Update global state
    251         this->current_thread = dst;
     241        this_thread = dst;
    252242
    253243        // Context Switch to the thread
     
    256246}
    257247
    258 // Once a thread has finished running, some of 
     248// Once a thread has finished running, some of
    259249// its final actions must be executed from the kernel
    260250void finishRunning(processor * this) {
     
    266256        }
    267257        else if( this->finish.action_code == Release_Schedule ) {
    268                 unlock( this->finish.lock );           
     258                unlock( this->finish.lock );
    269259                ScheduleThread( this->finish.thrd );
    270260        }
     
    299289        processor * proc = (processor *) arg;
    300290        this_processor = proc;
     291        this_coroutine = NULL;
     292        this_thread = NULL;
    301293        disable_preempt_count = 1;
    302294        // SKULLDUGGERY: We want to create a context for the processor coroutine
    303295        // which is needed for the 2-step context switch. However, there is no reason
    304         // to waste the perfectly valid stack create by pthread. 
     296        // to waste the perfectly valid stack create by pthread.
    305297        current_stack_info_t info;
    306298        machine_context_t ctx;
     
    311303
    312304        //Set global state
    313         proc->current_coroutine = &proc->runner->__cor;
    314         proc->current_thread = NULL;
     305        this_coroutine = &proc->runner->__cor;
     306        this_thread = NULL;
    315307
    316308        //We now have a proper context from which to schedule threads
    317309        LIB_DEBUG_PRINT_SAFE("Kernel : core %p created (%p, %p)\n", proc, proc->runner, &ctx);
    318310
    319         // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't 
    320         // resume it to start it like it normally would, it will just context switch 
    321         // back to here. Instead directly call the main since we already are on the 
     311        // SKULLDUGGERY: Since the coroutine doesn't have its own stack, we can't
     312        // resume it to start it like it normally would, it will just context switch
     313        // back to here. Instead directly call the main since we already are on the
    322314        // appropriate stack.
    323315        proc_cor_storage.__cor.state = Active;
     
    326318
    327319        // Main routine of the core returned, the core is now fully terminated
    328         LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner); 
     320        LIB_DEBUG_PRINT_SAFE("Kernel : core %p main ended (%p)\n", proc, proc->runner);
    329321
    330322        return NULL;
     
    363355        } // if
    364356
    365         LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);       
     357        LIB_DEBUG_PRINT_SAFE("Kernel : core %p started\n", this);
    366358}
    367359
     
    369361// Scheduler routines
    370362void ScheduleThread( thread_desc * thrd ) {
    371         if( !thrd ) return;
     363        // if( !thrd ) return;
     364        assert( thrd );
     365        assert( thrd->cor.state != Halted );
     366
     367        verify( disable_preempt_count > 0 );
    372368
    373369        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    374        
    375         lock( &systemProcessor->proc.cltr->lock );
     370
     371        lock( &systemProcessor->proc.cltr->lock, __PRETTY_FUNCTION__ );
    376372        append( &systemProcessor->proc.cltr->ready_queue, thrd );
    377373        unlock( &systemProcessor->proc.cltr->lock );
     374
     375        verify( disable_preempt_count > 0 );
    378376}
    379377
    380378thread_desc * nextThread(cluster * this) {
    381         lock( &this->lock );
     379        verify( disable_preempt_count > 0 );
     380        lock( &this->lock, __PRETTY_FUNCTION__ );
    382381        thread_desc * head = pop_head( &this->ready_queue );
    383382        unlock( &this->lock );
     383        verify( disable_preempt_count > 0 );
    384384        return head;
    385385}
     
    407407void BlockInternal( thread_desc * thrd ) {
    408408        disable_interrupts();
     409        assert( thrd->cor.state != Halted );
    409410        this_processor->finish.action_code = Schedule;
    410411        this_processor->finish.thrd = thrd;
     
    464465// Kernel boot procedures
    465466void kernel_startup(void) {
    466         LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");   
     467        LIB_DEBUG_PRINT_SAFE("Kernel : Starting\n");
    467468
    468469        // Start by initializing the main thread
    469         // SKULLDUGGERY: the mainThread steals the process main thread 
     470        // SKULLDUGGERY: the mainThread steals the process main thread
    470471        // which will then be scheduled by the systemProcessor normally
    471472        mainThread = (thread_desc *)&mainThread_storage;
     
    486487        systemProcessor{ systemCluster, (processorCtx_t *)&systemProcessorCtx_storage };
    487488
    488         // Add the main thread to the ready queue 
     489        // Add the main thread to the ready queue
    489490        // once resume is called on systemProcessor->runner the mainThread needs to be scheduled like any normal thread
    490491        ScheduleThread(mainThread);
     
    492493        //initialize the global state variables
    493494        this_processor = &systemProcessor->proc;
    494         this_processor->current_thread = mainThread;
    495         this_processor->current_coroutine = &mainThread->cor;
     495        this_thread = mainThread;
     496        this_coroutine = &mainThread->cor;
    496497        disable_preempt_count = 1;
    497498
     
    501502        // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX
    502503        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    503         // mainThread is on the ready queue when this call is made. 
     504        // mainThread is on the ready queue when this call is made.
    504505        resume( systemProcessor->proc.runner );
    505506
     
    537538        ^(mainThread){};
    538539
    539         LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");   
     540        LIB_DEBUG_PRINT_SAFE("Kernel : Shutdown complete\n");
    540541}
    541542
     
    547548        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    548549        // the globalAbort flag is true.
    549         lock( &kernel_abort_lock );
     550        lock( &kernel_abort_lock, __PRETTY_FUNCTION__ );
    550551
    551552        // first task to abort ?
     
    553554                kernel_abort_called = true;
    554555                unlock( &kernel_abort_lock );
    555         } 
     556        }
    556557        else {
    557558                unlock( &kernel_abort_lock );
    558                
     559
    559560                sigset_t mask;
    560561                sigemptyset( &mask );
     
    562563                sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    563564                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    564                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it             
    565         }
    566 
    567         return this_thread();
     565                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
     566        }
     567
     568        return this_thread;
    568569}
    569570
     
    574575        __lib_debug_write( STDERR_FILENO, abort_text, len );
    575576
    576         if ( thrd != this_coroutine() ) {
    577                 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine()->name, this_coroutine() );
     577        if ( thrd != this_coroutine ) {
     578                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", this_coroutine->name, this_coroutine );
    578579                __lib_debug_write( STDERR_FILENO, abort_text, len );
    579         } 
     580        }
    580581        else {
    581582                __lib_debug_write( STDERR_FILENO, ".\n", 2 );
     
    585586extern "C" {
    586587        void __lib_debug_acquire() {
    587                 lock(&kernel_debug_lock);
     588                lock(&kernel_debug_lock, __PRETTY_FUNCTION__);
    588589        }
    589590
     
    605606}
    606607
    607 bool try_lock( spinlock * this ) {
    608         return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
    609 }
    610 
    611 void lock( spinlock * this ) {
     608bool try_lock( spinlock * this, const char * caller ) {
     609        bool ret = this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0;
     610        this->prev = caller;
     611        return ret;
     612}
     613
     614void lock( spinlock * this, const char * caller ) {
    612615        for ( unsigned int i = 1;; i += 1 ) {
    613616                if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) break;
    614617        }
     618        this->prev = caller;
    615619}
    616620
     
    627631
    628632void wait( signal_once * this ) {
    629         lock( &this->lock );
     633        lock( &this->lock, __PRETTY_FUNCTION__ );
    630634        if( !this->cond ) {
    631                 append( &this->blocked, this_thread() );
     635                append( &this->blocked, (thread_desc*)this_thread );
    632636                BlockInternal( &this->lock );
    633637        }
     
    638642
    639643void signal( signal_once * this ) {
    640         lock( &this->lock );
     644        lock( &this->lock, __PRETTY_FUNCTION__ );
    641645        {
    642646                this->cond = true;
     
    673677                }
    674678                head->next = NULL;
    675         }       
     679        }
    676680        return head;
    677681}
     
    692696                this->top = top->next;
    693697                top->next = NULL;
    694         }       
     698        }
    695699        return top;
    696700}
  • src/libcfa/concurrency/kernel_private.h

    raa3d77b r1c273d0  
    2727//-----------------------------------------------------------------------------
    2828// Scheduler
     29
     30extern "C" {
     31        void disable_interrupts();
     32        void enable_interrupts_noRF();
     33        void enable_interrupts( const char * );
     34}
     35
    2936void ScheduleThread( thread_desc * );
     37static inline void WakeThread( thread_desc * thrd ) {
     38        if( !thrd ) return;
     39
     40        disable_interrupts();
     41        ScheduleThread( thrd );
     42        enable_interrupts( __PRETTY_FUNCTION__ );
     43}
    3044thread_desc * nextThread(cluster * this);
    3145
     
    6175extern system_proc_t * systemProcessor;
    6276extern volatile thread_local processor * this_processor;
     77extern volatile thread_local coroutine_desc * this_coroutine;
     78extern volatile thread_local thread_desc * this_thread;
    6379extern volatile thread_local unsigned short disable_preempt_count;
    64 
    65 extern "C" {
    66         void disable_interrupts();
    67         void enable_interrupts_noRF();
    68         void enable_interrupts( const char * );
    69 }
    7080
    7181//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor

    raa3d77b r1c273d0  
    2626static inline void ?{}(monitor_desc * this) {
    2727        this->owner = NULL;
    28         this->stack_owner = NULL;
    2928        this->recursion = 0;
    3029}
  • src/libcfa/concurrency/monitor.c

    raa3d77b r1c273d0  
    4444
    4545extern "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( &this->lock, __PRETTY_FUNCTION__ );
     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);
    5151
    5252                if( !this->owner ) {
     
    6262                        //Some one else has the monitor, wait in line for it
    6363                        append( &this->entry_queue, thrd );
    64                         LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
     64                        // LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    6565                        BlockInternal( &this->lock );
    6666
     
    7575        // leave pseudo code :
    7676        //      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( &this->lock, __PRETTY_FUNCTION__ );
     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 );
    8282
    8383                //Leaving a recursion level, decrement the counter
     
    9696                unlock( &this->lock );
    9797
    98                 LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner);
     98                // LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner);
    9999
    100100                //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( &this->lock, __PRETTY_FUNCTION__ );
     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 );
    102131        }
    103132}
     
    121150        enter( this->m, this->count );
    122151
    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;
    128157}
    129158
     
    131160        leave( this->m, this->count );
    132161
    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;
    135164}
    136165
     
    174203        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
    175204
    176         __condition_node_t waiter = { this_thread(), count, user_info };
     205        __condition_node_t waiter = { (thread_desc*)this_thread, count, user_info };
    177206
    178207        __condition_criterion_t criteria[count];
     
    234263        //Some more checking in debug
    235264        LIB_DEBUG_DO(
    236                 thread_desc * this_thrd = this_thread();
     265                thread_desc * this_thrd = this_thread;
    237266                if ( this->monitor_count != this_thrd->current_monitor_count ) {
    238267                        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 );
     
    286315
    287316        //create creteria
    288         __condition_node_t waiter = { this_thread(), count, 0 };
     317        __condition_node_t waiter = { (thread_desc*)this_thread, count, 0 };
    289318
    290319        __condition_criterion_t criteria[count];
     
    335364// Internal scheduling
    336365void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) {
    337         // thread_desc * this = this_thread();
     366        // thread_desc * this = this_thread;
    338367
    339368        // unsigned short count = this->current_monitor_count;
     
    393422static inline void lock_all( spinlock ** locks, unsigned short count ) {
    394423        for( int i = 0; i < count; i++ ) {
    395                 lock( locks[i] );
     424                lock( locks[i], __PRETTY_FUNCTION__ );
    396425        }
    397426}
     
    400429        for( int i = 0; i < count; i++ ) {
    401430                spinlock * l = &source[i]->lock;
    402                 lock( l );
     431                lock( l, __PRETTY_FUNCTION__ );
    403432                if(locks) locks[i] = l;
    404433        }
     
    457486
    458487static inline void brand_condition( condition * this ) {
    459         thread_desc * thrd = this_thread();
     488        thread_desc * thrd = this_thread;
    460489        if( !this->monitors ) {
    461490                LIB_DEBUG_PRINT_SAFE("Branding\n");
  • src/libcfa/concurrency/preemption.c

    raa3d77b r1c273d0  
    2020extern "C" {
    2121#include <errno.h>
     22#include <execinfo.h>
    2223#define __USE_GNU
    2324#include <signal.h>
     
    2829}
    2930
     31
     32#ifdef __USE_STREAM__
     33#include "fstream"
     34#endif
    3035#include "libhdr.h"
    3136
     
    4449void sigHandler_ctxSwitch( __CFA_SIGPARMS__ );
    4550void sigHandler_alarm    ( __CFA_SIGPARMS__ );
     51void sigHandler_segv     ( __CFA_SIGPARMS__ );
     52void sigHandler_abort    ( __CFA_SIGPARMS__ );
    4653
    4754static void __kernel_sigaction( int sig, void (*handler)(__CFA_SIGPARMS__), int flags );
     
    5562        __kernel_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO );
    5663        __kernel_sigaction( SIGALRM, sigHandler_alarm    , SA_SIGINFO );
     64        __kernel_sigaction( SIGSEGV, sigHandler_segv     , SA_SIGINFO );
     65        __kernel_sigaction( SIGBUS , sigHandler_segv     , SA_SIGINFO );
     66        // __kernel_sigaction( SIGABRT, sigHandler_abort    , SA_SIGINFO );
    5767}
    5868
     
    6474        LIB_DEBUG_PRINT_SAFE("Kernel : Preemption stopped\n");
    6575
    66         assert( !systemProcessor->alarms.head );
    67         assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );
     76        // assert( !systemProcessor->alarms.head );
     77        // assert( systemProcessor->alarms.tail == &systemProcessor->alarms.head );
    6878}
    6979
     
    7181
    7282void tick_preemption() {
    73         LIB_DEBUG_DO(
    74                 char text[256];
    75                 __attribute__((unused)) int len = snprintf( text, 256, "Ticking preemption\n" );
    76                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    77         );
     83        // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ticking preemption\n" );
    7884
    7985        alarm_list_t * alarms = &systemProcessor->alarms;
     
    8187        while( alarms->head && alarms->head->alarm < currtime ) {
    8288                alarm_node_t * node = pop(alarms);
    83                 LIB_DEBUG_DO(
    84                         len = snprintf( text, 256, "Ticking %p\n", node );
    85                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    86                 );
     89                // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking %p\n", node );
     90
    8791                if( node->kernel_alarm ) {
    8892                        preempt( node->proc );
     
    9296                }
    9397
    94                 LIB_DEBUG_DO( assert( validate( alarms ) ) );
     98                verify( validate( alarms ) );
    9599
    96100                if( node->period > 0 ) {
     
    108112
    109113        verify( validate( alarms ) );
    110         LIB_DEBUG_DO(
    111                 len = snprintf( text, 256, "Ticking preemption done\n" );
    112                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    113         );
     114        // LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ticking preemption done\n" );
    114115}
    115116
    116117void update_preemption( processor * this, __cfa_time_t duration ) {
    117         LIB_DEBUG_DO(
    118                 char text[256];
    119                 __attribute__((unused)) int len = snprintf( text, 256, "Processor : %p updating preemption to %lu\n", this, duration );
    120                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    121         );
     118        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p updating preemption to %lu\n", this, duration );
    122119
    123120        alarm_node_t * alarm = this->preemption_alarm;
     
    175172
    176173        void enable_interrupts( const char * func ) {
     174                processor * proc   = this_processor;
     175                thread_desc * thrd = this_thread;
    177176                unsigned short prev = __atomic_fetch_add_2( &disable_preempt_count, -1, __ATOMIC_SEQ_CST );
    178177                verify( prev != (unsigned short) 0 );
    179                 if( prev == 1 && this_processor->pending_preemption ) {
    180                         this_processor->pending_preemption = false;
    181                         LIB_DEBUG_DO(
    182                                 char text[256];
    183                                 __attribute__((unused)) int len = snprintf( text, 256, "Executing deferred CtxSwitch on %p\n", this_processor );
    184                                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    185                         );
    186                         BlockInternal( this_processor->current_thread );
    187                 }
    188 
    189                 this_processor->last_enable = func;
    190         }
    191 }
    192 
    193 static inline void signal_unblock( bool alarm ) {
     178                if( prev == 1 && proc->pending_preemption ) {
     179                        proc->pending_preemption = false;
     180                        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Executing deferred CtxSwitch on %p\n", this_processor );
     181                        BlockInternal( thrd );
     182                        LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Executing deferred back\n" );
     183                }
     184
     185                proc->last_enable = func;
     186        }
     187}
     188
     189static inline void signal_unblock( int sig ) {
     190        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : %p unblocking sig %i\n", this_processor, sig );
     191
    194192        sigset_t mask;
    195193        sigemptyset( &mask );
    196         sigaddset( &mask, SIGUSR1 );
    197 
    198         if( alarm ) sigaddset( &mask, SIGALRM );
     194        sigaddset( &mask, sig );
    199195
    200196        if ( sigprocmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     
    215211}
    216212
     213extern "C" {
     214        __attribute__((noinline)) void __debug_break() {
     215                pthread_kill( pthread_self(), SIGTRAP );
     216        }
     217}
     218
    217219void sigHandler_ctxSwitch( __CFA_SIGPARMS__ ) {
    218 
    219         LIB_DEBUG_DO(
    220                 char text[256];
    221                 __attribute__((unused)) int len = snprintf( text, 256, "Ctx Switch IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]));
    222                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    223         );
    224 
    225         signal_unblock( false );
     220        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Ctx Switch IRH %p running %p @ %p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) );
     221
    226222        if( preemption_ready() ) {
    227                 LIB_DEBUG_DO(
    228                         len = snprintf( text, 256, "Ctx Switch IRH : Blocking thread %p on %p\n", this_processor->current_thread, this_processor );
    229                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    230                 );
    231                 BlockInternal( this_processor->current_thread );
     223                LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Blocking thread %p on %p\n", this_thread, this_processor );
     224                signal_unblock( SIGUSR1 );
     225                BlockInternal( (thread_desc*)this_thread );
     226                LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Back\n\n");
    232227        }
    233228        else {
    234                 LIB_DEBUG_DO(
    235                         len = snprintf( text, 256, "Ctx Switch IRH : Defering\n" );
    236                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    237                 );
     229                LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Ctx Switch IRH : Defering\n" );
    238230                defer_ctxSwitch();
     231                signal_unblock( SIGUSR1 );
    239232        }
    240233}
    241234
    242235void sigHandler_alarm( __CFA_SIGPARMS__ ) {
    243 
    244         LIB_DEBUG_DO(
    245                 char text[256];
    246                 __attribute__((unused)) int len = snprintf( text, 256, "\nAlarm IRH %p\n", (void *)(cxt->uc_mcontext.gregs[REG_RIP]) );
    247                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    248         );
    249 
    250         signal_unblock( true );
    251         if( try_lock( &systemProcessor->alarm_lock ) ) {
     236        LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "\nAlarm IRH %p running %p @ %p\n", this_processor, this_thread, (void *)(cxt->uc_mcontext.gregs[REG_RIP]) );
     237
     238        // if( ((intptr_t)cxt->uc_mcontext.gregs[REG_RIP]) > 0xFFFFFF ) __debug_break();
     239
     240        if( try_lock( &systemProcessor->alarm_lock, __PRETTY_FUNCTION__ ) ) {
    252241                tick_preemption();
    253242                unlock( &systemProcessor->alarm_lock );
     
    257246        }
    258247
     248        signal_unblock( SIGALRM );
     249
    259250        if( preemption_ready() && this_processor->pending_preemption ) {
    260                 LIB_DEBUG_DO(
    261                         len = snprintf( text, 256, "Alarm IRH : Blocking thread\n" );
    262                         LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    263                 );
     251                LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm IRH : Blocking thread %p on %p\n", this_thread, this_processor );
    264252                this_processor->pending_preemption = false;
    265                 BlockInternal( this_processor->current_thread );
     253                BlockInternal( (thread_desc*)this_thread );
     254                LIB_DEBUG_PRINT_BUFFER_LOCAL( STDERR_FILENO, "Alarm Switch IRH : Back\n\n");
    266255        }
    267256}
    268257
    269258static void preempt( processor * this ) {
    270         LIB_DEBUG_DO(
    271                 char text[256];
    272                 __attribute__((unused)) int len = snprintf( text, 256, "Processor : signalling %p\n", this );
    273                 LIB_DEBUG_WRITE( STDERR_FILENO, text, len );
    274         );
     259        // LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO, "Processor : signalling %p\n", this );
    275260
    276261        if( this != systemProcessor ) {
     
    290275
    291276        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     277        act.sa_flags = flags;
     278
     279        // disabled during signal handler
    292280        sigemptyset( &act.sa_mask );
    293         sigaddset( &act.sa_mask, SIGALRM );             // disabled during signal handler
    294         sigaddset( &act.sa_mask, SIGUSR1 );
    295 
    296         act.sa_flags = flags;
     281        sigaddset( &act.sa_mask, sig );
    297282
    298283        if ( sigaction( sig, &act, NULL ) == -1 ) {
    299                 // THE KERNEL IS NOT STARTED SO CALL NO uC++ ROUTINES!
    300                 char helpText[256];
    301                 __attribute__((unused)) int len = snprintf( helpText, 256, " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
    302                                 sig, handler, flags, errno, strerror( errno ) );
    303                 LIB_DEBUG_WRITE( STDERR_FILENO, helpText, len );
     284                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     285                        " __kernel_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     286                        sig, handler, flags, errno, strerror( errno )
     287                );
    304288                _exit( EXIT_FAILURE );
    305         } // if
    306 }
     289        }
     290}
     291
     292typedef void (*sa_handler_t)(int);
     293
     294static void __kernel_sigdefault( int sig ) {
     295        struct sigaction act;
     296
     297        // act.sa_handler = SIG_DFL;
     298        act.sa_flags = 0;
     299        sigemptyset( &act.sa_mask );
     300
     301        if ( sigaction( sig, &act, NULL ) == -1 ) {
     302                LIB_DEBUG_PRINT_BUFFER_DECL( STDERR_FILENO,
     303                        " __kernel_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
     304                        sig, errno, strerror( errno )
     305                );
     306                _exit( EXIT_FAILURE );
     307        }
     308}
     309
     310//=============================================================================================
     311// Terminating Signals logic
     312//=============================================================================================
     313
     314LIB_DEBUG_DO(
     315        static void __kernel_backtrace( int start ) {
     316                // skip first N stack frames
     317
     318                enum { Frames = 50 };
     319                void * array[Frames];
     320                int size = backtrace( array, Frames );
     321                char ** messages = backtrace_symbols( array, size );
     322
     323                // find executable name
     324                *index( messages[0], '(' ) = '\0';
     325                #ifdef __USE_STREAM__
     326                serr | "Stack back trace for:" | messages[0] | endl;
     327                #else
     328                fprintf( stderr, "Stack back trace for: %s\n", messages[0]);
     329                #endif
     330
     331                // skip last 2 stack frames after main
     332                for ( int i = start; i < size && messages != NULL; i += 1 ) {
     333                        char * name = NULL;
     334                        char * offset_begin = NULL;
     335                        char * offset_end = NULL;
     336
     337                        for ( char *p = messages[i]; *p; ++p ) {
     338                                // find parantheses and +offset
     339                                if ( *p == '(' ) {
     340                                        name = p;
     341                                }
     342                                else if ( *p == '+' ) {
     343                                        offset_begin = p;
     344                                }
     345                                else if ( *p == ')' ) {
     346                                        offset_end = p;
     347                                        break;
     348                                }
     349                        }
     350
     351                        // if line contains symbol print it
     352                        int frameNo = i - start;
     353                        if ( name && offset_begin && offset_end && name < offset_begin ) {
     354                                // delimit strings
     355                                *name++ = '\0';
     356                                *offset_begin++ = '\0';
     357                                *offset_end++ = '\0';
     358
     359                                #ifdef __USE_STREAM__
     360                                serr    | "("  | frameNo | ")" | messages[i] | ":"
     361                                        | name | "+" | offset_begin | offset_end | endl;
     362                                #else
     363                                fprintf( stderr, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     364                                #endif
     365                        }
     366                        // otherwise, print the whole line
     367                        else {
     368                                #ifdef __USE_STREAM__
     369                                serr | "(" | frameNo | ")" | messages[i] | endl;
     370                                #else
     371                                fprintf( stderr, "(%i) %s\n", frameNo, messages[i] );
     372                                #endif
     373                        }
     374                }
     375
     376                free( messages );
     377        }
     378)
     379
     380void sigHandler_segv( __CFA_SIGPARMS__ ) {
     381        LIB_DEBUG_DO(
     382                #ifdef __USE_STREAM__
     383                serr    | "*CFA runtime error* program cfa-cpp terminated with"
     384                        | (sig == SIGSEGV ? "segment fault." : "bus error.")
     385                        | endl;
     386                #else
     387                fprintf( stderr, "*CFA runtime error* program cfa-cpp terminated with %s\n", sig == SIGSEGV ? "segment fault." : "bus error." );
     388                #endif
     389
     390                // skip first 2 stack frames
     391                __kernel_backtrace( 1 );
     392        )
     393        exit( EXIT_FAILURE );
     394}
     395
     396// void sigHandler_abort( __CFA_SIGPARMS__ ) {
     397//      // skip first 6 stack frames
     398//      LIB_DEBUG_DO( __kernel_backtrace( 6 ); )
     399
     400//      // reset default signal handler
     401//      __kernel_sigdefault( SIGABRT );
     402
     403//      raise( SIGABRT );
     404// }
  • src/libcfa/concurrency/thread

    raa3d77b r1c273d0  
    5454}
    5555
    56 thread_desc * this_thread(void);
     56extern volatile thread_local thread_desc * this_thread;
    5757
    5858forall( dtype T | is_thread(T) )
  • src/libcfa/concurrency/thread.c

    raa3d77b r1c273d0  
    7171        coroutine_desc* thrd_c = get_coroutine(this);
    7272        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;
    7574
    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);
    7776
     77        disable_interrupts();
    7878        create_stack(&thrd_c->stack, thrd_c->stack.size);
     79        this_coroutine = thrd_c;
    7980        CtxStart(this, CtxInvokeThread);
     81        assert( thrd_c->last->stack.context );
    8082        CtxSwitch( thrd_c->last->stack.context, thrd_c->stack.context );
    8183
    8284        ScheduleThread(thrd_h);
     85        enable_interrupts( __PRETTY_FUNCTION__ );
    8386}
    8487
    8588void yield( void ) {
    86         BlockInternal( this_processor->current_thread );
     89        BlockInternal( (thread_desc *)this_thread );
    8790}
    8891
     
    9598void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    9699        // set state of current coroutine to inactive
    97         src->state = Inactive;
     100        src->state = src->state == Halted ? Halted : Inactive;
    98101        dst->state = Active;
    99102
     
    103106        // set new coroutine that the processor is executing
    104107        // and context switch to it
    105         this_processor->current_coroutine = dst;
     108        this_coroutine = dst;
     109        assert( src->stack.context );
    106110        CtxSwitch( src->stack.context, dst->stack.context );
    107         this_processor->current_coroutine = src;
     111        this_coroutine = src;
    108112
    109113        // set state of new coroutine to active
    110         dst->state = Inactive;
     114        dst->state = dst->state == Halted ? Halted : Inactive;
    111115        src->state = Active;
    112116}
  • src/tests/sched-int-block.c

    raa3d77b r1c273d0  
    2929//------------------------------------------------------------------------------
    3030void wait_op( global_data_t * mutex a, global_data_t * mutex b, unsigned i ) {
    31         wait( &cond, (uintptr_t)this_thread() );
     31        wait( &cond, (uintptr_t)this_thread );
    3232
    3333        yield( ((unsigned)rand48()) % 10 );
     
    3838        }
    3939
    40         a->last_thread = b->last_thread = this_thread();
     40        a->last_thread = b->last_thread = this_thread;
    4141
    4242        yield( ((unsigned)rand48()) % 10 );
     
    5454        yield( ((unsigned)rand48()) % 10 );
    5555
    56         a->last_thread = b->last_thread = a->last_signaller = b->last_signaller = this_thread();
     56        a->last_thread = b->last_thread = a->last_signaller = b->last_signaller = this_thread;
    5757
    5858        if( !is_empty( &cond ) ) {
     
    8484//------------------------------------------------------------------------------
    8585void barge_op( global_data_t * mutex a ) {
    86         a->last_thread = this_thread();
     86        a->last_thread = this_thread;
    8787}
    8888
Note: See TracChangeset for help on using the changeset viewer.