Ignore:
Timestamp:
Jan 7, 2021, 3:27:00 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
2b4daf2, 64aeca0
Parents:
3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into park_unpark

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/monitor.cfa

    r3c64c668 r58fe85a  
    8282// Enter single monitor
    8383static void __enter( $monitor * this, const __monitor_group_t & group ) {
     84        $thread * thrd = active_thread();
     85
    8486        // Lock the monitor spinlock
    8587        lock( this->lock __cfaabi_dbg_ctx2 );
    86         // Interrupts disable inside critical section
    87         $thread * thrd = kernelTLS.this_thread;
    8888
    8989        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    9090
    91         if( !this->owner ) {
     91        if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
     92                abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
     93        }
     94        else if( !this->owner ) {
    9295                // No one has the monitor, just take it
    9396                __set_owner( this, thrd );
     
    114117
    115118                // Some one else has the monitor, wait in line for it
    116                 /* paranoid */ verify( thrd->next == 0p );
     119                /* paranoid */ verify( thrd->link.next == 0p );
    117120                append( this->entry_queue, thrd );
    118                 /* paranoid */ verify( thrd->next == 1p );
     121                /* paranoid */ verify( thrd->link.next == 1p );
    119122
    120123                unlock( this->lock );
     
    123126                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    124127
    125                 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     128                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    126129                return;
    127130        }
     
    129132        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    130133
    131         /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     134        /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    132135        /* paranoid */ verify( this->lock.lock );
    133136
     
    137140}
    138141
    139 static void __dtor_enter( $monitor * this, fptr_t func ) {
     142static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
     143        $thread * thrd = active_thread();
     144        #if defined( __CFA_WITH_VERIFY__ )
     145                bool is_thrd = this == &thrd->self_mon;
     146        #endif
     147
    140148        // Lock the monitor spinlock
    141149        lock( this->lock __cfaabi_dbg_ctx2 );
    142         // Interrupts disable inside critical section
    143         $thread * thrd = kernelTLS.this_thread;
    144150
    145151        __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     
    152158                __set_owner( this, thrd );
    153159
    154                 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     160                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     161                /* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled );
    155162
    156163                unlock( this->lock );
    157164                return;
    158165        }
    159         else if( this->owner == thrd) {
     166        else if( this->owner == thrd && !join) {
    160167                // We already have the monitor... but where about to destroy it so the nesting will fail
    161168                // Abort!
    162169                abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
    163170        }
     171        // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check
     172        // because join will not release the monitor after it executed.
     173        // to avoid that it sets the owner to the special value thrd | 1p before exiting
     174        else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) {
     175                // restore the owner and just return
     176                __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     177
     178                // No one has the monitor, just take it
     179                __set_owner( this, thrd );
     180
     181                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     182                /* paranoid */ verify( !is_thrd || thrd->state == Halted || thrd->state == Cancelled );
     183
     184                unlock( this->lock );
     185                return;
     186        }
     187
     188        // The monitor is busy, if this is a thread and the thread owns itself, it better be active
     189        /* paranoid */ verify( !is_thrd || this->owner != thrd || (thrd->state != Halted && thrd->state != Cancelled) );
    164190
    165191        __lock_size_t count = 1;
     
    183209
    184210                // Release the next thread
    185                 /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     211                /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    186212                unpark( urgent->owner->waiting_thread );
    187213
     
    190216
    191217                // Some one was waiting for us, enter
    192                 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     218                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     219
     220                __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
     221                return;
    193222        }
    194223        else {
     
    199228
    200229                // Some one else has the monitor, wait in line for it
    201                 /* paranoid */ verify( thrd->next == 0p );
     230                /* paranoid */ verify( thrd->link.next == 0p );
    202231                append( this->entry_queue, thrd );
    203                 /* paranoid */ verify( thrd->next == 1p );
     232                /* paranoid */ verify( thrd->link.next == 1p );
    204233                unlock( this->lock );
    205234
     
    207236                park();
    208237
    209                 /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     238                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    210239                return;
    211240        }
    212 
    213         __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
    214 
    215241}
    216242
     
    220246        lock( this->lock __cfaabi_dbg_ctx2 );
    221247
    222         __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
    223 
    224         /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     248        __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", active_thread(), this, this->owner);
     249
     250        /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    225251
    226252        // Leaving a recursion level, decrement the counter
     
    251277
    252278// Leave single monitor for the last time
    253 void __dtor_leave( $monitor * this ) {
     279void __dtor_leave( $monitor * this, bool join ) {
    254280        __cfaabi_dbg_debug_do(
    255                 if( TL_GET( this_thread ) != this->owner ) {
    256                         abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
     281                if( active_thread() != this->owner ) {
     282                        abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, active_thread(), this->owner);
    257283                }
    258                 if( this->recursion != 1 ) {
     284                if( this->recursion != 1  && !join ) {
    259285                        abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    260286                }
    261287        )
    262 }
    263 
    264 extern "C" {
    265         // Leave the thread monitor
    266         // last routine called by a thread.
    267         // Should never return
    268         void __cfactx_thrd_leave() {
    269                 $thread * thrd = TL_GET( this_thread );
    270                 $monitor * this = &thrd->self_mon;
    271 
    272                 // Lock the monitor now
    273                 lock( this->lock __cfaabi_dbg_ctx2 );
    274 
    275                 disable_interrupts();
    276 
    277                 thrd->state = Halted;
    278 
    279                 /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    280 
    281                 // Leaving a recursion level, decrement the counter
    282                 this->recursion -= 1;
    283 
    284                 // If we haven't left the last level of recursion
    285                 // it must mean there is an error
    286                 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); }
    287 
    288                 // Fetch the next thread, can be null
    289                 $thread * new_owner = next_thread( this );
    290 
    291                 // Release the monitor lock
    292                 unlock( this->lock );
    293 
    294                 // Unpark the next owner if needed
    295                 /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    296                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    297                 /* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
    298                 /* paranoid */ verify( thrd->state == Halted );
    299 
    300                 kernelTLS.this_processor->destroyer = new_owner;
    301 
    302                 // Leave the thread
    303                 __leave_thread();
    304 
    305                 // Control flow should never reach here!
    306         }
     288
     289        this->owner = ($thread*)(1 | (uintptr_t)this->owner);
     290}
     291
     292void __thread_finish( $thread * thrd ) {
     293        $monitor * this = &thrd->self_mon;
     294
     295        // Lock the monitor now
     296        /* paranoid */ verify( 0x0D15EA5E0D15EA5Ep == thrd->canary );
     297        /* paranoid */ verify( this->lock.lock );
     298        /* paranoid */ verify( thrd->context.SP );
     299        /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) > ((uintptr_t)__get_stack(thrd->curr_cor)->limit), "ERROR : $thread %p has been corrupted.\n StackPointer too large.\n", thrd );
     300        /* paranoid */ verifyf( ((uintptr_t)thrd->context.SP) < ((uintptr_t)__get_stack(thrd->curr_cor)->base ), "ERROR : $thread %p has been corrupted.\n StackPointer too small.\n", thrd );
     301        /* paranoid */ verify( ! __preemption_enabled() );
     302
     303        /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
     304        /* paranoid */ verify( thrd->state == Halting );
     305        /* paranoid */ verify( this->recursion == 1 );
     306
     307        // Leaving a recursion level, decrement the counter
     308        this->recursion -= 1;
     309        this->owner = 0p;
     310
     311        // Fetch the next thread, can be null
     312        $thread * new_owner = next_thread( this );
     313
     314        // Mark the state as fully halted
     315        thrd->state = Halted;
     316
     317        // Release the monitor lock
     318        unlock( this->lock );
     319
     320        // Unpark the next owner if needed
     321        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     322        /* paranoid */ verify( ! __preemption_enabled() );
     323        /* paranoid */ verify( thrd->state == Halted );
     324        unpark( new_owner );
    307325}
    308326
     
    326344// Sorts monitors before entering
    327345void ?{}( monitor_guard_t & this, $monitor * m [], __lock_size_t count, fptr_t func ) {
    328         $thread * thrd = TL_GET( this_thread );
     346        $thread * thrd = active_thread();
    329347
    330348        // Store current array
     
    361379
    362380        // Restore thread context
    363         TL_GET( this_thread )->monitors = this.prev;
     381        active_thread()->monitors = this.prev;
    364382}
    365383
    366384// Ctor for monitor guard
    367385// Sorts monitors before entering
    368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
     386void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
    369387        // optimization
    370         $thread * thrd = TL_GET( this_thread );
     388        $thread * thrd = active_thread();
    371389
    372390        // Store current array
     
    376394        this.prev = thrd->monitors;
    377395
     396        // Save whether we are in a join or not
     397        this.join = join;
     398
    378399        // Update thread context (needed for conditions)
    379400        (thrd->monitors){m, 1, func};
    380401
    381         __dtor_enter( this.m, func );
     402        __dtor_enter( this.m, func, join );
    382403}
    383404
     
    385406void ^?{}( monitor_dtor_guard_t & this ) {
    386407        // Leave the monitors in order
    387         __dtor_leave( this.m );
     408        __dtor_leave( this.m, this.join );
    388409
    389410        // Restore thread context
    390         TL_GET( this_thread )->monitors = this.prev;
     411        active_thread()->monitors = this.prev;
    391412}
    392413
     
    428449
    429450        // Create the node specific to this wait operation
    430         wait_ctx( TL_GET( this_thread ), user_info );
     451        wait_ctx( active_thread(), user_info );
    431452
    432453        // Append the current wait operation to the ones already queued on the condition
     
    479500        //Some more checking in debug
    480501        __cfaabi_dbg_debug_do(
    481                 $thread * this_thrd = TL_GET( this_thread );
     502                $thread * this_thrd = active_thread();
    482503                if ( this.monitor_count != this_thrd->monitors.size ) {
    483504                        abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     
    527548
    528549        // Create the node specific to this wait operation
    529         wait_ctx_primed( kernelTLS.this_thread, 0 )
     550        wait_ctx_primed( active_thread(), 0 )
    530551
    531552        //save contexts
     
    534555        //Find the thread to run
    535556        $thread * signallee = pop_head( this.blocked )->waiting_thread;
    536         /* paranoid */ verify( signallee->next == 0p );
    537557        __set_owner( monitors, count, signallee );
    538558
     
    627647
    628648                                // Create the node specific to this wait operation
    629                                 wait_ctx_primed( kernelTLS.this_thread, 0 );
     649                                wait_ctx_primed( active_thread(), 0 );
    630650
    631651                                // Save monitor states
     
    679699
    680700        // Create the node specific to this wait operation
    681         wait_ctx_primed( kernelTLS.this_thread, 0 );
     701        wait_ctx_primed( active_thread(), 0 );
    682702
    683703        monitor_save;
     
    685705
    686706        for( __lock_size_t i = 0; i < count; i++) {
    687                 verify( monitors[i]->owner == kernelTLS.this_thread );
     707                verify( monitors[i]->owner == active_thread() );
    688708        }
    689709
     
    721741static inline void __set_owner( $monitor * monitors [], __lock_size_t count, $thread * owner ) {
    722742        /* paranoid */ verify ( monitors[0]->lock.lock );
    723         /* paranoid */ verifyf( monitors[0]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[0]->owner, monitors[0]->recursion, monitors[0] );
     743        /* paranoid */ verifyf( monitors[0]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[0]->owner, monitors[0]->recursion, monitors[0] );
    724744        monitors[0]->owner        = owner;
    725745        monitors[0]->recursion    = 1;
    726746        for( __lock_size_t i = 1; i < count; i++ ) {
    727747                /* paranoid */ verify ( monitors[i]->lock.lock );
    728                 /* paranoid */ verifyf( monitors[i]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[i]->owner, monitors[i]->recursion, monitors[i] );
     748                /* paranoid */ verifyf( monitors[i]->owner == active_thread(), "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), monitors[i]->owner, monitors[i]->recursion, monitors[i] );
    729749                monitors[i]->owner        = owner;
    730750                monitors[i]->recursion    = 0;
     
    752772                //regardless of if we are ready to baton pass,
    753773                //we need to set the monitor as in use
    754                 /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     774                /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
    755775                __set_owner( this,  urgent->owner->waiting_thread );
    756776
     
    761781        // Get the next thread in the entry_queue
    762782        $thread * new_owner = pop_head( this->entry_queue );
    763         /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    764         /* paranoid */ verify( !new_owner || new_owner->next == 0p );
     783        /* paranoid */ verifyf( !this->owner || active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     784        /* paranoid */ verify( !new_owner || new_owner->link.next == 0p );
    765785        __set_owner( this, new_owner );
    766786
     
    884904        }
    885905
    886         __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : 0p );
     906        __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? (thread*)node->waiting_thread : (thread*)0p );
    887907        return ready2run ? node->waiting_thread : 0p;
    888908}
    889909
    890910static inline void brand_condition( condition & this ) {
    891         $thread * thrd = TL_GET( this_thread );
     911        $thread * thrd = active_thread();
    892912        if( !this.monitors ) {
    893913                // __cfaabi_dbg_print_safe( "Branding\n" );
     
    908928        // For each thread in the entry-queue
    909929        for(    $thread ** thrd_it = &entry_queue.head;
    910                 *thrd_it != 1p;
    911                 thrd_it = &(*thrd_it)->next
     930                (*thrd_it) != 1p;
     931                thrd_it = &(*thrd_it)->link.next
    912932        ) {
    913933                // For each acceptable check if it matches
Note: See TracChangeset for help on using the changeset viewer.