- File:
-
- 1 edited
-
src/libcfa/concurrency/monitor.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/libcfa/concurrency/monitor.c
rcd348e7 rcb0e6de 18 18 19 19 #include "kernel_private.h" 20 #include "libhdr.h"21 22 void set_owner( monitor_desc * this, thread_desc * owner ) {23 //Pass the monitor appropriately24 this->owner = owner;25 26 //We are passing the monitor to someone else, which means recursion level is not 027 this->recursion = owner ? 1 : 0;28 }29 20 30 21 extern "C" { 31 void __enter_monitor_desc(monitor_desc * this , monitor_desc * leader) {22 void __enter_monitor_desc(monitor_desc * this) { 32 23 lock( &this->lock ); 33 24 thread_desc * thrd = this_thread(); 34 25 35 // //Update the stack owner36 // this->stack_owner = leader;37 38 LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion);39 40 26 if( !this->owner ) { 41 27 //No one has the monitor, just take it 42 set_owner( this, thrd ); 28 this->owner = thrd; 29 this->recursion = 1; 43 30 } 44 31 else if( this->owner == thrd) { … … 57 44 58 45 unlock( &this->lock ); 59 return;60 46 } 61 47 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) { 78 49 lock( &this->lock ); 79 50 80 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);81 82 51 thread_desc * thrd = this_thread(); 83 assert f( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion);52 assert( thrd == this->owner ); 84 53 85 54 //Leaving a recursion level, decrement the counter 86 55 this->recursion -= 1; 87 56 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 ); 102 62 103 //We are the stack owner and have left the last recursion level.104 //We are in charge of passing the monitor105 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 } 106 66 107 //Check the signaller stack108 new_owner = pop( &this->signal_stack );109 if( new_owner ) {110 //The signaller stack is not empty,111 //transfer control immediately112 set_owner( this, new_owner );113 // this->stack_owner = leader;114 ScheduleInternal( &this->lock, new_owner );115 return;116 }117 118 // No signaller thread119 // Get the next thread in the entry_queue120 new_owner = pop_head( &this->entry_queue );121 set_owner( this, new_owner );122 123 // //Update the stack owner124 // this->stack_owner = leader;125 126 //We can now let other threads in safely127 67 unlock( &this->lock ); 128 68 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 } 131 73 } 132 74 } 133 75 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] ); 76 void enter(monitor_desc ** monitors, int count) { 77 for(int i = 0; i < count; i++) { 78 __enter_monitor_desc( monitors[i] ); 138 79 } 139 80 } 140 81 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] ); 82 void leave(monitor_desc ** monitors, int count) { 83 for(int i = count - 1; i >= 0; i--) { 84 __leave_monitor_desc( monitors[i] ); 145 85 } 146 86 } 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 scheduling170 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 expected183 assert( this->monitors != NULL );184 assert( this->monitor_count != 0 );185 186 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later187 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal188 189 // LIB_DEBUG_FPRINTF("Getting ready to wait\n");190 191 //Loop on all the monitors and release the owner192 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 later200 locks[i] = &cur->lock;201 202 //Protect the monitors203 lock( locks[i] );204 {205 //Save the recursion levels206 recursions[i] = cur->recursion;207 208 //Release the owner209 cur->recursion = 0;210 cur->owner = NULL;211 }212 //Release the monitor213 unlock( locks[i] );214 }215 216 // LIB_DEBUG_FPRINTF("Waiting now\n");217 218 //Everything is ready to go to sleep219 ScheduleInternal( locks, count );220 221 222 //WE WOKE UP223 224 225 //We are back, restore the owners and recursions226 for( unsigned int i = 0; i < count; i++ ) {227 monitor_desc * cur = this->monitors[i];228 229 //Protect the monitors230 lock( locks[i] );231 {232 //Release the owner233 cur->owner = this_thrd;234 cur->recursion = recursions[i];235 }236 //Release the monitor237 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 expected246 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 } // if253 );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.