Ignore:
File:
1 edited

Legend:

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

    rae66348 r09f357ec  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // $monitor.c --
     7// monitor_desc.c --
    88//
    99// Author           : Thierry Delisle
     
    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() {
     246                thread_desc * thrd = TL_GET( this_thread );
     247                monitor_desc * this = &thrd->self_mon;
    271248
    272249                // Lock the monitor now
     
    275252                disable_interrupts();
    276253
    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 );
     254                thrd->self_cor.state = Halted;
     255
     256                verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    280257
    281258                // Leaving a recursion level, decrement the counter
     
    287264
    288265                // 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();
     266                thread_desc * new_owner = next_thread( this );
     267
     268                // Leave the thread, this will unlock the spinlock
     269                // Use leave thread instead of BlockInternal which is
     270                // specialized for this case and supports null new_owner
     271                LeaveThread( &this->lock, new_owner );
    304272
    305273                // Control flow should never reach here!
     
    311279static inline void enter( __monitor_group_t monitors ) {
    312280        for( __lock_size_t i = 0; i < monitors.size; i++) {
    313                 __enter( monitors[i], monitors );
     281                __enter_monitor_desc( monitors[i], monitors );
    314282        }
    315283}
     
    317285// Leave multiple monitor
    318286// relies on the monitor array being sorted
    319 static inline void leave($monitor * monitors [], __lock_size_t count) {
     287static inline void leave(monitor_desc * monitors [], __lock_size_t count) {
    320288        for( __lock_size_t i = count - 1; i >= 0; i--) {
    321                 __leave( monitors[i] );
     289                __leave_monitor_desc( monitors[i] );
    322290        }
    323291}
     
    325293// Ctor for monitor guard
    326294// 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 );
     295void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {
     296        thread_desc * thrd = TL_GET( this_thread );
    329297
    330298        // Store current array
     
    366334// Ctor for monitor guard
    367335// Sorts monitors before entering
    368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
     336void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {
    369337        // optimization
    370         $thread * thrd = TL_GET( this_thread );
     338        thread_desc * thrd = TL_GET( this_thread );
    371339
    372340        // Store current array
     
    379347        (thrd->monitors){m, 1, func};
    380348
    381         __dtor_enter( this.m, func );
     349        __enter_monitor_dtor( this.m, func );
    382350}
    383351
     
    385353void ^?{}( monitor_dtor_guard_t & this ) {
    386354        // Leave the monitors in order
    387         __dtor_leave( this.m );
     355        __leave_dtor_monitor_desc( this.m );
    388356
    389357        // Restore thread context
     
    393361//-----------------------------------------------------------------------------
    394362// Internal scheduling types
    395 void ?{}(__condition_node_t & this, $thread * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
     363void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
    396364        this.waiting_thread = waiting_thread;
    397365        this.count = count;
     
    407375}
    408376
    409 void ?{}(__condition_criterion_t & this, $monitor * target, __condition_node_t & owner ) {
     377void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t & owner ) {
    410378        this.ready  = false;
    411379        this.target = target;
     
    432400        // Append the current wait operation to the ones already queued on the condition
    433401        // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion
    434         /* paranoid */ verify( waiter.next == 0p );
    435402        append( this.blocked, &waiter );
    436         /* paranoid */ verify( waiter.next == 1p );
    437403
    438404        // Lock all monitors (aggregates the locks as well)
     
    441407        // Find the next thread(s) to run
    442408        __lock_size_t thread_count = 0;
    443         $thread * threads[ count ];
     409        thread_desc * threads[ count ];
    444410        __builtin_memset( threads, 0, sizeof( threads ) );
    445411
     
    449415        // Remove any duplicate threads
    450416        for( __lock_size_t i = 0; i < count; i++) {
    451                 $thread * new_owner = next_thread( monitors[i] );
     417                thread_desc * new_owner = next_thread( monitors[i] );
    452418                insert_unique( threads, thread_count, new_owner );
    453419        }
    454420
    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 
    465421        // Everything is ready to go to sleep
    466         park( __cfaabi_dbg_ctx );
     422        BlockInternal( locks, count, threads, thread_count );
    467423
    468424        // We are back, restore the owners and recursions
     
    479435        //Some more checking in debug
    480436        __cfaabi_dbg_debug_do(
    481                 $thread * this_thrd = TL_GET( this_thread );
     437                thread_desc * this_thrd = TL_GET( this_thread );
    482438                if ( this.monitor_count != this_thrd->monitors.size ) {
    483439                        abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     
    533489
    534490        //Find the thread to run
    535         $thread * signallee = pop_head( this.blocked )->waiting_thread;
    536         __set_owner( monitors, count, signallee );
     491        thread_desc * signallee = pop_head( this.blocked )->waiting_thread;
     492        set_owner( monitors, count, signallee );
    537493
    538494        __cfaabi_dbg_print_buffer_decl( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );
    539495
    540         // unlock all the monitors
    541         unlock_all( locks, count );
    542 
    543         // unpark the thread we signalled
    544         unpark( signallee __cfaabi_dbg_ctx2 );
    545 
    546496        //Everything is ready to go to sleep
    547         park( __cfaabi_dbg_ctx );
     497        BlockInternal( locks, count, &signallee, 1 );
    548498
    549499
     
    586536        // Create one!
    587537        __lock_size_t max = count_max( mask );
    588         $monitor * mon_storage[max];
     538        monitor_desc * mon_storage[max];
    589539        __builtin_memset( mon_storage, 0, sizeof( mon_storage ) );
    590540        __lock_size_t actual_count = aggregate( mon_storage, mask );
     
    604554        {
    605555                // Check if the entry queue
    606                 $thread * next; int index;
     556                thread_desc * next; int index;
    607557                [next, index] = search_entry_queue( mask, monitors, count );
    608558
     
    614564                                verifyf( accepted.size == 1,  "ERROR: Accepted dtor has more than 1 mutex parameter." );
    615565
    616                                 $monitor * mon2dtor = accepted[0];
     566                                monitor_desc * mon2dtor = accepted[0];
    617567                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
    618568
     
    640590
    641591                                // 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 );
     592                                set_owner( monitors, count, next );
     593
     594                                // Everything is ready to go to sleep
     595                                BlockInternal( locks, count, &next, 1 );
    652596
    653597                                // We are back, restore the owners and recursions
     
    687631        }
    688632
    689         // unlock all the monitors
    690         unlock_all( locks, count );
    691 
    692633        //Everything is ready to go to sleep
    693         park( __cfaabi_dbg_ctx );
     634        BlockInternal( locks, count );
    694635
    695636
     
    708649// Utilities
    709650
    710 static inline void __set_owner( $monitor * this, $thread * owner ) {
    711         /* paranoid */ verify( this->lock.lock );
     651static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
     652        // __cfaabi_dbg_print_safe( "Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
    712653
    713654        //Pass the monitor appropriately
     
    718659}
    719660
    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;
     661static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {
     662        monitors[0]->owner     = owner;
     663        monitors[0]->recursion = 1;
    725664        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 ) {
     665                monitors[i]->owner     = owner;
     666                monitors[i]->recursion = 0;
     667        }
     668}
     669
     670static inline void set_mask( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {
    734671        for( __lock_size_t i = 0; i < count; i++) {
    735672                storage[i]->mask = mask;
     
    737674}
    738675
    739 static inline void reset_mask( $monitor * this ) {
     676static inline void reset_mask( monitor_desc * this ) {
    740677        this->mask.accepted = 0p;
    741678        this->mask.data = 0p;
     
    743680}
    744681
    745 static inline $thread * next_thread( $monitor * this ) {
     682static inline thread_desc * next_thread( monitor_desc * this ) {
    746683        //Check the signaller stack
    747684        __cfaabi_dbg_print_safe( "Kernel :  mon %p AS-stack top %p\n", this, this->signal_stack.top);
     
    751688                //regardless of if we are ready to baton pass,
    752689                //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 );
     690                set_owner( this,  urgent->owner->waiting_thread );
    755691
    756692                return check_condition( urgent );
     
    759695        // No signaller thread
    760696        // 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 );
     697        thread_desc * new_owner = pop_head( this->entry_queue );
     698        set_owner( this, new_owner );
    765699
    766700        return new_owner;
    767701}
    768702
    769 static inline bool is_accepted( $monitor * this, const __monitor_group_t & group ) {
     703static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) {
    770704        __acceptable_t * it = this->mask.data; // Optim
    771705        __lock_size_t count = this->mask.size;
     
    789723}
    790724
    791 static inline void init( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     725static inline void init( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    792726        for( __lock_size_t i = 0; i < count; i++) {
    793727                (criteria[i]){ monitors[i], waiter };
     
    797731}
    798732
    799 static inline void init_push( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     733static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    800734        for( __lock_size_t i = 0; i < count; i++) {
    801735                (criteria[i]){ monitors[i], waiter };
     
    813747}
    814748
    815 static inline void lock_all( $monitor * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
     749static inline void lock_all( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
    816750        for( __lock_size_t i = 0; i < count; i++ ) {
    817751                __spinlock_t * l = &source[i]->lock;
     
    827761}
    828762
    829 static inline void unlock_all( $monitor * locks [], __lock_size_t count ) {
     763static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) {
    830764        for( __lock_size_t i = 0; i < count; i++ ) {
    831765                unlock( locks[i]->lock );
     
    834768
    835769static inline void save(
    836         $monitor * ctx [],
     770        monitor_desc * ctx [],
    837771        __lock_size_t count,
    838772        __attribute((unused)) __spinlock_t * locks [],
     
    847781
    848782static inline void restore(
    849         $monitor * ctx [],
     783        monitor_desc * ctx [],
    850784        __lock_size_t count,
    851785        __spinlock_t * locks [],
     
    865799// 2 - Checks if all the monitors are ready to run
    866800//     if so return the thread to run
    867 static inline $thread * check_condition( __condition_criterion_t * target ) {
     801static inline thread_desc * check_condition( __condition_criterion_t * target ) {
    868802        __condition_node_t * node = target->owner;
    869803        unsigned short count = node->count;
     
    888822
    889823static inline void brand_condition( condition & this ) {
    890         $thread * thrd = TL_GET( this_thread );
     824        thread_desc * thrd = TL_GET( this_thread );
    891825        if( !this.monitors ) {
    892826                // __cfaabi_dbg_print_safe( "Branding\n" );
     
    894828                this.monitor_count = thrd->monitors.size;
    895829
    896                 this.monitors = ($monitor **)malloc( this.monitor_count * sizeof( *this.monitors ) );
     830                this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );
    897831                for( int i = 0; i < this.monitor_count; i++ ) {
    898832                        this.monitors[i] = thrd->monitors[i];
     
    901835}
    902836
    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;
     837static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {
     838
     839        __queue_t(thread_desc) & entry_queue = monitors[0]->entry_queue;
    906840
    907841        // For each thread in the entry-queue
    908         for(    $thread ** thrd_it = &entry_queue.head;
    909                 *thrd_it != 1p;
     842        for(    thread_desc ** thrd_it = &entry_queue.head;
     843                *thrd_it;
    910844                thrd_it = &(*thrd_it)->next
    911845        ) {
     
    950884}
    951885
    952 static inline __lock_size_t aggregate( $monitor * storage [], const __waitfor_mask_t & mask ) {
     886static inline __lock_size_t aggregate( monitor_desc * storage [], const __waitfor_mask_t & mask ) {
    953887        __lock_size_t size = 0;
    954888        for( __lock_size_t i = 0; i < mask.size; i++ ) {
Note: See TracChangeset for help on using the changeset viewer.