Changeset 563 for trunk/kernel/libk/remote_sem.c
- Timestamp:
- Oct 4, 2018, 11:16:13 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/libk/remote_sem.c
r469 r563 1 1 /* 2 * remote_sem.c - Kernel function implementing the semaphore related syscalls.2 * remote_sem.c - POSIX unnamed semaphore implementation. 3 3 * 4 * Author Alain Greiner (2016 )4 * Author Alain Greiner (2016,2017,2018) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 33 33 34 34 /////////////////////////////////////////////// 35 xptr_t remote_sem_from_ vaddr( intptr_t vaddr)35 xptr_t remote_sem_from_ident( intptr_t ident ) 36 36 { 37 37 // get pointer on local process_descriptor … … 45 45 process_t * ref_ptr = GET_PTR( ref_xp ); 46 46 47 // get extended pointer on root ofsemaphores list47 // get extended pointer on semaphores list 48 48 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root ); 49 xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock ); 49 50 51 // get lock protecting synchro lists 52 remote_queuelock_acquire( lock_xp ); 53 50 54 // scan reference process semaphores list 51 55 xptr_t iter_xp; … … 53 57 cxy_t sem_cxy; 54 58 remote_sem_t * sem_ptr; 55 intptr_t ident;59 intptr_t current; 56 60 bool_t found = false; 57 61 … … 61 65 sem_cxy = GET_CXY( sem_xp ); 62 66 sem_ptr = GET_PTR( sem_xp ); 63 ident= (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) );64 65 if( ident == vaddr)67 current = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) ); 68 69 if( current == ident ) 66 70 { 67 71 found = true; … … 70 74 } 71 75 76 // relese lock protecting synchros lists 77 remote_queuelock_release( lock_xp ); 78 72 79 if( found == false ) return XPTR_NULL; 73 80 else return sem_xp; 74 81 75 } // end remote_sem_from_ vaddr()82 } // end remote_sem_from_ident() 76 83 77 84 /////////////////////////////////////////// 78 85 error_t remote_sem_create( intptr_t vaddr, 79 uint32_t value, 80 xptr_t sem_xp_xp ) 86 uint32_t value ) 81 87 { 82 88 remote_sem_t * sem_ptr; … … 108 114 } 109 115 110 if( sem_xp == XPTR_NULL ) return -1;116 if( sem_xp == XPTR_NULL ) return 0xFFFFFFFF; 111 117 112 118 // initialise semaphore 113 hal_remote_s w( XPTR( ref_cxy , &sem_ptr->count ) , value );119 hal_remote_s32 ( XPTR( ref_cxy , &sem_ptr->count ) , value ); 114 120 hal_remote_spt( XPTR( ref_cxy , &sem_ptr->ident ) , (void *)vaddr ); 115 remote_spinlock_init( XPTR( ref_cxy , &sem_ptr->lock ) );116 121 xlist_root_init( XPTR( ref_cxy , &sem_ptr->root ) ); 117 122 xlist_entry_init( XPTR( ref_cxy , &sem_ptr->list ) ); 118 119 // register semaphore in reference process xlist 123 remote_busylock_init( XPTR( ref_cxy , &sem_ptr->lock ), LOCK_SEM_STATE ); 124 120 125 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root ); 121 xptr_t xp_list = XPTR( ref_cxy , &sem_ptr->list ); 122 remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 123 xlist_add_first( root_xp , xp_list ); 124 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 125 126 // write extended pointer on semaphore in calling thread buffer 127 hal_remote_swd( sem_xp_xp , sem_xp ); 126 xptr_t list_xp = XPTR( ref_cxy , &sem_ptr->list ); 127 128 // get lock protecting user synchro lists 129 remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 130 131 // register semaphore in reference process list of semaphores 132 xlist_add_first( root_xp , list_xp ); 133 134 // release lock protecting user synchro lists 135 remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 136 137 #if DEBUG_SEM 138 thread_t * this = CURRENT_THREAD; 139 if( (uint32_t)hal_get_cycles() > DEBUG_SEM ) 140 printk("\n[DBG] %s : thread %x in process %x INITIALIZE sem(%x,%x) / value %d\n", 141 __FUNCTION__, this->trdid, this->process->pid, local_cxy, sem_ptr, value ); 142 #endif 128 143 129 144 return 0; 130 145 131 } // en remote_sem_create()146 } // end remote_sem_create() 132 147 133 148 //////////////////////////////////////// … … 146 161 // get semaphore cluster and local pointer 147 162 cxy_t sem_cxy = GET_CXY( sem_xp ); 148 remote_sem_t * sem_ptr = (remote_sem_t *)GET_PTR( sem_xp ); 149 150 // get lock protecting semaphore 151 remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) ); 152 163 remote_sem_t * sem_ptr = GET_PTR( sem_xp ); 164 153 165 // get remote pointer on waiting queue root 154 166 xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root ); … … 161 173 } 162 174 163 // reset semaphore count164 hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , 0 );165 166 175 // remove semaphore from reference process xlist 167 remote_ spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );176 remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 168 177 xlist_unlink( XPTR( sem_cxy , &sem_ptr->list ) ); 169 remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 170 171 // release lock 172 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) ); 178 remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 173 179 174 180 // release memory allocated for semaphore descriptor … … 190 196 void remote_sem_wait( xptr_t sem_xp ) 191 197 { 198 thread_t * this = CURRENT_THREAD; 199 200 // check calling thread can yield 201 assert( (this->busylocks == 0), 202 "cannot yield : busylocks = %d\n", this->busylocks ); 203 204 192 205 // get semaphore cluster and local pointer 193 206 cxy_t sem_cxy = GET_CXY( sem_xp ); 194 207 remote_sem_t * sem_ptr = GET_PTR( sem_xp ); 195 208 196 // get lock protecting semaphore 197 remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) ); 209 // get extended pointers on sem fields 210 xptr_t count_xp = XPTR( sem_cxy , &sem_ptr->count ); 211 xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root ); 212 xptr_t lock_xp = XPTR( sem_cxy , &sem_ptr->lock ); 213 214 while( 1 ) 215 { 216 // get busylock protecting semaphore 217 remote_busylock_acquire( lock_xp ); 198 218 199 // get semaphore current value 200 uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) ); 201 202 if( count > 0 ) // success 203 { 204 // decrement semaphore value 205 hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count - 1 ); 206 207 // release lock 208 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) ); 209 } 210 else // failure 211 { 212 thread_t * this = CURRENT_THREAD; 213 214 // register thread in waiting queue 215 xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root ); 216 xptr_t list_xp = XPTR( local_cxy , &this->wait_list ); 217 xlist_add_last( root_xp , list_xp ); 218 219 // release lock 220 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) ); 221 222 // block and deschedule 223 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_SEM ); 224 sched_yield("blocked on semaphore"); 219 // get semaphore current value 220 uint32_t count = hal_remote_l32( count_xp ); 221 222 if( count > 0 ) // success 223 { 224 // decrement semaphore value 225 hal_remote_s32( count_xp , count - 1 ); 226 227 #if DEBUG_SEM 228 if( (uint32_t)hal_get_cycles() > DEBUG_SEM ) 229 printk("\n[DBG] %s : thread %x in process %x DECREMENT sem(%x,%x) / value %d\n", 230 __FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count-1 ); 231 #endif 232 // release busylock protecting semaphore 233 remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) ); 234 235 return; 236 } 237 else // failure 238 { 239 // get cluster and pointers on calling thread 240 cxy_t caller_cxy = local_cxy; 241 thread_t * caller_ptr = CURRENT_THREAD; 242 xptr_t caller_xp = XPTR( caller_cxy , caller_ptr ); 243 244 // block the calling thread 245 thread_block( caller_xp , THREAD_BLOCKED_SEM ); 246 247 // register calling thread in waiting queue 248 xptr_t entry_xp = XPTR( caller_cxy , &caller_ptr->wait_xlist ); 249 xlist_add_last( root_xp , entry_xp ); 250 251 #if DEBUG_SEM 252 if( (uint32_t)hal_get_cycles() > DEBUG_SEM ) 253 printk("\n[DBG] %s : thread %x in process %x BLOCK on sem(%x,%x) / value %d\n", 254 __FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count ); 255 #endif 256 // release busylock protecting semaphore 257 remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) ); 258 259 // deschedule calling thread 260 sched_yield("blocked on semaphore"); 261 } 225 262 } 226 263 } // end remote_sem_wait() … … 229 266 void remote_sem_post( xptr_t sem_xp ) 230 267 { 268 // memory barrier before sem release 269 hal_fence(); 270 231 271 // get semaphore cluster and local pointer 232 272 cxy_t sem_cxy = GET_CXY( sem_xp ); 233 273 remote_sem_t * sem_ptr = GET_PTR( sem_xp ); 234 274 235 // get lock protecting semaphore 236 remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) ); 275 // get extended pointers on sem fields 276 xptr_t count_xp = XPTR( sem_cxy , &sem_ptr->count ); 277 xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root ); 278 xptr_t lock_xp = XPTR( sem_cxy , &sem_ptr->lock ); 279 280 // get busylock protecting semaphore 281 remote_busylock_acquire( lock_xp ); 237 282 238 // get semaphore current value 239 uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) ); 240 241 // get remote pointer on waiting queue root 242 xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root ); 243 244 if( xlist_is_empty( root_xp ) ) // no waiting thread 245 { 246 // increment semaphore value 247 hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count + 1 ); 248 } 249 else 283 // increment semaphore value 284 hal_remote_atomic_add( count_xp , 1 ); 285 286 #if DEBUG_SEM 287 uint32_t count = hal_remote_l32( count_xp ); 288 thread_t * this = CURRENT_THREAD; 289 if( (uint32_t)hal_get_cycles() > DEBUG_SEM ) 290 printk("\n[DBG] %s : thread %x in process %x INCREMENT sem(%x,%x) / value %d\n", 291 __FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count ); 292 #endif 293 294 // scan waiting queue to unblock all waiting threads 295 while( xlist_is_empty( root_xp ) == false ) // waiting queue non empty 250 296 { 251 297 // get first waiting thread from queue 252 xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 253 254 // get thread cluster and local poiner 298 xptr_t thread_xp = XLIST_FIRST( root_xp , thread_t , wait_xlist ); 255 299 cxy_t thread_cxy = GET_CXY( thread_xp ); 256 300 thread_t * thread_ptr = GET_PTR( thread_xp ); 257 301 258 // remove this thread from the waiting queue, and unblock it 259 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_list ) ); 302 // remove this thread from the waiting queue 303 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) ); 304 305 // unblock this waiting thread 260 306 thread_unblock( thread_xp , THREAD_BLOCKED_SEM ); 261 } 262 263 // release lock 264 remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) ); 307 308 #if DEBUG_SEM 309 if( (uint32_t)hal_get_cycles() > DEBUG_SEM ) 310 { 311 trdid_t trdid = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) ); 312 process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) ); 313 pid_t pid = hal_remote_l32( XPTR( thread_cxy , &process->pid ) ); 314 printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %x / sem(%x,%x)\n", 315 __FUNCTION__, this->trdid, this->process->pid, trdid, pid, sem_cxy, sem_ptr ); 316 } 317 #endif 318 319 } 320 321 // release busylock protecting the semaphore 322 remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) ); 265 323 266 324 } // end remote_sem_post() … … 275 333 remote_sem_t * sem_ptr = GET_PTR( sem_xp ); 276 334 277 *data = hal_remote_l w( XPTR( sem_cxy , &sem_ptr->count ) );335 *data = hal_remote_l32( XPTR( sem_cxy , &sem_ptr->count ) ); 278 336 279 337 } // end remote_sem_get_value()
Note: See TracChangeset
for help on using the changeset viewer.