Ignore:
File:
1 edited

Legend:

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

    rae66348 r2026bb6  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // $monitor.c --
     7// monitor_desc.c --
    88//
    99// Author           : Thierry Delisle
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec  4 07:55:14 2019
    13 // Update Count     : 10
     12// Last Modified On : Fri Mar 30 14:30:26 2018
     13// Update Count     : 9
    1414//
    1515
     
    2727//-----------------------------------------------------------------------------
    2828// Forward declarations
    29 static inline void __set_owner ( $monitor * this, $thread * owner );
    30 static inline void __set_owner ( $monitor * storage [], __lock_size_t count, $thread * owner );
    31 static inline void set_mask  ( $monitor * storage [], __lock_size_t count, const __waitfor_mask_t & mask );
    32 static inline void reset_mask( $monitor * this );
    33 
    34 static inline $thread * next_thread( $monitor * this );
    35 static inline bool is_accepted( $monitor * this, const __monitor_group_t & monitors );
     29static inline void set_owner ( monitor_desc * this, thread_desc * owner );
     30static inline void set_owner ( monitor_desc * storage [], __lock_size_t count, thread_desc * owner );
     31static inline void set_mask  ( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask );
     32static inline void reset_mask( monitor_desc * this );
     33
     34static inline thread_desc * next_thread( monitor_desc * this );
     35static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors );
    3636
    3737static inline void lock_all  ( __spinlock_t * locks [], __lock_size_t count );
    38 static inline void lock_all  ( $monitor * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count );
     38static inline void lock_all  ( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count );
    3939static inline void unlock_all( __spinlock_t * locks [], __lock_size_t count );
    40 static inline void unlock_all( $monitor * locks [], __lock_size_t count );
    41 
    42 static inline void save   ( $monitor * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] );
    43 static inline void restore( $monitor * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );
    44 
    45 static inline void init     ( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
    46 static inline void init_push( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
    47 
    48 static inline $thread *        check_condition   ( __condition_criterion_t * );
     40static inline void unlock_all( monitor_desc * locks [], __lock_size_t count );
     41
     42static inline void save   ( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] );
     43static inline void restore( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );
     44
     45static inline void init     ( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
     46static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
     47
     48static inline thread_desc *        check_condition   ( __condition_criterion_t * );
    4949static inline void                 brand_condition   ( condition & );
    50 static inline [$thread *, int] search_entry_queue( const __waitfor_mask_t &, $monitor * monitors [], __lock_size_t count );
     50static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc * monitors [], __lock_size_t count );
    5151
    5252forall(dtype T | sized( T ))
    5353static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val );
    5454static inline __lock_size_t count_max    ( const __waitfor_mask_t & mask );
    55 static inline __lock_size_t aggregate    ( $monitor * storage [], const __waitfor_mask_t & mask );
     55static inline __lock_size_t aggregate    ( monitor_desc * storage [], const __waitfor_mask_t & mask );
    5656
    5757//-----------------------------------------------------------------------------
     
    6868
    6969#define monitor_ctx( mons, cnt )                                /* Define that create the necessary struct for internal/external scheduling operations */ \
    70         $monitor ** monitors = mons;                          /* Save the targeted monitors                                                          */ \
     70        monitor_desc ** monitors = mons;                          /* Save the targeted monitors                                                          */ \
    7171        __lock_size_t count = cnt;                                /* Save the count to a local variable                                                  */ \
    7272        unsigned int recursions[ count ];                         /* Save the current recursion levels to restore them later                             */ \
     
    8080//-----------------------------------------------------------------------------
    8181// Enter/Leave routines
    82 // Enter single monitor
    83 static void __enter( $monitor * this, const __monitor_group_t & group ) {
    84         // Lock the monitor spinlock
    85         lock( this->lock __cfaabi_dbg_ctx2 );
    86         // Interrupts disable inside critical section
    87         $thread * thrd = kernelTLS.this_thread;
    88 
    89         __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    90 
    91         if( !this->owner ) {
    92                 // No one has the monitor, just take it
    93                 __set_owner( this, thrd );
    94 
    95                 __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
    96         }
    97         else if( this->owner == thrd) {
    98                 // We already have the monitor, just note how many times we took it
    99                 this->recursion += 1;
    100 
    101                 __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
    102         }
    103         else if( is_accepted( this, group) ) {
    104                 // Some one was waiting for us, enter
    105                 __set_owner( this, thrd );
    106 
    107                 // Reset mask
    108                 reset_mask( this );
    109 
    110                 __cfaabi_dbg_print_safe( "Kernel :  mon accepts \n" );
    111         }
    112         else {
    113                 __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    114 
    115                 // Some one else has the monitor, wait in line for it
    116                 /* paranoid */ verify( thrd->next == 0p );
    117                 append( this->entry_queue, thrd );
    118                 /* paranoid */ verify( thrd->next == 1p );
    119 
    120                 unlock( this->lock );
    121                 park( __cfaabi_dbg_ctx );
     82
     83
     84extern "C" {
     85        // Enter single monitor
     86        static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) {
     87                // Lock the monitor spinlock
     88                lock( this->lock __cfaabi_dbg_ctx2 );
     89                // Interrupts disable inside critical section
     90                thread_desc * thrd = kernelTLS.this_thread;
     91
     92                __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     93
     94                if( !this->owner ) {
     95                        // No one has the monitor, just take it
     96                        set_owner( this, thrd );
     97
     98                        __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
     99                }
     100                else if( this->owner == thrd) {
     101                        // We already have the monitor, just note how many times we took it
     102                        this->recursion += 1;
     103
     104                        __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
     105                }
     106                else if( is_accepted( this, group) ) {
     107                        // Some one was waiting for us, enter
     108                        set_owner( this, thrd );
     109
     110                        // Reset mask
     111                        reset_mask( this );
     112
     113                        __cfaabi_dbg_print_safe( "Kernel :  mon accepts \n" );
     114                }
     115                else {
     116                        __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     117
     118                        // Some one else has the monitor, wait in line for it
     119                        append( this->entry_queue, thrd );
     120
     121                        BlockInternal( &this->lock );
     122
     123                        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     124
     125                        // BlockInternal will unlock spinlock, no need to unlock ourselves
     126                        return;
     127                }
    122128
    123129                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    124130
    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 );
    126                 return;
    127         }
    128 
    129         __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    130 
    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 );
    132         /* paranoid */ verify( this->lock.lock );
    133 
    134         // Release the lock and leave
    135         unlock( this->lock );
    136         return;
    137 }
    138 
    139 static void __dtor_enter( $monitor * this, fptr_t func ) {
    140         // Lock the monitor spinlock
    141         lock( this->lock __cfaabi_dbg_ctx2 );
    142         // Interrupts disable inside critical section
    143         $thread * thrd = kernelTLS.this_thread;
    144 
    145         __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
    146 
    147 
    148         if( !this->owner ) {
    149                 __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
    150 
    151                 // No one has the monitor, just take it
    152                 __set_owner( this, thrd );
    153 
    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 );
    155 
     131                // Release the lock and leave
    156132                unlock( this->lock );
    157133                return;
    158134        }
    159         else if( this->owner == thrd) {
    160                 // We already have the monitor... but where about to destroy it so the nesting will fail
    161                 // Abort!
    162                 abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
    163         }
    164 
    165         __lock_size_t count = 1;
    166         $monitor ** monitors = &this;
    167         __monitor_group_t group = { &this, 1, func };
    168         if( is_accepted( this, group) ) {
    169                 __cfaabi_dbg_print_safe( "Kernel :  mon accepts dtor, block and signal it \n" );
    170 
    171                 // Wake the thread that is waiting for this
    172                 __condition_criterion_t * urgent = pop( this->signal_stack );
    173                 /* paranoid */ verify( urgent );
    174 
    175                 // Reset mask
    176                 reset_mask( this );
    177 
    178                 // Create the node specific to this wait operation
    179                 wait_ctx_primed( thrd, 0 )
    180 
    181                 // Some one else has the monitor, wait for him to finish and then run
     135
     136        static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) {
     137                // Lock the monitor spinlock
     138                lock( this->lock __cfaabi_dbg_ctx2 );
     139                // Interrupts disable inside critical section
     140                thread_desc * thrd = kernelTLS.this_thread;
     141
     142                __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     143
     144
     145                if( !this->owner ) {
     146                        __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     147
     148                        // No one has the monitor, just take it
     149                        set_owner( this, thrd );
     150
     151                        unlock( this->lock );
     152                        return;
     153                }
     154                else if( this->owner == thrd) {
     155                        // We already have the monitor... but where about to destroy it so the nesting will fail
     156                        // Abort!
     157                        abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
     158                }
     159
     160                __lock_size_t count = 1;
     161                monitor_desc ** monitors = &this;
     162                __monitor_group_t group = { &this, 1, func };
     163                if( is_accepted( this, group) ) {
     164                        __cfaabi_dbg_print_safe( "Kernel :  mon accepts dtor, block and signal it \n" );
     165
     166                        // Wake the thread that is waiting for this
     167                        __condition_criterion_t * urgent = pop( this->signal_stack );
     168                        verify( urgent );
     169
     170                        // Reset mask
     171                        reset_mask( this );
     172
     173                        // Create the node specific to this wait operation
     174                        wait_ctx_primed( thrd, 0 )
     175
     176                        // Some one else has the monitor, wait for him to finish and then run
     177                        BlockInternal( &this->lock, urgent->owner->waiting_thread );
     178
     179                        // Some one was waiting for us, enter
     180                        set_owner( this, thrd );
     181                }
     182                else {
     183                        __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     184
     185                        wait_ctx( thrd, 0 )
     186                        this->dtor_node = &waiter;
     187
     188                        // Some one else has the monitor, wait in line for it
     189                        append( this->entry_queue, thrd );
     190                        BlockInternal( &this->lock );
     191
     192                        // BlockInternal will unlock spinlock, no need to unlock ourselves
     193                        return;
     194                }
     195
     196                __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
     197
     198        }
     199
     200        // Leave single monitor
     201        void __leave_monitor_desc( monitor_desc * this ) {
     202                // Lock the monitor spinlock
     203                lock( this->lock __cfaabi_dbg_ctx2 );
     204
     205                __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
     206
     207                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 );
     208
     209                // Leaving a recursion level, decrement the counter
     210                this->recursion -= 1;
     211
     212                // If we haven't left the last level of recursion
     213                // it means we don't need to do anything
     214                if( this->recursion != 0) {
     215                        __cfaabi_dbg_print_safe( "Kernel :  recursion still %d\n", this->recursion);
     216                        unlock( this->lock );
     217                        return;
     218                }
     219
     220                // Get the next thread, will be null on low contention monitor
     221                thread_desc * new_owner = next_thread( this );
     222
     223                // We can now let other threads in safely
    182224                unlock( this->lock );
    183225
    184                 // 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 );
    186                 unpark( urgent->owner->waiting_thread __cfaabi_dbg_ctx2 );
    187 
    188                 // Park current thread waiting
    189                 park( __cfaabi_dbg_ctx );
    190 
    191                 // 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 );
    193         }
    194         else {
    195                 __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    196 
    197                 wait_ctx( thrd, 0 )
    198                 this->dtor_node = &waiter;
    199 
    200                 // Some one else has the monitor, wait in line for it
    201                 /* paranoid */ verify( thrd->next == 0p );
    202                 append( this->entry_queue, thrd );
    203                 /* paranoid */ verify( thrd->next == 1p );
    204                 unlock( this->lock );
    205 
    206                 // Park current thread waiting
    207                 park( __cfaabi_dbg_ctx );
    208 
    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 );
    210                 return;
    211         }
    212 
    213         __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
    214 
    215 }
    216 
    217 // Leave single monitor
    218 void __leave( $monitor * this ) {
    219         // Lock the monitor spinlock
    220         lock( this->lock __cfaabi_dbg_ctx2 );
    221 
    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 );
    225 
    226         // Leaving a recursion level, decrement the counter
    227         this->recursion -= 1;
    228 
    229         // If we haven't left the last level of recursion
    230         // it means we don't need to do anything
    231         if( this->recursion != 0) {
    232                 __cfaabi_dbg_print_safe( "Kernel :  recursion still %d\n", this->recursion);
    233                 unlock( this->lock );
    234                 return;
    235         }
    236 
    237         // Get the next thread, will be null on low contention monitor
    238         $thread * new_owner = next_thread( this );
    239 
    240         // Check the new owner is consistent with who we wake-up
    241         // new_owner might be null even if someone owns the monitor when the owner is still waiting for another monitor
    242         /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    243 
    244         // We can now let other threads in safely
    245         unlock( this->lock );
    246 
    247         //We need to wake-up the thread
    248         /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    249         unpark( new_owner __cfaabi_dbg_ctx2 );
    250 }
    251 
    252 // Leave single monitor for the last time
    253 void __dtor_leave( $monitor * this ) {
    254         __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);
    257                 }
    258                 if( this->recursion != 1 ) {
    259                         abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    260                 }
    261         )
    262 }
    263 
    264 extern "C" {
     226                //We need to wake-up the thread
     227                WakeThread( new_owner );
     228        }
     229
     230        // Leave single monitor for the last time
     231        void __leave_dtor_monitor_desc( monitor_desc * this ) {
     232                __cfaabi_dbg_debug_do(
     233                        if( TL_GET( this_thread ) != this->owner ) {
     234                                abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
     235                        }
     236                        if( this->recursion != 1 ) {
     237                                abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
     238                        }
     239                )
     240        }
     241
    265242        // Leave the thread monitor
    266243        // last routine called by a thread.
    267244        // Should never return
    268         void __cfactx_thrd_leave() {
    269                 $thread * thrd = TL_GET( this_thread );
    270                 $monitor * this = &thrd->self_mon;
     245        void __leave_thread_monitor( thread_desc * thrd ) {
     246                monitor_desc * this = &thrd->self_mon;
    271247
    272248                // Lock the monitor now
     
    275251                disable_interrupts();
    276252
    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 );
     253                thrd->self_cor.state = Halted;
     254
     255                verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    280256
    281257                // Leaving a recursion level, decrement the counter
     
    287263
    288264                // 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();
     265                thread_desc * new_owner = next_thread( this );
     266
     267                // Leave the thread, this will unlock the spinlock
     268                // Use leave thread instead of BlockInternal which is
     269                // specialized for this case and supports null new_owner
     270                LeaveThread( &this->lock, new_owner );
    304271
    305272                // Control flow should never reach here!
     
    311278static inline void enter( __monitor_group_t monitors ) {
    312279        for( __lock_size_t i = 0; i < monitors.size; i++) {
    313                 __enter( monitors[i], monitors );
     280                __enter_monitor_desc( monitors[i], monitors );
    314281        }
    315282}
     
    317284// Leave multiple monitor
    318285// relies on the monitor array being sorted
    319 static inline void leave($monitor * monitors [], __lock_size_t count) {
     286static inline void leave(monitor_desc * monitors [], __lock_size_t count) {
    320287        for( __lock_size_t i = count - 1; i >= 0; i--) {
    321                 __leave( monitors[i] );
     288                __leave_monitor_desc( monitors[i] );
    322289        }
    323290}
     
    325292// Ctor for monitor guard
    326293// Sorts monitors before entering
    327 void ?{}( monitor_guard_t & this, $monitor * m [], __lock_size_t count, fptr_t func ) {
    328         $thread * thrd = TL_GET( this_thread );
     294void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {
     295        thread_desc * thrd = TL_GET( this_thread );
    329296
    330297        // Store current array
     
    366333// Ctor for monitor guard
    367334// Sorts monitors before entering
    368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
     335void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {
    369336        // optimization
    370         $thread * thrd = TL_GET( this_thread );
     337        thread_desc * thrd = TL_GET( this_thread );
    371338
    372339        // Store current array
     
    379346        (thrd->monitors){m, 1, func};
    380347
    381         __dtor_enter( this.m, func );
     348        __enter_monitor_dtor( this.m, func );
    382349}
    383350
     
    385352void ^?{}( monitor_dtor_guard_t & this ) {
    386353        // Leave the monitors in order
    387         __dtor_leave( this.m );
     354        __leave_dtor_monitor_desc( this.m );
    388355
    389356        // Restore thread context
     
    393360//-----------------------------------------------------------------------------
    394361// Internal scheduling types
    395 void ?{}(__condition_node_t & this, $thread * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
     362void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
    396363        this.waiting_thread = waiting_thread;
    397364        this.count = count;
    398         this.next = 0p;
     365        this.next = NULL;
    399366        this.user_info = user_info;
    400367}
     
    402369void ?{}(__condition_criterion_t & this ) with( this ) {
    403370        ready  = false;
    404         target = 0p;
    405         owner  = 0p;
    406         next   = 0p;
    407 }
    408 
    409 void ?{}(__condition_criterion_t & this, $monitor * target, __condition_node_t & owner ) {
     371        target = NULL;
     372        owner  = NULL;
     373        next   = NULL;
     374}
     375
     376void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t & owner ) {
    410377        this.ready  = false;
    411378        this.target = target;
    412379        this.owner  = &owner;
    413         this.next   = 0p;
     380        this.next   = NULL;
    414381}
    415382
     
    420387
    421388        // Check that everything is as expected
    422         assertf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
     389        assertf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
    423390        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    424391        verifyf( this.monitor_count < 32u, "Excessive monitor count (%"PRIiFAST16")", this.monitor_count );
     
    432399        // Append the current wait operation to the ones already queued on the condition
    433400        // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion
    434         /* paranoid */ verify( waiter.next == 0p );
    435401        append( this.blocked, &waiter );
    436         /* paranoid */ verify( waiter.next == 1p );
    437402
    438403        // Lock all monitors (aggregates the locks as well)
     
    441406        // Find the next thread(s) to run
    442407        __lock_size_t thread_count = 0;
    443         $thread * threads[ count ];
     408        thread_desc * threads[ count ];
    444409        __builtin_memset( threads, 0, sizeof( threads ) );
    445410
     
    449414        // Remove any duplicate threads
    450415        for( __lock_size_t i = 0; i < count; i++) {
    451                 $thread * new_owner = next_thread( monitors[i] );
     416                thread_desc * new_owner = next_thread( monitors[i] );
    452417                insert_unique( threads, thread_count, new_owner );
    453418        }
    454419
    455         // Unlock the locks, we don't need them anymore
    456         for(int i = 0; i < count; i++) {
    457                 unlock( *locks[i] );
    458         }
    459 
    460         // Wake the threads
    461         for(int i = 0; i < thread_count; i++) {
    462                 unpark( threads[i] __cfaabi_dbg_ctx2 );
    463         }
    464 
    465420        // Everything is ready to go to sleep
    466         park( __cfaabi_dbg_ctx );
     421        BlockInternal( locks, count, threads, thread_count );
    467422
    468423        // We are back, restore the owners and recursions
     
    479434        //Some more checking in debug
    480435        __cfaabi_dbg_debug_do(
    481                 $thread * this_thrd = TL_GET( this_thread );
     436                thread_desc * this_thrd = TL_GET( this_thread );
    482437                if ( this.monitor_count != this_thrd->monitors.size ) {
    483438                        abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     
    494449
    495450        // Lock all monitors
    496         lock_all( this.monitors, 0p, count );
     451        lock_all( this.monitors, NULL, count );
    497452
    498453        //Pop the head of the waiting queue
     
    516471
    517472        //Check that everything is as expected
    518         verifyf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
     473        verifyf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
    519474        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    520475
     
    533488
    534489        //Find the thread to run
    535         $thread * signallee = pop_head( this.blocked )->waiting_thread;
    536         __set_owner( monitors, count, signallee );
     490        thread_desc * signallee = pop_head( this.blocked )->waiting_thread;
     491        set_owner( monitors, count, signallee );
    537492
    538493        __cfaabi_dbg_print_buffer_decl( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );
    539494
    540         // unlock all the monitors
    541         unlock_all( locks, count );
    542 
    543         // unpark the thread we signalled
    544         unpark( signallee __cfaabi_dbg_ctx2 );
    545 
    546495        //Everything is ready to go to sleep
    547         park( __cfaabi_dbg_ctx );
     496        BlockInternal( locks, count, &signallee, 1 );
    548497
    549498
     
    586535        // Create one!
    587536        __lock_size_t max = count_max( mask );
    588         $monitor * mon_storage[max];
     537        monitor_desc * mon_storage[max];
    589538        __builtin_memset( mon_storage, 0, sizeof( mon_storage ) );
    590539        __lock_size_t actual_count = aggregate( mon_storage, mask );
     
    604553        {
    605554                // Check if the entry queue
    606                 $thread * next; int index;
     555                thread_desc * next; int index;
    607556                [next, index] = search_entry_queue( mask, monitors, count );
    608557
     
    614563                                verifyf( accepted.size == 1,  "ERROR: Accepted dtor has more than 1 mutex parameter." );
    615564
    616                                 $monitor * mon2dtor = accepted[0];
     565                                monitor_desc * mon2dtor = accepted[0];
    617566                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
    618567
     
    640589
    641590                                // Set the owners to be the next thread
    642                                 __set_owner( monitors, count, next );
    643 
    644                                 // unlock all the monitors
    645                                 unlock_all( locks, count );
    646 
    647                                 // unpark the thread we signalled
    648                                 unpark( next __cfaabi_dbg_ctx2 );
    649 
    650                                 //Everything is ready to go to sleep
    651                                 park( __cfaabi_dbg_ctx );
     591                                set_owner( monitors, count, next );
     592
     593                                // Everything is ready to go to sleep
     594                                BlockInternal( locks, count, &next, 1 );
    652595
    653596                                // We are back, restore the owners and recursions
     
    687630        }
    688631
    689         // unlock all the monitors
    690         unlock_all( locks, count );
    691 
    692632        //Everything is ready to go to sleep
    693         park( __cfaabi_dbg_ctx );
     633        BlockInternal( locks, count );
    694634
    695635
     
    708648// Utilities
    709649
    710 static inline void __set_owner( $monitor * this, $thread * owner ) {
    711         /* paranoid */ verify( this->lock.lock );
     650static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
     651        // __cfaabi_dbg_print_safe( "Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
    712652
    713653        //Pass the monitor appropriately
     
    718658}
    719659
    720 static inline void __set_owner( $monitor * monitors [], __lock_size_t count, $thread * owner ) {
    721         /* paranoid */ verify ( monitors[0]->lock.lock );
    722         /* 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] );
    723         monitors[0]->owner        = owner;
    724         monitors[0]->recursion    = 1;
     660static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {
     661        monitors[0]->owner     = owner;
     662        monitors[0]->recursion = 1;
    725663        for( __lock_size_t i = 1; i < count; i++ ) {
    726                 /* paranoid */ verify ( monitors[i]->lock.lock );
    727                 /* 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] );
    728                 monitors[i]->owner        = owner;
    729                 monitors[i]->recursion    = 0;
    730         }
    731 }
    732 
    733 static inline void set_mask( $monitor * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {
     664                monitors[i]->owner     = owner;
     665                monitors[i]->recursion = 0;
     666        }
     667}
     668
     669static inline void set_mask( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {
    734670        for( __lock_size_t i = 0; i < count; i++) {
    735671                storage[i]->mask = mask;
     
    737673}
    738674
    739 static inline void reset_mask( $monitor * this ) {
    740         this->mask.accepted = 0p;
    741         this->mask.data = 0p;
     675static inline void reset_mask( monitor_desc * this ) {
     676        this->mask.accepted = NULL;
     677        this->mask.data = NULL;
    742678        this->mask.size = 0;
    743679}
    744680
    745 static inline $thread * next_thread( $monitor * this ) {
     681static inline thread_desc * next_thread( monitor_desc * this ) {
    746682        //Check the signaller stack
    747683        __cfaabi_dbg_print_safe( "Kernel :  mon %p AS-stack top %p\n", this, this->signal_stack.top);
     
    751687                //regardless of if we are ready to baton pass,
    752688                //we need to set the monitor as in use
    753                 /* 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 );
    754                 __set_owner( this,  urgent->owner->waiting_thread );
     689                set_owner( this,  urgent->owner->waiting_thread );
    755690
    756691                return check_condition( urgent );
     
    759694        // No signaller thread
    760695        // Get the next thread in the entry_queue
    761         $thread * new_owner = pop_head( this->entry_queue );
    762         /* 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 );
    763         /* paranoid */ verify( !new_owner || new_owner->next == 0p );
    764         __set_owner( this, new_owner );
     696        thread_desc * new_owner = pop_head( this->entry_queue );
     697        set_owner( this, new_owner );
    765698
    766699        return new_owner;
    767700}
    768701
    769 static inline bool is_accepted( $monitor * this, const __monitor_group_t & group ) {
     702static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) {
    770703        __acceptable_t * it = this->mask.data; // Optim
    771704        __lock_size_t count = this->mask.size;
     
    789722}
    790723
    791 static inline void init( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     724static inline void init( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    792725        for( __lock_size_t i = 0; i < count; i++) {
    793726                (criteria[i]){ monitors[i], waiter };
     
    797730}
    798731
    799 static inline void init_push( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     732static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    800733        for( __lock_size_t i = 0; i < count; i++) {
    801734                (criteria[i]){ monitors[i], waiter };
     
    813746}
    814747
    815 static inline void lock_all( $monitor * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
     748static inline void lock_all( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
    816749        for( __lock_size_t i = 0; i < count; i++ ) {
    817750                __spinlock_t * l = &source[i]->lock;
     
    827760}
    828761
    829 static inline void unlock_all( $monitor * locks [], __lock_size_t count ) {
     762static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) {
    830763        for( __lock_size_t i = 0; i < count; i++ ) {
    831764                unlock( locks[i]->lock );
     
    834767
    835768static inline void save(
    836         $monitor * ctx [],
     769        monitor_desc * ctx [],
    837770        __lock_size_t count,
    838771        __attribute((unused)) __spinlock_t * locks [],
     
    847780
    848781static inline void restore(
    849         $monitor * ctx [],
     782        monitor_desc * ctx [],
    850783        __lock_size_t count,
    851784        __spinlock_t * locks [],
     
    865798// 2 - Checks if all the monitors are ready to run
    866799//     if so return the thread to run
    867 static inline $thread * check_condition( __condition_criterion_t * target ) {
     800static inline thread_desc * check_condition( __condition_criterion_t * target ) {
    868801        __condition_node_t * node = target->owner;
    869802        unsigned short count = node->count;
     
    883816        }
    884817
    885         __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : 0p );
    886         return ready2run ? node->waiting_thread : 0p;
     818        __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : NULL );
     819        return ready2run ? node->waiting_thread : NULL;
    887820}
    888821
    889822static inline void brand_condition( condition & this ) {
    890         $thread * thrd = TL_GET( this_thread );
     823        thread_desc * thrd = TL_GET( this_thread );
    891824        if( !this.monitors ) {
    892825                // __cfaabi_dbg_print_safe( "Branding\n" );
    893                 assertf( thrd->monitors.data != 0p, "No current monitor to brand condition %p", thrd->monitors.data );
     826                assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
    894827                this.monitor_count = thrd->monitors.size;
    895828
    896                 this.monitors = ($monitor **)malloc( this.monitor_count * sizeof( *this.monitors ) );
     829                this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );
    897830                for( int i = 0; i < this.monitor_count; i++ ) {
    898831                        this.monitors[i] = thrd->monitors[i];
     
    901834}
    902835
    903 static inline [$thread *, int] search_entry_queue( const __waitfor_mask_t & mask, $monitor * monitors [], __lock_size_t count ) {
    904 
    905         __queue_t($thread) & entry_queue = monitors[0]->entry_queue;
     836static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {
     837
     838        __queue_t(thread_desc) & entry_queue = monitors[0]->entry_queue;
    906839
    907840        // For each thread in the entry-queue
    908         for(    $thread ** thrd_it = &entry_queue.head;
    909                 *thrd_it != 1p;
     841        for(    thread_desc ** thrd_it = &entry_queue.head;
     842                *thrd_it;
    910843                thrd_it = &(*thrd_it)->next
    911844        ) {
     
    950883}
    951884
    952 static inline __lock_size_t aggregate( $monitor * storage [], const __waitfor_mask_t & mask ) {
     885static inline __lock_size_t aggregate( monitor_desc * storage [], const __waitfor_mask_t & mask ) {
    953886        __lock_size_t size = 0;
    954887        for( __lock_size_t i = 0; i < mask.size; i++ ) {
Note: See TracChangeset for help on using the changeset viewer.