Ignore:
File:
1 edited

Legend:

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

    rcd348e7 rcb0e6de  
    1818
    1919#include "kernel_private.h"
    20 #include "libhdr.h"
    21 
    22 void set_owner( monitor_desc * this, thread_desc * owner ) {
    23         //Pass the monitor appropriately
    24         this->owner = owner;
    25 
    26         //We are passing the monitor to someone else, which means recursion level is not 0
    27         this->recursion = owner ? 1 : 0;
    28 }
    2920
    3021extern "C" {
    31         void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) {
     22        void __enter_monitor_desc(monitor_desc * this) {
    3223                lock( &this->lock );
    3324                thread_desc * thrd = this_thread();
    3425
    35                 // //Update the stack owner
    36                 // this->stack_owner = leader;
    37 
    38                 LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
    39 
    4026                if( !this->owner ) {
    4127                        //No one has the monitor, just take it
    42                         set_owner( this, thrd );
     28                        this->owner = thrd;
     29                        this->recursion = 1;
    4330                }
    4431                else if( this->owner == thrd) {
     
    5744
    5845                unlock( &this->lock );
    59                 return;
    6046        }
    6147
    62         // leave pseudo code :
    63         //      decrement level
    64         //      leve == 0 ?
    65         //              no : done
    66         //              yes :
    67         //                      signal stack empty ?
    68         //                              has leader :
    69         //                                      bulk acquiring means we don't own the signal stack
    70         //                                      ignore it but don't release the monitor
    71         //                              yes :
    72         //                                      next in entry queue is new owner
    73         //                              no :
    74         //                                      top of the signal stack is the owner
    75         //                                      context switch to him right away
    76         //
    77         void __leave_monitor_desc(monitor_desc * this, monitor_desc * leader) {
     48        void __leave_monitor_desc(monitor_desc * this) {
    7849                lock( &this->lock );
    7950
    80                 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);
    81 
    8251                thread_desc * thrd = this_thread();
    83                 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion );
     52                assert( thrd == this->owner );
    8453
    8554                //Leaving a recursion level, decrement the counter
    8655                this->recursion -= 1;
    8756
    88                 //If we haven't left the last level of recursion
    89                 //it means we don't need to do anything
    90                 if( this->recursion != 0) {
    91                         // this->stack_owner = leader;
    92                         unlock( &this->lock );
    93                         return;
    94                 }
    95                        
    96                 // //If we don't own the signal stack then just leave it to the owner
    97                 // if( this->stack_owner ) {
    98                 //      this->stack_owner = leader;
    99                 //      unlock( &this->lock );
    100                 //      return;
    101                 // }
     57                //If we left the last level of recursion it means we are changing who owns the monitor
     58                thread_desc * new_owner = 0;
     59                if( this->recursion == 0) {
     60                        //Get the next thread in the list
     61                        new_owner = this->owner = pop_head( &this->entry_queue );
    10262
    103                 //We are the stack owner and have left the last recursion level.
    104                 //We are in charge of passing the monitor
    105                 thread_desc * new_owner = 0;
     63                        //We are passing the monitor to someone else, which means recursion level is not 0
     64                        this->recursion = new_owner ? 1 : 0;
     65                }       
    10666
    107                 //Check the signaller stack
    108                 new_owner = pop( &this->signal_stack );
    109                 if( new_owner ) {
    110                         //The signaller stack is not empty,
    111                         //transfer control immediately
    112                         set_owner( this, new_owner );
    113                         // this->stack_owner = leader;
    114                         ScheduleInternal( &this->lock, new_owner );
    115                         return;
    116                 }
    117                
    118                 // No signaller thread
    119                 // Get the next thread in the entry_queue
    120                 new_owner = pop_head( &this->entry_queue );
    121                 set_owner( this, new_owner );
    122 
    123                 // //Update the stack owner
    124                 // this->stack_owner = leader;
    125 
    126                 //We can now let other threads in safely
    12767                unlock( &this->lock );
    12868
    129                 //We need to wake-up the thread
    130                 ScheduleThread( new_owner );
     69                //If we have a new owner, we need to wake-up the thread
     70                if( new_owner ) {
     71                        ScheduleThread( new_owner );
     72                }
    13173        }
    13274}
    13375
    134 static inline void enter(monitor_desc ** monitors, int count) {
    135         __enter_monitor_desc( monitors[0], NULL );
    136         for(int i = 1; i < count; i++) {
    137                 __enter_monitor_desc( monitors[i], monitors[0] );
     76void enter(monitor_desc ** monitors, int count) {
     77        for(int i = 0; i < count; i++) {
     78                __enter_monitor_desc( monitors[i] );
    13879        }
    13980}
    14081
    141 static inline void leave(monitor_desc ** monitors, int count) {
    142         __leave_monitor_desc( monitors[0], NULL );
    143         for(int i = count - 1; i >= 1; i--) {
    144                 __leave_monitor_desc( monitors[i], monitors[0] );
     82void leave(monitor_desc ** monitors, int count) {
     83        for(int i = count - 1; i >= 0; i--) {
     84                __leave_monitor_desc( monitors[i] );
    14585        }
    14686}
    147 
    148 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) {
    149         this->m = m;
    150         this->count = count;
    151         qsort(this->m, count);
    152         enter( this->m, this->count );
    153 
    154         this->prev_mntrs = this_thread()->current_monitors;
    155         this->prev_count = this_thread()->current_monitor_count;
    156 
    157         this_thread()->current_monitors      = m;
    158         this_thread()->current_monitor_count = count;
    159 }
    160 
    161 void ^?{}( monitor_guard_t * this ) {
    162         leave( this->m, this->count );
    163 
    164         this_thread()->current_monitors      = this->prev_mntrs;
    165         this_thread()->current_monitor_count = this->prev_count;
    166 }
    167 
    168 //-----------------------------------------------------------------------------
    169 // Internal scheduling
    170 void wait( condition * this ) {
    171         assertf(false, "NO SUPPORTED");
    172         // LIB_DEBUG_FPRINTF("Waiting\n");
    173         thread_desc * this_thrd = this_thread();
    174 
    175         if( !this->monitors ) {
    176                 this->monitors = this_thrd->current_monitors;
    177                 this->monitor_count = this_thrd->current_monitor_count;
    178         }
    179 
    180         unsigned short count = this->monitor_count;
    181 
    182         //Check that everything is as expected
    183         assert( this->monitors != NULL );
    184         assert( this->monitor_count != 0 );
    185 
    186         unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
    187         spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
    188 
    189         // LIB_DEBUG_FPRINTF("Getting ready to wait\n");
    190 
    191         //Loop on all the monitors and release the owner
    192         for( unsigned int i = 0; i < count; i++ ) {
    193                 monitor_desc * cur = this->monitors[i];
    194 
    195                 assert( cur );
    196 
    197                 // LIB_DEBUG_FPRINTF("cur %p lock %p\n", cur, &cur->lock);
    198 
    199                 //Store the locks for later
    200                 locks[i] = &cur->lock;
    201 
    202                 //Protect the monitors
    203                 lock( locks[i] );
    204                 {               
    205                         //Save the recursion levels
    206                         recursions[i] = cur->recursion;
    207 
    208                         //Release the owner
    209                         cur->recursion = 0;
    210                         cur->owner = NULL;
    211                 }
    212                 //Release the monitor
    213                 unlock( locks[i] );
    214         }
    215 
    216         // LIB_DEBUG_FPRINTF("Waiting now\n");
    217 
    218         //Everything is ready to go to sleep
    219         ScheduleInternal( locks, count );
    220 
    221 
    222         //WE WOKE UP
    223 
    224 
    225         //We are back, restore the owners and recursions
    226         for( unsigned int i = 0; i < count; i++ ) {
    227                 monitor_desc * cur = this->monitors[i];
    228 
    229                 //Protect the monitors
    230                 lock( locks[i] );
    231                 {
    232                         //Release the owner
    233                         cur->owner = this_thrd;
    234                         cur->recursion = recursions[i];
    235                 }
    236                 //Release the monitor
    237                 unlock( locks[i] );
    238         }
    239 }
    240 
    241 static void __signal_internal( condition * this ) {
    242         assertf(false, "NO SUPPORTED");
    243         if( !this->blocked.head ) return;
    244 
    245         //Check that everything is as expected
    246         assert( this->monitors );
    247         assert( this->monitor_count != 0 );
    248        
    249         LIB_DEBUG_DO(
    250                 if ( this->monitors != this_thread()->current_monitors ) {
    251                         abortf( "Signal on condition %p made outside of the correct monitor(s)", this );
    252                 } // if
    253         );
    254 
    255         monitor_desc * owner = this->monitors[0];
    256         lock( &owner->lock );
    257         {
    258                 thread_desc * unblock = pop_head( &this->blocked );
    259                 push( &owner->signal_stack, unblock );
    260         }
    261         unlock( &owner->lock );
    262 }
    263 
    264 void signal( condition * this ) {
    265         __signal_internal( this );
    266 }
Note: See TracChangeset for help on using the changeset viewer.