Changeset 563 for trunk/kernel/libk/remote_condvar.c
- Timestamp:
- Oct 4, 2018, 11:16:13 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/libk/remote_condvar.c
r457 r563 1 1 /* 2 * remote_condvar.c - distributed kernel condvar implementaion3 * 4 * Author Alain Greiner (2016)2 * remote_condvar.c - remote kernel condition variable implementation. 3 * 4 * Authors Alain Greiner (2016,2017,2018) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 22 22 */ 23 23 24 #include <kernel_config.h> 24 25 #include <hal_kernel_types.h> 25 #include <hal_remote.h>26 #include <hal_irqmask.h>27 26 #include <thread.h> 28 #include <kmem.h> 29 #include <printk.h> 30 #include <process.h> 31 #include <vmm.h> 27 #include <scheduler.h> 32 28 #include <xlist.h> 33 29 #include <remote_mutex.h> 30 #include <remote_busylock.h> 34 31 #include <remote_condvar.h> 32 35 33 36 34 /////////////////////////////////////////////////// … … 45 43 // get cluster and local pointer on reference process 46 44 cxy_t ref_cxy = GET_CXY( ref_xp ); 47 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );48 49 // get extended pointer on root ofcondvars list45 process_t * ref_ptr = GET_PTR( ref_xp ); 46 47 // get extended pointer on condvars list 50 48 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->condvar_root ); 51 52 // scan reference process condvars list 49 xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock ); 50 51 // get lock protecting synchro lists 52 remote_queuelock_acquire( lock_xp ); 53 54 // scan reference process condvar list 53 55 xptr_t iter_xp; 54 56 xptr_t condvar_xp; 55 57 cxy_t condvar_cxy; 56 struct remote_condvar_s* condvar_ptr;58 remote_condvar_t * condvar_ptr; 57 59 intptr_t current; 58 60 bool_t found = false; … … 62 64 condvar_xp = XLIST_ELEMENT( iter_xp , remote_condvar_t , list ); 63 65 condvar_cxy = GET_CXY( condvar_xp ); 64 condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp ); 65 current = (intptr_t)hal_remote_lpt( XPTR( condvar_cxy , &condvar_ptr->ident ) ); 66 if( ident == current ) 66 condvar_ptr = GET_PTR( condvar_xp ); 67 current = (intptr_t)hal_remote_lpt( XPTR( condvar_cxy , &condvar_ptr->ident ) ); 68 69 if( current == ident ) 67 70 { 68 71 found = true; … … 71 74 } 72 75 76 // relese lock protecting synchros lists 77 remote_queuelock_release( lock_xp ); 78 73 79 if( found == false ) return XPTR_NULL; 74 80 else return condvar_xp; … … 76 82 } // end remote_condvar_from_ident() 77 83 78 /////////////////////////////////////////////// 79 error_t remote_condvar_create( intptr_t ident ) 80 { 84 ///////////////////////////////////////////////// 85 error_t remote_condvar_create( intptr_t ident ) 86 { 87 remote_condvar_t * condvar_ptr; 81 88 xptr_t condvar_xp; 82 remote_condvar_t * condvar_ptr;83 89 84 90 // get pointer on local process descriptor … … 92 98 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 93 99 94 // allocate memory for condvar descriptor95 if( ref_cxy == local_cxy ) // local cluster is the reference100 // allocate memory for new condvar in reference cluster 101 if( ref_cxy == local_cxy ) // local cluster is the reference 96 102 { 97 103 kmem_req_t req; 98 req.type 99 req.flags 100 condvar_ptr 101 condvar_xp 102 } 103 else // referenceis remote104 req.type = KMEM_CONDVAR; 105 req.flags = AF_ZERO; 106 condvar_ptr = kmem_alloc( &req ); 107 condvar_xp = XPTR( local_cxy , condvar_ptr ); 108 } 109 else // reference cluster is remote 104 110 { 105 111 rpc_kcm_alloc_client( ref_cxy , KMEM_CONDVAR , &condvar_xp ); 106 condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );107 } 108 109 if( condvar_ ptr == NULL ) return ENOMEM;112 condvar_ptr = GET_PTR( condvar_xp ); 113 } 114 115 if( condvar_xp == XPTR_NULL ) return 0xFFFFFFFF; 110 116 111 117 // initialise condvar 112 hal_remote_spt( XPTR( ref_cxy , &condvar_ptr->ident ) , (void*)ident ); 113 xlist_entry_init( XPTR( ref_cxy , &condvar_ptr->list ) ); 114 xlist_root_init( XPTR( ref_cxy , &condvar_ptr->root ) ); 115 116 // register condvar in reference process xlist 118 hal_remote_spt( XPTR( ref_cxy , &condvar_ptr->ident ) , (void *)ident ); 119 xlist_root_init( XPTR( ref_cxy , &condvar_ptr->root ) ); 120 xlist_entry_init( XPTR( ref_cxy , &condvar_ptr->list ) ); 121 remote_busylock_init( XPTR( ref_cxy , &condvar_ptr->lock ), LOCK_CONDVAR_STATE ); 122 123 // register condvar in reference process xlist 117 124 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->condvar_root ); 118 xptr_t xp_list= XPTR( ref_cxy , &condvar_ptr->list );119 120 remote_ spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );121 xlist_add_first( root_xp , xp_list);122 remote_ spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );125 xptr_t list_xp = XPTR( ref_cxy , &condvar_ptr->list ); 126 127 remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 128 xlist_add_first( root_xp , list_xp ); 129 remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 123 130 124 131 return 0; … … 137 144 // get reference process cluster and local pointer 138 145 cxy_t ref_cxy = GET_CXY( ref_xp ); 139 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 140 141 // get condvar cluster and local pointer 142 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 143 remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp ); 146 process_t * ref_ptr = GET_PTR( ref_xp ); 147 148 // get condvar cluster and local pointer 149 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 150 remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp ); 151 152 // get remote pointer on waiting queue root 153 xptr_t root_xp = XPTR( condvar_cxy , &condvar_ptr->root ); 154 155 if( !xlist_is_empty( root_xp ) ) // user error 156 { 157 printk("WARNING in %s for thread %x in process %x : " 158 "destroy condvar, but waiting threads queue not empty\n", 159 __FUNCTION__ , CURRENT_THREAD->trdid , CURRENT_THREAD->process->pid ); 160 } 144 161 145 162 // remove condvar from reference process xlist 146 remote_ spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );163 remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 147 164 xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) ); 148 remote_ spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );149 150 // release memory allocated for condvar aphoredescriptor165 remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 166 167 // release memory allocated for condvar descriptor 151 168 if( condvar_cxy == local_cxy ) // reference is local 152 169 { 153 170 kmem_req_t req; 154 req.type = KMEM_ BARRIER;171 req.type = KMEM_SEM; 155 172 req.ptr = condvar_ptr; 156 173 kmem_free( &req ); … … 158 175 else // reference is remote 159 176 { 160 rpc_kcm_free_client( condvar_cxy , condvar_ptr , KMEM_ BARRIER );161 } 162 163 } // end remote_con dvar_destroy()177 rpc_kcm_free_client( condvar_cxy , condvar_ptr , KMEM_CONDVAR ); 178 } 179 180 } // end remote_convar_destroy() 164 181 165 182 //////////////////////////////////////////// … … 167 184 xptr_t mutex_xp ) 168 185 { 169 // unlock the mutex 186 thread_t * this = CURRENT_THREAD; 187 188 // check calling thread can yield 189 assert( (this->busylocks == 0), 190 "cannot yield : busylocks = %d\n", this->busylocks ); 191 192 // get condvar cluster and local pointer 193 remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp ); 194 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 195 196 // register the calling thread in condvar waiting queue 197 xlist_add_last( XPTR( condvar_cxy , &condvar_ptr->root ), 198 XPTR( local_cxy , &this->wait_xlist ) ); 199 200 // block the calling thread 201 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_USERSYNC ); 202 203 // release the mutex 170 204 remote_mutex_unlock( mutex_xp ); 171 205 172 thread_t * this = CURRENT_THREAD; 173 174 // get condvar cluster an local pointer 175 remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp ); 176 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 177 178 // get extended pointer on condvar waiting queue 179 xptr_t root_xp = XPTR( condvar_cxy , &condvar_ptr->root ); 180 181 // get extended pointer on calling thread xlist_entry 182 xptr_t entry_xp = XPTR( local_cxy , &this->wait_list ); 183 184 // register the calling thread in the condvar waiting queue 185 remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 186 xlist_add_last( root_xp , entry_xp ); 187 remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 188 189 // block the calling thread 190 thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_USERSYNC ); 206 // deschedule 191 207 sched_yield("blocked on condvar"); 192 208 193 // lock the mutex before return194 remote_mutex_ unlock( mutex_xp );209 // re-acquire the mutex 210 remote_mutex_lock( mutex_xp ); 195 211 196 212 } // end remote_condvar_wait() … … 199 215 void remote_condvar_signal( xptr_t condvar_xp ) 200 216 { 201 reg_t irq_state; 202 203 // get condvar cluster an local pointer 204 remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp ); 205 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 206 207 // get extended pointer on condvar waiting queue 208 xptr_t root_xp = XPTR( condvar_cxy , &condvar_ptr->root ); 209 210 if( xlist_is_empty( root_xp ) ) return; 211 212 // disable interrupts 213 hal_disable_irq( &irq_state ); 214 215 // get extended pointer on the first waiting thread 216 xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list ); 217 218 // remove the first waiting thread from queue 219 remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 220 xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) ); 221 remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 222 223 // unblock first waiting thread 224 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 225 226 // restore interrupts 227 hal_restore_irq( irq_state ); 217 // get condvar cluster and local pointer 218 remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp ); 219 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 220 221 // does nothing if waiting queue empty 222 if( xlist_is_empty( XPTR( condvar_cxy, &condvar_ptr->root ) ) == false ) 223 { 224 // get first waiting thread 225 xptr_t thread_xp = XLIST_FIRST( XPTR( condvar_cxy , &condvar_ptr->root ), 226 thread_t , wait_xlist ); 227 228 // remove this waiting thread from queue 229 thread_t * thread_ptr = GET_PTR( thread_xp ); 230 cxy_t thread_cxy = GET_CXY( thread_xp ); 231 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) ); 232 233 // unblock this waiting thread 234 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 235 } 228 236 229 237 } // end remote_condvar_signal() … … 232 240 void remote_condvar_broadcast( xptr_t condvar_xp ) 233 241 { 234 reg_t irq_state; 235 236 // get condvar cluster an local pointer 237 remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp ); 238 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 239 240 // get extended pointer on condvar waiting queue 241 xptr_t root_xp = XPTR( condvar_cxy , &condvar_ptr->root ); 242 243 if( xlist_is_empty( root_xp ) ) return; 244 245 // disable interrupts 246 hal_disable_irq( &irq_state ); 247 248 // loop on waiting threads 249 xptr_t iter_xp; 250 xptr_t thread_xp; 251 XLIST_FOREACH( root_xp , iter_xp ) 252 { 253 // get extended pointer on waiting thread 254 thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list ); 255 256 // remove waiting thread from queue 257 remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 258 xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) ); 259 remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) ); 260 261 // unblock waiting thread 262 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 263 } 264 265 // restore interrupts 266 hal_restore_irq( irq_state ); 267 242 // get condvar cluster and local pointer 243 remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp ); 244 cxy_t condvar_cxy = GET_CXY( condvar_xp ); 245 246 // does nothing if waiting queue empty 247 while( xlist_is_empty( XPTR( condvar_cxy , &condvar_ptr->root ) ) == false ) 248 { 249 // get first waiting thread 250 xptr_t thread_xp = XLIST_FIRST( XPTR( condvar_cxy , &condvar_ptr->root ), 251 thread_t , wait_xlist ); 252 253 // remove this waiting thread from queue 254 thread_t * thread_ptr = GET_PTR( thread_xp ); 255 cxy_t thread_cxy = GET_CXY( thread_xp ); 256 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) ); 257 258 // unblock this waiting thread 259 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 260 } 268 261 } // end remote_condvar_broadcast() 262
Note: See TracChangeset
for help on using the changeset viewer.