- Timestamp:
- Feb 12, 2019, 1:15:47 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 45 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/generic/hal_exception.h
r587 r619 26 26 27 27 #include <hal_kernel_types.h> 28 #include <thread.h> 28 29 29 30 ////////////////////////////////////////////////////////////////////////////////////////// … … 59 60 EXCP_USER_ERROR, 60 61 EXCP_KERNEL_PANIC, 62 61 63 } 62 64 exception_handling_type_t; … … 69 71 void hal_do_exception( void ); 70 72 73 71 74 #endif // _HAL_EXCEPTION_H_ -
trunk/hal/generic/hal_remote.h
r570 r619 166 166 * destination remote buffer in kernel space. 167 167 ***************************************************************************************** 168 * @ dst 169 * @ src 168 * @ dst_xp : extended pointer to destination buffer 169 * @ src_xp : extended pointer to source buffer 170 170 * @ size : number of bytes to move 171 171 ****************************************************************************************/ 172 void hal_remote_memcpy( xptr_t dst ,173 xptr_t src ,172 void hal_remote_memcpy( xptr_t dst_xp, 173 xptr_t src_xp, 174 174 uint32_t size ); 175 175 -
trunk/hal/generic/hal_special.h
r480 r619 84 84 * This function returns the current value of stack pointer from core register. 85 85 ****************************************************************************************/ 86 uint32_t hal_get_stack( void ); 86 uint32_t hal_get_sp( void ); 87 88 /***************************************************************************************** 89 * This function returns the current value of the return adddress from core register. 90 ****************************************************************************************/ 91 uint32_t hal_get_ra( void ); 87 92 88 93 /***************************************************************************************** 89 94 * This function registers a new value in the core stack pointer and returns previous one. 90 95 ****************************************************************************************/ 91 inline uint32_t hal_set_s tack( void * new_val );96 inline uint32_t hal_set_sp( void * new_val ); 92 97 93 98 /***************************************************************************************** -
trunk/hal/tsar_mips32/core/hal_exception.c
r611 r619 219 219 uint32_t cycle = (uint32_t)hal_get_cycles(); 220 220 if( DEBUG_HAL_EXCEPTIONS < cycle ) 221 printk("\n[%s] thread[%x,%x] on core [%x,%x] enter /is_ins %d / %s / vaddr %x / cycle %d\n",221 printk("\n[%s] thread[%x,%x] on core [%x,%x] enter\n is_ins %d / %s / vaddr %x / cycle %d\n", 222 222 __FUNCTION__, process->pid, this->trdid, local_cxy, this->core->lid, 223 223 is_ins, hal_mmu_exception_str(excp_code), bad_vaddr, cycle); … … 242 242 cycle = (uint32_t)hal_get_cycles(); 243 243 if( DEBUG_HAL_EXCEPTIONS < cycle ) 244 printk("\n[%s] thread[%x,%x] on core [%x,%x] exit /page-fault handled for vaddr = %x\n",244 printk("\n[%s] thread[%x,%x] on core [%x,%x] exit\n page-fault handled for vaddr = %x\n", 245 245 __FUNCTION__, process->pid, this->trdid, local_cxy, this->core->lid, bad_vaddr ); 246 246 #endif … … 342 342 343 343 ////////////////////////////////////////////////////////////////////////////////////////// 344 // This staticfunction prints on the kernel terminal the saved context (core registers)344 // This function prints on the kernel terminal the saved context (core registers) 345 345 // and the thread state of a faulty thread. 346 346 ////////////////////////////////////////////////////////////////////////////////////////// 347 347 // @ this : pointer on faulty thread descriptor. 348 // @ uzone : pointer on register array.349 348 // @ error : EXCP_USER_ERROR or EXCP_KERNEL_PANIC 350 349 ////////////////////////////////////////////////////////////////////////////////////////// 351 350 static void hal_exception_dump( thread_t * this, 352 reg_t * uzone,353 351 error_t error ) 354 352 { 355 353 core_t * core = this->core; 356 354 process_t * process = this->process; 355 reg_t * uzone = this->uzone_current; 357 356 358 357 // get pointers on TXT0 chdev … … 399 398 uzone[UZ_S0], uzone[UZ_S1], uzone[UZ_S2], uzone[UZ_S3], uzone[UZ_S4] ); 400 399 401 nolock_printk("s5_21 %X s6_22 %X s7_23 %X s8_24 %X ra_25 %X\n",400 nolock_printk("s5_21 %X s6_22 %X s7_23 %X t8_24 %X t9_25 %X\n", 402 401 uzone[UZ_S5], uzone[UZ_S6], uzone[UZ_S7], uzone[UZ_T8], uzone[UZ_T9] ); 403 402 … … 508 507 if( error == EXCP_USER_ERROR ) // user error => kill user process 509 508 { 510 hal_exception_dump( this , uzone ,error );509 hal_exception_dump( this , error ); 511 510 512 511 sys_exit( EXIT_FAILURE ); … … 514 513 else if( error == EXCP_KERNEL_PANIC ) // kernel error => kernel panic 515 514 { 516 hal_exception_dump( this , uzone ,error );515 hal_exception_dump( this , error ); 517 516 518 517 hal_core_sleep(); -
trunk/hal/tsar_mips32/core/hal_special.c
r570 r619 25 25 #include <hal_kernel_types.h> 26 26 #include <hal_special.h> 27 #include <hal_exception.h> 27 28 #include <core.h> 28 29 #include <thread.h> … … 145 146 } 146 147 147 /////////////////////////// ///148 uint32_t hal_get_s tack( void )148 /////////////////////////// 149 uint32_t hal_get_sp( void ) 149 150 { 150 151 register uint32_t sp; … … 155 156 } 156 157 157 ///////////////////////////////////// ///158 uint32_t hal_set_s tack( void * new_val )158 ///////////////////////////////////// 159 uint32_t hal_set_sp( void * new_val ) 159 160 { 160 161 register uint32_t sp; … … 168 169 } 169 170 171 /////////////////////////// 172 uint32_t hal_get_ra( void ) 173 { 174 register uint32_t ra; 175 176 asm volatile ("or %0, $0, $31" : "=&r" (ra)); 177 178 return ra; 179 } 180 170 181 ////////////////////////////////// 171 182 uint32_t hal_get_bad_vaddr( void ) … … 216 227 void hal_core_sleep( void ) 217 228 { 229 thread_t * this = CURRENT_THREAD; 230 231 printk("\n*** thread[%x,%x] on core[%x,%d]/n" 232 " sr = %X / sp = %X / ra = %X\n", 233 this->process->pid, this->trdid, local_cxy, this->core->lid, 234 hal_get_sr(), hal_get_sp(), hal_get_ra() ); 235 218 236 while( 1 ) asm volatile ("nop"); 219 237 } -
trunk/hal/tsar_mips32/drivers/soclib_tty.c
r570 r619 131 131 #endif 132 132 133 #if( DEBUG_HAL_TXT_TX || DEBUG_HAL_TXT_RX ) 134 thread_t * this = CURRENT_THREAD; 135 #endif 136 133 137 // get TXT device cluster and pointers 134 138 xptr_t dev_xp = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) ); … … 160 164 161 165 #if DEBUG_HAL_TXT_TX 162 uint32_t tx_cycle = (uint32_t)hal_get_cycles();166 uint32_t tx_cycle = (uint32_t)hal_get_cycles(); 163 167 if( DEBUG_HAL_TXT_TX < tx_cycle ) 164 printk("\n[ DBG] %s : thread %xput character <%c> to TXT%d_TX fifo / cycle %d\n",165 __FUNCTION__, CURRENT_THREAD, byte, channel, tx_cycle );168 printk("\n[%s] thread[%x,%x] put character <%c> to TXT%d_TX fifo / cycle %d\n", 169 __FUNCTION__, this->process->pid, this->trdid, byte, channel, tx_cycle ); 166 170 #endif 167 171 // write byte to FIFO … … 195 199 } 196 200 /////////////////////////// 197 else if( type == TXT_READ ) // read bytes from TTY_RX FIFO201 else if( type == TXT_READ ) // read several bytes from TTY_RX FIFO 198 202 { 199 203 fifo = &tty_rx_fifo[channel]; … … 211 215 uint32_t rx_cycle = (uint32_t)hal_get_cycles(); 212 216 if( DEBUG_HAL_TXT_RX < rx_cycle ) 213 printk("\n[ DBG] %s : thread %xget character <%c> from TXT%d_RX fifo / cycle %d\n",214 __FUNCTION__, CURRENT_THREAD, byte, channel, rx_cycle );217 printk("\n[%s] thread[%x,%x] get character <%c> from TXT%d_RX fifo / cycle %d\n", 218 __FUNCTION__, this->process->pid, this->trdid, byte, channel, rx_cycle ); 215 219 #endif 216 220 // update FIFO state … … 328 332 #if DEBUG_HAL_TXT_RX 329 333 if( DEBUG_HAL_TXT_RX < rx_cycle ) 330 printk("\n[ DBG] %s :read ^Z character from TXT%d\n", __FUNCTION__, channel );334 printk("\n[%s] read ^Z character from TXT%d\n", __FUNCTION__, channel ); 331 335 #endif 332 336 // get pointers on TXT owner process in owner cluster … … 381 385 #if DEBUG_HAL_TXT_RX 382 386 if( DEBUG_HAL_TXT_RX < rx_cycle ) 383 printk("\n[ DBG] %s :read ^C character from TXT%d\n", __FUNCTION__, channel );387 printk("\n[%s] read ^C character from TXT%d\n", __FUNCTION__, channel ); 384 388 #endif 385 389 // get pointer on TXT owner process in owner cluster … … 434 438 #if DEBUG_HAL_TXT_RX 435 439 if( DEBUG_HAL_TXT_RX < rx_cycle ) 436 printk("\n[ DBG] %s :put character <%c> to TXT%d_RX fifo\n",440 printk("\n[%s] put character <%c> to TXT%d_RX fifo\n", 437 441 __FUNCTION__, byte, channel ); 438 442 #endif … … 481 485 #if DEBUG_HAL_TXT_TX 482 486 if( DEBUG_HAL_TXT_TX < tx_cycle ) 483 printk("\n[ DBG] %s :get character <%c> from TXT%d_TX fifo\n",487 printk("\n[%s] get character <%c> from TXT%d_TX fifo\n", 484 488 __FUNCTION__, byte, channel ); 485 489 #endif -
trunk/kernel/devices/dev_dma.c
r565 r619 63 63 error = thread_kernel_create( &new_thread, 64 64 THREAD_DEV, 65 &chdev_se quencial_server,65 &chdev_server_func, 66 66 dma, 67 67 cluster_select_local_core() ); -
trunk/kernel/devices/dev_ioc.c
r614 r619 71 71 error = thread_kernel_create( &new_thread, 72 72 THREAD_DEV, 73 &chdev_se quencial_server,73 &chdev_server_func, 74 74 ioc, 75 75 lid ); -
trunk/kernel/devices/dev_nic.c
r565 r619 70 70 error = thread_kernel_create( &new_thread, 71 71 THREAD_DEV, 72 &chdev_se quencial_server,72 &chdev_server_func, 73 73 nic, 74 74 lid ); -
trunk/kernel/devices/dev_txt.c
r565 r619 53 53 const char * dev_txt_type_str( dev_txt_cmd_t type ) 54 54 { 55 switch (type) { 56 case (TXT_SYNC_WRITE): return "TXT_SYNC_WRITE"; 57 case (TXT_READ): return "TXT_READ"; 58 case (TXT_WRITE): return "TXT_WRITE"; 59 default: return "undefined"; 60 } 55 switch (type) 56 { 57 case (TXT_SYNC_WRITE): return "TXT_SYNC_WRITE"; 58 case (TXT_READ): return "TXT_READ"; 59 case (TXT_WRITE): return "TXT_WRITE"; 60 default: return "undefined"; 61 } 61 62 } 62 63 … … 115 116 error = thread_kernel_create( &new_thread, 116 117 THREAD_DEV, 117 &chdev_se quencial_server,118 &chdev_server_func, 118 119 txt, 119 120 lid ); … … 178 179 179 180 #if DEBUG_DEV_TXT_TX 180 uint32_t cycle = (uint32_t)hal_get_cycles(); 181 thread_t * this = CURRENT_THREAD; 182 uint32_t cycle = (uint32_t)hal_get_cycles(); 181 183 if( DEBUG_DEV_TXT_TX < cycle ) 182 printk("\n[DBG] %s : thread %x enters / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle ); 184 printk("\n[%s] thread[%x,%x] enters / cycle %d\n", 185 __FUNCTION__, this->process->pid, this->trdid, cycle ); 183 186 #endif 184 187 … … 194 197 195 198 // If we use MTTYs (vci_multi_tty), we perform only sync writes 199 // Otherwise, we use vci_tty_tsar so we can use async writes 200 196 201 if( dev_ptr->impl == IMPL_TXT_MTY ) 197 202 { … … 212 217 } 213 218 214 // Otherwise, we use vci_tty_tsar so we can use async writes215 219 else 216 220 { 217 return dev_txt_access( TXT_WRITE , channel , buffer , count );221 return dev_txt_access( TXT_WRITE , channel , buffer , count ); 218 222 } 219 223 … … 221 225 cycle = (uint32_t)hal_get_cycles(); 222 226 if( DEBUG_DEV_TXT_TX < cycle ) 223 printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle ); 227 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 228 __FUNCTION__, this->process->pid, this->trdid, cycle ); 224 229 #endif 225 230 … … 240 245 241 246 #if DEBUG_DEV_TXT_RX 242 uint32_t cycle = (uint32_t)hal_get_cycles(); 247 thread_t * this = CURRENT_THREAD; 248 uint32_t cycle = (uint32_t)hal_get_cycles(); 243 249 if( DEBUG_DEV_TXT_RX < cycle ) 244 printk("\n[DBG] %s : thread %x enters / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle ); 250 printk("\n[%s] thread[%x,%x] enters / cycle %d\n", 251 __FUNCTION__, this->process->pid, this->trdid, cycle ); 245 252 #endif 246 253 … … 250 257 cycle = (uint32_t)hal_get_cycles(); 251 258 if( DEBUG_DEV_TXT_RX < cycle ) 252 printk("\n[DBG] %s : thread %x exit / cycle %d\n", __FUNCTION__, CURRENT_THREAD, cycle ); 259 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 260 __FUNCTION__, this->process->pid, this->trdid, cycle ); 253 261 #endif 254 262 -
trunk/kernel/kern/chdev.c
r601 r619 168 168 169 169 #if (DEBUG_CHDEV_CMD_RX || DEBUG_CHDEV_CMD_TX) 170 bool_t is_rx = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->is_rx ) ); 170 bool_t is_rx = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->is_rx ) ); 171 trdid_t server_trdid = hal_remote_l32( XPTR( chdev_cxy , &server_ptr->trdid ) ); 172 process_t * process_ptr = hal_remote_lpt( XPTR( chdev_cxy , &server_ptr->process ) ); 173 pid_t server_pid = hal_remote_l32( XPTR( chdev_cxy , &process_ptr->pid ) ); 171 174 #endif 172 175 … … 175 178 if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) ) 176 179 printk("\n[%s] client[%x,%x] enter for RX / server[%x,%x] / cycle %d\n", 177 __FUNCTION__, this->process->pid, this->trdid, 178 server_ptr->process->pid, server_ptr->trdid, rx_cycle ); 180 __FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, rx_cycle ); 179 181 #endif 180 182 … … 183 185 if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) ) 184 186 printk("\n[%s] client[%x,%x] enter for TX / server[%x,%x] / cycle %d\n", 185 __FUNCTION__, this->process->pid, this->trdid, 186 server_ptr->process->pid, server_ptr->trdid, tx_cycle ); 187 __FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, tx_cycle ); 187 188 #endif 188 189 … … 241 242 if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) ) 242 243 printk("\n[%s] TX server thread[%x,%x] unblocked\n", 243 __FUNCTION__, server_p tr->process->pid, server_ptr->trdid );244 __FUNCTION__, server_pid, server_trdid ); 244 245 #endif 245 246 … … 247 248 if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) ) 248 249 printk("\n[%s] RX server thread[%x,%x] unblocked\n", 249 __FUNCTION__, server_p tr->process->pid, server_ptr->trdid );250 __FUNCTION__, server_pid, server_trdid ); 250 251 #endif 251 252 … … 273 274 if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) ) 274 275 printk("\n[%s] client thread[%x,%x] sent IPI to TX server thread[%x,%x]\n", 275 __FUNCTION__, this->process->pid, this->trdid, server_p tr->process->pid, server_ptr->trdid );276 __FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid ); 276 277 #endif 277 278 … … 279 280 if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) ) 280 281 printk("\n[%s] client thread[%x,%x] sent IPI to RX server thread[%x,%x]\n", 281 __FUNCTION__, this->process->pid, this->trdid, server_p tr->process->pid, server_ptr->trdid );282 __FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid ); 282 283 #endif 283 284 … … 317 318 } // end chdev_register_command() 318 319 319 ///////////////////////////////////////// //////320 void chdev_se quencial_server( chdev_t * chdev )320 ///////////////////////////////////////// 321 void chdev_server_func( chdev_t * chdev ) 321 322 { 322 323 xptr_t client_xp; // extended pointer on waiting thread … … 340 341 { 341 342 342 #if DEBUG_CHDEV_SERVER_RX343 #if( DEBUG_CHDEV_SERVER_RX || DEBUG_CHDEV_SERVER_TX ) 343 344 uint32_t rx_cycle = (uint32_t)hal_get_cycles(); 344 345 if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) ) 345 printk("\n[%s] thread[%x,%x] start RX/ cycle %d\n",346 __FUNCTION__ , server->process->pid, server->trdid, rx_cycle );346 printk("\n[%s] DEV thread[%x,%x] check TXT_RX channel %d / cycle %d\n", 347 __FUNCTION__ , server->process->pid, server->trdid, chdev->channel, rx_cycle ); 347 348 #endif 348 349 … … 350 351 uint32_t tx_cycle = (uint32_t)hal_get_cycles(); 351 352 if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) ) 352 printk("\n[%s] thread[%x,%x] start TX/ cycle %d\n",353 __FUNCTION__ , server->process->pid, server->trdid, tx_cycle );353 printk("\n[%s] thread[%x,%x] check TXT_TX channel %d / cycle %d\n", 354 __FUNCTION__ , server->process->pid, server->trdid, chdev->channel, tx_cycle ); 354 355 #endif 355 356 … … 397 398 client_ptr = GET_PTR( client_xp ); 398 399 399 #if( D DEBUG_CHDEV_SERVER_TX || DEBUG_CHDEV_SERVER_RX )400 #if( DEBUG_CHDEV_SERVER_TX || DEBUG_CHDEV_SERVER_RX ) 400 401 process_t * process = hal_remote_lpt( XPTR( client_cxy , &client_ptr->process ) ); 401 402 pid_t client_pid = hal_remote_l32( XPTR( client_cxy , &process->pid ) ); 402 process_tclient_trdid = hal_remote_l32( XPTR( client_cxy , &client_ptr->trdid ) );403 trdid_t client_trdid = hal_remote_l32( XPTR( client_cxy , &client_ptr->trdid ) ); 403 404 #endif 404 405 … … 407 408 if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) ) 408 409 printk("\n[%s] thread[%x,%x] for RX get client thread[%x,%x] / cycle %d\n", 409 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, cycle );410 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle ); 410 411 #endif 411 412 … … 414 415 if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) ) 415 416 printk("\n[%s] thread[%x,%x] for TX get client thread[%x,%x] / cycle %d\n", 416 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, cycle );417 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tx_cycle ); 417 418 #endif 418 419 … … 445 446 if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) ) 446 447 printk("\n[%s] thread[%x,%x] completes RX for client thread[%x,%x] / cycle %d\n", 447 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, cycle );448 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle ); 448 449 #endif 449 450 … … 452 453 if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) ) 453 454 printk("\n[%s] thread[%x,%x] completes TX for client thread[%x,%x] / cycle %d\n", 454 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, cycle );455 __FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tX_cycle ); 455 456 #endif 456 457 … … 465 466 } 466 467 } // end while 467 } // end chdev_se quencial_server()468 } // end chdev_server_func() 468 469 469 470 //////////////////////////////////////// -
trunk/kernel/kern/chdev.h
r564 r619 240 240 * @ chdev : local pointer on device descriptor. 241 241 *****************************************************************************************/ 242 void chdev_se quencial_server( chdev_t * chdev );242 void chdev_server_func( chdev_t * chdev ); 243 243 244 244 /****************************************************************************************** -
trunk/kernel/kern/kernel_init.c
r614 r619 154 154 "CONDVAR_STATE", // 17 155 155 "SEM_STATE", // 18 156 "RPOCESS_CWD", // 19 157 158 "unused_20", // 20 156 "PROCESS_CWD", // 19 157 "BARRIER_STATE", // 20 159 158 160 159 "CLUSTER_PREFTBL", // 21 -
trunk/kernel/kern/process.c
r618 r619 528 528 process_t * process_ptr; // local pointer on process copy 529 529 reg_t save_sr; // for critical section 530 rpc_desc_t rpc; // shared RPC descriptor531 530 thread_t * client; // pointer on client thread 532 531 xptr_t client_xp; // extended pointer on client thread 533 532 process_t * local; // pointer on process copy in local cluster 534 533 uint32_t remote_nr; // number of remote process copies 534 rpc_desc_t rpc; // shared RPC descriptor 535 uint32_t responses; // shared RPC responses counter 535 536 536 537 client = CURRENT_THREAD; … … 579 580 thread_block( client_xp , THREAD_BLOCKED_RPC ); 580 581 582 // initialize RPC responses counter 583 responses = 0; 584 581 585 // initialize shared RPC descriptor 582 rpc.responses = 0; 586 // can be shared, because no out arguments 587 rpc.rsp = &responses; 583 588 rpc.blocking = false; 584 589 rpc.index = RPC_PROCESS_SIGACTION; … … 608 613 remote_nr++; 609 614 610 // atomically increment responses counter611 hal_atomic_add( (void *)&rpc.responses , 1 );615 // atomically increment RPC responses counter 616 hal_atomic_add( &responses , 1 ); 612 617 613 618 #if DEBUG_PROCESS_SIGACTION … … 617 622 #endif 618 623 // call RPC in target cluster 619 rpc_ process_sigaction_client( process_cxy , &rpc );624 rpc_send( process_cxy , &rpc ); 620 625 } 621 626 } // end list of copies … … 685 690 686 691 // check target process is an user process 687 assert( (LPID_FROM_PID( process->pid ) != 0 ), "target process must be an user process" ); 692 assert( (LPID_FROM_PID( process->pid ) != 0 ), 693 "process %x is not an user process\n", process->pid ); 688 694 689 695 // get target process owner cluster … … 773 779 774 780 // check target process is an user process 775 assert( (LPID_FROM_PID( process->pid ) != 0), "process %x not an user process", process->pid ); 781 assert( (LPID_FROM_PID( process->pid ) != 0), 782 "process %x is not an user process\n", process->pid ); 776 783 777 784 // get lock protecting process th_tbl[] … … 831 838 832 839 // check target process is an user process 833 assert( ( process->pid!= 0 ),834 " target process must be an user process");840 assert( ( LPID_FROM_PID( process->pid ) != 0 ), 841 "process %x is not an user process\n", process->pid ); 835 842 836 843 // get lock protecting process th_tbl[] -
trunk/kernel/kern/rpc.c
r614 r619 143 143 client_core_lid = this->core->lid; 144 144 145 // check calling thread can yield when client threadis not the IDLE thread145 // check calling thread can yield when is not the IDLE thread 146 146 // RPCs executed by the IDLE thread during kernel_init do not deschedule 147 147 if( this->type != THREAD_IDLE ) thread_assert_can_yield( this , __FUNCTION__ ); … … 184 184 while( full ); 185 185 186 hal_fence();187 188 186 #if DEBUG_RPC_CLIENT_GENERIC 189 187 uint32_t cycle = (uint32_t)hal_get_cycles(); … … 199 197 200 198 // wait RPC completion before returning if blocking RPC : 201 // - deschedul ingwithout blocking if thread idle (in kernel init)199 // - deschedule without blocking if thread idle (in kernel init) 202 200 // - block and deschedule policy for any other thread 203 201 if ( rpc->blocking ) … … 212 210 __FUNCTION__, this->process->pid, this->trdid, rpc_str[rpc->index], cycle ); 213 211 #endif 214 215 while( rpc->responses ) sched_yield( "busy waiting on RPC"); 216 212 while( 1 ) 213 { 214 // check responses counter 215 if( hal_remote_l32( XPTR( local_cxy , rpc->rsp ) ) == 0 ) break; 216 217 // deschedule 218 sched_yield("busy_waiting RPC completion"); 219 } 220 217 221 #if DEBUG_RPC_CLIENT_GENERIC 218 222 cycle = (uint32_t)hal_get_cycles(); … … 242 246 cycle = (uint32_t)hal_get_cycles(); 243 247 if( DEBUG_RPC_CLIENT_GENERIC < cycle ) 244 printk("\n[%s] thread[%x,%x] resumes for rpc %s / cycle %d\n",248 printk("\n[%s] thread[%x,%x] resumes after rpc %s / cycle %d\n", 245 249 __FUNCTION__, this->process->pid, this->trdid, rpc_str[rpc->index], cycle ); 246 250 #endif … … 248 252 249 253 // response must be available for a blocking RPC 250 assert( ( rpc->responses== 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] );254 assert( (*rpc->rsp == 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] ); 251 255 252 256 } … … 270 274 271 275 //////////////////////////// 272 void rpc_ thread_func( void )276 void rpc_server_func( void ) 273 277 { 274 278 error_t empty; // local RPC fifo state … … 278 282 uint32_t index; // RPC request index 279 283 thread_t * client_ptr; // local pointer on client thread 284 xptr_t client_xp; // extended pointer on client thread 285 lid_t client_lid; // local index of client core 280 286 thread_t * server_ptr; // local pointer on server thread 281 287 xptr_t server_xp; // extended pointer on server thread 282 lid_t client_core_lid; // local index of client core 283 lid_t server_core_lid; // local index of server core 284 bool_t blocking; // blocking RPC when true 288 lid_t server_lid; // local index of server core 285 289 remote_fifo_t * rpc_fifo; // local pointer on RPC fifo 286 uint32_t count; // current number of expected responses 287 290 uint32_t * rsp_ptr; // local pointer on responses counter 291 xptr_t rsp_xp; // extended pointer on responses counter 292 uint32_t responses; // number of expected responses 293 288 294 // makes RPC thread not preemptable 289 295 hal_disable_irq( NULL ); … … 291 297 server_ptr = CURRENT_THREAD; 292 298 server_xp = XPTR( local_cxy , server_ptr ); 293 server_ core_lid= server_ptr->core->lid;294 rpc_fifo = &LOCAL_CLUSTER->rpc_fifo[server_ core_lid];299 server_lid = server_ptr->core->lid; 300 rpc_fifo = &LOCAL_CLUSTER->rpc_fifo[server_lid]; 295 301 296 302 // "infinite" RPC thread loop … … 305 311 if( DEBUG_RPC_SERVER_GENERIC < cycle ) 306 312 printk("\n[%s] RPC thread[%x,%x] on core[%d] takes RPC_FIFO ownership / cycle %d\n", 307 __FUNCTION__, server_ptr->process->pid, server_ptr->trdid, server_ core_lid, cycle );313 __FUNCTION__, server_ptr->process->pid, server_ptr->trdid, server_lid, cycle ); 308 314 #endif 309 315 // try to consume one RPC request … … 320 326 desc_ptr = GET_PTR( desc_xp ); 321 327 328 // get relevant infos from RPC descriptor 322 329 index = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->index ) ); 323 blocking = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->blocking ) );324 330 client_ptr = hal_remote_lpt( XPTR( desc_cxy , &desc_ptr->thread ) ); 331 rsp_ptr = hal_remote_lpt( XPTR( desc_cxy , &desc_ptr->rsp ) ); 332 client_lid = hal_remote_l32( XPTR( desc_cxy , &desc_ptr->lid ) ); 333 334 rsp_xp = XPTR( desc_cxy , rsp_ptr ); 335 client_xp = XPTR( desc_cxy , client_ptr ); 325 336 326 337 #if DEBUG_RPC_SERVER_GENERIC … … 332 343 #endif 333 344 // register client thread in RPC thread descriptor 334 server_ptr->rpc_client_xp = XPTR( desc_cxy , client_ptr );345 server_ptr->rpc_client_xp = client_xp; 335 346 336 347 // call the relevant server function … … 343 354 __FUNCTION__, server_ptr->process->pid, server_ptr->trdid, rpc_str[index], desc_cxy, cycle ); 344 355 #endif 345 // decrement expected responses counter in RPC descriptor346 count = hal_remote_atomic_add( XPTR( desc_cxy, &desc_ptr->responses ), -1 );347 348 // decrement response counter in RPC descriptorif last response349 if( count== 1 )356 // decrement expected responses counter 357 responses = hal_remote_atomic_add( rsp_xp , -1 ); 358 359 // unblock client thread if last response 360 if( responses == 1 ) 350 361 { 351 // get client thread pointer and client core lid from RPC descriptor352 client_ptr = hal_remote_lpt( XPTR( desc_cxy , &desc_ptr->thread ) );353 client_core_lid = hal_remote_l32 ( XPTR( desc_cxy , &desc_ptr->lid ) );354 355 362 // unblock client thread 356 thread_unblock( XPTR( desc_cxy , client_ptr ), THREAD_BLOCKED_RPC );363 thread_unblock( client_xp , THREAD_BLOCKED_RPC ); 357 364 358 365 hal_fence(); … … 360 367 #if DEBUG_RPC_SERVER_GENERIC 361 368 cycle = (uint32_t)hal_get_cycles(); 369 trdid_t client_trdid = hal_remote_l32( XPTR( desc_cxy , &client_ptr->trdid ) ); 370 process_t * process = hal_remote_lpt( XPTR( desc_cxy , &client_ptr->process ) ); 371 pid_t client_pid = hal_remote_l32( XPTR( desc_cxy , &process->pid ) ); 362 372 if( DEBUG_RPC_SERVER_GENERIC < cycle ) 363 373 printk("\n[%s] RPC thread[%x,%x] unblocked client thread[%x,%x] / cycle %d\n", 364 374 __FUNCTION__, server_ptr->process->pid, server_ptr->trdid, 365 client_p tr->process->pid, client_ptr->trdid, cycle );375 client_pid, client_trdid, cycle ); 366 376 #endif 367 377 // send IPI to client core 368 dev_pic_send_ipi( desc_cxy , client_ core_lid );378 dev_pic_send_ipi( desc_cxy , client_lid ); 369 379 } 370 380 } // end RPC handling if fifo non empty … … 372 382 373 383 // sucide if too many RPC threads 374 if( LOCAL_CLUSTER->rpc_threads[server_ core_lid] >= CONFIG_RPC_THREADS_MAX )384 if( LOCAL_CLUSTER->rpc_threads[server_lid] >= CONFIG_RPC_THREADS_MAX ) 375 385 { 376 386 … … 382 392 #endif 383 393 // update RPC threads counter 384 hal_atomic_add( &LOCAL_CLUSTER->rpc_threads[server_ core_lid] , -1 );394 hal_atomic_add( &LOCAL_CLUSTER->rpc_threads[server_lid] , -1 ); 385 395 386 396 // RPC thread blocks on GLOBAL … … 397 407 uint32_t cycle = (uint32_t)hal_get_cycles(); 398 408 if( DEBUG_RPC_SERVER_GENERIC < cycle ) 399 printk("\n[%s] RPC thread[%x,%x] block IDLE& deschedules / cycle %d\n",409 printk("\n[%s] RPC thread[%x,%x] blocks & deschedules / cycle %d\n", 400 410 __FUNCTION__, server_ptr->process->pid, server_ptr->trdid, cycle ); 401 411 #endif … … 407 417 } 408 418 } // end infinite loop 409 } // end rpc_thread_func() 419 420 } // end rpc_server_func() 410 421 411 422 … … 427 438 #endif 428 439 429 assert( (cxy != local_cxy) , "server cluster is not remote\n");440 uint32_t responses = 1; 430 441 431 442 // initialise RPC descriptor header … … 433 444 rpc.index = RPC_PMEM_GET_PAGES; 434 445 rpc.blocking = true; 435 rpc.r esponses = 1;446 rpc.rsp = &responses; 436 447 437 448 // set input arguments in RPC descriptor … … 485 496 486 497 ///////////////////////////////////////////////////////////////////////////////////////// 487 // [1] Marshaling functions attached to RPC_PMEM_RELEASE_PAGES (blocking)498 // [1] Marshaling functions attached to RPC_PMEM_RELEASE_PAGES 488 499 ///////////////////////////////////////////////////////////////////////////////////////// 489 500 … … 500 511 #endif 501 512 502 assert( (cxy != local_cxy) , "server cluster is not remote\n");513 uint32_t responses = 1; 503 514 504 515 // initialise RPC descriptor header … … 506 517 rpc.index = RPC_PMEM_RELEASE_PAGES; 507 518 rpc.blocking = true; 508 rpc.r esponses = 1;519 rpc.rsp = &responses; 509 520 510 521 // set input arguments in RPC descriptor … … 559 570 560 571 ///////////////////////////////////////////////////////////////////////////////////////// 561 // [3] Marshaling functions attached to RPC_PROCESS_MAKE_FORK (blocking)572 // [3] Marshaling functions attached to RPC_PROCESS_MAKE_FORK 562 573 ///////////////////////////////////////////////////////////////////////////////////////// 563 574 … … 578 589 #endif 579 590 580 assert( (cxy != local_cxy) , "server cluster is not remote\n");591 uint32_t responses = 1; 581 592 582 593 // initialise RPC descriptor header … … 584 595 rpc.index = RPC_PROCESS_MAKE_FORK; 585 596 rpc.blocking = true; 586 rpc.r esponses = 1;597 rpc.rsp = &responses; 587 598 588 599 // set input arguments in RPC descriptor … … 651 662 652 663 ///////////////////////////////////////////////////////////////////////////////////////// 653 // [4] Marshaling functions attached to RPC_USER_DIR_CREATE (blocking)664 // [4] Marshaling functions attached to RPC_USER_DIR_CREATE 654 665 ///////////////////////////////////////////////////////////////////////////////////////// 655 666 … … 668 679 #endif 669 680 670 assert( (cxy != local_cxy) , "server cluster is not remote\n");681 uint32_t responses = 1; 671 682 672 683 // initialise RPC descriptor header … … 674 685 rpc.index = RPC_USER_DIR_CREATE; 675 686 rpc.blocking = true; 676 rpc.r esponses = 1;687 rpc.rsp = &responses; 677 688 678 689 // set input arguments in RPC descriptor … … 732 743 733 744 ///////////////////////////////////////////////////////////////////////////////////////// 734 // [5] Marshaling functions attached to RPC_USER_DIR_DESTROY (blocking)745 // [5] Marshaling functions attached to RPC_USER_DIR_DESTROY 735 746 ///////////////////////////////////////////////////////////////////////////////////////// 736 747 … … 748 759 #endif 749 760 750 assert( (cxy != local_cxy) , "server cluster is not remote\n");761 uint32_t responses = 1; 751 762 752 763 // initialise RPC descriptor header … … 754 765 rpc.index = RPC_USER_DIR_DESTROY; 755 766 rpc.blocking = true; 756 rpc.r esponses = 1;767 rpc.rsp = &responses; 757 768 758 769 // set input arguments in RPC descriptor … … 805 816 806 817 ///////////////////////////////////////////////////////////////////////////////////////// 807 // [6] Marshaling functions attached to RPC_THREAD_USER_CREATE (blocking)818 // [6] Marshaling functions attached to RPC_THREAD_USER_CREATE 808 819 ///////////////////////////////////////////////////////////////////////////////////////// 809 820 … … 824 835 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle ); 825 836 #endif 826 827 assert( (cxy != local_cxy) , "server cluster is not remote\n");837 838 uint32_t responses = 1; 828 839 829 840 // initialise RPC descriptor header … … 831 842 rpc.index = RPC_THREAD_USER_CREATE; 832 843 rpc.blocking = true; 833 rpc.r esponses = 1;844 rpc.rsp = &responses; 834 845 835 846 // set input arguments in RPC descriptor … … 929 940 #endif 930 941 931 assert( (cxy != local_cxy) , "server cluster is not remote\n");942 uint32_t responses = 1; 932 943 933 944 // initialise RPC descriptor header … … 935 946 rpc.index = RPC_THREAD_KERNEL_CREATE; 936 947 rpc.blocking = true; 937 rpc.r esponses = 1;948 rpc.rsp = &responses; 938 949 939 950 // set input arguments in RPC descriptor … … 1007 1018 1008 1019 ///////////////////////////////////////////////////////////////////////////////////////// 1009 // [9] Marshaling functions attached to RPC_PROCESS_SIGACTION (non blocking)1020 // [9] Marshaling functions attached to RPC_PROCESS_SIGACTION 1010 1021 ///////////////////////////////////////////////////////////////////////////////////////// 1011 1022 1012 1023 //////////////////////////////////////////////////// 1013 1024 void rpc_process_sigaction_client( cxy_t cxy, 1014 rpc_desc_t * rpc ) 1025 pid_t pid, 1026 uint32_t action ) 1015 1027 { 1016 1028 #if DEBUG_RPC_PROCESS_SIGACTION … … 1018 1030 thread_t * this = CURRENT_THREAD; 1019 1031 if( DEBUG_RPC_PROCESS_SIGACTION < cycle ) 1020 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n", 1021 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle ); 1022 #endif 1023 1024 // check RPC "index" and "blocking" arguments 1025 assert( (rpc->blocking == false) , "must be non-blocking\n"); 1026 assert( (rpc->index == RPC_PROCESS_SIGACTION ) , "bad RPC index\n" ); 1027 1028 // register RPC request in remote RPC fifo and return 1029 rpc_send( cxy , rpc ); 1032 printk("\n[%s] thread[%x,%x] on core %d : enter to %s process %x / cycle %d\n", 1033 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, 1034 process_action_str( action ), pid, cycle ); 1035 #endif 1036 1037 uint32_t responses = 1; 1038 rpc_desc_t rpc; 1039 1040 // initialise RPC descriptor header 1041 rpc.index = RPC_PROCESS_SIGACTION; 1042 rpc.blocking = true; 1043 rpc.rsp = &responses; 1044 1045 // set input arguments in RPC descriptor 1046 rpc.args[0] = (uint64_t)pid; 1047 rpc.args[1] = (uint64_t)action; 1048 1049 // register RPC request in remote RPC fifo 1050 rpc_send( cxy , &rpc ); 1030 1051 1031 1052 #if DEBUG_RPC_PROCESS_SIGACTION 1032 1053 cycle = (uint32_t)hal_get_cycles(); 1033 1054 if( DEBUG_RPC_PROCESS_SIGACTION < cycle ) 1034 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 1035 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle ); 1055 printk("\n[%s] thread[%x,%x] on core %d : exit after %s process %x / cycle %d\n", 1056 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, 1057 process_action_str( action ), pid, cycle ); 1036 1058 #endif 1037 1059 } // end rpc_process_sigaction_client() … … 1040 1062 void rpc_process_sigaction_server( xptr_t xp ) 1041 1063 { 1042 #if DEBUG_RPC_PROCESS_SIGACTION1043 uint32_t cycle = (uint32_t)hal_get_cycles();1044 thread_t * this = CURRENT_THREAD;1045 if( DEBUG_RPC_PROCESS_SIGACTION < cycle )1046 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n",1047 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle );1048 #endif1049 1050 1064 // get client cluster identifier and pointer on RPC descriptor 1051 1065 cxy_t client_cxy = GET_CXY( xp ); … … 1056 1070 uint32_t action = (uint32_t)hal_remote_l64( XPTR(client_cxy , &desc->args[1]) ); 1057 1071 1072 #if DEBUG_RPC_PROCESS_SIGACTION 1073 uint32_t cycle = (uint32_t)hal_get_cycles(); 1074 thread_t * this = CURRENT_THREAD; 1075 if( DEBUG_RPC_PROCESS_SIGACTION < cycle ) 1076 printk("\n[%s] thread[%x,%x] on core %d : enter to %s process %x / cycle %d\n", 1077 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, 1078 process_action_str( action ), pid, cycle ); 1079 #endif 1080 1058 1081 // get client thread pointers 1059 1082 thread_t * client_ptr = hal_remote_lpt( XPTR( client_cxy , &desc->thread ) ); … … 1063 1086 process_t * process = cluster_get_local_process_from_pid( pid ); 1064 1087 1065 // call relevant kernel function 1066 if ( action == DELETE_ALL_THREADS ) process_delete_threads ( process , client_xp ); 1067 else if ( action == BLOCK_ALL_THREADS ) process_block_threads ( process ); 1068 else if ( action == UNBLOCK_ALL_THREADS ) process_unblock_threads( process ); 1088 // call relevant kernel function if found / does nothing if not found 1089 if( process != NULL ) 1090 { 1091 if ( action == DELETE_ALL_THREADS ) process_delete_threads ( process , client_xp ); 1092 if ( action == BLOCK_ALL_THREADS ) process_block_threads ( process ); 1093 if ( action == UNBLOCK_ALL_THREADS ) process_unblock_threads( process ); 1094 } 1069 1095 1070 1096 #if DEBUG_RPC_PROCESS_SIGACTION 1071 1097 cycle = (uint32_t)hal_get_cycles(); 1072 1098 if( DEBUG_RPC_PROCESS_SIGACTION < cycle ) 1073 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 1074 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, cycle ); 1099 printk("\n[%s] thread[%x,%x] on core %d : exit after %s process %x / cycle %d\n", 1100 __FUNCTION__, this->process->pid, this->trdid, this->core->lid, 1101 process_action_str( action ), pid, cycle ); 1075 1102 #endif 1076 1103 } // end rpc_process_sigaction_server() 1077 1104 1078 1105 ///////////////////////////////////////////////////////////////////////////////////////// 1079 // [10] Marshaling functions attached to RPC_VFS_INODE_CREATE (blocking)1106 // [10] Marshaling functions attached to RPC_VFS_INODE_CREATE 1080 1107 ///////////////////////////////////////////////////////////////////////////////////////// 1081 1108 … … 1099 1126 #endif 1100 1127 1101 assert( (cxy != local_cxy) , "server cluster is not remote\n");1128 uint32_t responses = 1; 1102 1129 1103 1130 // initialise RPC descriptor header … … 1105 1132 rpc.index = RPC_VFS_INODE_CREATE; 1106 1133 rpc.blocking = true; 1107 rpc.r esponses = 1;1134 rpc.rsp = &responses; 1108 1135 1109 1136 // set input arguments in RPC descriptor … … 1184 1211 1185 1212 ///////////////////////////////////////////////////////////////////////////////////////// 1186 // [11] Marshaling functions attached to RPC_VFS_INODE_DESTROY (blocking)1213 // [11] Marshaling functions attached to RPC_VFS_INODE_DESTROY 1187 1214 ///////////////////////////////////////////////////////////////////////////////////////// 1188 1215 … … 1199 1226 #endif 1200 1227 1201 assert( (cxy != local_cxy) , "server cluster is not remote\n");1228 uint32_t responses = 1; 1202 1229 1203 1230 // initialise RPC descriptor header … … 1205 1232 rpc.index = RPC_VFS_INODE_DESTROY; 1206 1233 rpc.blocking = true; 1207 rpc.r esponses = 1;1234 rpc.rsp = &responses; 1208 1235 1209 1236 // set input arguments in RPC descriptor … … 1253 1280 1254 1281 ///////////////////////////////////////////////////////////////////////////////////////// 1255 // [12] Marshaling functions attached to RPC_VFS_DENTRY_CREATE (blocking)1282 // [12] Marshaling functions attached to RPC_VFS_DENTRY_CREATE 1256 1283 ///////////////////////////////////////////////////////////////////////////////////////// 1257 1284 … … 1271 1298 #endif 1272 1299 1273 assert( (cxy != local_cxy) , "server cluster is not remote\n");1300 uint32_t responses = 1; 1274 1301 1275 1302 // initialise RPC descriptor header … … 1277 1304 rpc.index = RPC_VFS_DENTRY_CREATE; 1278 1305 rpc.blocking = true; 1279 rpc.r esponses = 1;1306 rpc.rsp = &responses; 1280 1307 1281 1308 // set input arguments in RPC descriptor … … 1344 1371 1345 1372 ///////////////////////////////////////////////////////////////////////////////////////// 1346 // [13] Marshaling functions attached to RPC_VFS_DENTRY_DESTROY (blocking)1373 // [13] Marshaling functions attached to RPC_VFS_DENTRY_DESTROY 1347 1374 ///////////////////////////////////////////////////////////////////////////////////////// 1348 1375 … … 1359 1386 #endif 1360 1387 1361 assert( (cxy != local_cxy) , "server cluster is not remote\n");1388 uint32_t responses = 1; 1362 1389 1363 1390 // initialise RPC descriptor header … … 1365 1392 rpc.index = RPC_VFS_DENTRY_DESTROY; 1366 1393 rpc.blocking = true; 1367 rpc.r esponses = 1;1394 rpc.rsp = &responses; 1368 1395 1369 1396 // set input arguments in RPC descriptor … … 1414 1441 1415 1442 ///////////////////////////////////////////////////////////////////////////////////////// 1416 // [14] Marshaling functions attached to RPC_VFS_FILE_CREATE (blocking)1443 // [14] Marshaling functions attached to RPC_VFS_FILE_CREATE 1417 1444 ///////////////////////////////////////////////////////////////////////////////////////// 1418 1445 … … 1432 1459 #endif 1433 1460 1434 assert( (cxy != local_cxy) , "server cluster is not remote\n");1461 uint32_t responses = 1; 1435 1462 1436 1463 // initialise RPC descriptor header … … 1438 1465 rpc.index = RPC_VFS_FILE_CREATE; 1439 1466 rpc.blocking = true; 1440 rpc.r esponses = 1;1467 rpc.rsp = &responses; 1441 1468 1442 1469 // set input arguments in RPC descriptor … … 1501 1528 1502 1529 ///////////////////////////////////////////////////////////////////////////////////////// 1503 // [15] Marshaling functions attached to RPC_VFS_FILE_DESTROY (blocking)1530 // [15] Marshaling functions attached to RPC_VFS_FILE_DESTROY 1504 1531 ///////////////////////////////////////////////////////////////////////////////////////// 1505 1532 … … 1516 1543 #endif 1517 1544 1518 assert( (cxy != local_cxy) , "server cluster is not remote\n");1545 uint32_t responses = 1; 1519 1546 1520 1547 // initialise RPC descriptor header … … 1522 1549 rpc.index = RPC_VFS_FILE_DESTROY; 1523 1550 rpc.blocking = true; 1524 rpc.r esponses = 1;1551 rpc.rsp = &responses; 1525 1552 1526 1553 // set input arguments in RPC descriptor … … 1570 1597 1571 1598 ///////////////////////////////////////////////////////////////////////////////////////// 1572 // [16] Marshaling functions attached to RPC_VFS_FS_GET_DENTRY (blocking)1599 // [16] Marshaling functions attached to RPC_VFS_FS_GET_DENTRY 1573 1600 ///////////////////////////////////////////////////////////////////////////////////////// 1574 1601 … … 1588 1615 #endif 1589 1616 1590 assert( (cxy != local_cxy) , "server cluster is not remote\n");1617 uint32_t responses = 1; 1591 1618 1592 1619 // initialise RPC descriptor header … … 1594 1621 rpc.index = RPC_VFS_FS_GET_DENTRY; 1595 1622 rpc.blocking = true; 1596 rpc.r esponses = 1;1623 rpc.rsp = &responses; 1597 1624 1598 1625 // set input arguments in RPC descriptor … … 1661 1688 1662 1689 ///////////////////////////////////////////////////////////////////////////////////////// 1663 // [17] Marshaling function attached to RPC_VFS_FS_ADD_DENTRY (blocking)1690 // [17] Marshaling function attached to RPC_VFS_FS_ADD_DENTRY 1664 1691 ///////////////////////////////////////////////////////////////////////////////////////// 1665 1692 … … 1677 1704 #endif 1678 1705 1679 assert( (cxy != local_cxy) , "server cluster is not remote\n");1706 uint32_t responses = 1; 1680 1707 1681 1708 // initialise RPC descriptor header … … 1683 1710 rpc.index = RPC_VFS_FS_ADD_DENTRY; 1684 1711 rpc.blocking = true; 1685 rpc.r esponses = 1;1712 rpc.rsp = &responses; 1686 1713 1687 1714 // set input arguments in RPC descriptor … … 1703 1730 } 1704 1731 1705 ////////////////////////////////////////////// ///1732 ////////////////////////////////////////////// 1706 1733 void rpc_vfs_fs_add_dentry_server( xptr_t xp ) 1707 1734 { … … 1741 1768 1742 1769 ///////////////////////////////////////////////////////////////////////////////////////// 1743 // [18] Marshaling function attached to RPC_VFS_FS_REMOVE_DENTRY (blocking)1770 // [18] Marshaling function attached to RPC_VFS_FS_REMOVE_DENTRY 1744 1771 ///////////////////////////////////////////////////////////////////////////////////////// 1745 1772 … … 1757 1784 #endif 1758 1785 1759 assert( (cxy != local_cxy) , "server cluster is not remote\n");1786 uint32_t responses = 1; 1760 1787 1761 1788 // initialise RPC descriptor header … … 1763 1790 rpc.index = RPC_VFS_FS_REMOVE_DENTRY; 1764 1791 rpc.blocking = true; 1765 rpc.r esponses = 1;1792 rpc.rsp = &responses; 1766 1793 1767 1794 // set input arguments in RPC descriptor … … 1821 1848 1822 1849 ///////////////////////////////////////////////////////////////////////////////////////// 1823 // [19] Marshaling functions attached to RPC_VFS_INODE_LOAD_ALL_PAGES (blocking)1850 // [19] Marshaling functions attached to RPC_VFS_INODE_LOAD_ALL_PAGES 1824 1851 ///////////////////////////////////////////////////////////////////////////////////////// 1825 1852 … … 1837 1864 #endif 1838 1865 1839 assert( (cxy != local_cxy) , "server cluster is not remote\n");1866 uint32_t responses = 1; 1840 1867 1841 1868 // initialise RPC descriptor header … … 1843 1870 rpc.index = RPC_VFS_INODE_LOAD_ALL_PAGES; 1844 1871 rpc.blocking = true; 1845 rpc.r esponses = 1;1872 rpc.rsp = &responses; 1846 1873 1847 1874 // set input arguments in RPC descriptor … … 1898 1925 1899 1926 ///////////////////////////////////////////////////////////////////////////////////////// 1900 // [20] Marshaling functions attached to RPC_VMM_GET_VSEG (blocking)1927 // [20] Marshaling functions attached to RPC_VMM_GET_VSEG 1901 1928 ///////////////////////////////////////////////////////////////////////////////////////// 1902 1929 … … 1916 1943 #endif 1917 1944 1918 assert( (cxy != local_cxy) , "server cluster is not remote\n");1945 uint32_t responses = 1; 1919 1946 1920 1947 // initialise RPC descriptor header … … 1922 1949 rpc.index = RPC_VMM_GET_VSEG; 1923 1950 rpc.blocking = true; 1924 rpc.r esponses = 1;1951 rpc.rsp = &responses; 1925 1952 1926 1953 // set input arguments in RPC descriptor … … 1986 2013 1987 2014 ///////////////////////////////////////////////////////////////////////////////////////// 1988 // [21] Marshaling functions attached to RPC_VMM_GLOBAL_UPDATE_PTE (blocking)2015 // [21] Marshaling functions attached to RPC_VMM_GLOBAL_UPDATE_PTE 1989 2016 ///////////////////////////////////////////////////////////////////////////////////////// 1990 2017 … … 2004 2031 #endif 2005 2032 2006 assert( (cxy != local_cxy) , "server cluster is not remote\n");2033 uint32_t responses = 1; 2007 2034 2008 2035 // initialise RPC descriptor header … … 2010 2037 rpc.index = RPC_VMM_GLOBAL_UPDATE_PTE; 2011 2038 rpc.blocking = true; 2012 rpc.r esponses = 1;2039 rpc.rsp = &responses; 2013 2040 2014 2041 // set input arguments in RPC descriptor … … 2067 2094 2068 2095 ///////////////////////////////////////////////////////////////////////////////////////// 2069 // [22] Marshaling functions attached to RPC_KCM_ALLOC (blocking)2096 // [22] Marshaling functions attached to RPC_KCM_ALLOC 2070 2097 ///////////////////////////////////////////////////////////////////////////////////////// 2071 2098 … … 2073 2100 void rpc_kcm_alloc_client( cxy_t cxy, 2074 2101 uint32_t kmem_type, // in 2075 xptr_t *buf_xp ) // out2102 xptr_t * buf_xp ) // out 2076 2103 { 2077 2104 #if DEBUG_RPC_KCM_ALLOC … … 2083 2110 #endif 2084 2111 2085 assert( (cxy != local_cxy) , "server cluster is not remote\n");2112 uint32_t responses = 1; 2086 2113 2087 2114 // initialise RPC descriptor header … … 2089 2116 rpc.index = RPC_KCM_ALLOC; 2090 2117 rpc.blocking = true; 2091 rpc.r esponses = 1;2118 rpc.rsp = &responses; 2092 2119 2093 2120 // set input arguments in RPC descriptor … … 2145 2172 2146 2173 ///////////////////////////////////////////////////////////////////////////////////////// 2147 // [23] Marshaling functions attached to RPC_KCM_FREE (blocking)2174 // [23] Marshaling functions attached to RPC_KCM_FREE 2148 2175 ///////////////////////////////////////////////////////////////////////////////////////// 2149 2176 … … 2161 2188 #endif 2162 2189 2163 assert( (cxy != local_cxy) , "server cluster is not remote\n");2190 uint32_t responses = 1; 2164 2191 2165 2192 // initialise RPC descriptor header … … 2167 2194 rpc.index = RPC_KCM_FREE; 2168 2195 rpc.blocking = true; 2169 rpc.r esponses = 1;2196 rpc.rsp = &responses; 2170 2197 2171 2198 // set input arguments in RPC descriptor … … 2222 2249 2223 2250 ///////////////////////////////////////////////////////////////////////////////////////// 2224 // [25] Marshaling functions attached to RPC_MAPPER_HANDLE_MISS (blocking)2251 // [25] Marshaling functions attached to RPC_MAPPER_HANDLE_MISS 2225 2252 ///////////////////////////////////////////////////////////////////////////////////////// 2226 2253 … … 2240 2267 #endif 2241 2268 2242 assert( (cxy != local_cxy) , "server cluster is not remote\n");2269 uint32_t responses = 1; 2243 2270 2244 2271 // initialise RPC descriptor header … … 2246 2273 rpc.index = RPC_MAPPER_HANDLE_MISS; 2247 2274 rpc.blocking = true; 2248 rpc.r esponses = 1;2275 rpc.rsp = &responses; 2249 2276 2250 2277 // set input arguments in RPC descriptor … … 2309 2336 2310 2337 ///////////////////////////////////////////////////////////////////////////////////////// 2311 // [26] Marshaling functions attached to RPC_VMM_DELETE_VSEG (parallel / non blocking)2338 // [26] Marshaling functions attached to RPC_VMM_DELETE_VSEG 2312 2339 ///////////////////////////////////////////////////////////////////////////////////////// 2313 2340 2314 2341 ////////////////////////////////////////////////// 2315 2342 void rpc_vmm_delete_vseg_client( cxy_t cxy, 2316 rpc_desc_t * rpc ) 2343 pid_t pid, 2344 intptr_t vaddr ) 2317 2345 { 2318 2346 #if DEBUG_RPC_VMM_DELETE_VSEG … … 2324 2352 #endif 2325 2353 2326 // check RPC "index" and "blocking" arguments 2327 assert( (rpc->blocking == false) , "must be non-blocking\n"); 2328 assert( (rpc->index == RPC_VMM_DELETE_VSEG ) , "bad RPC index\n" ); 2354 uint32_t responses = 1; 2355 rpc_desc_t rpc; 2356 2357 // initialise RPC descriptor header 2358 rpc.index = RPC_VMM_DELETE_VSEG; 2359 rpc.blocking = true; 2360 rpc.rsp = &responses; 2361 2362 // set input arguments in RPC descriptor 2363 rpc.args[0] = (uint64_t)pid; 2364 rpc.args[1] = (uint64_t)vaddr; 2329 2365 2330 2366 // register RPC request in remote RPC fifo 2331 rpc_send( cxy , rpc );2367 rpc_send( cxy , &rpc ); 2332 2368 2333 2369 #if DEBUG_RPC_VMM_DELETE_VSEG … … 2370 2406 2371 2407 ///////////////////////////////////////////////////////////////////////////////////////// 2372 // [27] Marshaling functions attached to RPC_VMM_CREATE_VSEG (blocking)2408 // [27] Marshaling functions attached to RPC_VMM_CREATE_VSEG 2373 2409 ///////////////////////////////////////////////////////////////////////////////////////// 2374 2410 … … 2393 2429 #endif 2394 2430 2395 assert( (cxy != local_cxy) , "server cluster is not remote\n");2431 uint32_t responses = 1; 2396 2432 2397 2433 // initialise RPC descriptor header … … 2399 2435 rpc.index = RPC_VMM_CREATE_VSEG; 2400 2436 rpc.blocking = true; 2401 rpc.r esponses = 1;2437 rpc.rsp = &responses; 2402 2438 2403 2439 // set input arguments in RPC descriptor … … 2472 2508 2473 2509 ///////////////////////////////////////////////////////////////////////////////////////// 2474 // [28] Marshaling functions attached to RPC_VMM_SET_COW (blocking)2510 // [28] Marshaling functions attached to RPC_VMM_SET_COW 2475 2511 ///////////////////////////////////////////////////////////////////////////////////////// 2476 2512 … … 2479 2515 process_t * process ) 2480 2516 { 2481 assert( (cxy != local_cxy) , "server cluster is not remote\n"); 2517 #if DEBUG_RPC_VMM_SET_COW 2518 thread_t * this = CURRENT_THREAD; 2519 uint32_t cycle = (uint32_t)hal_get_cycles(); 2520 if( cycle > DEBUG_RPC_VMM_SET_COW ) 2521 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n", 2522 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2523 #endif 2524 2525 uint32_t responses = 1; 2482 2526 2483 2527 // initialise RPC descriptor header … … 2485 2529 rpc.index = RPC_VMM_SET_COW; 2486 2530 rpc.blocking = true; 2487 rpc.r esponses = 1;2531 rpc.rsp = &responses; 2488 2532 2489 2533 // set input arguments in RPC descriptor … … 2493 2537 rpc_send( cxy , &rpc ); 2494 2538 2539 #if DEBUG_RPC_VMM_SET_COW 2540 cycle = (uint32_t)hal_get_cycles(); 2541 if( cycle > DEBUG_RPC_VMM_SET_COW ) 2542 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 2543 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2544 #endif 2495 2545 } 2496 2546 … … 2498 2548 void rpc_vmm_set_cow_server( xptr_t xp ) 2499 2549 { 2550 #if DEBUG_RPC_VMM_SET_COW 2551 thread_t * this = CURRENT_THREAD; 2552 uint32_t cycle = (uint32_t)hal_get_cycles(); 2553 if( cycle > DEBUG_RPC_VMM_SET_COW ) 2554 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n", 2555 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2556 #endif 2557 2500 2558 process_t * process; 2501 2559 … … 2510 2568 vmm_set_cow( process ); 2511 2569 2512 } 2513 2514 ///////////////////////////////////////////////////////////////////////////////////////// 2515 // [29] Marshaling functions attached to RPC_VMM_DISPLAY (blocking) 2570 #if DEBUG_RPC_VMM_SET_COW 2571 cycle = (uint32_t)hal_get_cycles(); 2572 if( cycle > DEBUG_RPC_VMM_SET_COW ) 2573 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 2574 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2575 #endif 2576 } 2577 2578 ///////////////////////////////////////////////////////////////////////////////////////// 2579 // [29] Marshaling functions attached to RPC_VMM_DISPLAY 2516 2580 ///////////////////////////////////////////////////////////////////////////////////////// 2517 2581 … … 2521 2585 bool_t detailed ) 2522 2586 { 2523 assert( (cxy != local_cxy) , "server cluster is not remote\n"); 2587 #if DEBUG_RPC_VMM_DISPLAY 2588 thread_t * this = CURRENT_THREAD; 2589 uint32_t cycle = (uint32_t)hal_get_cycles(); 2590 if( cycle > DEBUG_RPC_VMM_DISPLAY ) 2591 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n", 2592 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2593 #endif 2594 2595 uint32_t responses = 1; 2524 2596 2525 2597 // initialise RPC descriptor header … … 2527 2599 rpc.index = RPC_VMM_DISPLAY; 2528 2600 rpc.blocking = true; 2529 rpc.r esponses = 1;2601 rpc.rsp = &responses; 2530 2602 2531 2603 // set input arguments in RPC descriptor … … 2536 2608 rpc_send( cxy , &rpc ); 2537 2609 2610 #if DEBUG_RPC_VMM_DISPLAY 2611 cycle = (uint32_t)hal_get_cycles(); 2612 if( cycle > DEBUG_RPC_VMM_DISPLAY ) 2613 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 2614 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2615 #endif 2538 2616 } 2539 2617 … … 2541 2619 void rpc_vmm_display_server( xptr_t xp ) 2542 2620 { 2621 #if DEBUG_RPC_VMM_DISPLAY 2622 thread_t * this = CURRENT_THREAD; 2623 uint32_t cycle = (uint32_t)hal_get_cycles(); 2624 if( cycle > DEBUG_RPC_VMM_DISPLAY ) 2625 printk("\n[%s] thread[%x,%x] on core %d enter / cycle %d\n", 2626 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2627 #endif 2628 2543 2629 process_t * process; 2544 2630 bool_t detailed; … … 2555 2641 vmm_display( process , detailed ); 2556 2642 2557 } 2558 2559 2643 #if DEBUG_RPC_VMM_DISPLAY 2644 cycle = (uint32_t)hal_get_cycles(); 2645 if( cycle > DEBUG_RPC_VMM_DISPLAY ) 2646 printk("\n[%s] thread[%x,%x] on core %d exit / cycle %d\n", 2647 __FUNCTION__, this->process->pid, this->trdid, this->core->lid , cycle ); 2648 #endif 2649 } 2650 2651 -
trunk/kernel/kern/rpc.h
r614 r619 69 69 RPC_THREAD_KERNEL_CREATE = 7, 70 70 RPC_UNDEFINED_8 = 8, 71 RPC_PROCESS_SIGACTION = 9, // non blocking71 RPC_PROCESS_SIGACTION = 9, 72 72 73 73 RPC_VFS_INODE_CREATE = 10, … … 88 88 RPC_UNDEFINED_24 = 24, 89 89 RPC_MAPPER_HANDLE_MISS = 25, 90 RPC_VMM_DELETE_VSEG = 26, // non blocking90 RPC_VMM_DELETE_VSEG = 26, 91 91 RPC_VMM_CREATE_VSEG = 27, 92 92 RPC_VMM_SET_COW = 28, … … 105 105 106 106 /*********************************************************************************** 107 * This structure defines the RPC descriptor 107 * This structure defines the RPC descriptor (100 bytes on a 32bits core) 108 108 **********************************************************************************/ 109 109 110 110 typedef struct rpc_desc_s 111 111 { 112 rpc_index_t index; /*! index of requested RPC service 113 volatile uint32_t responses; /*! number of expected responses*/114 struct thread_s * thread; /*! local pointer on client thread 115 uint32_t lid; /*! index of core running the calling thread*/116 bool_t blocking; /*! blocking RPC when true*/117 uint64_t args[10]; /*! input/output arguments buffer 112 rpc_index_t index; /*! index of requested RPC service ( 4) */ 113 uint32_t * rsp; /*! local pointer ond responses counter ( 4) */ 114 struct thread_s * thread; /*! local pointer on client thread ( 4) */ 115 uint32_t lid; /*! index of core running client thread ( 4) */ 116 bool_t blocking; /*! simple RPC mode when true ( 4) */ 117 uint64_t args[10]; /*! input/output arguments buffer (80) */ 118 118 } 119 119 rpc_desc_t; … … 161 161 * - it block on IDLE and deschedule otherwise. 162 162 **********************************************************************************/ 163 void rpc_ thread_func( void );163 void rpc_server_func( void ); 164 164 165 165 /*********************************************************************************** … … 309 309 310 310 /*********************************************************************************** 311 * [9] The non blocking RPC_PROCESS_SIGACTION allows any client thread running in 312 * any cluster to send parallel RPC requests to one or several servers (that can be 313 * local or remote), to execute a given sigaction, defined by the <action_type> 314 * argument[1], for a given process identified by the <pid> argument[0]. 315 * 316 * WARNING : It is implemented as a NON BLOCKING RPC, that can be sent in parallel 317 * to several servers. The RPC descriptor, containing the <action_type> and <pid> 318 * arguments, as well as the RPC <index>, <blocked>, and <response> fields, must 319 * be allocated and initialised by the calling function itself. 320 * Each RPC server thread atomically decrements the <response> field in this 321 * shared RPC descriptor. The last server thread unblock the client thread, 322 * that blocked only after sending all parallel RPC requests to all servers. 311 * [9] The RPC_PROCESS_SIGACTION allows any client thread to request to any cluster 312 * execute a given sigaction, defined by the <action_type> for a given process, 313 * identified by the <pid> argument. 323 314 *********************************************************************************** 324 315 * @ cxy : server cluster identifier. 325 * @ rpc : pointer on shared RPC descriptor initialized by the client thread. 326 **********************************************************************************/ 327 void rpc_process_sigaction_client( cxy_t cxy, 328 struct rpc_desc_s * rpc ); 316 * @ pid : [in] target process identifier. 317 * @ action : [in] sigaction index. 318 **********************************************************************************/ 319 void rpc_process_sigaction_client( cxy_t cxy, 320 pid_t pid, 321 uint32_t action ); 329 322 330 323 void rpc_process_sigaction_server( xptr_t xp ); … … 596 589 597 590 /*********************************************************************************** 598 * [26] The non blocking RPC_VMM_DELETE_VSEG allows any client thread running in 599 * any cluster to send parallel RPC requests to one or several clusters (that can be 600 * local or remote), to delete from a given VMM, identified by the <pid> argument[0] 601 * a given vseg, identified by the <vaddr> argument[1]. 602 * 603 * WARNING : It is implemented as a NON BLOCKING RPC, that can be sent in parallel 604 * to several servers. The RPC descriptor, containing the <pid> and <vaddr> 605 * arguments, as well as the RPC <index>, <blocked>, and <response> fields, must 606 * be allocated and initialised by the calling function itself. 607 * Each RPC server thread atomically decrements the the <response> field in this 608 * shared RPC descriptor. The last server thread unblock the client thread, 609 * that blocked only after sending all paralle RPC requests to all servers. 591 * [26] The RPC_VMM_DELETE_VSEG allows any client thread to request a remote 592 * cluster to delete from a given VMM, identified by the <pid> argument 593 * a given vseg, identified by the <vaddr> argument. 610 594 *********************************************************************************** 611 595 * @ cxy : server cluster identifier. 612 * @ rpc : pointer on shared RPC descriptor initialized by the client thread. 613 **********************************************************************************/ 614 void rpc_vmm_delete_vseg_client( cxy_t cxy, 615 struct rpc_desc_s * rpc ); 596 * @ pid : [in] target process identifier. 597 * @ vaddr : [in] vseg base address. 598 **********************************************************************************/ 599 void rpc_vmm_delete_vseg_client( cxy_t cxy, 600 pid_t pid, 601 intptr_t vaddr ); 616 602 617 603 void rpc_vmm_delete_vseg_server( xptr_t xp ); -
trunk/kernel/kern/scheduler.c
r614 r619 29 29 #include <printk.h> 30 30 #include <list.h> 31 #include <rpc.h> 31 32 #include <core.h> 32 33 #include <thread.h> … … 146 147 //////////////////////////////////////////////////////////////////////////////////////////// 147 148 // This static function is the only function that can actually delete a thread, 148 // and the associated process descriptor, if required.149 // It is private, because it is called by the sched_yield() public function.149 // (and the associated process descriptor if required). 150 // It is private, because it is only called by the sched_yield() public function. 150 151 // It scan all threads attached to a given scheduler, and executes the relevant 151 152 // actions for two types of pending requests: … … 376 377 error = thread_kernel_create( &thread, 377 378 THREAD_RPC, 378 &rpc_ thread_func,379 &rpc_server_func, 379 380 NULL, 380 381 lid ); -
trunk/kernel/kern/thread.c
r611 r619 1378 1378 } // end thread_assert_can yield() 1379 1379 1380 ////////////////////////////////////////////////// 1381 void thread_display_busylocks( xptr_t thread_xp )1382 { 1383 // get cluster and local pointer of target thread 1380 ////////////////////////////////////////////////////// 1381 void thread_display_busylocks( xptr_t thread_xp, 1382 const char * string ) 1383 { 1384 1384 cxy_t thread_cxy = GET_CXY( thread_xp ); 1385 1385 thread_t * thread_ptr = GET_PTR( thread_xp ); … … 1389 1389 xptr_t iter_xp; 1390 1390 1391 // get target thread TRDID and busylocks 1392 trdid_t trdid = hal_remote_l32(XPTR( thread_cxy , &thread_ptr->trdid )); 1393 uint32_t locks = hal_remote_l32(XPTR( thread_cxy , &thread_ptr->busylocks )); 1394 1395 // get target thread process and PID; 1396 process_t * process = hal_remote_lpt(XPTR( thread_cxy , &thread_ptr->process )); 1397 pid_t pid = hal_remote_l32(XPTR( thread_cxy , &process->pid )); 1391 // get relevant info from target trhead descriptor 1392 uint32_t locks = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->busylocks ) ); 1393 trdid_t trdid = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) ); 1394 process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) ); 1395 pid_t pid = hal_remote_l32( XPTR( thread_cxy , &process->pid ) ); 1398 1396 1399 1397 // get extended pointer on root of busylocks 1400 xptr_t 1398 xptr_t root_xp = XPTR( thread_cxy , &thread_ptr->busylocks_root ); 1401 1399 1402 1400 // get pointers on TXT0 chdev … … 1412 1410 1413 1411 // display header 1414 nolock_printk("\n***** thread %x in process %x : %d busylocks at cycle %d\n",1415 trdid, pid, locks, (uint32_t)hal_get_cycles());1412 nolock_printk("\n***** thread[%x,%x] in <%s> : %d busylocks *****\n", 1413 pid, trdid, string, locks ); 1416 1414 1417 1415 // scan the xlist of busylocks when required … … 1436 1434 1437 1435 // display a warning 1438 printk("\n[WARNING] set the DEBUG_BUSYLOCK par meter in kernel_config.h"1439 " to display busylocks for thread %x/%x\n", thread_cxy, thread_ptr);1436 printk("\n[WARNING] set the DEBUG_BUSYLOCK parameter in kernel_config.h" 1437 " to display busylocks for thread(%x,%x)\n", pid, trdid ); 1440 1438 1441 1439 } // end thread_display_busylock() -
trunk/kernel/kern/thread.h
r610 r619 143 143 typedef struct thread_s 144 144 { 145 void * cpu_context; /*! pointer on CPU context switch*/146 void * fpu_context; /*! pointer on FPU context switch*/145 void * cpu_context; /*! CPU context used by sched_yield */ 146 void * fpu_context; /*! FPU context used by sched_yield */ 147 147 void * uzone_current; /*! used by hal_do_syscall & hal_do_except */ 148 148 void * uzone_previous; /*! used by hal_do_syscall & hal_do_except */ … … 465 465 466 466 /*************************************************************************************** 467 * This debug function display the list of busylocks (local or remote) currently owned468 * by a thread identified by the <thread_xp> argument.469 * WARNING : it can be called by the idbg tool, but the DEBUG_BUSYLOCK parameter470 * must be set in the kernel_config.h file.467 * This debug function display the list of busylocks (local or remote) 468 * currently owned by a the thread identified by the <thead_xp> argument. 469 * The <string> argument is printed in header (can be the calling function name). 470 * WARNING : the DEBUG_BUSYLOCK parameter must be set in the kernel_config.h file. 471 471 *************************************************************************************** 472 472 * @ thread_xp : extended pointer on target thread. 473 **************************************************************************************/ 474 void thread_display_busylocks( xptr_t thread_xp ); 473 * @ string : defines the calling context. 474 **************************************************************************************/ 475 void thread_display_busylocks( xptr_t thread_xp, 476 const char * string ); 475 477 476 478 -
trunk/kernel/kernel_config.h
r614 r619 35 35 //////////////////////////////////////////////////////////////////////////////////////////// 36 36 37 #define DEBUG_BARRIER 0 38 39 #define DEBUG_BUSYLOCK 0 40 #define DEBUG_BUSYLOCK_THREAD_XP 0x0000000000ULL // selected thread xptr 37 #define DEBUG_BARRIER_CREATE 1 38 #define DEBUG_BARRIER_DESTROY 1 39 #define DEBUG_BARRIER_WAIT 0 40 41 #define DEBUG_BUSYLOCK 1 42 #define DEBUG_BUSYLOCK_THREAD_XP 0x0ULL // selected thread xptr 41 43 42 44 #define DEBUG_CHDEV_CMD_RX 0 … … 104 106 #define DEBUG_KMEM 0 105 107 106 #define DEBUG_KERNEL_INIT 2108 #define DEBUG_KERNEL_INIT 0 107 109 108 110 #define DEBUG_MAPPER_GET_PAGE 0 … … 153 155 #define DEBUG_RPC_VMM_GET_PTE 0 154 156 #define DEBUG_RPC_VMM_GET_VSEG 0 155 #define DEBUG_RPC_VMM_ UNMAP_VSEG0157 #define DEBUG_RPC_VMM_DELETE_VSEG 0 156 158 157 159 #define DEBUG_RWLOCK_TYPE 0 // lock type (0 is undefined) … … 276 278 #define LOCK_SEM_STATE 18 // remote (B) protect user semaphore state 277 279 #define LOCK_PROCESS_CWD 19 // remote (B) protect current working directory in process 278 279 #define BUSYLOCK_TYPE_MAX 20 280 #define LOCK_BARRIER_STATE 20 // remote (B) protect user barrier state 280 281 281 282 #define LOCK_CLUSTER_PREFTBL 21 // local (Q) protect array of ref. processes in cluster … … 285 286 #define LOCK_CLUSTER_COPIES 24 // remote (Q) protect xlist of process copies in cluster 286 287 #define LOCK_PROCESS_CHILDREN 25 // remote (Q) protect xlist of chidren process in process 287 #define LOCK_PROCESS_USERSYNC 26 // remote (Q) protect alllists of user synchros in process288 #define LOCK_PROCESS_USERSYNC 26 // remote (Q) protect lists of user synchros in process 288 289 #define LOCK_PROCESS_FDARRAY 27 // remote (Q) protect array of open files in owner process 289 290 #define LOCK_FATFS_FREE 28 // remote (Q) protect the FATFS context (free clusters) … … 419 420 420 421 //////////////////////////////////////////////////////////////////////////////////////////// 421 // PHYSICAL MEMORY MANAGEMENT (GENERIC)422 // PHYSICAL MEMORY MANAGEMENT 422 423 //////////////////////////////////////////////////////////////////////////////////////////// 423 424 -
trunk/kernel/libk/remote_barrier.c
r581 r619 2 2 * remote_barrier.c - POSIX barrier implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018 )4 * Author Alain Greiner (2016,2017,2018,2019) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 23 23 24 24 #include <hal_kernel_types.h> 25 #include <hal_macros.h> 25 26 #include <hal_remote.h> 26 27 #include <hal_irqmask.h> … … 33 34 #include <remote_barrier.h> 34 35 36 //////////////////////////////////////////////////// 37 // generic (implementation independant) functions 38 //////////////////////////////////////////////////// 35 39 36 40 /////////////////////////////////////////////////// 37 xptr_t remote_barrier_from_ident( intptr_t ident )41 xptr_t generic_barrier_from_ident( intptr_t ident ) 38 42 { 39 43 // get pointer on local process_descriptor 40 44 process_t * process = CURRENT_THREAD->process; 41 45 42 // get extended pointer on reference process 43 xptr_t ref_xp = process->ref_xp; 44 45 // get cluster and local pointer on reference process 46 // get pointers on reference process 47 xptr_t ref_xp = process->ref_xp; 46 48 cxy_t ref_cxy = GET_CXY( ref_xp ); 47 49 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); … … 51 53 52 54 // scan reference process barriers list 53 xptr_t iter_xp;54 xptr_t barrier_xp;55 cxy_t barrier_cxy;56 remote_barrier_t * barrier_ptr;57 intptr_t current;58 bool_t found = false;55 xptr_t iter_xp; 56 xptr_t barrier_xp; 57 cxy_t barrier_cxy; 58 generic_barrier_t * barrier_ptr; 59 intptr_t current; 60 bool_t found = false; 59 61 60 62 XLIST_FOREACH( root_xp , iter_xp ) 61 63 { 62 barrier_xp = XLIST_ELEMENT( iter_xp , remote_barrier_t , list );64 barrier_xp = XLIST_ELEMENT( iter_xp , generic_barrier_t , list ); 63 65 barrier_cxy = GET_CXY( barrier_xp ); 64 barrier_ptr = ( remote_barrier_t *)GET_PTR( barrier_xp );66 barrier_ptr = (generic_barrier_t *)GET_PTR( barrier_xp ); 65 67 current = (intptr_t)hal_remote_lpt( XPTR( barrier_cxy , &barrier_ptr->ident ) ); 66 68 if( ident == current ) … … 73 75 if( found == false ) return XPTR_NULL; 74 76 else return barrier_xp; 75 } 76 77 ////////////////////////////////////////////// 78 error_t remote_barrier_create( intptr_t ident, 79 uint32_t count ) 77 78 } // end generic_barrier_from_ident() 79 80 ////////////////////////////////////////////////////////////// 81 error_t generic_barrier_create( intptr_t ident, 82 uint32_t count, 83 pthread_barrierattr_t * attr ) 84 { 85 xptr_t gen_barrier_xp; // extended pointer on generic barrier descriptor 86 generic_barrier_t * gen_barrier_ptr; // local pointer on generic barrier descriptor 87 void * barrier; // local pointer on implementation barrier descriptor 88 kmem_req_t req; // kmem request 89 90 // get pointer on local process_descriptor 91 process_t * process = CURRENT_THREAD->process; 92 93 // get pointers on reference process 94 xptr_t ref_xp = process->ref_xp; 95 cxy_t ref_cxy = GET_CXY( ref_xp ); 96 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp ); 97 98 // allocate memory for generic barrier descriptor 99 if( ref_cxy == local_cxy ) // reference cluster is local 100 { 101 req.type = KMEM_GEN_BARRIER; 102 req.flags = AF_ZERO; 103 gen_barrier_ptr = kmem_alloc( &req ); 104 gen_barrier_xp = XPTR( local_cxy , gen_barrier_ptr ); 105 } 106 else // reference cluster is remote 107 { 108 rpc_kcm_alloc_client( ref_cxy, 109 KMEM_GEN_BARRIER, 110 &gen_barrier_xp ); 111 gen_barrier_ptr = GET_PTR( gen_barrier_xp ); 112 } 113 114 if( gen_barrier_ptr == NULL ) 115 { 116 printk("\n[ERROR] in %s : cannot create generic barrier\n", __FUNCTION__ ); 117 return -1; 118 } 119 120 // create implementation specific barrier descriptor 121 if( attr == NULL ) // simple barrier implementation 122 { 123 // create simple barrier descriptor 124 barrier = simple_barrier_create( count ); 125 126 if( barrier == NULL ) 127 { 128 printk("\n[ERROR] in %s : cannot create simple barrier\n", __FUNCTION__); 129 return -1; 130 } 131 } 132 else // QDT barrier implementation 133 { 134 uint32_t x_size = attr->x_size; 135 uint32_t y_size = attr->y_size; 136 uint32_t nthreads = attr->nthreads; 137 138 // check attributes / count 139 if( (x_size * y_size * nthreads) != count ) 140 { 141 printk("\n[ERROR] in %s : count(%d) != x_size(%d) * y_size(%d) * nthreads(%d)\n", 142 __FUNCTION__, count, x_size, y_size, nthreads ); 143 return -1; 144 } 145 146 // create DQT barrier descriptor 147 barrier = dqt_barrier_create( x_size , y_size , nthreads ); 148 149 if( barrier == NULL ) 150 { 151 printk("\n[ERROR] in %s : cannot create DQT barrier descriptor\n", __FUNCTION__); 152 return -1; 153 } 154 } 155 156 // initialize the generic barrier descriptor 157 hal_remote_spt( XPTR( ref_cxy , &gen_barrier_ptr->ident ) , (void*)ident ); 158 hal_remote_s32( XPTR( ref_cxy , &gen_barrier_ptr->is_dqt ) , (attr != NULL) ); 159 hal_remote_spt( XPTR( ref_cxy , &gen_barrier_ptr->extend ) , barrier ); 160 161 // build extended pointers on lock, root and entry for reference process xlist 162 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 163 xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock ); 164 xptr_t entry_xp = XPTR( ref_cxy , &gen_barrier_ptr->list ); 165 166 // register barrier in reference process xlist of barriers 167 remote_busylock_acquire( lock_xp ); 168 xlist_add_first( root_xp , entry_xp ); 169 remote_busylock_release( lock_xp ); 170 171 return 0; 172 173 } // en generic_barrier_create() 174 175 ///////////////////////////////////////////////////// 176 void generic_barrier_destroy( xptr_t gen_barrier_xp ) 177 { 178 kmem_req_t req; // kmem request 179 180 // get pointer on local process_descriptor 181 process_t * process = CURRENT_THREAD->process; 182 183 // get pointers on reference process 184 xptr_t ref_xp = process->ref_xp; 185 cxy_t ref_cxy = GET_CXY( ref_xp ); 186 process_t * ref_ptr = GET_PTR( ref_xp ); 187 188 // get cluster and local pointer on generic barrier descriptor 189 generic_barrier_t * gen_barrier_ptr = GET_PTR( gen_barrier_xp ); 190 cxy_t gen_barrier_cxy = GET_CXY( gen_barrier_xp ); 191 192 // get barrier type and extension pointer 193 bool_t is_dqt = hal_remote_l32( XPTR( gen_barrier_cxy , &gen_barrier_ptr->is_dqt ) ); 194 void * extend = hal_remote_lpt( XPTR( gen_barrier_cxy , &gen_barrier_ptr->extend ) ); 195 196 // build extended pointer on implementation dependant barrier descriptor 197 xptr_t barrier_xp = XPTR( gen_barrier_cxy , extend ); 198 199 // delete the implementation specific barrier 200 if( is_dqt ) dqt_barrier_destroy( barrier_xp ); 201 else simple_barrier_destroy( barrier_xp ); 202 203 // build extended pointers on lock and entry for reference process xlist 204 xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock ); 205 xptr_t entry_xp = XPTR( gen_barrier_cxy , &gen_barrier_ptr->list ); 206 207 // remove barrier from reference process xlist 208 remote_busylock_acquire( lock_xp ); 209 xlist_unlink( entry_xp ); 210 remote_busylock_release( lock_xp ); 211 212 // release memory allocated to barrier descriptor 213 if( gen_barrier_cxy == local_cxy ) 214 { 215 req.type = KMEM_GEN_BARRIER; 216 req.ptr = gen_barrier_ptr; 217 kmem_free( &req ); 218 } 219 else 220 { 221 rpc_kcm_free_client( gen_barrier_cxy, 222 gen_barrier_ptr, 223 KMEM_GEN_BARRIER ); 224 } 225 } // end generic_barrier_destroy() 226 227 ////////////////////////////////////////////////// 228 void generic_barrier_wait( xptr_t gen_barrier_xp ) 229 { 230 // get generic barrier descriptor cluster and pointer 231 cxy_t gen_barrier_cxy = GET_CXY( gen_barrier_xp ); 232 generic_barrier_t * gen_barrier_ptr = GET_PTR( gen_barrier_xp ); 233 234 // get implementation type and extend local pointer 235 bool_t is_dqt = hal_remote_l32( XPTR( gen_barrier_cxy , &gen_barrier_ptr->is_dqt ) ); 236 void * extend = hal_remote_lpt( XPTR( gen_barrier_cxy , &gen_barrier_ptr->extend ) ); 237 238 // build extended pointer on implementation specific barrier descriptor 239 xptr_t barrier_xp = XPTR( gen_barrier_cxy , extend ); 240 241 // call the relevant wait function 242 if( is_dqt ) dqt_barrier_wait( barrier_xp ); 243 else simple_barrier_wait( barrier_xp ); 244 245 } // end generic_barrier_wait() 246 247 248 249 250 251 ///////////////////////////////////////////////////////////// 252 // simple barrier functions 253 ///////////////////////////////////////////////////////////// 254 255 /////////////////////////////////////////////////////////// 256 simple_barrier_t * simple_barrier_create( uint32_t count ) 80 257 { 81 258 xptr_t barrier_xp; 82 remote_barrier_t * barrier_ptr;83 84 // get pointer on local process descriptor259 simple_barrier_t * barrier; 260 261 // get pointer on local client process descriptor 85 262 thread_t * this = CURRENT_THREAD; 86 263 process_t * process = this->process; 87 264 88 #if DEBUG_BARRIER 265 // get reference process cluster 266 xptr_t ref_xp = process->ref_xp; 267 cxy_t ref_cxy = GET_CXY( ref_xp ); 268 269 // allocate memory for simple barrier descriptor 270 if( ref_cxy == local_cxy ) // reference is local 271 { 272 kmem_req_t req; 273 req.type = KMEM_SMP_BARRIER; 274 req.flags = AF_ZERO; 275 barrier = kmem_alloc( &req ); 276 barrier_xp = XPTR( local_cxy , barrier ); 277 } 278 else // reference is remote 279 { 280 rpc_kcm_alloc_client( ref_cxy, 281 KMEM_SMP_BARRIER, 282 &barrier_xp ); 283 barrier = GET_PTR( barrier_xp ); 284 } 285 286 if( barrier == NULL ) return NULL; 287 288 // initialise simple barrier descriptor 289 hal_remote_s32 ( XPTR( ref_cxy , &barrier->arity ) , count ); 290 hal_remote_s32 ( XPTR( ref_cxy , &barrier->current ) , 0 ); 291 hal_remote_s32 ( XPTR( ref_cxy , &barrier->sense ) , 0 ); 292 293 xlist_root_init ( XPTR( ref_cxy , &barrier->root ) ); 294 remote_busylock_init( XPTR( ref_cxy , &barrier->lock ) , LOCK_BARRIER_STATE ); 295 296 #if DEBUG_BARRIER_CREATE 89 297 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 94 95 // get extended pointer on reference process 96 xptr_t ref_xp = process->ref_xp; 97 98 // get reference process cluster and local pointer 99 cxy_t ref_cxy = GET_CXY( ref_xp ); 100 process_t * ref_ptr = GET_PTR( ref_xp ); 101 102 // allocate memory for barrier descriptor 103 if( ref_cxy == local_cxy ) // local cluster is the reference 104 { 105 kmem_req_t req; 106 req.type = KMEM_BARRIER; 107 req.flags = AF_ZERO; 108 barrier_ptr = kmem_alloc( &req ); 109 barrier_xp = XPTR( local_cxy , barrier_ptr ); 110 } 111 else // reference is remote 112 { 113 rpc_kcm_alloc_client( ref_cxy , KMEM_BARRIER , &barrier_xp ); 114 barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 115 } 116 117 if( barrier_ptr == NULL ) return ENOMEM; 118 119 // initialise barrier 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 ); 123 hal_remote_spt( XPTR( ref_cxy , &barrier_ptr->ident ) , (void*)ident ); 124 125 xlist_root_init( XPTR( ref_cxy , &barrier_ptr->root ) ); 126 127 // register barrier in reference process xlist 128 xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root ); 129 xptr_t entry_xp = XPTR( ref_cxy , &barrier_ptr->list ); 130 131 remote_busylock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 132 xlist_add_first( root_xp , entry_xp ); 133 remote_busylock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 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 142 return 0; 143 144 } // end remote_barrier_create() 298 if( cycle > DEBUG_BARRIER_CREATE ) 299 printk("\n[%s] thread[%x,%x] created barrier (%x,%x) / count %d / cycle %d\n", 300 __FUNCTION__, process->pid, this->trdid, ref_cxy, barrier, count, cycle ); 301 #endif 302 303 return barrier; 304 305 } // end simple_barrier_create() 145 306 146 307 //////////////////////////////////////////////// 147 void remote_barrier_destroy( xptr_t barrier_xp )308 void simple_barrier_destroy( xptr_t barrier_xp ) 148 309 { 149 // get pointer on local process descriptor150 process_t * process = CURRENT_THREAD->process;151 152 // get extended pointer on reference process153 xptr_t ref_xp = process->ref_xp;154 155 // get reference process cluster and local pointer156 cxy_t ref_cxy = GET_CXY( ref_xp );157 process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );158 159 310 // get barrier cluster and local pointer 160 311 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 161 remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp ); 162 163 // remove barrier from reference process xlist 164 remote_busylock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 165 xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) ); 166 remote_busylock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 312 simple_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 167 313 168 314 // release memory allocated for barrier descriptor 169 if( barrier_cxy == local_cxy ) // reference is local315 if( barrier_cxy == local_cxy ) 170 316 { 171 317 kmem_req_t req; 172 req.type = KMEM_ BARRIER;318 req.type = KMEM_SMP_BARRIER; 173 319 req.ptr = barrier_ptr; 174 320 kmem_free( &req ); 175 321 } 176 else // reference is remote 177 { 178 rpc_kcm_free_client( barrier_cxy , barrier_ptr , KMEM_BARRIER ); 179 } 180 } // end remote_barrier_destroy() 322 else 323 { 324 rpc_kcm_free_client( barrier_cxy, 325 barrier_ptr, 326 KMEM_SMP_BARRIER ); 327 } 328 329 #if DEBUG_BARRIER_DESTROY 330 uint32_t cycle = (uint32_t)hal_get_cycles(); 331 thread_t * this = CURRENT_THREAD; 332 process_t * process = this->process; 333 if( cycle > DEBUG_BARRIER_DESTROY ) 334 printk("\n[%s] thread[%x,%x] deleted barrier (%x,%x) / cycle %d\n", 335 __FUNCTION__, process->pid, this->trdid, barrier_ptr, barrier_cxy, cycle ); 336 #endif 337 338 } // end simple_barrier_destroy() 181 339 182 340 ///////////////////////////////////////////// 183 void remote_barrier_wait( xptr_t barrier_xp )341 void simple_barrier_wait( xptr_t barrier_xp ) 184 342 { 185 343 uint32_t expected; 186 344 uint32_t sense; 187 345 uint32_t current; 188 uint32_t nb_threads;346 uint32_t arity; 189 347 xptr_t root_xp; 190 348 xptr_t lock_xp; 191 349 xptr_t current_xp; 192 350 xptr_t sense_xp; 193 xptr_t nb_threads_xp;351 xptr_t arity_xp; 194 352 195 353 // get pointer on calling thread … … 200 358 201 359 // get cluster and local pointer on remote barrier 202 remote_barrier_t * barrier_ptr = GET_PTR( barrier_xp );360 simple_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 203 361 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 204 362 205 #if DEBUG_BARRIER 363 #if DEBUG_BARRIER_WAIT 206 364 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 fields213 lock_xp 214 root_xp 215 current_xp 216 sense_xp 217 nb_threads_xp = XPTR( barrier_cxy , &barrier_ptr->nb_threads);218 219 // take busylock protecting the remote_barrier365 if( cycle > DEBUG_BARRIER_WAIT ) 366 printk("\n[%s] thread[%x,%x] enter / barrier (%x,%x) / cycle %d\n", 367 __FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle ); 368 #endif 369 370 // build extended pointers on various barrier descriptor fields 371 lock_xp = XPTR( barrier_cxy , &barrier_ptr->lock ); 372 root_xp = XPTR( barrier_cxy , &barrier_ptr->root ); 373 current_xp = XPTR( barrier_cxy , &barrier_ptr->current ); 374 sense_xp = XPTR( barrier_cxy , &barrier_ptr->sense ); 375 arity_xp = XPTR( barrier_cxy , &barrier_ptr->arity ); 376 377 // take busylock protecting the barrier state 220 378 remote_busylock_acquire( lock_xp ); 221 379 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 ); 380 // get sense and threads values from barrier descriptor 381 sense = hal_remote_l32( sense_xp ); 382 arity = hal_remote_l32( arity_xp ); 232 383 233 384 // compute expected value … … 235 386 else expected = 0; 236 387 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 388 // increment current number of arrived threads / get value before increment 245 389 current = hal_remote_atomic_add( current_xp , 1 ); 246 390 … … 248 392 // other threads block, register in queue, and deschedule 249 393 250 if( current == ( nb_threads-1) ) // last thread394 if( current == (arity - 1) ) // last thread 251 395 { 252 396 hal_remote_s32( current_xp , 0 ); … … 261 405 thread_t * thread_ptr = GET_PTR( thread_xp ); 262 406 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 ); 407 #if (DEBUG_BARRIER_WAIT & 1) 408 trdid_t trdid = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) ); 409 process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) ); 410 pid_t pid = hal_remote_l32( XPTR( thread_cxy , &process->pid ) ); 411 if( cycle > DEBUG_BARRIER_WAIT ) 412 printk("\n[%s] thread[%x,%x] unblocks thread[%x,%x]\n", 413 __FUNCTION__, this->process->pid, this->trdid, pid, trdid ); 268 414 #endif 269 415 … … 275 421 } 276 422 423 // release busylock protecting the barrier 424 remote_busylock_release( lock_xp ); 425 } 426 else // not the last thread 427 { 428 429 #if (DEBUG_BARRIER_WAIT & 1) 430 if( cycle > DEBUG_BARRIER_WAIT ) 431 printk("\n[%s] thread[%x,%x] blocks\n", 432 __FUNCTION__, this->process->pid, this->trdid ); 433 #endif 434 435 // register calling thread in barrier waiting queue 436 xlist_add_last( root_xp , XPTR( local_cxy , &this->wait_list ) ); 437 438 // block calling thread 439 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_USERSYNC ); 440 277 441 // release busylock protecting the remote_barrier 278 442 remote_busylock_release( lock_xp ); 279 } 280 else // not the last thread 281 { 282 283 #if (DEBUG_BARRIER & 1) 443 444 // deschedule 445 sched_yield("blocked on barrier"); 446 } 447 448 #if DEBUG_BARRIER_WAIT 284 449 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 289 450 if( cycle > DEBUG_BARRIER_WAIT ) 451 printk("\n[%s] thread[%x,%x] exit / barrier (%x,%x) / cycle %d\n", 452 __FUNCTION__, this->trdid, this->process->pid, barrier_cxy, barrier_ptr, cycle ); 453 #endif 454 455 } // end simple_barrier_wait() 456 457 458 ///////////////////////////////////////////////////////////// 459 // DQT barrier functions 460 ///////////////////////////////////////////////////////////// 461 462 static void dqt_barrier_increment( xptr_t node_xp ); 463 464 #if DEBUG_BARRIER_CREATE 465 static void dqt_barrier_display( xptr_t barrier_xp ); 466 #endif 467 468 /////////////////////////////////////////////////////// 469 dqt_barrier_t * dqt_barrier_create( uint32_t x_size, 470 uint32_t y_size, 471 uint32_t nthreads ) 472 { 473 page_t * dqt_page; 474 xptr_t dqt_page_xp; 475 page_t * rpc_page; 476 xptr_t rpc_page_xp; 477 dqt_barrier_t * barrier; // local pointer on DQT barrier descriptor 478 xptr_t barrier_xp; // extended pointer on DQT barrier descriptor 479 uint32_t z; // actual DQT size == max(x_size,y_size) 480 uint32_t levels; // actual number of DQT levels 481 kmem_req_t req; // kmem request 482 xptr_t rpc_xp; // extended pointer on RPC descriptors array 483 rpc_desc_t * rpc; // pointer on RPC descriptors array 484 uint32_t responses; // responses counter for parallel RPCs 485 reg_t save_sr; // for critical section 486 uint32_t x; // X coordinate in QDT mesh 487 uint32_t y; // Y coordinate in QDT mesh 488 uint32_t l; // level coordinate 489 490 // compute size and number of DQT levels 491 z = (x_size > y_size) ? x_size : y_size; 492 levels = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 3 : (z < 9) ? 4 : 5; 493 494 // check x_size and y_size arguments 495 assert( (z <= 16) , "DQT dqth larger than (16*16)\n"); 496 497 // check RPC descriptor size 498 assert( (sizeof(rpc_desc_t) <= 128), "RPC descriptor larger than 128 bytes\n"); 499 500 // check size of an array of 5 DQT nodes 501 assert( (sizeof(dqt_node_t) * 5 <= 512 ), "array of DQT nodes larger than 512 bytes\n"); 502 503 // check size of DQT barrier descriptor 504 assert( (sizeof(dqt_barrier_t) <= 0x4000 ), "DQT barrier descriptor larger than 4 pages\n"); 505 506 // get pointer on local client process descriptor 507 thread_t * this = CURRENT_THREAD; 508 process_t * process = this->process; 509 510 #if DEBUG_BARRIER_CREATE 511 uint32_t cycle = (uint32_t)hal_get_cycles(); 512 if( cycle > DEBUG_BARRIER_CREATE ) 513 printk("\n[%s] thread[%x,%x] enter : x_size %d / y_size %d / levels %d / cycle %d\n", 514 __FUNCTION__, process->pid, this->trdid, x_size, y_size, levels, cycle ); 515 #endif 516 517 // get reference process cluster 518 xptr_t ref_xp = process->ref_xp; 519 cxy_t ref_cxy = GET_CXY( ref_xp ); 520 521 // 1. allocate memory for DQT barrier descriptor in reference cluster 522 if( ref_cxy == local_cxy ) 523 { 524 req.type = KMEM_PAGE; 525 req.size = 2; // 4 pages == 16 Kbytes 526 req.flags = AF_ZERO; 527 dqt_page = kmem_alloc( &req ); 528 dqt_page_xp = XPTR( local_cxy , dqt_page ); 529 } 530 else 531 { 532 rpc_pmem_get_pages_client( ref_cxy, 533 2, 534 &dqt_page ); 535 dqt_page_xp = XPTR( ref_cxy , dqt_page ); 536 } 537 538 if( dqt_page == NULL ) return NULL; 539 540 // get pointers on DQT barrier descriptor 541 barrier_xp = ppm_page2base( dqt_page_xp ); 542 barrier = GET_PTR( barrier_xp ); 543 544 // initialize global parameters in DQT barrier descriptor 545 hal_remote_s32( XPTR( ref_cxy , &barrier->x_size ) , x_size ); 546 hal_remote_s32( XPTR( ref_cxy , &barrier->y_size ) , x_size ); 547 hal_remote_s32( XPTR( ref_cxy , &barrier->nthreads ) , nthreads ); 548 549 #if DEBUG_BARRIER_CREATE 550 if( cycle > DEBUG_BARRIER_CREATE ) 551 printk("\n[%s] thread[%x,%x] created DQT barrier descriptor at (%x,%x)\n", 552 __FUNCTION__, process->pid, this->trdid, ref_cxy, barrier ); 553 #endif 554 555 // 2. allocate memory from local cluster for an array of 256 RPCs descriptors 556 // cannot share the RPC descriptor, because the returned argument is not shared 557 req.type = KMEM_PAGE; 558 req.size = 3; // 8 pages == 32 Kbytes 559 req.flags = AF_ZERO; 560 rpc_page = kmem_alloc( &req ); 561 rpc_page_xp = XPTR( local_cxy , rpc_page ); 562 563 // get pointers on RPC descriptors array 564 rpc_xp = ppm_page2base( rpc_page_xp ); 565 rpc = GET_PTR( rpc_xp ); 566 567 #if DEBUG_BARRIER_CREATE 568 if( cycle > DEBUG_BARRIER_CREATE ) 569 printk("\n[%s] thread[%x,%x] created RPC descriptors array at (%x,%s)\n", 570 __FUNCTION__, process->pid, this->trdid, local_cxy, rpc ); 571 #endif 572 573 // 3. send parallel RPCs to all existing clusters covered by the DQT 574 // to allocate memory for an array of 5 DQT nodes in each cluster 575 // (5 nodes per cluster <= 512 bytes per cluster) 576 577 responses = 0; // initialize RPC responses counter 578 579 // mask IRQs 580 hal_disable_irq( &save_sr); 581 582 // client thread blocks itself 583 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC ); 584 585 for ( x = 0 ; x < x_size ; x++ ) 586 { 587 for ( y = 0 ; y < y_size ; y++ ) 588 { 589 // send RPC to existing clusters only 590 if( LOCAL_CLUSTER->cluster_info[x][y] ) 591 { 592 cxy_t cxy = HAL_CXY_FROM_XY( x , y ); // target cluster identifier 593 594 // build a specific RPC descriptor for each target cluster 595 rpc[cxy].rsp = &responses; 596 rpc[cxy].blocking = false; 597 rpc[cxy].index = RPC_KCM_ALLOC; 598 rpc[cxy].thread = this; 599 rpc[cxy].lid = this->core->lid; 600 rpc[cxy].args[0] = (uint64_t)KMEM_512_BYTES; 601 602 // atomically increment expected responses counter 603 hal_atomic_add( &responses , 1 ); 604 605 // send a non-blocking RPC to allocate 512 bytes in target cluster 606 rpc_send( cxy , &rpc[cxy] ); 607 } 608 } 609 } 610 611 #if DEBUG_BARRIER_CREATE 612 if( cycle > DEBUG_BARRIER_CREATE ) 613 printk("\n[%s] thread[%x,%x] sent all RPC requests to allocate dqt_nodes array\n", 614 __FUNCTION__, process->pid, this->trdid ); 615 #endif 616 617 // client thread deschedule 618 sched_yield("blocked on parallel rpc_kcm_alloc"); 619 620 // restore IRQs 621 hal_restore_irq( save_sr); 622 623 // 4. initialize the node_xp[x][y][l] array in DQT barrier descriptor 624 // the node_xp[x][y][0] value is available in rpc.args[1] 625 626 #if DEBUG_BARRIER_CREATE 627 if( cycle > DEBUG_BARRIER_CREATE ) 628 printk("\n[%s] thread[%x,%x] initialises array of pointers on dqt_nodes\n", 629 __FUNCTION__, process->pid, this->trdid ); 630 #endif 631 632 for ( x = 0 ; x < x_size ; x++ ) 633 { 634 for ( y = 0 ; y < y_size ; y++ ) 635 { 636 cxy_t cxy = HAL_CXY_FROM_XY( x , y ); // target cluster identifier 637 xptr_t array_xp = (xptr_t)rpc[cxy].args[1]; // x_pointer on node array 638 uint32_t offset = sizeof( dqt_node_t ); // size of a DQT node 639 640 // set values into the node_xp[x][y][l] array 641 for ( l = 0 ; l < levels ; l++ ) 642 { 643 xptr_t node_xp = array_xp + (offset * l); 644 hal_remote_s64( XPTR( ref_cxy , &barrier->node_xp[x][y][l] ), node_xp ); 645 646 #if DEBUG_BARRIER_CREATE 647 if( cycle > DEBUG_BARRIER_CREATE ) 648 printk(" - dqt_node_xp[%d,%d,%d] = (%x,%x) / &dqt_node_xp = %x\n", 649 x , y , l , GET_CXY( node_xp ), GET_PTR( node_xp ), &barrier->node_xp[x][y][l] ); 650 #endif 651 } 652 } 653 } 654 655 // 5. release memory locally allocated for the RPCs array 656 req.type = KMEM_PAGE; 657 req.ptr = rpc_page; 658 kmem_free( &req ); 659 660 #if DEBUG_BARRIER_CREATE 661 if( cycle > DEBUG_BARRIER_CREATE ) 662 printk("\n[%s] thread[%x,%x] released memory for RPC descriptors array\n", 663 __FUNCTION__, process->pid, this->trdid ); 664 #endif 665 666 // 6. initialise all distributed DQT nodes using remote accesses 667 // and the pointers stored in the node_xp[x][y][l] array 668 for ( x = 0 ; x < x_size ; x++ ) 669 { 670 for ( y = 0 ; y < y_size ; y++ ) 671 { 672 // initialize existing clusters only 673 if( LOCAL_CLUSTER->cluster_info[x][y] ) 674 { 675 for ( l = 0 ; l < levels ; l++ ) 676 { 677 xptr_t parent_xp; 678 xptr_t child_xp[4]; 679 uint32_t arity = 0; 680 681 // get DQT node pointers 682 xptr_t node_xp = hal_remote_l64( XPTR( ref_cxy, 683 &barrier->node_xp[x][y][l] ) ); 684 cxy_t node_cxy = GET_CXY( node_xp ); 685 dqt_node_t * node_ptr = GET_PTR( node_xp ); 686 687 // compute arity and child_xp[i] 688 if (l == 0 ) // bottom DQT node 689 { 690 arity = nthreads; 691 692 child_xp[0] = XPTR_NULL; 693 child_xp[1] = XPTR_NULL; 694 child_xp[2] = XPTR_NULL; 695 child_xp[3] = XPTR_NULL; 696 } 697 else // not a bottom DQT node 698 { 699 arity = 0; 700 701 // only few non-bottom nodes must be initialised 702 if( ((x & ((1<<l)-1)) == 0) && ((y & ((1<<l)-1)) == 0) ) 703 { 704 uint32_t cx[4]; // x coordinate for children 705 uint32_t cy[4]; // y coordinate for children 706 uint32_t i; 707 708 // the child0 coordinates are equal to the parent coordinates 709 // other children coordinates depend on the level value 710 cx[0] = x; 711 cy[0] = y; 712 713 cx[1] = x; 714 cy[1] = y + (1 << (l-1)); 715 716 cx[2] = x + (1 << (l-1)); 717 cy[2] = y; 718 719 cx[3] = x + (1 << (l-1)); 720 cy[3] = y + (1 << (l-1)); 721 722 for ( i = 0 ; i < 4 ; i++ ) 723 { 724 // child pointer is NULL if outside the mesh 725 if ( (cx[i] < x_size) && (cy[i] < y_size) ) 726 { 727 // get child_xp[i] 728 child_xp[i] = hal_remote_l64( XPTR( ref_cxy, 729 &barrier->node_xp[cx[i]][cy[i]][l-1] ) ); 730 731 // increment arity 732 arity++; 733 } 734 else 735 { 736 child_xp[i] = XPTR_NULL; 737 } 738 } 739 } 740 } 741 742 // compute parent_xp 743 if( l == (levels - 1) ) // root DQT node 744 { 745 parent_xp = XPTR_NULL; 746 } 747 else // not the root 748 { 749 uint32_t px = 0; // parent X coordinate 750 uint32_t py = 0; // parent Y coordinate 751 bool_t found = false; 752 753 // compute macro_cluster x_min, x_max, y_min, y_max 754 uint32_t x_min = x & ~((1<<(l+1))-1); 755 uint32_t x_max = x_min + (1<<(l+1)); 756 uint32_t y_min = y & ~((1<<(l+1))-1); 757 uint32_t y_max = y_min + (1<<(l+1)); 758 759 // scan all clusters in macro-cluster[x][y][l] / take first active 760 for( px = x_min ; px < x_max ; px++ ) 761 { 762 for( py = y_min ; py < y_max ; py++ ) 763 { 764 if( LOCAL_CLUSTER->cluster_info[px][py] ) found = true; 765 if( found ) break; 766 } 767 if( found ) break; 768 } 769 770 parent_xp = hal_remote_l64( XPTR( ref_cxy , 771 &barrier->node_xp[px][py][l+1] ) ); 772 } 773 774 // initializes the DQT node 775 hal_remote_s32( XPTR( node_cxy , &node_ptr->arity ) , arity ); 776 hal_remote_s32( XPTR( node_cxy , &node_ptr->current ) , 0 ); 777 hal_remote_s32( XPTR( node_cxy , &node_ptr->sense ) , 0 ); 778 hal_remote_s32( XPTR( node_cxy , &node_ptr->level ) , l ); 779 hal_remote_s64( XPTR( node_cxy , &node_ptr->parent_xp ) , parent_xp ); 780 hal_remote_s64( XPTR( node_cxy , &node_ptr->child_xp[0] ) , child_xp[0] ); 781 hal_remote_s64( XPTR( node_cxy , &node_ptr->child_xp[1] ) , child_xp[1] ); 782 hal_remote_s64( XPTR( node_cxy , &node_ptr->child_xp[2] ) , child_xp[2] ); 783 hal_remote_s64( XPTR( node_cxy , &node_ptr->child_xp[3] ) , child_xp[3] ); 784 785 xlist_root_init( XPTR( node_cxy , &node_ptr->root ) ); 786 787 remote_busylock_init( XPTR( node_cxy , &node_ptr->lock ), 788 LOCK_BARRIER_STATE ); 789 } 790 } 791 } 792 } 793 794 #if DEBUG_BARRIER_CREATE 795 cycle = (uint32_t)hal_get_cycles(); 796 if( cycle > DEBUG_BARRIER_CREATE ) 797 printk("\n[%s] thread[%x,%x] completed DQT barrier initialisation / cycle %d\n", 798 __FUNCTION__, process->pid, this->trdid, cycle ); 799 dqt_barrier_display( barrier_xp ); 800 #endif 801 802 return barrier; 803 804 } // end dqt_barrier_create() 805 806 /////////////////////////////////////////////// 807 void dqt_barrier_destroy( xptr_t barrier_xp ) 808 { 809 page_t * rpc_page; 810 xptr_t rpc_page_xp; 811 rpc_desc_t * rpc; // local pointer on RPC descriptors array 812 xptr_t rpc_xp; // extended pointer on RPC descriptor array 813 reg_t save_sr; // for critical section 814 kmem_req_t req; // kmem request 815 816 thread_t * this = CURRENT_THREAD; 817 818 // get DQT barrier descriptor cluster and local pointer 819 dqt_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 820 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 821 822 #if DEBUG_BARRIER_DESTROY 823 uint32_t cycle = (uint32_t)hal_get_cycles(); 824 if( cycle > DEBUG_BARRIER_DESTROY ) 825 printk("\n[%s] thread[%x,%x] enter for barrier (%x,%x) / cycle %d\n", 826 __FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle ); 827 #endif 828 829 // get x_size and y_size global parameters 830 uint32_t x_size = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->x_size ) ); 831 uint32_t y_size = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->y_size ) ); 832 833 // 1. allocate memory from local cluster for an array of 256 RPCs descriptors 834 // cannot share the RPC descriptor, because the "buf" argument is not shared 835 req.type = KMEM_PAGE; 836 req.size = 3; // 8 pages == 32 Kbytes 837 req.flags = AF_ZERO; 838 rpc_page = kmem_alloc( &req ); 839 rpc_page_xp = XPTR( local_cxy , rpc_page ); 840 841 // get pointers on RPC descriptors array 842 rpc_xp = ppm_page2base( rpc_page_xp ); 843 rpc = GET_PTR( rpc_xp ); 844 845 // 2. send parallel RPCs to all existing clusters covered by the DQT 846 // to release memory allocated for the arrays of DQT nodes in each cluster 847 848 uint32_t responses = 0; // initialize RPC responses counter 849 850 // mask IRQs 851 hal_disable_irq( &save_sr); 852 853 // client thread blocks itself 854 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC ); 855 856 uint32_t x , y; 857 858 #if DEBUG_BARRIER_DESTROY 859 if( cycle > DEBUG_BARRIER_DESTROY ) 860 printk("\n[%s] thread[%x,%x] send RPCs to release the distributed dqt_node array\n", 861 __FUNCTION__, this->process->pid, this->trdid ); 862 #endif 863 864 for ( x = 0 ; x < x_size ; x++ ) 865 { 866 for ( y = 0 ; y < y_size ; y++ ) 867 { 868 // send RPC to existing cluster only 869 if( LOCAL_CLUSTER->cluster_info[x][y] ) 870 { 871 // compute target cluster identifier 872 cxy_t cxy = HAL_CXY_FROM_XY( x , y ); 873 874 // get local pointer on dqt_nodes array in target cluster 875 xptr_t buf_xp_xp = XPTR( barrier_cxy , &barrier_ptr->node_xp[x][y][0] ); 876 xptr_t buf_xp = hal_remote_l64( buf_xp_xp ); 877 void * buf = GET_PTR( buf_xp ); 878 879 assert( (cxy == GET_CXY(buf_xp)) , "bad extended pointer on dqt_nodes array\n" ); 880 881 // build a specific RPC descriptor 882 rpc[cxy].rsp = &responses; 883 rpc[cxy].blocking = false; 884 rpc[cxy].index = RPC_KCM_FREE; 885 rpc[cxy].thread = this; 886 rpc[cxy].lid = this->core->lid; 887 rpc[cxy].args[0] = (uint64_t)(intptr_t)buf; 888 rpc[cxy].args[1] = (uint64_t)KMEM_512_BYTES; 889 890 // atomically increment expected responses counter 891 hal_atomic_add( &responses , 1 ); 892 893 #if DEBUG_BARRIER_DESTROY 894 if( cycle > DEBUG_BARRIER_DESTROY ) 895 printk(" - target cluster(%d,%d) / buffer %x\n", x, y, buf ); 896 #endif 897 // send a non-blocking RPC to release 512 bytes in target cluster 898 rpc_send( cxy , &rpc[cxy] ); 899 } 900 } 901 } 902 903 // client thread deschedule 904 sched_yield("blocked on parallel rpc_kcm_free"); 905 906 // restore IRQs 907 hal_restore_irq( save_sr); 908 909 // 3. release memory locally allocated for the RPC descriptors array 910 req.type = KMEM_PAGE; 911 req.ptr = rpc_page; 912 kmem_free( &req ); 913 914 // 4. release memory allocated for barrier descriptor 915 xptr_t page_xp = ppm_base2page( barrier_xp ); 916 page_t * page = GET_PTR( page_xp ); 917 918 if( barrier_cxy == local_cxy ) 919 { 920 req.type = KMEM_PAGE; 921 req.ptr = page; 922 kmem_free( &req ); 923 } 924 else 925 { 926 rpc_pmem_release_pages_client( barrier_cxy, 927 page ); 928 } 929 930 #if DEBUG_BARRIER_DESTROY 931 cycle = (uint32_t)hal_get_cycles(); 932 if( cycle > DEBUG_BARRIER_DESTROY ) 933 printk("\n[%s] thread[%x,%x] exit for barrier (%x,%x) / cycle %d\n", 934 __FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle ); 935 #endif 936 937 } // end dqt_barrier_destroy() 938 939 //////////////////////////////////////////// 940 void dqt_barrier_wait( xptr_t barrier_xp ) 941 { 942 thread_t * this = CURRENT_THREAD; 943 944 // check calling thread can yield 945 thread_assert_can_yield( this , __FUNCTION__ ); 946 947 // get cluster and local pointer on DQT barrier descriptor 948 dqt_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 949 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 950 951 #if DEBUG_BARRIER_WAIT 952 uint32_t cycle = (uint32_t)hal_get_cycles(); 953 if( cycle > DEBUG_BARRIER_WAIT ) 954 printk("\n[%s] thread[%x,%x] enter / barrier (%x,%x) / cycle %d\n", 955 __FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle ); 956 #endif 957 958 // get extended pointer on local bottom DQT node 959 uint32_t x = HAL_X_FROM_CXY( local_cxy ); 960 uint32_t y = HAL_Y_FROM_CXY( local_cxy ); 961 xptr_t node_xp = hal_remote_l64( XPTR( barrier_cxy , &barrier_ptr->node_xp[x][y][0] ) ); 962 963 // call recursive function to traverse DQT from bottom to root 964 dqt_barrier_increment( node_xp ); 965 966 #if DEBUG_BARRIER_WAIT 967 cycle = (uint32_t)hal_get_cycles(); 968 if( cycle > DEBUG_BARRIER_WAIT ) 969 printk("\n[%s] thread[%x,%x] exit / barrier (%x,%x) / cycle %d\n", 970 __FUNCTION__, this->trdid, this->process->pid, barrier_cxy, barrier_ptr, cycle ); 971 #endif 972 973 } // end dqt_barrier_wait() 974 975 976 //////////////////////////////////////////////////////////////////////////////////////////// 977 // DQT static functions 978 //////////////////////////////////////////////////////////////////////////////////////////// 979 980 981 ////////////////////////////////////////////////////////////////////////////////////////// 982 // This recursive function decrements the distributed "count" variables, 983 // traversing the DQT from bottom to root. 984 // The last arrived thread reset the local node before returning. 985 ////////////////////////////////////////////////////////////////////////////////////////// 986 static void dqt_barrier_increment( xptr_t node_xp ) 987 { 988 uint32_t expected; 989 uint32_t sense; 990 uint32_t arity; 991 992 thread_t * this = CURRENT_THREAD; 993 994 // get node cluster and local pointer 995 dqt_node_t * node_ptr = GET_PTR( node_xp ); 996 cxy_t node_cxy = GET_CXY( node_xp ); 997 998 // build relevant extended pointers 999 xptr_t arity_xp = XPTR( node_cxy , &node_ptr->arity ); 1000 xptr_t sense_xp = XPTR( node_cxy , &node_ptr->sense ); 1001 xptr_t current_xp = XPTR( node_cxy , &node_ptr->current ); 1002 xptr_t lock_xp = XPTR( node_cxy , &node_ptr->lock ); 1003 xptr_t root_xp = XPTR( node_cxy , &node_ptr->root ); 1004 1005 #if DEBUG_BARRIER_WAIT 1006 uint32_t cycle = (uint32_t)hal_get_cycles(); 1007 uint32_t level = hal_remote_l32( XPTR( node_cxy, &node_ptr->level ) ); 1008 if( cycle > DEBUG_BARRIER_WAIT ) 1009 printk("\n[%s] thread[%x,%x] increments DQT node(%d,%d,%d) / cycle %d\n", 1010 __FUNCTION__ , this->process->pid, this->trdid, 1011 HAL_X_FROM_CXY(node_cxy), HAL_Y_FROM_CXY(node_cxy), level ); 1012 #endif 1013 1014 // get extended pointer on parent node 1015 xptr_t parent_xp = hal_remote_l64( XPTR( node_cxy , &node_ptr->parent_xp ) ); 1016 1017 // take busylock 1018 remote_busylock_acquire( lock_xp ); 1019 1020 // get sense and arity values from barrier descriptor 1021 sense = hal_remote_l32( sense_xp ); 1022 arity = hal_remote_l32( arity_xp ); 1023 1024 // compute expected value 1025 expected = (sense == 0) ? 1 : 0; 1026 1027 // increment current number of arrived threads / get value before increment 1028 uint32_t current = hal_remote_atomic_add( current_xp , 1 ); 1029 1030 // last arrived thread reset the local node, makes the recursive call 1031 // on parent node, and reactivates all waiting thread when returning. 1032 // other threads block, register in queue, and deschedule. 1033 1034 if ( current == (arity - 1) ) // last thread 1035 { 1036 1037 #if DEBUG_BARRIER_WAIT 1038 if( cycle > DEBUG_BARRIER_WAIT ) 1039 printk("\n[%s] thread[%x,%x] reset DQT node(%d,%d,%d)\n", 1040 __FUNCTION__ , this->process->pid, this->trdid, 1041 HAL_X_FROM_CXY(node_cxy), HAL_Y_FROM_CXY(node_cxy), level ); 1042 #endif 1043 // reset the current node 1044 hal_remote_s32( sense_xp , expected ); 1045 hal_remote_s32( current_xp , 0 ); 1046 1047 // release busylock protecting the current node 1048 remote_busylock_release( lock_xp ); 1049 1050 // recursive call on parent node when current node is not the root 1051 if( parent_xp != XPTR_NULL) dqt_barrier_increment( parent_xp ); 1052 1053 // unblock all waiting threads on this node 1054 while( xlist_is_empty( root_xp ) == false ) 1055 { 1056 // get pointers on first waiting thread 1057 xptr_t thread_xp = XLIST_FIRST( root_xp , thread_t , wait_list ); 1058 cxy_t thread_cxy = GET_CXY( thread_xp ); 1059 thread_t * thread_ptr = GET_PTR( thread_xp ); 1060 1061 #if (DEBUG_BARRIER_WAIT & 1) 1062 trdid_t trdid = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) ); 1063 process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) ); 1064 pid_t pid = hal_remote_l32( XPTR( thread_cxy , &process->pid ) ); 1065 if( cycle > DEBUG_BARRIER_WAIT ) 1066 printk("\n[%s] thread[%x,%x] unblock thread[%x,%x]\n", 1067 __FUNCTION__, this->process->pid, this->trdid, pid, trdid ); 1068 #endif 1069 // remove waiting thread from queue 1070 xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_list ) ); 1071 1072 // unblock waiting thread 1073 thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC ); 1074 } 1075 } 1076 else // not the last thread 1077 { 1078 // get extended pointer on xlist entry from thread 1079 xptr_t entry_xp = XPTR( local_cxy , &this->wait_list ); 1080 290 1081 // register calling thread in barrier waiting queue 291 xlist_add_last( root_xp , XPTR( local_cxy , &this->wait_list ));1082 xlist_add_last( root_xp , entry_xp ); 292 1083 293 1084 // block calling thread … … 297 1088 remote_busylock_release( lock_xp ); 298 1089 1090 #if DEBUG_BARRIER_WAIT 1091 if( cycle > DEBUG_BARRIER_WAIT ) 1092 printk("\n[%s] thread[%x,%x] blocks on node(%d,%d,%d)\n", 1093 __FUNCTION__ , this->process->pid, this->trdid, 1094 HAL_X_FROM_CXY(node_cxy), HAL_Y_FROM_CXY(node_cxy), level ); 1095 #endif 299 1096 // deschedule 300 1097 sched_yield("blocked on barrier"); 301 1098 } 302 1099 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() 1100 return; 1101 1102 } // end dqt_barrier_decrement() 1103 1104 #if DEBUG_BARRIER_CREATE 1105 1106 //////////////////////////////////////////////////////////////////////////////////////////// 1107 // This debug function displays all DQT nodes in all clusters. 1108 //////////////////////////////////////////////////////////////////////////////////////////// 1109 // @ barrier_xp : extended pointer on DQT barrier descriptor. 1110 //////////////////////////////////////////////////////////////////////////////////////////// 1111 static void dqt_barrier_display( xptr_t barrier_xp ) 1112 { 1113 // get cluster and local pointer on DQT barrier 1114 dqt_barrier_t * barrier_ptr = GET_PTR( barrier_xp ); 1115 cxy_t barrier_cxy = GET_CXY( barrier_xp ); 1116 1117 // get barrier global parameters 1118 uint32_t x_size = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->x_size ) ); 1119 uint32_t y_size = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->y_size ) ); 1120 uint32_t nthreads = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->nthreads ) ); 1121 1122 // compute size and number of DQT levels 1123 uint32_t z = (x_size > y_size) ? x_size : y_size; 1124 uint32_t levels = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 3 : (z < 9) ? 4 : 5; 1125 1126 printk("\n***** DQT barrier : x_size %d / y_size %d / nthreads %d / levels %d *****\n", 1127 x_size, y_size, nthreads, levels ); 1128 1129 uint32_t x , y , l; 1130 1131 for ( x = 0 ; x < x_size ; x++ ) 1132 { 1133 for ( y = 0 ; y < y_size ; y++ ) 1134 { 1135 printk(" - cluster[%d,%d]\n", x , y ); 1136 1137 for ( l = 0 ; l < levels ; l++ ) 1138 { 1139 // get pointers on target node 1140 xptr_t node_xp = hal_remote_l64( XPTR( barrier_cxy , 1141 &barrier_ptr->node_xp[x][y][l] ) ); 1142 dqt_node_t * node_ptr = GET_PTR( node_xp ); 1143 cxy_t node_cxy = GET_CXY( node_xp ); 1144 1145 if( node_xp != XPTR_NULL ) 1146 { 1147 uint32_t level = hal_remote_l32( XPTR( node_cxy , &node_ptr->level )); 1148 uint32_t arity = hal_remote_l32( XPTR( node_cxy , &node_ptr->arity )); 1149 xptr_t pa_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->parent_xp )); 1150 xptr_t c0_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[0] )); 1151 xptr_t c1_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[1] )); 1152 xptr_t c2_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[2] )); 1153 xptr_t c3_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[3] )); 1154 1155 printk(" . level %d : (%x,%x) / arity %d / P(%x,%x) / C0(%x,%x)" 1156 " C1(%x,%x) / C2(%x,%x) / C3(%x,%x)\n", 1157 level, node_cxy, node_ptr, arity, 1158 GET_CXY(pa_xp), GET_PTR(pa_xp), 1159 GET_CXY(c0_xp), GET_PTR(c0_xp), 1160 GET_CXY(c1_xp), GET_PTR(c1_xp), 1161 GET_CXY(c2_xp), GET_PTR(c2_xp), 1162 GET_CXY(c3_xp), GET_PTR(c3_xp) ); 1163 } 1164 } 1165 } 1166 } 1167 } // end dqt_barrier_display() 1168 1169 #endif -
trunk/kernel/libk/remote_barrier.h
r581 r619 2 2 * remote_barrier.h - POSIX barrier definition. 3 3 * 4 * Author Alain Greiner (2016,2017,2018 )4 * Author Alain Greiner (2016,2017,2018,2019) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 29 29 #include <remote_busylock.h> 30 30 #include <xlist.h> 31 #include <shared_pthread.h> 31 32 32 33 /*************************************************************************************** 33 * This file definesa POSIX compliant barrier.34 * This file defines two implementations for a POSIX compliant barrier. 34 35 * 35 36 * It is used by multi-threaded user applications to synchronise threads running in 36 * different clusters, as all access functions uses hal_remote_l32() / hal_remote_s32() 37 * remote access primitives. 38 * 39 * A barrier is declared by a given user process as a "pthread_barrier_t" global variable. 40 * This user type is implemented as an unsigned long, but the value is not used by the 41 * kernel. ALMOS-MKH uses only the barrier virtual address as an identifier. 42 * For each user barrier, ALMOS-MKH creates a kernel "remote_barrier_t" structure, 43 * dynamically allocated in the reference cluster by the remote_barrier_create() function, 44 * and destroyed by the remote_barrier_destroy() function, using RPC if the calling thread 45 * is not running in the reference cluster. 46 * 47 * The blocking "remote_barrier_wait()" function implements a descheduling policy when 48 * the calling thread is not the last expected thread: the calling thread is registered 49 * in a waiting queue, rooted in the barrier structure, and the the calling thread 50 * is blocked on the THREAD_BLOCKED_USERSYNC condition. The last arrived thread 51 * unblocks all registtered waiting threads. 37 * different clusters. Access functions use RPCs for barrier creation/destruction, 38 * and use remote access primitives for actual synchronisation (wait function). 39 * 40 * A barrier is declared by a given user process as a "pthread_barrier_t" user variable. 41 * This user type is implemented in user space as an unsigned long, but the value is not 42 * used by the kernel. ALMOS-MKH uses only the barrier virtual address as an identifier. 43 * For each user barrier, ALMOS-MKH creates a kernel structure, dynamically allocated 44 * by the "generic_barrier_create()" function, destroyed by the "remote_barrier_destroy()" 45 * function, and used by the "generic_barrier_wait()" function. 46 * 47 * Implementation note: 48 * ALMOS-MKH supports two barrier implementations: 49 * 50 * 1) simple_barrier_t 51 * If the pointer on the barrier attributes is NULL, the barrier is implemented as 52 * a shared variable localized in the reference process cluster. 53 * There is a risk of contention when the number of synchronizing threads is large. 54 * 55 * 2) dqt_barrier_t 56 * If the (x_size, y_size, nthreads) arguments are defined in the barrier attributes, 57 * the barrier is implemented as a hierarchical quad-tree covering all clusters in the 58 * (x_size * ysize) mesh, including cluster (0,0), with nthreads per cluster, and called 59 * DQT : Distributed Quad Tree. This DQT implementation supposes a regular architecture, 60 * and a strong contraint on the threads placement: exactly "nthreads" threads per 61 * cluster in the (x_size * y_size) mesh. 62 * 63 * For both implementations, the blocking "generic_barrier_wait()" function implements 64 * a descheduling policy when the calling thread is not the last expected thread: 65 * the calling thread is registered in a waiting queue, rooted in the barrier structure, 66 * and the the calling thread is blocked on the THREAD_BLOCKED_USERSYNC condition. 67 * The last arrived thread unblocks all registered waiting threads. 52 68 * **************************************************************************************/ 53 69 54 /***************************************************************************************** 55 * This structure defines the barrier descriptor. 56 * - It contains an xlist of all barriers dynamically created by a given process, 57 * rooted in the reference process descriptor. 58 * - It contains the root of another xlist to register all arrived threads. 59 ****************************************************************************************/ 60 61 typedef struct remote_barrier_s 62 { 63 remote_busylock_t lock; /*! lock protecting list of waiting threads */ 64 intptr_t ident; /*! virtual address in user space == identifier */ 65 uint32_t current; /*! number of arrived threads */ 66 uint32_t sense; /*! barrier state (toggle) */ 67 uint32_t nb_threads; /*! number of expected threads */ 68 xlist_entry_t list; /*! member of list of barriers in same process */ 69 xlist_entry_t root; /*! root of list of waiting threads */ 70 71 72 /***************************************************************************************** 73 * generic barrier descriptor and access functions 74 ***************************************************************************************** 75 * This generic structure is used by both the simple and the QOT implementations. 76 * It is implemented in the reference process cluster, and contains 77 * - the barrier identifier, 78 * - the implementation type (simple or QDT), 79 * - an xlist implementing the set of barriers dynamically created by a given process, 80 * - a pointer on the implementation specific descriptor (simple_barrier / sqt_barrier). 81 ****************************************************************************************/ 82 83 typedef struct generic_barrier_s 84 { 85 intptr_t ident; /*! virtual address in user space == identifier */ 86 xlist_entry_t list; /*! member of list of barriers in same process */ 87 bool_t is_dqt; /*! DQT implementation when true */ 88 void * extend; /*! implementation specific barrier descriptor */ 70 89 } 71 remote_barrier_t; 72 90 generic_barrier_t; 73 91 74 92 /***************************************************************************************** … … 76 94 * by its virtual address in a given user process. It makes an associative search, 77 95 * scanning the list of barriers rooted in the reference process descriptor. 96 * It can be used for both simple and DQT barriers, registered in the same list. 78 97 ***************************************************************************************** 79 98 * @ ident : barrier virtual address, used as identifier. 80 99 * @ returns extended pointer on barrier if success / returns XPTR_NULL if not found. 81 100 ****************************************************************************************/ 82 xptr_t remote_barrier_from_ident( intptr_t ident ); 83 84 /***************************************************************************************** 85 * This function implement the pthread_barrier_init() syscall. 86 * It allocates memory for the barrier descriptor in the reference cluster for 87 * the calling process, it initializes the barrier state, and register it in the 88 * list of barriers owned by the reference process. 89 ***************************************************************************************** 90 * @ count : number of expected threads. 91 * @ ident : barrier identifier (virtual address in user space). 92 * @ return 0 if success / return ENOMEM if failure. 93 ****************************************************************************************/ 94 error_t remote_barrier_create( intptr_t ident, 95 uint32_t count ); 96 97 /***************************************************************************************** 98 * This function implement the pthread_barrier_destroy() syscall. 99 * It releases thr memory allocated for the barrier descriptor, and remove the barrier 100 * from the list of barriers owned by the reference process. 101 ***************************************************************************************** 102 * @ barrier_xp : extended pointer on barrier descriptor. 103 ****************************************************************************************/ 104 void remote_barrier_destroy( xptr_t barrier_xp ); 105 106 /***************************************************************************************** 107 * This function implement the pthread_barrier_wait() syscall. 108 * It returns only when the number of expected threads (registered in the barrier 109 * dexcriptor) reach the barrier. 110 ***************************************************************************************** 111 * @ barrier_xp : extended pointer on barrier descriptor. 112 ****************************************************************************************/ 113 void remote_barrier_wait( xptr_t barrier_xp ); 101 xptr_t generic_barrier_from_ident( intptr_t ident ); 102 103 /***************************************************************************************** 104 * This function implements the pthread_barrier_init() syscall. 105 * It allocates and initialises the generic barrier descriptor in the reference process 106 * cluster, and - depending on the <attr> argument, calls the relevant (simple or DQT) 107 * function to allocate and initialize the implementation dependant barrier descriptor. 108 * Finally, it registers the barrier in the reference process xlist of user barriers. 109 * It can be called by a thread running in any cluster, as it use RPC if required. 110 ***************************************************************************************** 111 * @ ident : barrier virtual address, used as identifier. 112 * @ count : number of expected threads. 113 * @ attr : barrier attributes (x_size,y_size,nthreads), used by QDT implementation. 114 * @ returns 0 if success / returns -1 if not found. 115 ****************************************************************************************/ 116 error_t generic_barrier_create( intptr_t ident, 117 uint32_t count, 118 pthread_barrierattr_t * attr ); 119 120 /***************************************************************************************** 121 * This function implements the pthread_barrier_destroy() syscall. 122 * It calls the relevant function (simple or DQT) to release the memory allocated for 123 * the implementation specific barrier descriptor, and releases the memory allocated 124 * for the generic barrier descriptor. 125 * It removes the barrier from the list of barriers rooted in the reference process. 126 * It can be called by a thread running in any cluster, as it use RPC if required. 127 ***************************************************************************************** 128 * @ gen_barrier_xp : extended pointer on generic barrier descriptor. 129 ****************************************************************************************/ 130 void generic_barrier_destroy( xptr_t gen_barrier_xp ); 131 132 /***************************************************************************************** 133 * This blocking function implements the pthread_barrier_wait() syscall. 134 * It calls the relevant function (simple or DQT) depending on the implementation, 135 * and returns only when all expected threads reach the barrier. 136 * It can be called by a thread running in any cluster, as it use remote accesses. 137 ***************************************************************************************** 138 * @ gen_barrier_xp : extended pointer on generic barrier descriptor. 139 ****************************************************************************************/ 140 void generic_barrier_wait( xptr_t gen_barrier_xp ); 141 142 143 144 145 146 147 /***************************************************************************************** 148 * simple barrier descriptor 149 ***************************************************************************************** 150 * This structure defines the simple barrier descriptor. It is localized in the process 151 * reference cluster, as an extension of the generic barrier descriptor. 152 * It implements a toggle barrier remotely accessed by all threads. 153 * It contains the root of the xlist registering all arrived threads. 154 ****************************************************************************************/ 155 156 typedef struct simple_barrier_s 157 { 158 remote_busylock_t lock; /*! lock protecting list of waiting threads */ 159 uint32_t current; /*! number of arrived threads */ 160 uint32_t sense; /*! barrier state (toggle) */ 161 uint32_t arity; /*! number of expected threads */ 162 xlist_entry_t root; /*! root of list of waiting threads */ 163 } 164 simple_barrier_t; 165 166 /***************************************************************************************** 167 * This function allocates memory for the simple barrier descriptor in the reference 168 * cluster of the calling process. It initializes the barrier state and returns 169 * a local pointer on the created simple barrier descriptor in reference cluster. 170 * It can be called by a thread running in any cluster, as it use RPC if required. 171 ***************************************************************************************** 172 * @ count : [in] number of expected threads. 173 * @ return Local pointer on barrier descriptor if success / return NULL if failure. 174 ****************************************************************************************/ 175 simple_barrier_t * simple_barrier_create( uint32_t count ); 176 177 /***************************************************************************************** 178 * This function releases the memory allocated for the simple barrier descriptor. 179 * It can be called by a thread running in any cluster, as it use RPC if required. 180 ***************************************************************************************** 181 * @ barrier_xp : extended pointer on simple barrier descriptor. 182 ****************************************************************************************/ 183 void simple_barrier_destroy( xptr_t barrier_xp ); 184 185 /***************************************************************************************** 186 * This blocking function returns only when all expected threads reach the barrier. 187 * It can be called by a thread running in any cluster, as it use remote accesses. 188 * Waiting threads use a descheduling policy. 189 ***************************************************************************************** 190 * @ barrier_xp : extended pointer on simple barrier descriptor. 191 ****************************************************************************************/ 192 void simple_barrier_wait( xptr_t barrier_xp ); 193 194 195 196 197 198 /***************************************************************************************** 199 * dqt_barrier 200 ***************************************************************************************** 201 * These structuree define the hierarchical DQT barrier, physically distributed in a 202 * mesh of clusters defined by the (x_size, y_size, nthreads) arguments: 203 * . The involved clusters form a mesh [x_size * y_size] 204 * . The lower left involved cluster is cluster(0,0) 205 * . The number of threads per cluster is the same in all clusters. 206 * 207 * Implementation note: 208 * - The quad three is implemented as a three dimensions array of node[x][y][l] 209 * . [x][y] are the cluster coordinates / max values are (DQT_XMAX-1), (DQT_YMAX-1) 210 * . [l] is the node level / 0 for terminal nodes / (DQT_LMAX-1) for the root node 211 * - The dqt_barrier_t is the global barrier descriptor, allocated in the reference 212 * process cluster as an extension of the generic barrier descriptor. It contains a 213 * 3D array of extended pointers on all DQT nodes implementing the DQT barrier. 214 * - The dqt_node_t is a local barrier implementing a togle barrier between all threads 215 * of a given cluster (for a terminal node), or between all representatives of the four 216 * children nodes (for a non terminal node). 217 ****************************************************************************************/ 218 219 #define DQT_XMAX 16 // max number of clusters in a row 220 #define DQT_YMAX 16 // max number of clusters in a column 221 #define DQT_LMAX 5 // max depth of the quad tree 222 223 typedef struct dqt_node_s 224 { 225 remote_busylock_t lock; /*! lock protecting list of waiting threads */ 226 volatile uint32_t sense; /*! barrier state (toggle) */ 227 volatile uint32_t current; /*! number of locally arrived threads */ 228 uint32_t arity; /*! total number of locally expected threads */ 229 uint32_t level; /*! hierarchical level (0 is bottom) */ 230 xptr_t parent_xp; /*! x_pointer on parent node (NULL for root) */ 231 xptr_t child_xp[4]; /*! x_pointer on children node (NULL for bottom) */ 232 xlist_entry_t root; /*! root of list of waiting threads */ 233 } 234 dqt_node_t; 235 236 typedef struct dqt_barrier_s 237 { 238 xptr_t node_xp[DQT_XMAX][DQT_YMAX][DQT_LMAX]; /*! array of xptr on DQT nodes */ 239 240 uint32_t x_size; /*! number of clusters in one row of DQT mesh */ 241 uint32_t y_size; /*! number of clusters in one column of DQT mesh */ 242 uint32_t nthreads; /*! number of expected threads in one cluster */ 243 } 244 dqt_barrier_t; 245 246 /***************************************************************************************** 247 * This function allocates memory for the DQT barrier descriptor in the reference cluster 248 * of the calling process. It allocates also memory in all clusters of the QDT mesh, 249 * to store up to 5 QDT nodes per cluster. 250 * It initializes the barrier descriptor, including initialisation of the parent/children 251 * extended pointers in the distributed QDT nodes. 252 * It returns a local pointer on the QDT barrier descriptor in reference cluster. 253 * It can be called by a thread running in any cluster, as it use RPCs for memory 254 * allocation, and remote access for QDT initialisation. 255 ***************************************************************************************** 256 * @ x_size : [in] number of clusters in a line of DQT mesh. 257 * @ y_size : [in] number of clusters in a column of DQT mesh. 258 * @ nthreads : [in] number of threads per cluster. 259 * @ return Local pointer on barrier descriptor if success / return NULL if failure. 260 ****************************************************************************************/ 261 dqt_barrier_t * dqt_barrier_create( uint32_t x_size, 262 uint32_t y_size, 263 uint32_t nthreads ); 264 265 /***************************************************************************************** 266 * This function releases all memory allocated for the QDT barrier descriptor. 267 * It removes the barrier from the list of barriers rooted in the reference process. 268 * It can be called by a thread running in any cluster, as it use RPCs. 269 ***************************************************************************************** 270 * @ barrier_xp : extended pointer on DQT barrier descriptor. 271 ****************************************************************************************/ 272 void dqt_barrier_destroy( xptr_t barrier_xp ); 273 274 /***************************************************************************************** 275 * This blocking function returns only when all expected threads reach the barrier. 276 * It can be called by a thread running in any cluster, as it use remote accesses. 277 * Waiting threads use a descheduling policy. 278 ***************************************************************************************** 279 * @ barrier_xp : extended pointer on DQT barrier descriptor. 280 ****************************************************************************************/ 281 void dqt_barrier_wait( xptr_t barrier_xp ); 282 114 283 115 284 -
trunk/kernel/libk/remote_busylock.c
r600 r619 101 101 (XPTR( local_cxy , this ) == DEBUG_BUSYLOCK_THREAD_XP) ) 102 102 { 103 // get cluster and local pointer of target thread104 cxy_t thread_cxy = GET_CXY( DEBUG_BUSYLOCK_THREAD_XP );105 thread_t * thread_ptr = GET_PTR( DEBUG_BUSYLOCK_THREAD_XP );106 107 // display message on kernel TXT0108 103 printk("\n[%s] thread[%x,%x] ACQUIRE lock %s\n", 109 __FUNCTION_ , this->process->pid, this->trdid, lock_type_str[type] );104 __FUNCTION__, this->process->pid, this->trdid, lock_type_str[type] ); 110 105 } 111 106 #endif … … 149 144 (XPTR( local_cxy , this ) == DEBUG_BUSYLOCK_THREAD_XP) ) 150 145 { 151 // get cluster and local pointer of target thread152 cxy_t thread_cxy = GET_CXY( DEBUG_BUSYLOCK_THREAD_XP );153 thread_t * thread_ptr = GET_PTR( DEBUG_BUSYLOCK_THREAD_XP );154 155 // display message on kernel TXT0156 146 printk("\n[%s] thread[%x,%x] RELEASE lock %s\n", 157 147 __FUNCTION__, this->process->pid, this->trdid, lock_type_str[type] ); -
trunk/kernel/libk/remote_busylock.h
r603 r619 42 42 * makes an atomic increment on a "ticket" allocator, and keep polling the "current" 43 43 * value until current == ticket. 44 44 * 45 45 * - To release the lock, the owner thread increments the "current" value, 46 46 * decrements its busylocks counter. -
trunk/kernel/libk/remote_mutex.c
r611 r619 138 138 thread_t * this = CURRENT_THREAD; 139 139 if( (uint32_t)hal_get_cycles() > DEBUG_MUTEX ) 140 printk("\n[ DBG] %s : thread %x in %x process /mutex(%x,%x)\n",141 __FUNCTION__, this-> trdid, this->process->pid, local_cxy, mutex_ptr );140 printk("\n[%s] : thread[%x,%x] created mutex(%x,%x)\n", 141 __FUNCTION__, this->process->pid, this->trdid, local_cxy, mutex_ptr ); 142 142 #endif 143 143 … … 173 173 remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) ); 174 174 175 // release memory allocated for mutex aphoredescriptor175 // release memory allocated for mutex descriptor 176 176 if( mutex_cxy == local_cxy ) // reference is local 177 177 { … … 183 183 else // reference is remote 184 184 { 185 rpc_kcm_free_client( mutex_cxy , mutex_ptr , KMEM_ BARRIER);185 rpc_kcm_free_client( mutex_cxy , mutex_ptr , KMEM_MUTEX ); 186 186 } 187 187 … … 226 226 thread_t * this = CURRENT_THREAD; 227 227 if( (uint32_t)hal_get_cycles() > DEBUG_MUTEX ) 228 printk("\n[ DBG] %s : thread %x in process %xSUCCESS on mutex(%x,%x)\n",229 __FUNCTION__, this-> trdid, this->process->pid, mutex_cxy, mutex_ptr );228 printk("\n[%s] thread[%x,%x] SUCCESS on mutex(%x,%x)\n", 229 __FUNCTION__, this->process->pid, this->trdid, mutex_cxy, mutex_ptr ); 230 230 #endif 231 231 … … 247 247 thread_t * this = CURRENT_THREAD; 248 248 if( (uint32_t)hal_get_cycles() > DEBUG_MUTEX ) 249 printk("\n[ DBG] %s : thread %x in process %xBLOCKED on mutex(%x,%x)\n",250 __FUNCTION__, this-> trdid, this->process->pid, mutex_cxy, mutex_ptr );249 printk("\n[%s] thread[%x,%x] BLOCKED on mutex(%x,%x)\n", 250 __FUNCTION__, this->process->pid, this->trdid, mutex_cxy, mutex_ptr ); 251 251 #endif 252 252 … … 296 296 thread_t * this = CURRENT_THREAD; 297 297 if( (uint32_t)hal_get_cycles() > DEBUG_MUTEX ) 298 printk("\n[ DBG] %s : thread %x in %x processEXIT / mutex(%x,%x)\n",299 __FUNCTION__, this-> trdid, this->process->pid, mutex_cxy, mutex_ptr );298 printk("\n[%s] thread[%x,%x] EXIT / mutex(%x,%x)\n", 299 __FUNCTION__, this->process->pid, this->trdid, mutex_cxy, mutex_ptr ); 300 300 #endif 301 301 … … 320 320 process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) ); 321 321 pid_t pid = hal_remote_l32( XPTR( thread_cxy , &process->pid ) ); 322 printk("\n[ DBG] %s : thread %x in process %xUNBLOCK thread %x in process %d / mutex(%x,%x)\n",323 __FUNCTION__, this-> trdid, this->process->pid, trdid, pid, mutex_cxy, mutex_ptr );322 printk("\n[%s] thread[%x,%x] UNBLOCK thread %x in process %d / mutex(%x,%x)\n", 323 __FUNCTION__, this->process->pid, this->trdid, trdid, pid, mutex_cxy, mutex_ptr ); 324 324 } 325 325 #endif … … 371 371 thread_t * this = CURRENT_THREAD; 372 372 if( (uint32_t)hal_get_cycles() > DEBUG_QUEUELOCK ) 373 printk("\n[ DBG] %s : SUCCESS for thread %x in process %x/ mutex(%x,%x)\n",374 __FUNCTION__, this-> trdid, this->process->pid, mutex_cxy, mutex_ptr );373 printk("\n[%s] SUCCESS for thread[%x,%x] / mutex(%x,%x)\n", 374 __FUNCTION__, this->process->pid, this->trdid, mutex_cxy, mutex_ptr ); 375 375 #endif 376 376 // release busylock protecting mutex state … … 385 385 thread_t * this = CURRENT_THREAD; 386 386 if( (uint32_t)hal_get_cycles() > DEBUG_QUEUELOCK ) 387 printk("\n[ DBG] %s : FAILURE for thread %x in process %x/ mutex(%x,%x)\n",388 __FUNCTION__, this-> trdid, this->process->pid, mutex_cxy, mutex_ptr );387 printk("\n[%s] FAILURE for thread[%x,%x] / mutex(%x,%x)\n", 388 __FUNCTION__, this->process->pid, this->trdid, mutex_cxy, mutex_ptr ); 389 389 #endif 390 390 // release busylock protecting mutex state -
trunk/kernel/libk/user_dir.c
r614 r619 286 286 printk("\n[ERROR] in %s : cannot map vpn %x in GPT\n", 287 287 __FUNCTION__, (vpn + page_id) ); 288 // use the non blocking RPC to delete the remote vseg 289 rpc_desc_t desc; 290 desc.index = RPC_VMM_DELETE_VSEG; 291 desc.responses = 1; 292 desc.thread = CURRENT_THREAD; 293 desc.lid = CURRENT_THREAD->core->lid; 294 desc.blocking = true; 295 desc.args[0] = ref_pid; 296 desc.args[1] = vpn << CONFIG_PPM_PAGE_SHIFT; 297 rpc_vmm_delete_vseg_client( ref_cxy , &desc ); 288 289 // delete the vseg 290 if( ref_cxy == local_cxy) vmm_delete_vseg( ref_pid, vpn<<CONFIG_PPM_PAGE_SHIFT ); 291 else rpc_vmm_delete_vseg_client( ref_cxy, ref_pid, vpn<<CONFIG_PPM_PAGE_SHIFT ); 292 298 293 // release the user_dir descriptor 299 294 req.type = KMEM_DIR; … … 387 382 lpid_t lpid; // process local index 388 383 rpc_desc_t rpc; // rpc descriptor 384 uint32_t responses; // response counter 389 385 390 386 // get pointers on calling process & thread … … 441 437 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC ); 442 438 443 // initialize RPC descriptor shared fields 444 rpc.responses = 0; 439 // initialize responses counter 440 responses = 0; 441 442 // initialize a shared RPC descriptor 443 // can be shared, because no out arguments 444 rpc.rsp = &responses; 445 445 rpc.blocking = false; 446 446 rpc.index = RPC_VMM_DELETE_VSEG; … … 461 461 462 462 // atomically increment responses counter 463 hal_atomic_add( (void *)&rpc.responses , 1 ); 464 465 // call RPC 466 rpc_vmm_delete_vseg_client( process_cxy , &rpc ); 467 468 } // end list of copies 463 hal_atomic_add( &responses , 1 ); 464 465 // send RPC to target cluster 466 rpc_send( process_cxy , &rpc ); 467 } 469 468 470 469 // release the lock protecting process copies … … 472 471 473 472 // client thread deschedule 474 sched_yield("blocked on rpc_vmm_ unmap_vseg");473 sched_yield("blocked on rpc_vmm_delete_vseg"); 475 474 476 475 // restore IRQs -
trunk/kernel/mm/kcm.c
r567 r619 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018 )5 * Alain Greiner (2016,2017,2018,2019) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 51 51 52 52 #if DEBUG_KCM 53 thread_t * this = CURRENT_THREAD; 53 54 uint32_t cycle = (uint32_t)hal_get_cycles(); 54 55 if( DEBUG_KCM < cycle ) 55 printk("\n[ DBG] %s : thread %xenters for %s / page %x / count %d / active %d\n",56 __FUNCTION__ , CURRENT_THREAD , kmem_type_str( kcm->type ),56 printk("\n[%s] thread[%x,%x] enters for %s / page %x / count %d / active %d\n", 57 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(kcm->type), 57 58 (intptr_t)kcm_page , kcm_page->count , kcm_page->active ); 58 59 #endif 59 60 60 61 assert( kcm_page->active , "kcm_page should be active" ); 61 62 62 63 // get first block available 63 64 int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr ); 64 65 65 66 assert( (index != -1) , "kcm_page should not be full" ); 66 67 67 68 // allocate block … … 90 91 cycle = (uint32_t)hal_get_cycles(); 91 92 if( DEBUG_KCM < cycle ) 92 printk("\n[ DBG] %s : thread %x exit / type%s / ptr %x / page %x / count %d\n",93 __FUNCTION__ , CURRENT_THREAD , kmem_type_str( kcm->type ) , (intptr_t)ptr,94 (intptr_t) kcm_page, kcm_page->count );93 printk("\n[%s] thread[%x,%x] exit for %s / ptr %x / page %x / count %d\n", 94 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(kcm->type), 95 (intptr_t)ptr, (intptr_t)kcm_page, kcm_page->count ); 95 96 #endif 96 97 … … 115 116 index = ((uint8_t *)ptr - (uint8_t *)kcm_page - CONFIG_KCM_SLOT_SIZE) / kcm->block_size; 116 117 117 assert( !bitmap_state( kcm_page->bitmap , index ) , "page already freed" ); 118 assert( (kcm_page->count > 0) , "count already zero" ); 118 assert( !bitmap_state( kcm_page->bitmap , index ) , "page already freed" ); 119 120 assert( (kcm_page->count > 0) , "count already zero" ); 119 121 120 122 bitmap_set( kcm_page->bitmap , index ); … … 163 165 if( page == NULL ) 164 166 { 165 printk("\n[ERROR] in %s : failed to allocate page in cluster % d\n",166 167 printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n", 168 __FUNCTION__ , local_cxy ); 167 169 return ENOMEM; 168 170 } … … 216 218 uint32_t type ) 217 219 { 218 // the kcm_page descriptor mut fit in the KCM slot 219 assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) , 220 "KCM slot too small\n" ); 220 221 // the kcm_page descriptor must fit in the KCM slot 222 assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) , "KCM slot too small\n" ); 223 224 // the allocated object must fit in one single page 225 assert( (kmem_type_size(type) <= (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE)), 226 "allocated object requires more than one single page\n" ); 221 227 222 228 // initialize lock … … 241 247 uint32_t blocks_nr = (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE) / block_size; 242 248 kcm->blocks_nr = blocks_nr; 249 250 #if DEBUG_KCM 251 thread_t * this = CURRENT_THREAD; 252 uint32_t cycle = (uint32_t)hal_get_cycles(); 253 if( DEBUG_KCM < cycle ) 254 printk("\n[%s] thread[%x,%x] initialised KCM %s : block_size %d / blocks_nr %d\n", 255 __FUNCTION__, this->process->pid, this->trdid, 256 kmem_type_str( kcm->type ), block_size, blocks_nr ); 257 #endif 258 243 259 } 244 260 … … 331 347 kcm_t * kcm; 332 348 333 assert( (ptr != NULL) , "pointer cannot be NULL" ); 349 // check argument 350 assert( (ptr != NULL) , "pointer cannot be NULL" ); 334 351 335 352 kcm_page = (kcm_page_t *)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK); -
trunk/kernel/mm/kcm.h
r567 r619 37 37 * for fixed size objects. It exists a specific KCM allocator for each object type. 38 38 * The actual allocated block size is the smallest multiple of the KCM slot, that 39 * contain one single object. The KCM slot is typically 64 bytes, as it must be large40 * enoughto store the kcm_page descriptor, defined below.39 * contain one single object. The KCM slot is 64 bytes, as it must be large enough 40 * to store the kcm_page descriptor, defined below. 41 41 * The various KCM allocators themselves are not statically allocated in the cluster 42 42 * manager, but are dynamically allocated when required, using the embedded KCM -
trunk/kernel/mm/khm.h
r567 r619 3 3 * 4 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018 )5 * Alain Greiner (2016,2017,2018,2019) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 32 32 /******************************************************************************************* 33 33 * This structure defines a Kernel Heap Manager (KHM) in a given cluster. 34 * It is used to allocate memory objects, that are not enough replicated to justify35 * a dedicated KCM allocator.34 * It is used to allocate memory objects, that too large, or not enough replicated 35 * to use a dedicated KCM allocator. 36 36 ******************************************************************************************/ 37 37 -
trunk/kernel/mm/kmem.c
r612 r619 90 90 else if( type == KMEM_CPU_CTX ) return CONFIG_CPU_CTX_SIZE; 91 91 else if( type == KMEM_FPU_CTX ) return CONFIG_FPU_CTX_SIZE; 92 else if( type == KMEM_BARRIER ) return sizeof( remote_barrier_t ); 93 92 else if( type == KMEM_GEN_BARRIER ) return sizeof( generic_barrier_t ); 93 94 else if( type == KMEM_SMP_BARRIER ) return sizeof( simple_barrier_t ); 94 95 else if( type == KMEM_DEVFS_CTX ) return sizeof( fatfs_ctx_t ); 95 96 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t ); … … 101 102 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t ); 102 103 else if( type == KMEM_MUTEX ) return sizeof( remote_mutex_t ); 104 103 105 else if( type == KMEM_DIR ) return sizeof( user_dir_t ); 104 105 106 else if( type == KMEM_512_BYTES ) return 512; 106 107 … … 120 121 else if( type == KMEM_CPU_CTX ) return "KMEM_CPU_CTX"; 121 122 else if( type == KMEM_FPU_CTX ) return "KMEM_FPU_CTX"; 122 else if( type == KMEM_BARRIER ) return "KMEM_BARRIER"; 123 123 else if( type == KMEM_GEN_BARRIER ) return "KMEM_GEN_BARRIER"; 124 125 else if( type == KMEM_SMP_BARRIER ) return "KMEM_SMP_BARRIER"; 124 126 else if( type == KMEM_DEVFS_CTX ) return "KMEM_DEVFS_CTX"; 125 127 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX"; … … 131 133 else if( type == KMEM_CONDVAR ) return "KMEM_CONDVAR"; 132 134 else if( type == KMEM_MUTEX ) return "KMEM_MUTEX"; 135 133 136 else if( type == KMEM_DIR ) return "KMEM_DIR"; 134 135 137 else if( type == KMEM_512_BYTES ) return "KMEM_512_BYTES"; 136 138 -
trunk/kernel/mm/kmem.h
r611 r619 45 45 KMEM_CPU_CTX = 7, /*! hal_cpu_context_t */ 46 46 KMEM_FPU_CTX = 8, /*! hal_fpu_context_t */ 47 KMEM_ BARRIER = 9, /*! remote_barrier_t*/47 KMEM_GEN_BARRIER = 9, /*! generi_cbarrier_t */ 48 48 49 KMEM_ DEVFS_CTX = 10, /*! fatfs_inode_t*/50 KMEM_ FATFS_CTX = 11, /*! fatfs_ctx_t*/51 KMEM_ VFS_CTX = 12, /*! vfs_context_t*/52 KMEM_VFS_ INODE = 13, /*! vfs_inode_t*/53 KMEM_VFS_ DENTRY = 14, /*! vfs_dentry_t*/54 KMEM_VFS_ FILE = 15, /*! vfs_file_t*/55 KMEM_ SEM = 16, /*! remote_sem_t*/56 KMEM_ CONDVAR = 17, /*! remote_condvar_t*/57 KMEM_ MUTEX = 18, /*! remote_mutex_t*/58 KMEM_ DIR = 19, /*! remote_dir_t*/49 KMEM_SMP_BARRIER = 10, /*! simple_barrier_t */ 50 KMEM_DEVFS_CTX = 11, /*! fatfs_inode_t */ 51 KMEM_FATFS_CTX = 12, /*! fatfs_ctx_t */ 52 KMEM_VFS_CTX = 13, /*! vfs_context_t */ 53 KMEM_VFS_INODE = 14, /*! vfs_inode_t */ 54 KMEM_VFS_DENTRY = 15, /*! vfs_dentry_t */ 55 KMEM_VFS_FILE = 16, /*! vfs_file_t */ 56 KMEM_SEM = 17, /*! remote_sem_t */ 57 KMEM_CONDVAR = 18, /*! remote_condvar_t */ 58 KMEM_MUTEX = 19, /*! remote_mutex_t */ 59 59 60 KMEM_512_BYTES = 20, /*! 512 bytes aligned */ 60 KMEM_DIR = 20, /*! remote_dir_t */ 61 KMEM_512_BYTES = 21, /*! 512 bytes aligned */ 61 62 62 KMEM_TYPES_NR = 2 1,63 KMEM_TYPES_NR = 22, 63 64 }; 64 65 … … 97 98 ************************************************************************************* 98 99 * @ req : local pointer to allocation request. 99 * @ return a local pointer on page descriptor if PPM (i.e. type KMEM_PAGE).100 * @ return a local pointer on page descriptor if KMEM_PAGE. 100 101 * return a local pointer to allocated buffer if KCM or KHM. 101 102 * return NULL if no physical memory available. -
trunk/kernel/mm/vmm.c
r617 r619 800 800 // scan the VSL to delete all registered vsegs 801 801 // (don't use a FOREACH for item deletion in xlist) 802 while( !xlist_is_empty( root_xp ) ) 802 803 uint32_t count = 0; 804 805 while( !xlist_is_empty( root_xp ) && (count < 10 ) ) 803 806 { 804 807 // get pointer on first vseg in VSL … … 814 817 __FUNCTION__ , vseg_type_str( vseg->type ), vseg->vpn_base, vseg->vpn_size ); 815 818 #endif 819 820 count++; 816 821 817 822 } … … 1463 1468 1464 1469 #if DEBUG_VMM_ALLOCATE_PAGE 1465 uint32_t cycle = (uint32_t)hal_get_cycles(); 1466 thread_t * this = CURRENT_THREAD; 1470 uint32_t cycle = (uint32_t)hal_get_cycles(); 1471 thread_t * this = CURRENT_THREAD; 1472 xptr_t this_xp = XPTR( local_cxy , this ); 1467 1473 if( DEBUG_VMM_ALLOCATE_PAGE < (uint32_t)hal_get_cycles() ) 1468 1474 printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n", … … 1950 1956 1951 1957 #if DEBUG_VMM_HANDLE_COW 1952 uint32_t cycle = (uint32_t)hal_get_cycles(); 1953 thread_t * this = CURRENT_THREAD; 1958 uint32_t cycle = (uint32_t)hal_get_cycles(); 1959 thread_t * this = CURRENT_THREAD; 1960 xptr_t this_xp = XPTR( local_cxy , this ); 1954 1961 if( DEBUG_VMM_HANDLE_COW < cycle ) 1955 1962 printk("\n[%s] thread[%x,%x] enter for vpn %x / core[%x,%d] / cycle %d\n", 1956 __FUNCTION__, process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle );1963 __FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle ); 1957 1964 #endif 1958 1965 … … 1974 1981 } 1975 1982 1983 #if( DEBUG_VMM_HANDLE_COW & 1) 1984 if( DEBUG_VMM_HANDLE_COW < cycle ) 1985 printk("\n[%s] thread[%x,%x] get vseg for vpn %x\n", 1986 __FUNCTION__, this->process->pid, this->trdid, vpn ); 1987 #endif 1988 1976 1989 // get reference GPT cluster and local pointer 1977 1990 ref_cxy = GET_CXY( process->ref_xp ); … … 2001 2014 &old_ppn ); 2002 2015 2016 #if( DEBUG_VMM_HANDLE_COW & 1) 2017 if( DEBUG_VMM_HANDLE_COW < cycle ) 2018 printk("\n[%s] thread[%x,%x] get pte for vpn %x : ppn %x / attr %x\n", 2019 __FUNCTION__, this->process->pid, this->trdid, vpn, old_ppn, old_attr ); 2020 #endif 2021 2003 2022 // the PTE must be mapped for a COW 2004 2023 if( (old_attr & GPT_MAPPED) == 0 ) … … 2008 2027 2009 2028 // release GPT lock in write mode 2010 remote_rwlock_wr_ acquire( gpt_lock_xp );2029 remote_rwlock_wr_release( gpt_lock_xp ); 2011 2030 2012 2031 return EXCP_KERNEL_PANIC; 2013 2032 } 2014 2033 2015 // get extended pointer, cluster and local pointeron physical page descriptor2034 // get pointers on physical page descriptor 2016 2035 xptr_t page_xp = ppm_ppn2page( old_ppn ); 2017 2036 cxy_t page_cxy = GET_CXY( page_xp ); … … 2028 2047 uint32_t forks = hal_remote_l32( forks_xp ); 2029 2048 2049 #if( DEBUG_VMM_HANDLE_COW & 1) 2050 if( DEBUG_VMM_HANDLE_COW < cycle ) 2051 printk("\n[%s] thread[%x,%x] get forks = %d for vpn %x\n", 2052 __FUNCTION__, this->process->pid, this->trdid, forks, vpn ); 2053 #endif 2054 2030 2055 if( forks ) // pending fork => allocate a new page, and copy old to new 2031 2056 { 2032 // allocate a new physical page 2057 // decrement pending forks counter in page descriptor 2058 hal_remote_atomic_add( forks_xp , -1 ); 2059 2060 // release lock protecting "forks" counter 2061 remote_busylock_release( forks_lock_xp ); 2062 2063 // allocate a new page 2033 2064 page_xp = vmm_page_allocate( vseg , vpn ); 2065 2034 2066 if( page_xp == XPTR_NULL ) 2035 2067 { … … 2040 2072 remote_rwlock_wr_acquire( gpt_lock_xp ); 2041 2073 2042 // release lock protecting "forks" counter2043 remote_busylock_release( forks_lock_xp );2044 2045 2074 return EXCP_KERNEL_PANIC; 2046 2075 } … … 2049 2078 new_ppn = ppm_page2ppn( page_xp ); 2050 2079 2080 #if( DEBUG_VMM_HANDLE_COW & 1) 2081 if( DEBUG_VMM_HANDLE_COW < cycle ) 2082 printk("\n[%s] thread[%x,%x] get new ppn %x for vpn %x\n", 2083 __FUNCTION__, this->process->pid, this->trdid, new_ppn, vpn ); 2084 #endif 2085 2051 2086 // copy old page content to new page 2052 xptr_t old_base_xp = ppm_ppn2base( old_ppn ); 2053 xptr_t new_base_xp = ppm_ppn2base( new_ppn ); 2054 memcpy( GET_PTR( new_base_xp ), 2055 GET_PTR( old_base_xp ), 2056 CONFIG_PPM_PAGE_SIZE ); 2057 2058 // decrement pending forks counter in page descriptor 2059 hal_remote_atomic_add( forks_xp , -1 ); 2087 hal_remote_memcpy( ppm_ppn2base( new_ppn ), 2088 ppm_ppn2base( old_ppn ), 2089 CONFIG_PPM_PAGE_SIZE ); 2060 2090 2061 2091 #if(DEBUG_VMM_HANDLE_COW & 1) 2062 2092 if( DEBUG_VMM_HANDLE_COW < cycle ) 2063 printk("\n[%s] thread[%x,%x] : pending forks => allocate a new PPN %x\n",2064 __FUNCTION__, process->pid, this->trdid, new_ppn);2093 printk("\n[%s] thread[%x,%x] copied old page to new page\n", 2094 __FUNCTION__, this->process->pid, this->trdid ); 2065 2095 #endif 2066 2096 … … 2068 2098 else // no pending fork => keep the existing page 2069 2099 { 2100 // release lock protecting "forks" counter 2101 remote_busylock_release( forks_lock_xp ); 2070 2102 2071 2103 #if(DEBUG_VMM_HANDLE_COW & 1) 2072 2104 if( DEBUG_VMM_HANDLE_COW < cycle ) 2073 printk("\n[%s] thread[%x,%x] no pending forks =>keep existing PPN %x\n",2074 __FUNCTION__, process->pid, this->trdid, new_ppn );2105 printk("\n[%s] thread[%x,%x] no pending forks / keep existing PPN %x\n", 2106 __FUNCTION__, this->process->pid, this->trdid, old_ppn ); 2075 2107 #endif 2076 2108 new_ppn = old_ppn; 2077 2109 } 2078 2079 // release lock protecting "forks" counter2080 remote_busylock_release( forks_lock_xp );2081 2110 2082 2111 // build new_attr : reset COW and set WRITABLE, 2083 2112 new_attr = (old_attr | GPT_WRITABLE) & (~GPT_COW); 2084 2113 2085 // update the relevan GPT2114 // update the relevant GPT 2086 2115 // - private vseg => update local GPT 2087 2116 // - public vseg => update all GPT copies … … 2119 2148 if( DEBUG_VMM_HANDLE_COW < cycle ) 2120 2149 printk("\n[%s] thread[%x,%x] exit for vpn %x / core[%x,%d] / cycle %d\n", 2121 __FUNCTION__, process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle );2150 __FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle ); 2122 2151 #endif 2123 2152 -
trunk/kernel/syscalls/sys_barrier.c
r581 r619 24 24 #include <hal_kernel_types.h> 25 25 #include <hal_special.h> 26 #include <hal_uspace.h> 26 27 #include <errno.h> 27 28 #include <thread.h> … … 43 44 44 45 ////////////////////////////////// 45 int sys_barrier( void *vaddr,46 int sys_barrier( intptr_t vaddr, 46 47 uint32_t operation, 47 uint32_t count ) 48 uint32_t count, 49 intptr_t attr ) 48 50 { 49 error_t error; 50 vseg_t * vseg; 51 52 thread_t * this = CURRENT_THREAD; 53 process_t * process = this->process; 51 error_t error; 52 vseg_t * vseg; 53 pthread_barrierattr_t k_attr; 54 55 thread_t * this = CURRENT_THREAD; 56 process_t * process = this->process; 54 57 55 58 #if DEBUG_SYS_BARRIER … … 58 61 tm_start = hal_get_cycles(); 59 62 if( DEBUG_SYS_BARRIER < tm_start ) 60 printk("\n[ DBG] %s : thread %x in process %x enterfor %s / count %d / cycle %d\n",61 __FUNCTION__, this->trdid, process->pid, sys_barrier_op_str(operation), count,63 printk("\n[%s] thread[%x,%x] enters for %s / count %d / cycle %d\n", 64 __FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), count, 62 65 (uint32_t)tm_start ); 63 66 #endif 64 67 65 68 // check vaddr in user vspace 66 error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg ); 67 69 error = vmm_get_vseg( process , vaddr , &vseg ); 68 70 if( error ) 69 71 { … … 71 73 #if DEBUG_SYSCALLS_ERROR 72 74 printk("\n[ERROR] in %s : unmapped barrier %x / thread %x / process %x\n", 73 __FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );75 __FUNCTION__ , vaddr , this->trdid , process->pid ); 74 76 vmm_display( process , false ); 75 77 #endif … … 84 86 case BARRIER_INIT: 85 87 { 86 error = remote_barrier_create( (intptr_t)vaddr , count ); 87 88 if( attr != 0 ) // QDT barrier required 89 { 90 error = vmm_get_vseg( process , attr , &vseg ); 91 if( error ) 92 { 93 94 #if DEBUG_SYSCALLS_ERROR 95 printk("\n[ERROR] in %s : unmapped barrier attributes %x / thread %x / process %x\n", 96 __FUNCTION__ , attr , this->trdid , process->pid ); 97 vmm_display( process , false ); 98 #endif 99 this->errno = EINVAL; 100 return -1; 101 } 102 103 // copy barrier attributes into kernel space 104 hal_copy_from_uspace( &k_attr , (void*)attr , sizeof(pthread_barrierattr_t) ); 105 106 if ( count != k_attr.x_size * k_attr.y_size *k_attr.nthreads ) 107 { 108 109 #if DEBUG_SYSCALLS_ERROR 110 printk("\n[ERROR] in %s : wrong arguments / count %d / x_size %d / y_size %d / nthreads %x\n", 111 __FUNCTION__, count, k_attr.x_size, k_attr.y_size, k_attr.nthreads ); 112 #endif 113 this->errno = EINVAL; 114 return -1; 115 } 116 117 118 // call relevant system function 119 error = generic_barrier_create( vaddr , count , &k_attr ); 120 } 121 else // simple barrier required 122 { 123 error = generic_barrier_create( vaddr , count , NULL ); 124 } 125 88 126 if( error ) 89 127 { … … 91 129 #if DEBUG_SYSCALLS_ERROR 92 130 printk("\n[ERROR] in %s : cannot create barrier %x / thread %x / process %x\n", 93 __FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );131 __FUNCTION__ , vaddr , this->trdid , process->pid ); 94 132 #endif 95 this->errno = error;133 this->errno = ENOMEM; 96 134 return -1; 97 135 } … … 101 139 case BARRIER_WAIT: 102 140 { 103 xptr_t barrier_xp = remote_barrier_from_ident( (intptr_t)vaddr );141 xptr_t barrier_xp = generic_barrier_from_ident( vaddr ); 104 142 105 143 if( barrier_xp == XPTR_NULL ) // user error … … 115 153 else // success 116 154 { 117 remote_barrier_wait( barrier_xp );155 generic_barrier_wait( barrier_xp ); 118 156 } 119 157 break; … … 122 160 case BARRIER_DESTROY: 123 161 { 124 xptr_t barrier_xp = remote_barrier_from_ident( (intptr_t)vaddr );162 xptr_t barrier_xp = generic_barrier_from_ident( vaddr ); 125 163 126 164 if( barrier_xp == XPTR_NULL ) // user error … … 136 174 else // success 137 175 { 138 remote_barrier_destroy( barrier_xp );176 generic_barrier_destroy( barrier_xp ); 139 177 } 140 178 break; … … 149 187 tm_end = hal_get_cycles(); 150 188 if( DEBUG_SYS_BARRIER < tm_end ) 151 printk("\n[ DBG] %s : thread %x in process %xexit for %s / cost %d / cycle %d\n",152 __FUNCTION__, this->trdid, process->pid, sys_barrier_op_str(operation),189 printk("\n[%s] thread[%x,%x] exit for %s / cost %d / cycle %d\n", 190 __FUNCTION__, process->pid, this->trdid, sys_barrier_op_str(operation), 153 191 (uint32_t)(tm_end - tm_start), (uint32_t)tm_end ); 154 192 #endif -
trunk/kernel/syscalls/sys_display.c
r614 r619 77 77 tm_start = hal_get_cycles(); 78 78 if( DEBUG_SYS_DISPLAY < tm_start ) 79 printk("\n[ DBG] %s :thread[%x,%x] enter / type %s / cycle = %d\n",79 printk("\n[%s] thread[%x,%x] enter / type %s / cycle = %d\n", 80 80 __FUNCTION__, process->pid, this->trdid, display_type_str(type), (uint32_t)tm_start ); 81 81 #endif … … 84 84 if( type == DISPLAY_STRING ) 85 85 { 86 char kbuf[ 256];86 char kbuf[512]; 87 87 uint32_t length; 88 88 … … 106 106 length = hal_strlen_from_uspace( string ); 107 107 108 if( length >= 256)108 if( length >= 512 ) 109 109 { 110 110 … … 118 118 119 119 // copy string to kernel space 120 hal_strcpy_from_uspace( kbuf , string , 256);120 hal_strcpy_from_uspace( kbuf , string , 512 ); 121 121 122 122 // print message on TXT0 kernel terminal … … 281 281 } 282 282 283 thread_display_busylocks( thread_xp );283 thread_display_busylocks( thread_xp , __FUNCTION__ ); 284 284 } 285 285 ///////////////////////////////// … … 388 388 #if DEBUG_SYS_DISPLAY 389 389 if( DEBUG_SYS_DISPLAY < tm_end ) 390 printk("\n[ DBG] %s :thread[%x,%x] exit / cycle %d\n",390 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 391 391 __FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end ); 392 392 #endif -
trunk/kernel/syscalls/sys_exit.c
r584 r619 58 58 tm_start = hal_get_cycles(); 59 59 if( DEBUG_SYS_EXIT < tm_start ) 60 printk("\n[ DBG] %s :thread[%x,%x] enter / status %x / cycle %d\n",60 printk("\n[%s] thread[%x,%x] enter / status %x / cycle %d\n", 61 61 __FUNCTION__, process->pid, this->trdid , status , (uint32_t)tm_start ); 62 62 #endif … … 69 69 #if (DEBUG_SYS_EXIT & 1) 70 70 if( DEBUG_SYS_EXIT < tm_start ) 71 printk("\n[ DBG] %s :thread[%x,%x] get owner process in cluster %x\n",71 printk("\n[%s] thread[%x,%x] get owner process in cluster %x\n", 72 72 __FUNCTION__, process->pid, this->trdid, owner_cxy ); 73 73 #endif … … 83 83 #if (DEBUG_SYS_EXIT & 1) 84 84 if( DEBUG_SYS_EXIT < tm_start ) 85 printk("\n[ DBG] %s :thread[%x,%x] get parent process in cluster %x\n",85 printk("\n[%s] thread[%x,%x] get parent process in cluster %x\n", 86 86 __FUNCTION__, process->pid, this->trdid, parent_cxy ); 87 87 #endif … … 96 96 #if( DEBUG_SYS_EXIT & 1) 97 97 if( DEBUG_SYS_EXIT < tm_start ) 98 printk("\n[ DBG] %s :thread[%x,%x] detached process from TXT\n",98 printk("\n[%s] thread[%x,%x] detached process from TXT\n", 99 99 __FUNCTION__, process->pid, this->trdid ); 100 100 #endif … … 106 106 #if( DEBUG_SYS_EXIT & 1) 107 107 if( DEBUG_SYS_EXIT < tm_start ) 108 printk("\n[ DBG] %s :thread[%x,%x] deleted all threads but itself\n",108 printk("\n[%s] thread[%x,%x] deleted all threads but itself\n", 109 109 __FUNCTION__, process->pid, this->trdid ); 110 110 #endif … … 116 116 #if( DEBUG_SYS_EXIT & 1) 117 117 if( tm_start > DEBUG_SYS_EXIT ) 118 printk("\n[ DBG] %s :thread[%x,%x] marked iself for delete\n",118 printk("\n[%u] thread[%x,%x] marked iself for delete\n", 119 119 __FUNCTION__, process->pid, this->trdid ); 120 120 #endif … … 127 127 #if( DEBUG_SYS_EXIT & 1) 128 128 if( tm_start > DEBUG_SYS_EXIT ) 129 printk("\n[ DBG] %s :thread[%x,%x] blocked main thread\n",129 printk("\n[%s] thread[%x,%x] blocked main thread\n", 130 130 __FUNCTION__, process->pid, this->trdid ); 131 131 #endif … … 138 138 #if( DEBUG_SYS_EXIT & 1) 139 139 if( tm_start > DEBUG_SYS_EXIT ) 140 printk("\n[ DBG] %s :thread[%x,%x] set exit status %x in owner process\n",140 printk("\n[%s] thread[%x,%x] set exit status %x in owner process\n", 141 141 __FUNCTION__, process->pid, this->trdid, term_state ); 142 142 #endif … … 147 147 #if( DEBUG_SYS_EXIT & 1) 148 148 if( tm_start > DEBUG_SYS_EXIT ) 149 printk("\n[ DBG] %s :thread[%x,%x] unblocked parent main thread in process %x\n",149 printk("\n[%s] thread[%x,%x] unblocked parent main thread in process %x\n", 150 150 __FUNCTION__ , process->pid, this->trdid, 151 151 hal_remote_l32( XPTR( parent_cxy , &parent_ptr->pid) ) ); … … 157 157 tm_end = hal_get_cycles(); 158 158 if( DEBUG_SYS_EXIT < tm_end ) 159 printk("\n[ DBG] %s :thread[%x,%x] exit / status %x / cost = %d / cycle %d\n",159 printk("\n[%s] thread[%x,%x] exit / status %x / cost = %d / cycle %d\n", 160 160 __FUNCTION__, process->pid, this->trdid, status, 161 161 (uint32_t)(tm_end - tm_start), (uint32_t)tm_end ); -
trunk/kernel/syscalls/sys_thread_create.c
r594 r619 70 70 if( DEBUG_SYS_THREAD_CREATE < tm_start ) 71 71 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 72 __FUNCTION__, process _pid, parent->trdid, (uint32_t)tm_start );72 __FUNCTION__, process->pid, parent->trdid, (uint32_t)tm_start ); 73 73 #endif 74 74 -
trunk/kernel/syscalls/sys_thread_exit.c
r584 r619 64 64 uint64_t tm_start = hal_get_cycles(); 65 65 if( DEBUG_SYS_THREAD_EXIT < tm_start ) 66 printk("\n[ DBG] %s :thread[%x,%x] / main => delete process / cycle %d\n",66 printk("\n[%s] thread[%x,%x] / main => delete process / cycle %d\n", 67 67 __FUNCTION__ , pid , trdid , (uint32_t)tm_start ); 68 68 #endif … … 76 76 uint64_t tm_start = hal_get_cycles(); 77 77 if( DEBUG_SYS_THREAD_EXIT < tm_start ) 78 printk("\n[ DBG] %s :thread[%x,%x] / not main => delete thread / cycle %d\n",78 printk("\n[%s] thread[%x,%x] / not main => delete thread / cycle %d\n", 79 79 __FUNCTION__ , pid , trdid , (uint32_t)tm_start ); 80 80 #endif -
trunk/kernel/syscalls/syscalls.h
r611 r619 146 146 * The code implementting the operations is defined in the remote_barrier.c file. 147 147 ****************************************************************************************** 148 * @ vaddr : barrier virtualaddress in user space == identifier.148 * @ vaddr : barrier address in user space == identifier. 149 149 * @ operation : BARRIER_INIT / BARRIER_DESTROY / BARRIER_WAIT. 150 * @ count : number of expected threads (only used by BARRIER_INIT operation). 151 * @ return 0 if success / return -1 if failure. 152 *****************************************************************************************/ 153 int sys_barrier( void * vaddr, 150 * @ count : number of expected threads (only used by BARRIER_INIT). 151 * @ attr : barrier attributes address in user space (only used by BARRIER_INIT). 152 * @ return 0 if success / return -1 if failure. 153 *****************************************************************************************/ 154 int sys_barrier( intptr_t vaddr, 154 155 uint32_t operation, 155 uint32_t count ); 156 uint32_t count, 157 intptr_t attr ); 156 158 157 159 /****************************************************************************************** -
trunk/libs/libpthread/pthread.c
r609 r619 2 2 * pthread.c - User level <pthread> library implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018 )4 * Author Alain Greiner (2016,2017,2018,2019) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 202 202 unsigned int count ) 203 203 { 204 if ( attr )205 {206 printf("[ERROR] in %s ; <attr> argument must be NULL\n", __FUNCTION__ );207 return -1;208 }209 210 204 return hal_user_syscall( SYS_BARRIER, 211 205 (reg_t)barrier, 212 206 BARRIER_INIT, 213 207 (reg_t)count, 214 0);208 (reg_t)attr ); 215 209 } 216 210 … … 362 356 } 363 357 364 // check attributes 358 // check attributes / count 365 359 if( (x_size * y_size * nthreads) != count ) 366 360 { -
trunk/libs/libsemaphore/semaphore.h
r573 r619 27 27 ////////////////////////////////////////////////////////////////////////////////////////////// 28 28 // POSIX unnamed semaphores related functions 29 // 30 // This synchonisation object allows several thread in a given process to share one 31 // (or several) shared resource(s). 32 // - The sem_wait() function allows a thread to take one resource and atomically 33 // decrement the semaphore count. If the count value is zero, the calling thread 34 // blocks and deschedules. It is unblocked by another thread when it becomes possible 35 // to make the decrement. 36 // - the sem_post() functions allows a thread to release a resource and atomicalli 37 // increment the semaphore count. 29 38 ////////////////////////////////////////////////////////////////////////////////////////////// 30 39 … … 37 46 * @ sem : [in] pointer on semaphore. 38 47 * @ pshared : [in] unsupported => must be zero. 39 * @ value: [in] initial semaphore value.48 * @ count : [in] initial semaphore value. 40 49 * @ return 0 if success / return -1 if failure. 41 50 ********************************************************************************************/ 42 51 int sem_init( sem_t * sem, 43 52 int pshared, 44 unsigned int value);53 unsigned int count ); 45 54 46 55 /********************************************************************************************* -
trunk/libs/mini-libc/string.c
r473 r619 80 80 81 81 82 ////////////////////////// /83 char * strcpy (char * d est,82 ////////////////////////// 83 char * strcpy (char * dst, 84 84 char * src ) 85 85 { 86 char *src_ptr = src; 87 char *dst_ptr = dest; 88 89 while(*src_ptr) *(dst_ptr++) = *(src_ptr++); 90 91 *dst_ptr = 0; 92 return dest; 93 } 94 95 //////////////////////////////////// 96 char * strncpy( char * dest, 86 while( *src ) 87 { 88 *(dst) = *(src); 89 dst++; 90 src++; 91 } 92 93 // set NUL terminating character 94 *dst = 0; 95 96 return dst; 97 } 98 99 /////////////////////////////////// 100 char * strncpy( char * dst, 97 101 char * src, 98 unsigned int n)102 unsigned int count ) 99 103 { 100 104 unsigned int i; 101 105 102 for (i = 0; (i < n) && (src[i] != '\0') ; i++) dest[i] = src[i]; 103 104 for (; i < n; i++) dest[i] = '\0'; 105 106 return dest; 106 // copy at most count characters 107 for (i = 0 ; (i < count) && (src[i] != '\0') ; i++) dst[i] = src[i]; 108 109 // complete with NUL characters 110 for ( ; i < count ; i++) dst[i] = '\0'; 111 112 return dst; 107 113 } 108 114 -
trunk/libs/mini-libc/string.h
r445 r619 70 70 * @ return 0 if s1 == s2 / return 1 if s1 > s2 / return -1 if s1 < s2 71 71 *******************************************************************************************/ 72 int strncmp ( const char * s1,73 const char * s2,72 int strncmp ( const char * s1, 73 const char * s2, 74 74 unsigned int n ); 75 75 … … 84 84 85 85 /******************************************************************************************** 86 * This function copies < n> characters from the <sr> buffer to the <dst> buffer.86 * This function copies <count> characters from the <src> buffer to the <dst> buffer. 87 87 ******************************************************************************************** 88 88 * @ dst : pointer on destination buffer. 89 89 * @ src : pointer on source buffer. 90 * @ n: number of characters to be copied.90 * @ count : number of characters to be copied. 91 91 *******************************************************************************************/ 92 92 char * strncpy ( char * dst, 93 93 char * src, 94 unsigned int n);94 unsigned int count ); 95 95 96 96 /******************************************************************************************** -
trunk/params-hard.mk
r611 r619 3 3 ARCH = /users/alain/soc/tsar-trunk-svn-2013/platforms/tsar_generic_iob 4 4 X_SIZE = 1 5 Y_SIZE = 15 Y_SIZE = 2 6 6 NB_PROCS = 1 7 7 NB_TTYS = 2 -
trunk/user/ksh/ksh.c
r616 r619 21 21 // the TXT terminal ownership. 22 22 // 23 // We use a semaphore to synchronize the two KSH threads. A t each iteration,24 // the interactive thread check the semaphore (with a sem_wait). It blocks25 // and deschedules, if the KSH process loosed the TXT ownership (after a load,26 // or for any other cause . It unblockswith the following policy:23 // We use a semaphore to synchronize the two KSH threads. After each command 24 // completion, the interactive thread check the TXT ownership (with a sem_wait), 25 // and blocks, if the KSH process loosed the TXT ownership (after a load, 26 // or for any other cause). It is unblocked with the following policy: 27 27 // . if the command is "not a load", the semaphore is incremented by the 28 // cmd_***() function when the command is completed, to allow the KSH interactive()29 // function to get the next commandin the while loop.28 // cmd_***() function when the command is completed, to get the next command 29 // in the while loop. 30 30 // . if the command is a "load without &", the TXT is given to the NEW process by the 31 31 // execve() syscall, and is released to the KSH process when NEW process terminates. … … 56 56 57 57 #define DEBUG_MAIN 0 58 58 #define DEBUG_INTER 0 59 #define DEBUG_PARSE 0 59 60 #define DEBUG_CMD_CAT 0 60 61 #define DEBUG_CMD_CP 0 61 62 #define DEBUG_CMD_LOAD 0 62 63 #define DEBUG_CMD_LS 0 64 #define DEBUG_CMD_PS 0 63 65 64 66 ////////////////////////////////////////////////////////////////////////////////////////// … … 88 90 ////////////////////////////////////////////////////////////////////////////////////////// 89 91 90 ksh_cmd_t c md[];// array of supported commands92 ksh_cmd_t command[]; // array of supported commands 91 93 92 94 log_entry_t log_entries[LOG_DEPTH]; // array of registered commands … … 99 101 sem_t semaphore; // block interactive thread when zero 100 102 103 pthread_t trdid; // interactive thread identifier 104 101 105 ////////////////////////////////////////////////////////////////////////////////////////// 102 106 // Shell Commands … … 112 116 char * buf; 113 117 118 #if DEBUG_CMD_CAT 119 char string[64]; 120 #endif 121 114 122 if (argc != 2) 115 123 { … … 134 142 135 143 #if DEBUG_CMD_CAT 136 long long unsigned cycle; 137 get_cycle( &cycle ); 138 printf("\n[%s] file %s open / cycle %d\n", 139 __FUNCTION__ , path , (int)cycle ); 144 snprintf( string , 64 , "[KSH] %s : file %s open", __FUNCTION__, path ); 145 display_string( string ); 140 146 #endif 141 147 … … 161 167 162 168 #if DEBUG_CMD_CAT 163 get_cycle( &cycle ); 164 printf("\n[%s] get size %d / cycle %d\n", 165 __FUNCTION__ , size , (int)cycle ); 169 snprintf( string , 64 , "[KSH] %s : get size = %d", __FUNCTION__, size ); 170 display_string( string ); 166 171 #endif 167 172 … … 176 181 177 182 #if DEBUG_CMD_CAT 178 get_cycle( &cycle ); 179 printf("\n[%s] map file %d to buffer %x / cycle %d\n", 180 __FUNCTION__ , fd , buf , (int)cycle ); 183 snprintf( string , 64 , "[KSH] %s : map file %d to buffer %x", __FUNCTION__, fd , buf ); 184 display_string( string ); 181 185 display_vmm( 0 , getpid() ); 182 186 #endif … … 237 241 struct stat st; 238 242 243 #if DEBUG_CMD_CP 244 char string[64]; 245 #endif 246 239 247 if (argc != 3) 240 248 { … … 259 267 260 268 #if DEBUG_CMD_CP 261 long long unsigned cycle; 262 get_cycle( &cycle ); 263 printf("\n[%s] open file <%s> done / cycle %d\n", 264 __FUNCTION__ , srcpath , (int)cycle ); 269 snprintf( string , 64 , "[KSH] %s : file %s open", __FUNCTION__, srcpath ); 270 display_string( string ); 265 271 #endif 266 272 … … 274 280 275 281 #if DEBUG_CMD_CP 276 get_cycle( &cycle ); 277 printf("\n[%s] stats file <%s> done / cycle %d\n", 278 __FUNCTION__ , srcpath , (int)cycle ); 282 snprintf( string , 64 , "[KSH] %s : got stats for %s", __FUNCTION__, srcpath ); 283 display_string( string ); 279 284 #endif 280 285 … … 299 304 300 305 #if DEBUG_CMD_CP 301 get_cycle( &cycle ); 302 printf("\n[%s] open file <%s> done / cycle %d\n", 303 __FUNCTION__ , dstpath , (int)cycle ); 306 snprintf( string , 64 , "[KSH] %s : file %s open", __FUNCTION__, dstpath ); 307 display_string( string ); 304 308 #endif 305 309 … … 311 315 312 316 #if DEBUG_CMD_CP 313 get_cycle( &cycle ); 314 printf("\n[%s] stats file <%s> done / cycle %d\n", 315 __FUNCTION__ , dstpath , (int)cycle ); 317 snprintf( string , 64 , "[KSH] %s : got stats for %s", __FUNCTION__, dstpath ); 318 display_string( string ); 316 319 #endif 317 320 … … 336 339 337 340 #if DEBUG_CMD_CP 338 get_cycle( &cycle ); 339 printf("\n[%s] %d bytes read from <%s> / cycle %d\n", 340 __FUNCTION__ , len, srcpath , (int)cycle ); 341 snprintf( string , 64 , "[KSH] %s : read %d bytes from %s", __FUNCTION__, len, srcpath ); 342 display_string( string ); 341 343 #endif 342 344 … … 349 351 350 352 #if DEBUG_CMD_CP 351 get_cycle( &cycle ); 352 printf("\n[%s] %d bytes writen to <%s> / cycle %d\n", 353 __FUNCTION__ , len, dstpath , (int)cycle ); 353 snprintf( string , 64 , "[KSH] %s : write %d bytes to %s", __FUNCTION__, len, dstpath ); 354 display_string( string ); 354 355 #endif 355 356 … … 573 574 else 574 575 { 575 576 for (i = 0 ; c md[i].name ; i++)577 { 578 printf("\t%s\t : %s\n", c md[i].name , cmd[i].desc);576 printf("available commands:\n"); 577 for (i = 0 ; command[i].name ; i++) 578 { 579 printf("\t%s\t : %s\n", command[i].name , command[i].desc); 579 580 } 580 581 } … … 624 625 unsigned int placement; // placement specified if non zero 625 626 unsigned int cxy; // target cluster if placement specified 627 628 #if DEBUG_CMD_LOAD 629 char string[64]; 630 #endif 626 631 627 632 if( (argc < 2) || (argc > 4) ) … … 661 666 } 662 667 668 /* 669 // take semaphore to block the interactive thread 670 if ( sem_wait( &semaphore ) ) 671 { 672 printf("\n[ksh error] cannot found semafore\n" ); 673 exit( 1 ); 674 } 675 */ 663 676 // get KSH process PID 664 677 ksh_pid = getpid(); 665 678 666 679 #if DEBUG_CMD_LOAD 667 long long unsigned cycle; 668 get_cycle( &cycle ); 669 printf("\n[ksh] %s : ksh_pid %x / path %s / bg %d / place %d (%x) / cycle %d\n", 670 __FUNCTION__, ksh_pid, argv[1], background, placement, cxy, (int)cycle ); 680 snprintf( string , 64 , "[KSH] %s : ksh_pid %x / path %s / bg %d / place %d (%x)\n", 681 __FUNCTION__, ksh_pid, argv[1], background, placement, cxy ); 682 display_string( string ); 671 683 #endif 672 684 … … 685 697 686 698 #if DEBUG_CMD_LOAD 687 get_cycle( &cycle ); 688 printf("\n[ksh] %s : child_pid %x after fork, before exec / cycle %d\n", 689 __FUNCTION__ , getpid(), (int)cycle);699 snprintf( string , 64 , "[KSH] %s : child_pid %x after fork, before exec\n", 700 __FUNCTION__ , getpid() ); 701 display_string( string ); 690 702 #endif 691 703 … … 694 706 695 707 #if DEBUG_CMD_LOAD 696 get_cycle( &cycle ); 697 printf("\n[ksh] %s : child_pid %x after exec / ret_exec %d / cycle %d\n", 698 __FUNCTION__ , getpid(), ret_exec, (int)cycle);708 snprintf( string , 64 , "[KSH] %s : child_pid %x after exec / ret_exec %x\n", 709 __FUNCTION__ , getpid(), ret_exec ); 710 display_string( string ); 699 711 #endif 700 712 … … 710 722 711 723 #if DEBUG_CMD_LOAD 712 get_cycle( &cycle ); 713 printf("\n[ksh] %s : ksh_pid %x after fork / ret_fork %x / cycle %d\n", 714 __FUNCTION__, getpid(), ret_fork, (int)cycle);715 #endif 716 717 if( background ) // child in background =>KSH must keep TXT ownership724 snprintf( string , 64 , "[KSH] %s : ksh_pid %x after fork / ret_fork %x\n", 725 __FUNCTION__, getpid(), ret_fork ); 726 display_string( string ); 727 #endif 728 729 if( background ) // KSH must keep TXT ownership 718 730 { 731 // get back the TXT ownership 719 732 fg( ksh_pid ); 733 734 // release semaphore to get next command 735 sem_post( &semaphore ); 720 736 } 721 } 722 } 723 724 // release semaphore to get next command 725 sem_post( &semaphore ); 726 737 else // KSH loosed TXT ownership 738 { 739 // semaphore will be released by the KSH main thread 740 // when the loaded process exit 741 } 742 } 743 } 727 744 } // end cmd_load 728 745 … … 758 775 DIR * dir; 759 776 777 #if DEBUG_CMD_LS 778 char string[64]; 779 #endif 780 760 781 if (argc > 2 ) 761 782 { … … 774 795 775 796 #if DEBUG_CMD_LS 776 printf("\n[ksh] %s : directory <%s> open / DIR %x\n",797 snprintf( string , 64 , "[KSH] %s : directory <%s> open / DIR %x\n", 777 798 __FUNCTION__, pathname , dir ); 799 display_string( string ); 778 800 #endif 779 801 … … 794 816 795 817 #if DEBUG_CMD_LS 796 printf("\n[ksh] %s : directory <%s> closed\n",818 snprintf( string , 64 , "[KSH] %s : directory <%s> closed\n", 797 819 __FUNCTION__, pathname ); 820 display_string( string ); 798 821 #endif 799 822 … … 865 888 unsigned int y; 866 889 890 #if DEBUG_CMD_PS 891 char string[64]; 892 #endif 893 867 894 if (argc != 1) 868 895 { … … 879 906 for( y = 0 ; y < y_size ; y++ ) 880 907 { 908 909 #if DEBUG_CMD_PS 910 snprintf( string , 64 , "\n[KSH] %s : call display_cluster_process()", __FUNCTION__ ); 911 display_string( string ); 912 #endif 913 881 914 // display only owned processes 882 915 display_cluster_processes( HAL_CXY_FROM_XY(x,y), 1 ); … … 1003 1036 /////////////////////////////////////////////////////////////////////////////////// 1004 1037 1005 ksh_cmd_t c md[] =1038 ksh_cmd_t command[] = 1006 1039 { 1007 1040 { "cat", "display file content", cmd_cat }, … … 1031 1064 static void __attribute__ ((noinline)) parse( char * buf ) 1032 1065 { 1033 int argc = 0; 1034 char *argv[MAX_ARGS]; 1035 int i; 1036 int len = strlen(buf); 1066 int argc = 0; 1067 char * argv[MAX_ARGS]; 1068 int i; 1069 int len = strlen(buf); 1070 1071 #if DEBUG_PARSE 1072 char string[64]; 1073 snprintf( string , 64 , "\n[KSH] %s : <%s>", __FUNCTION__ , buf ); 1074 display_string( string ); 1075 #endif 1037 1076 1038 1077 // build argc/argv 1039 1078 for (i = 0; i < len; i++) 1040 1079 { 1080 // convert SPACE to NUL 1041 1081 if (buf[i] == ' ') 1042 1082 { … … 1053 1093 } 1054 1094 1095 #if DEBUG_PARSE 1096 snprintf( string , 64 , "\n[KSH] %s : argc = %d for <%s>", __FUNCTION__ , argc , argv[0] ); 1097 display_string( string ); 1098 #endif 1099 1055 1100 // analyse command type 1056 1101 if (argc > 0) … … 1058 1103 int found = 0; 1059 1104 1060 argv[argc] = NULL;1061 1062 1105 // try to match typed command 1063 for ( i = 0 ; cmd[i].name ; i++)1064 { 1065 if (strcmp(argv[0], c md[i].name) == 0)1106 for ( i = 0 ; command[i].name ; i++ ) 1107 { 1108 if (strcmp(argv[0], command[i].name) == 0) 1066 1109 { 1067 c md[i].fn(argc, argv);1110 command[i].fn(argc, argv); 1068 1111 found = 1; 1069 1112 break; … … 1085 1128 { 1086 1129 char c; // read character 1087 char buf[CMD_MAX_SIZE]; // buffer for one command1088 1130 unsigned int end_command; // last character found in a command 1089 1131 unsigned int count; // pointer in command buffer … … 1091 1133 unsigned int state; // escape sequence state 1092 1134 1135 char cmd[CMD_MAX_SIZE]; // buffer for one command 1136 1137 #if DEBUG_INTER 1138 char string[64]; 1139 #endif 1093 1140 1094 1141 /* To lauch one command without interactive mode 1095 1096 1142 if( sem_wait( &semaphore ) ) 1097 1143 { … … 1101 1147 else 1102 1148 { 1103 printf("\n[ksh] l s bin/user\n");1149 printf("\n[ksh] load bin/user/sort.elf\n"); 1104 1150 } 1105 1151 1106 strcpy( buf , "ls bin/user" ); 1107 parse( buf ); 1108 1152 strcpy( cmd , "load bin/user/sort.elf" ); 1153 parse( cmd ); 1109 1154 */ 1110 1155 … … 1127 1172 // - BRAKET : the wo characters (ESC,[) have been found 1128 1173 1129 // external loop on the commands 1130 // the in teractive thread should not exit this loop 1174 // take the semaphore for the first command 1175 if ( sem_wait( &semaphore ) ) 1176 { 1177 printf("\n[ksh error] cannot found semafore\n" ); 1178 exit( 1 ); 1179 } 1180 1181 // display prompt for the first command 1182 printf("\n[ksh] "); 1183 1184 // external loop on the commands / the interactive thread do not exit this loop 1131 1185 while (1) 1132 1186 { 1133 1187 // initialize command buffer 1134 memset( buf, 0x20 , sizeof(buf) ); // TODO useful ? 1135 count = 0; 1136 state = NORMAL; 1137 1138 // decrement semaphore, and block if the KSH process is not the TXT owner 1139 if ( sem_wait( &semaphore ) ) 1140 { 1141 printf("\n[ksh error] cannot found semafore\n" ); 1142 exit( 1 ); 1143 } 1144 1145 // display prompt on a new line 1146 printf("\n[ksh] "); 1147 1188 memset( cmd, 0x20 , sizeof(cmd) ); // TODO useful ? 1189 count = 0; 1190 state = NORMAL; 1148 1191 end_command = 0; 1192 1193 #if DEBUG_INTER 1194 unsigned int pid = getpid(); 1195 snprintf( string , 64 , "\n[KSH] %s : request a new command", __FUNCTION__ ); 1196 display_string( string ); 1197 #endif 1149 1198 1150 1199 // internal loop on characters in one command … … 1171 1220 { 1172 1221 // complete command with NUL character 1173 buf[count] = 0;1222 cmd[count] = 0; 1174 1223 count++; 1175 1224 1176 // register command in log arrays 1177 str cpy(log_entries[ptw].buf, buf);1225 // register command in log 1226 strncpy( log_entries[ptw].buf , cmd , count ); 1178 1227 log_entries[ptw].count = count; 1179 1228 ptw = (ptw + 1) % LOG_DEPTH; 1180 1229 ptr = ptw; 1181 1230 1231 #if DEBUG_INTER 1232 snprintf( string , 64 , "[KSH] %s : parse and execute <%s>", __FUNCTION__, cmd ); 1233 display_string( string ); 1234 #endif 1182 1235 // echo character 1183 1236 putchar( c ); 1184 1237 1185 1238 // call parser to analyse and execute command 1186 parse( buf);1239 parse( cmd ); 1187 1240 } 1188 1241 else // no command registered … … 1204 1257 else // normal character 1205 1258 { 1206 if (count < sizeof(buf) - 1)1259 if (count < (sizeof(cmd) - 1) ) 1207 1260 { 1208 1261 // register character in command buffer 1209 buf[count] = c;1262 cmd[count] = c; 1210 1263 count++; 1211 1264 … … 1213 1266 putchar( c ); 1214 1267 } 1268 else 1269 { 1270 printf("\none command cannot exceed %d characters\n", sizeof(cmd) ); 1271 } 1215 1272 } 1216 1273 } … … 1228 1285 else if( state == BRAKET ) 1229 1286 { 1230 if (c == 'D') // valid LEFT sequence => move bufpointer left1287 if (c == 'D') // valid LEFT sequence => move cmd pointer left 1231 1288 { 1232 1289 if (count > 0) … … 1239 1296 state = NORMAL; 1240 1297 } 1241 else if (c == 'C') // valid RIGHT sequence => move bufpointer right1298 else if (c == 'C') // valid RIGHT sequence => move cmd pointer right 1242 1299 { 1243 if (count < sizeof( buf) - 1)1300 if (count < sizeof(cmd) - 1) 1244 1301 { 1245 printf("%c", buf[count]);1302 printf("%c", cmd[count]); 1246 1303 count++; 1247 1304 } … … 1256 1313 count = 0; 1257 1314 1258 // copy log command into buf1315 // copy log command into cmd 1259 1316 ptr = (ptr - 1) % LOG_DEPTH; 1260 strcpy( buf, log_entries[ptr].buf);1317 strcpy(cmd, log_entries[ptr].buf); 1261 1318 count = log_entries[ptr].count - 1; 1262 1319 1263 1320 // display log command 1264 printf("%s", buf);1321 printf("%s", cmd); 1265 1322 1266 1323 // get next user char … … 1273 1330 count = 0; 1274 1331 1275 // copy log command into buf1332 // copy log command into cmd 1276 1333 ptr = (ptr + 1) % LOG_DEPTH; 1277 strcpy( buf, log_entries[ptr].buf);1334 strcpy(cmd, log_entries[ptr].buf); 1278 1335 count = log_entries[ptr].count; 1279 1336 1280 1337 // display log command 1281 printf("%s", buf);1338 printf("%s", cmd); 1282 1339 1283 1340 // get next user char … … 1291 1348 } 1292 1349 } // end internal while loop on characters 1350 1351 #if DEBUG_INTER 1352 snprintf( string , 64 , "\n[KSH] %s : complete <%s> command", __FUNCTION__, cmd ); 1353 display_string( string ); 1354 #endif 1355 1356 // block interactive thread if KSH loose TXT ownership 1357 if ( sem_wait( &semaphore ) ) 1358 { 1359 printf("\n[ksh error] cannot found semafore\n" ); 1360 exit( 1 ); 1361 } 1362 1363 // display prompt for next command 1364 printf("\n[ksh] "); 1365 1293 1366 } // end external while loop on commands 1367 1294 1368 } // end interactive() 1295 1369 … … 1302 1376 int child_pid; // child process identifier 1303 1377 int parent_pid; // parent process identifier (i.e. this process) 1304 pthread_t trdid; // interactive thread identifier (unused)1305 1378 unsigned int is_owner; // non-zero if KSH process is TXT owner 1306 1379 … … 1315 1388 1316 1389 #if DEBUG_MAIN 1317 printf("\n[ksh] main started on core[%x,%d]\n", cxy , lid );1390 printf("\n[ksh] main thread started on core[%x,%d]\n", cxy , lid ); 1318 1391 #endif 1319 1392 … … 1339 1412 NULL ); 1340 1413 #if DEBUG_MAIN 1341 printf("\n[ksh] main launched interactive thread => wait children termination\n");1414 printf("\n[ksh] main thread launched interactive thread %x\n", trdid ); 1342 1415 #endif 1343 1416 … … 1360 1433 is_fg( parent_pid , &is_owner ); 1361 1434 if( is_owner ) sem_post( &semaphore ); 1362 1363 1435 } 1364 1436 } // end main() -
trunk/user/sort/sort.c
r596 r619 29 29 #include <hal_macros.h> 30 30 31 #define ARRAY_LENGTH 0x1000 // 4096 values 32 31 #define ARRAY_LENGTH 256 // number of values 33 32 #define MAX_THREADS 1024 // 16 * 16 * 4 34 33 #define USE_DQT_BARRIER 1 35 34 #define DISPLAY_ARRAY 0 36 35 #define INTERACTIVE_MODE 0 … … 42 41 typedef struct 43 42 { 44 unsigned int threads; // total number of threads43 unsigned int threads; // total number of threads 45 44 unsigned int thread_uid; // thread user index (0 to threads -1) 46 45 unsigned int main_uid; // main thread user index … … 206 205 void main( void ) 207 206 { 207 int error; 208 208 unsigned int x_size; // number of rows 209 209 unsigned int y_size; // number of columns 210 210 unsigned int ncores; // number of cores per cluster 211 unsigned int t hreads;// total number of threads211 unsigned int total_threads; // total number of threads 212 212 unsigned int thread_uid; // user defined thread index 213 213 unsigned int main_cxy; // cluster identifier for main … … 226 226 // compute number of threads (one thread per core) 227 227 get_config( &x_size , &y_size , &ncores ); 228 t hreads = x_size * y_size * ncores;228 total_threads = x_size * y_size * ncores; 229 229 230 230 // get core coordinates and user index for the main thread … … 235 235 236 236 // checks number of threads 237 if ( (t hreads != 1) && (threads != 2) && (threads != 4) &&238 (t hreads != 8) && (threads != 16 ) && (threads != 32) &&239 (t hreads != 64) && (threads != 128) && (threads != 256) &&240 (t hreads != 512) && (threads != 1024) )237 if ( (total_threads != 1) && (total_threads != 2) && (total_threads != 4) && 238 (total_threads != 8) && (total_threads != 16 ) && (total_threads != 32) && 239 (total_threads != 64) && (total_threads != 128) && (total_threads != 256) && 240 (total_threads != 512) && (total_threads != 1024) ) 241 241 { 242 242 printf("\n[SORT ERROR] number of cores must be power of 2\n"); … … 245 245 246 246 // check array size 247 if ( ARRAY_LENGTH % t hreads)247 if ( ARRAY_LENGTH % total_threads) 248 248 { 249 249 printf("\n[SORT ERROR] array size must be multiple of number of threads\n"); … … 251 251 } 252 252 253 printf("\n[SORT] main starts on core[%x,%d] / %d thread(s) / %d values / PID %x\n", 254 main_cxy, main_lid, threads, ARRAY_LENGTH, getpid() ); 255 256 // Barrier initialization 257 barrier_attr.x_size = x_size; 258 barrier_attr.y_size = y_size; 259 barrier_attr.nthreads = ncores; 260 if( pthread_barrier_init( &barrier, &barrier_attr , threads ) ) 253 printf("\n\n[SORT] main starts on core[%x,%d] / %d threads / %d values / PID %x\n", 254 main_cxy, main_lid, total_threads, ARRAY_LENGTH, getpid() ); 255 256 // initialize barrier 257 if( USE_DQT_BARRIER ) 258 { 259 barrier_attr.x_size = x_size; 260 barrier_attr.y_size = y_size; 261 barrier_attr.nthreads = ncores; 262 error = pthread_barrier_init( &barrier, &barrier_attr , total_threads ); 263 } 264 else // use SIMPLE_BARRIER 265 { 266 error = pthread_barrier_init( &barrier, NULL , total_threads ); 267 } 268 269 if( error ) 261 270 { 262 271 printf("\n[SORT ERROR] cannot initialise barrier\n" ); … … 290 299 291 300 // set sort arguments for all threads 292 arg[thread_uid].threads = t hreads;301 arg[thread_uid].threads = total_threads; 293 302 arg[thread_uid].thread_uid = thread_uid; 294 303 arg[thread_uid].main_uid = main_uid; … … 330 339 sort( &arg[main_uid] ); 331 340 341 #if INTERACTIVE_MODE 342 idbg(); 343 #endif 344 345 // destroy barrier 346 pthread_barrier_destroy( &barrier ); 347 348 #if INTERACTIVE_MODE 349 idbg(); 350 #endif 351 332 352 // Check result 333 353 int success = 1; 334 int* res_array = ( (t hreads==2) ||335 (t hreads==8) ||336 (t hreads==32) ||337 (t hreads==128) ||338 (t hreads==512) ) ? array1 : array0;354 int* res_array = ( (total_threads == 2) || 355 (total_threads == 8) || 356 (total_threads == 32) || 357 (total_threads == 128) || 358 (total_threads == 512) ) ? array1 : array0; 339 359 340 360 for( n=0 ; n<(ARRAY_LENGTH-2) ; n++ ) … … 359 379 { 360 380 printf("\n[SORT] success at cycle %d\n", (unsigned int)cycle ); 361 exit( 0 );362 381 } 363 382 else 364 383 { 365 384 printf("\n[SORT] failure at cycle %d\n", (unsigned int)cycle ); 366 exit( 1 ); 367 } 385 } 386 387 #if INTERACTIVE_MODE 388 idbg(); 389 #endif 390 391 exit( 0 ); 368 392 369 393 } // end main()
Note: See TracChangeset
for help on using the changeset viewer.