Changeset 23 for trunk/kernel/libk/remote_barrier.c
- Timestamp:
- Jun 18, 2017, 10:06:41 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/libk/remote_barrier.c
r14 r23 1 1 /* 2 * remote_barrier.c - distributed kernel barrier implementaion2 * remote_barrier.c - Access a POSIX barrier. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 24 24 #include <hal_types.h> 25 25 #include <hal_remote.h> 26 #include <hal_irqmask.h> 27 #include <remote_spinlock.h> 28 #include <thread.h> 29 #include <kmem.h> 30 #include <printk.h> 31 #include <process.h> 32 #include <vmm.h> 26 33 #include <remote_barrier.h> 27 34 28 ///////////////////////////////////////// 29 inline void remote_barrier( xptr_t xp,35 ///////////////////////////////////////////////// 36 inline void remote_barrier( xptr_t barrier_xp, 30 37 uint32_t count ) 31 38 { 32 39 uint32_t expected; 33 40 34 remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( xp );35 cxy_t cxy = GET_CXY( xp );41 remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 42 cxy_t cxy = GET_CXY( barrier_xp ); 36 43 37 44 // get barrier sense value … … 57 64 } 58 65 59 66 /////////////////////////////////////////////////// 67 xptr_t remote_barrier_from_ident( intptr_t ident ) 68 { 69 // get pointer on local process_descriptor 70 process_t * process = CURRENT_THREAD->process; 71 72 // get extended pointer on reference process 73 xptr_t ref_xp = process->ref_xp; 74 75 // get cluster and local pointer on reference process 76 cxy_t ref_cxy = GET_CXY( ref_xp ); 77 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 78 79 // get extended pointer on root of barriers list 80 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 81 82 // scan reference process barriers list 83 xptr_t iter_xp; 84 xptr_t barrier_xp; 85 cxy_t barrier_cxy; 86 remote_barrier_t * barrier_ptr; 87 intptr_t current; 88 bool_t found = false; 89 90 XLIST_FOREACH( root_xp , iter_xp ) 91 { 92 barrier_xp = XLIST_ELEMENT( iter_xp , remote_barrier_t , list ); 93 barrier_cxy = GET_CXY( barrier_xp ); 94 barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 95 current = (intptr_t)hal_remote_lpt( XPTR( barrier_cxy , &barrier_ptr->ident ) ); 96 if( ident == current ) 97 { 98 found = true; 99 break; 100 } 101 } 102 103 if( found == false ) return XPTR_NULL; 104 else return barrier_xp; 105 106 } // end remote_barrier_from_ident() 107 108 ////////////////////////////////////////////// 109 error_t remote_barrier_create( intptr_t ident, 110 uint32_t count ) 111 { 112 xptr_t barrier_xp; 113 remote_barrier_t * barrier_ptr; 114 115 // get pointer on local process descriptor 116 process_t * process = CURRENT_THREAD->process; 117 118 // get extended pointer on reference process 119 xptr_t ref_xp = process->ref_xp; 120 121 // get reference process cluster and local pointer 122 cxy_t ref_cxy = GET_CXY( ref_xp ); 123 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 124 125 // allocate memory for barrier descriptor 126 if( ref_cxy == local_cxy ) // local cluster is the reference 127 { 128 kmem_req_t req; 129 req.type = KMEM_BARRIER; 130 req.flags = AF_ZERO; 131 barrier_ptr = kmem_alloc( &req ); 132 barrier_xp = XPTR( local_cxy , barrier_ptr ); 133 } 134 else // reference is remote 135 { 136 rpc_kcm_alloc_client( ref_cxy , KMEM_BARRIER , &barrier_xp ); 137 barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 138 } 139 140 if( barrier_ptr == NULL ) return ENOMEM; 141 142 // initialise barrier 143 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->nb_threads ) , count ); 144 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->current ) , 0 ); 145 hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->sense ) , 0 ); 146 hal_remote_spt( XPTR( ref_cxy , &barrier_ptr->ident ) , (void*)ident ); 147 148 xlist_entry_init( XPTR( ref_cxy , &barrier_ptr->list ) ); 149 150 // register barrier in reference process xlist 151 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 152 xptr_t entry_xp = XPTR( ref_cxy , &barrier_ptr->list ); 153 154 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 155 xlist_add_first( root_xp , entry_xp ); 156 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 157 158 return 0; 159 160 } // end remote_barrier_create() 161 162 //////////////////////////////////////////////// 163 void remote_barrier_destroy( xptr_t barrier_xp ) 164 { 165 // get pointer on local process descriptor 166 process_t * process = CURRENT_THREAD->process; 167 168 // get extended pointer on reference process 169 xptr_t ref_xp = process->ref_xp; 170 171 // get reference process cluster and local pointer 172 cxy_t ref_cxy = GET_CXY( ref_xp ); 173 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 174 175 // get barrier cluster and local pointer 176 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 177 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 178 179 // remove barrier from reference process xlist 180 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 181 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 182 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 183 184 // release memory allocated for barrier descriptor 185 if( barrier_cxy == local_cxy ) // reference is local 186 { 187 kmem_req_t req; 188 req.type = KMEM_BARRIER; 189 req.ptr = barrier_ptr; 190 kmem_free( &req ); 191 } 192 else // reference is remote 193 { 194 rpc_kcm_free_client( barrier_cxy , barrier_ptr , KMEM_BARRIER ); 195 } 196 197 } // end remote_barrier_destroy() 198 199 ///////////////////////////////////////////// 200 void remote_barrier_wait( xptr_t barrier_xp ) 201 { 202 uint32_t expected; 203 uint32_t current; 204 uint32_t count; 205 uint32_t sense; 206 uint32_t irq_state; 207 xptr_t root_xp; 208 209 // get cluster and local pointer on calling thread 210 cxy_t thread_cxy = local_cxy; 211 thread_t * thread_ptr = CURRENT_THREAD; 212 213 // get cluster and local pointer on remote barrier 214 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 215 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 216 217 // get count and root fields from barrier descriptor 218 count = hal_remote_lw ( XPTR( barrier_cxy , &barrier_ptr->nb_threads ) ); 219 root_xp = hal_remote_lwd( XPTR( barrier_cxy , &barrier_ptr->root ) ); 220 221 // get barrier sense value 222 sense = hal_remote_lw( XPTR( barrier_cxy , &barrier_ptr->sense ) ); 223 224 // compute expected value 225 if ( sense == 0 ) expected = 1; 226 else expected = 0; 227 228 // atomically increment current 229 current = hal_remote_atomic_add( XPTR( barrier_cxy , &barrier_ptr->current ) , 1 ); 230 231 // last thread reset current, toggle sense, and activate all waiting threads 232 // other threads block, register in queue, and deschedule 233 234 if( current == (count-1) ) // last thread 235 { 236 hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->current) , 0 ); 237 hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->sense ) , expected ); 238 239 // activate waiting threads if required 240 if( xlist_is_empty( root_xp ) == false ) 241 { 242 // disable interrupts 243 hal_disable_irq( &irq_state ); 244 245 xptr_t iter_xp; 246 xptr_t thread_xp; 247 XLIST_FOREACH( root_xp , iter_xp ) 248 { 249 // get extended pointer on waiting thread 250 thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list ); 251 252 // remove waiting thread from queue 253 remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 254 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 255 remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 256 257 // unblock waiting thread 258 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 259 } 260 261 // restore interrupts 262 hal_restore_irq( irq_state ); 263 } 264 } 265 else // not the last thread 266 { 267 // disable interrupts 268 hal_disable_irq( &irq_state ); 269 270 // register calling thread in barrier waiting queue 271 xptr_t entry_xp = XPTR( thread_cxy , &thread_ptr->wait_list ); 272 273 remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 274 xlist_add_last( root_xp , entry_xp ); 275 remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) ); 276 277 // block & deschedule the calling thread 278 thread_block( thread_ptr , THREAD_BLOCKED_USERSYNC ); 279 sched_yield(); 280 281 // restore interrupts 282 hal_restore_irq( irq_state ); 283 } 284 } // end remote_barrier_wait()
Note: See TracChangeset
for help on using the changeset viewer.