Changeset 581 for trunk/kernel/libk/remote_barrier.c
- Timestamp:
- Oct 10, 2018, 3:11:53 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/libk/remote_barrier.c
r563 r581 83 83 84 84 // get pointer on local process descriptor 85 process_t * process = CURRENT_THREAD->process; 85 thread_t * this = CURRENT_THREAD; 86 process_t * process = this->process; 87 88 #if DEBUG_BARRIER 89 uint32_t cycle = (uint32_t)hal_get_cycles(); 90 if( cycle > DEBUG_BARRIER ) 91 printk("\n[DBG] %s : thread %x in process %x enter / count %d / cycle %d\n", 92 __FUNCTION__, this->trdid, process->pid, count, cycle ); 93 #endif 86 94 87 95 // get extended pointer on reference process … … 110 118 111 119 // initialise barrier 112 hal_remote_s32 113 hal_remote_s32 114 hal_remote_s32 120 hal_remote_s32( XPTR( ref_cxy , &barrier_ptr->nb_threads ) , count ); 121 hal_remote_s32( XPTR( ref_cxy , &barrier_ptr->current ) , 0 ); 122 hal_remote_s32( XPTR( ref_cxy , &barrier_ptr->sense ) , 0 ); 115 123 hal_remote_spt( XPTR( ref_cxy , &barrier_ptr->ident ) , (void*)ident ); 116 124 117 xlist_ entry_init( XPTR( ref_cxy , &barrier_ptr->list ) );125 xlist_root_init( XPTR( ref_cxy , &barrier_ptr->root ) ); 118 126 119 127 // register barrier in reference process xlist … … 125 133 remote_busylock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 126 134 135 #if DEBUG_BARRIER 136 cycle = (uint32_t)hal_get_cycles(); 137 if( cycle > DEBUG_BARRIER ) 138 printk("\n[DBG] %s : thread %x in process %x exit / barrier %x in cluster %x / cycle %d\n", 139 __FUNCTION__, this->trdid, process->pid, barrier_ptr, ref_cxy, cycle ); 140 #endif 141 127 142 return 0; 128 } 143 144 } // end remote_barrier_create() 129 145 130 146 //////////////////////////////////////////////// … … 162 178 rpc_kcm_free_client( barrier_cxy , barrier_ptr , KMEM_BARRIER ); 163 179 } 164 } 180 } // end remote_barrier_destroy() 165 181 166 182 ///////////////////////////////////////////// … … 168 184 { 169 185 uint32_t expected; 186 uint32_t sense; 170 187 uint32_t current; 171 uint32_t count; 172 uint32_t sense; 173 reg_t irq_state; 188 uint32_t nb_threads; 174 189 xptr_t root_xp; 175 176 // get cluster and local pointer on calling thread 177 cxy_t thread_cxy = local_cxy; 178 thread_t * thread_ptr = CURRENT_THREAD; 179 180 // check calling thread can yield 181 assert( (thread_ptr->busylocks == 0), 182 "cannot yield : busylocks = %d\n", thread_ptr->busylocks ); 190 xptr_t lock_xp; 191 xptr_t current_xp; 192 xptr_t sense_xp; 193 xptr_t nb_threads_xp; 194 195 // get pointer on calling thread 196 thread_t * this = CURRENT_THREAD; 197 198 // check calling thread can yield 199 thread_assert_can_yield( this , __FUNCTION__ ); 183 200 184 201 // get cluster and local pointer on remote barrier 185 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp );202 remote_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 186 203 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 187 204 188 // get count and root fields from barrier descriptor 189 count = hal_remote_l32 ( XPTR( barrier_cxy , &barrier_ptr->nb_threads ) ); 190 root_xp = hal_remote_l64( XPTR( barrier_cxy , &barrier_ptr->root ) ); 191 192 // get barrier sense value 193 sense = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->sense ) ); 205 #if DEBUG_BARRIER 206 uint32_t cycle = (uint32_t)hal_get_cycles(); 207 if( cycle > DEBUG_BARRIER ) 208 printk("\n[DBG] %s : thread %x in process %x enter / barrier %x in cluster %x / cycle %d\n", 209 __FUNCTION__, this->trdid, this->process->pid, barrier_ptr, barrier_cxy, cycle ); 210 #endif 211 212 // compute extended pointers on various barrier fields 213 lock_xp = XPTR( barrier_cxy , &barrier_ptr->lock ); 214 root_xp = XPTR( barrier_cxy , &barrier_ptr->root ); 215 current_xp = XPTR( barrier_cxy , &barrier_ptr->current ); 216 sense_xp = XPTR( barrier_cxy , &barrier_ptr->sense ); 217 nb_threads_xp = XPTR( barrier_cxy , &barrier_ptr->nb_threads ); 218 219 // take busylock protecting the remote_barrier 220 remote_busylock_acquire( lock_xp ); 221 222 #if (DEBUG_BARRIER & 1) 223 cycle = (uint32_t)hal_get_cycles(); 224 if( cycle > DEBUG_BARRIER ) 225 printk("\n[DBG] %s : thread %x in process %x get lock / cycle %d\n", 226 __FUNCTION__, this->trdid, this->process->pid, cycle ); 227 #endif 228 229 // get sense and nb_threads values from barrier descriptor 230 sense = hal_remote_l32( sense_xp ); 231 nb_threads = hal_remote_l32( nb_threads_xp ); 194 232 195 233 // compute expected value … … 197 235 else expected = 0; 198 236 199 // atomically increment current 200 current = hal_remote_atomic_add( XPTR( barrier_cxy , &barrier_ptr->current ) , 1 ); 237 #if (DEBUG_BARRIER & 1) 238 cycle = (uint32_t)hal_get_cycles(); 239 if( cycle > DEBUG_BARRIER ) 240 printk("\n[DBG] %s : thread %x in process %x / count %d / sense %d / cycle %d\n", 241 __FUNCTION__, this->trdid, this->process->pid, nb_threads, sense, cycle ); 242 #endif 243 244 // atomically increment current, and get value before increment 245 current = hal_remote_atomic_add( current_xp , 1 ); 201 246 202 247 // last thread reset current, toggle sense, and activate all waiting threads 203 248 // other threads block, register in queue, and deschedule 204 249 205 if( current == ( count-1) ) // last thread206 { 207 hal_remote_s32( XPTR( barrier_cxy , &barrier_ptr->current), 0 );208 hal_remote_s32( XPTR( barrier_cxy , &barrier_ptr->sense ), expected );209 210 // activate waiting threads if required211 if( xlist_is_empty( root_xp ) == false )250 if( current == (nb_threads-1) ) // last thread 251 { 252 hal_remote_s32( current_xp , 0 ); 253 hal_remote_s32( sense_xp , expected ); 254 255 // unblock all waiting threads 256 while( xlist_is_empty( root_xp ) == false ) 212 257 { 213 // disable interrupts 214 hal_disable_irq( &irq_state ); 215 216 xptr_t iter_xp; 217 xptr_t thread_xp; 218 XLIST_FOREACH( root_xp , iter_xp ) 219 { 220 // get extended pointer on waiting thread 221 thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list ); 222 223 // remove waiting thread from queue 224 remote_busylock_acquire( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 225 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 226 remote_busylock_release( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 227 228 // unblock waiting thread 229 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 230 } 231 232 // restore interrupts 233 hal_restore_irq( irq_state ); 258 // get pointers on first waiting thread 259 xptr_t thread_xp = XLIST_FIRST( root_xp , thread_t , wait_list ); 260 cxy_t thread_cxy = GET_CXY( thread_xp ); 261 thread_t * thread_ptr = GET_PTR( thread_xp ); 262 263 #if (DEBUG_BARRIER & 1) 264 cycle = (uint32_t)hal_get_cycles(); 265 if( cycle > DEBUG_BARRIER ) 266 printk("\n[DBG] %s : thread %x in process %x / unblock thread %x / cycle %d\n", 267 __FUNCTION__, this->trdid, this->process->pid, thread_ptr, cycle ); 268 #endif 269 270 // remove waiting thread from queue 271 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_list ) ); 272 273 // unblock waiting thread 274 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 234 275 } 276 277 // release busylock protecting the remote_barrier 278 remote_busylock_release( lock_xp ); 235 279 } 236 280 else // not the last thread 237 281 { 238 // disable interrupts 239 hal_disable_irq( &irq_state ); 282 283 #if (DEBUG_BARRIER & 1) 284 cycle = (uint32_t)hal_get_cycles(); 285 if( cycle > DEBUG_BARRIER ) 286 printk("\n[DBG] %s : thread %x in process %x / blocked / cycle %d\n", 287 __FUNCTION__, this->trdid, this->process->pid, cycle ); 288 #endif 240 289 241 290 // register calling thread in barrier waiting queue 242 xptr_t entry_xp = XPTR( thread_cxy , &thread_ptr->wait_list ); 243 244 remote_busylock_acquire( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 245 xlist_add_last( root_xp , entry_xp ); 246 remote_busylock_release( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 247 248 // block & deschedule the calling thread 249 thread_block( XPTR( local_cxy , thread_ptr ) , THREAD_BLOCKED_USERSYNC ); 291 xlist_add_last( root_xp , XPTR( local_cxy , &this->wait_list ) ); 292 293 // block calling thread 294 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_USERSYNC ); 295 296 // release busylock protecting the remote_barrier 297 remote_busylock_release( lock_xp ); 298 299 // deschedule 250 300 sched_yield("blocked on barrier"); 251 252 // restore interrupts 253 hal_restore_irq( irq_state ); 254 } 255 } 301 } 302 303 #if DEBUG_BARRIER 304 cycle = (uint32_t)hal_get_cycles(); 305 if( cycle > DEBUG_BARRIER ) 306 printk("\n[DBG] %s : thread %x in process %x exit / barrier %x in cluster %x / cycle %d\n", 307 __FUNCTION__, this->trdid, this->process->pid, barrier_ptr, barrier_cxy, cycle ); 308 #endif 309 310 } // end remote_barrier_wait()
Note: See TracChangeset
for help on using the changeset viewer.