Changeset 416 for trunk/kernel/kern
- Timestamp:
- Jan 4, 2018, 10:05:47 AM (7 years ago)
- Location:
- trunk/kernel/kern
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/cluster.c
r409 r416 228 228 } 229 229 230 //////////////////////////////////////////////// 231 error_t cluster_pid_alloc( xptr_t process_xp, 232 pid_t * pid ) 233 { 234 error_t error; 230 /////////////////////////////////////////////// 231 error_t cluster_pid_alloc( process_t * process, 232 pid_t * pid ) 233 { 235 234 lpid_t lpid; 236 235 bool_t found; … … 255 254 { 256 255 // register process in pref_tbl[] 257 pm->pref_tbl[lpid] = process_xp;256 pm->pref_tbl[lpid] = XPTR( local_cxy , process ); 258 257 pm->pref_nr++; 259 258 … … 261 260 *pid = PID( local_cxy , lpid ); 262 261 263 error = 0; 262 // release the processs_manager lock 263 spinlock_unlock( &pm->pref_lock ); 264 265 return 0; 264 266 } 265 267 else 266 268 { 267 error = EAGAIN; 268 } 269 270 // release the processs_manager lock 271 spinlock_unlock( &pm->pref_lock ); 272 273 return error; 269 // release the processs_manager lock 270 spinlock_unlock( &pm->pref_lock ); 271 272 return -1; 273 } 274 274 275 275 } // end cluster_pid_alloc() … … 286 286 assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER) && (owner_cxy == local_cxy) , 287 287 __FUNCTION__ , "illegal PID" ); 288 289 // check number of copies290 assert( (pm->copies_nr[lpid] == 0) ,291 __FUNCTION__ , "number of copies must be 0" );292 288 293 289 // get the process manager lock -
trunk/kernel/kern/cluster.h
r409 r416 197 197 * It registers the process descriptor extended pointer in the local processs manager 198 198 * pref_tbl[] array. This function is called by the process_make_fork() function, 199 * orby the process_init_create() function.200 ****************************************************************************************** 201 * @ process : [in] extended pointer on theprocess descriptor.199 * by the process_make_exec() function, and by the process_init_create() function. 200 ****************************************************************************************** 201 * @ process : pointer on process descriptor. 202 202 * @ pid : [out] allocated PID. 203 * @ return 0 if success / return EAGAIN if no PID slot available204 *****************************************************************************************/ 205 error_t cluster_pid_alloc( xptr_t process_xp,206 pid_t * pid );203 * @ return 0 if success / return -1 if no PID slot available. 204 *****************************************************************************************/ 205 error_t cluster_pid_alloc( struct process_s * process, 206 pid_t * pid ); 207 207 208 208 /****************************************************************************************** -
trunk/kernel/kern/process.c
r415 r416 337 337 pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr; 338 338 339 // get the lock protecting the list of local process descriptors339 // remove the process descriptor from local_list in cluster manager 340 340 remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) ); 341 342 // remove the process descriptor from local_list in local cluster manager343 341 xlist_unlink( XPTR( local_cxy , &process->local_list ) ); 344 345 // release the lock protecting the list of local process descriptors346 342 remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) ); 347 343 … … 356 352 remote_spinlock_unlock( copies_lock ); 357 353 354 // release the process PID to cluster manager 355 cluster_pid_release( process->pid ); 356 358 357 hal_fence(); 359 358 … … 370 369 vmm_destroy( process ); 371 370 372 process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n", 373 __FUNCTION__ , process->pid, process->vmm.pgfault_nr);371 // release memory allocated to process descriptor 372 process_free( process ); 374 373 375 374 } // end process_destroy() … … 393 392 xptr_t root_xp; // extended pointer on root of copies 394 393 xptr_t lock_xp; // extended pointer on lock protecting copies 395 xptr_t client_xp; // extended pointer on client thread396 uint32_t rsp_count; // number of expected responses397 xptr_t rsp_xp; // extended pointer on responses counter398 394 xptr_t iter_xp; // iterator on copies list 399 395 xptr_t process_xp; // extended pointer on process copy 400 396 cxy_t process_cxy; // process copy cluster identifier 401 397 process_t * process_ptr; // local pointer on process copy 402 403 sigaction_dmsg("\n[DBG] %s : enter for signal %s to process %x in cluster %x\n", 404 __FUNCTION__ , process_action_str( action_type ) , process , local_cxy ); 405 406 thread_t * this = CURRENT_THREAD; 407 408 // get extended pointer on client thread and response counter 409 client_xp = XPTR( local_cxy , this ); 410 rsp_xp = XPTR( local_cxy , &rsp_count ); 398 uint32_t responses; // number of remote process copies 399 uint32_t rsp_count; // used to assert number of copies 400 401 rpc_desc_t rpc; // rpc descriptor allocated in stack 402 403 sigaction_dmsg("\n[DBG] %s : enter to %s process %x in cluster %x\n", 404 __FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy ); 405 406 thread_t * client = CURRENT_THREAD; 407 xptr_t client_xp = XPTR( local_cxy , client ); 408 409 // get local pointer on local cluster manager 410 cluster = LOCAL_CLUSTER; 411 411 412 412 // get owner cluster identifier and process lpid … … 414 414 lpid = LPID_FROM_PID( process->pid ); 415 415 416 assert( (owner_cxy == local_cxy) , __FUNCTION__ , "illegal cluster\n" ); 416 // check owner cluster 417 assert( (owner_cxy == local_cxy) , __FUNCTION__ , 418 "must be executed in the owner cluster\n" ); 417 419 418 // get local pointer on local cluster manager 419 cluster = LOCAL_CLUSTER; 420 // get number of remote copies 421 responses = cluster->pmgr.copies_nr[lpid] - 1; 422 rsp_count = 0; 423 424 // check action type 425 assert( ((action_type == DELETE_ALL_THREADS ) || 426 (action_type == BLOCK_ALL_THREADS ) || 427 (action_type == UNBLOCK_ALL_THREADS )), 428 __FUNCTION__ , "illegal action type" ); 429 430 // initialise rpc descriptor 431 rpc.index = RPC_PROCESS_SIGACTION; 432 rpc.response = responses; 433 rpc.blocking = false; 434 rpc.thread = client; 420 435 421 436 // get extended pointers on copies root, copies lock, and number of copies … … 423 438 lock_xp = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] ); 424 439 425 // initialize responses number426 rsp_count = cluster->pmgr.copies_nr[lpid];427 428 440 // take the lock protecting the copies 429 441 remote_spinlock_lock( lock_xp ); 430 442 431 // send RPCs to all process copies443 // send RPCs to remote clusters 432 444 XLIST_FOREACH( root_xp , iter_xp ) 433 445 { … … 436 448 process_ptr = (process_t *)GET_PTR( process_xp ); 437 449 438 sigaction_dmsg("\n[DBG] %s : process = %x / pid = %x / ppid = %x\n", 439 __FUNCTION__ , process_ptr , process_ptr->pid , process_ptr->ppid ); 440 441 rpc_process_sigaction_client( process_cxy, 442 process_ptr, 443 action_type, 444 rsp_xp, 445 client_xp ); 450 // send RPC to remote clusters 451 if( process_cxy != local_cxy ) 452 { 453 454 sigaction_dmsg("\n[DBG] %s : send RPC to remote cluster %x\n", 455 __FUNCTION__ , process_cxy ); 456 457 rpc.args[0] = (uint64_t)action_type; 458 rpc.args[1] = (uint64_t)(intptr_t)process_ptr; 459 rpc_process_sigaction_client( process_cxy , &rpc ); 460 rsp_count++; 461 } 446 462 } 447 463 … … 449 465 remote_spinlock_unlock( lock_xp ); 450 466 451 // block and deschedule to wait response 452 thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC ); 453 sched_yield("BLOCKED on RPC"); 454 455 sigaction_dmsg("\n[DBG] %s : exit for signal %s to process %x in cluster %x\n", 456 __FUNCTION__ , process_action_str( action_type ) , process , local_cxy ); 467 // check number of copies... 468 assert( (rsp_count == responses) , __FUNCTION__ , 469 "unconsistent number of process copies : rsp_count = %d / responses = %d", 470 rsp_count , responses ); 471 472 // block and deschedule to wait RPC responses if required 473 if( responses ) 474 { 475 thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC ); 476 sched_yield("BLOCKED on RPC_PROCESS_SIGACTION"); 477 } 478 479 sigaction_dmsg("\n[DBG] %s : make action in owner cluster %x\n", 480 __FUNCTION__ , local_cxy ); 481 482 483 // call directly the relevant function in local owner cluster 484 if (action_type == DELETE_ALL_THREADS ) process_delete ( process , client_xp ); 485 else if (action_type == BLOCK_ALL_THREADS ) process_block ( process , client_xp ); 486 else if (action_type == UNBLOCK_ALL_THREADS ) process_unblock( process ); 487 488 sigaction_dmsg("\n[DBG] %s : exit after %s process %x in cluster %x\n", 489 __FUNCTION__ , process_action_str( action_type ) , process->pid , local_cxy ); 457 490 458 491 } // end process_sigaction() … … 460 493 //////////////////////////////////////// 461 494 void process_block( process_t * process, 462 xptr_t rsp_xp,463 495 xptr_t client_xp ) 464 496 { 465 497 thread_t * target; // pointer on target thread 466 498 uint32_t ltid; // index in process th_tbl 467 thread_t * killer; // killerthread pointer499 thread_t * requester; // requesting thread pointer 468 500 uint32_t count; // requests counter 469 volatile uint32_t sig_rsp_count; // responses counter 470 cxy_t client_cxy; // client thread cluster identifier 471 thread_t * client_ptr; // client thread pointer 472 core_t * client_core; // client thread core pointer 473 474 // get local killer thread pointer 475 killer = CURRENT_THREAD; 501 volatile uint32_t rsp_count; // responses counter 502 503 // get calling thread pointer 504 requester = CURRENT_THREAD; 476 505 477 506 sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n", … … 482 511 483 512 // initialize local responses counter 484 sig_rsp_count = process->th_nr;513 rsp_count = process->th_nr; 485 514 486 515 // loop on process threads to block and deschedule all threads in cluster … … 494 523 count++; 495 524 496 // set signal in target thread descriptor 497 thread_set_signal( target , (uint32_t *)sig_rsp_count ); 498 499 // set the global blocked bit in target thread descriptor. 500 thread_block( target , THREAD_BLOCKED_GLOBAL ); 501 502 // - if the killer thread and the target thread are not on the same core 503 // we want the scheduler of target thread to acknowlege the signal 504 // to be sure that the target thread is descheduled 505 // - if the killer thread and the target thread are on the same core 506 // we simply decrement the response counter. 507 if( killer->core->lid != target->core->lid ) 525 // - if the target thread is the client thread, we do nothing, 526 // and simply decrement the responses counter. 527 // - if the calling thread and the target thread are on the same core, 528 // we block the target thread, we don't ask ask anything to the scheduler, 529 // and simply decrement the responses counter. 530 // - if the calling thread and the target thread are not running on the same 531 // core, we ask the target scheduler to acknowlege the blocking 532 // to be sure that the target thread is not running. 533 534 if( XPTR( local_cxy , target ) == client_xp ) 508 535 { 536 // decrement responses counter 537 hal_atomic_add( (void *)&rsp_count , -1 ); 538 } 539 else if( requester->core->lid == target->core->lid ) 540 { 541 // set the global blocked bit in target thread descriptor. 542 thread_block( target , THREAD_BLOCKED_GLOBAL ); 543 544 // decrement responses counter 545 hal_atomic_add( (void *)&rsp_count , -1 ); 546 } 547 else 548 { 549 // set the global blocked bit in target thread descriptor. 550 thread_block( target , THREAD_BLOCKED_GLOBAL ); 551 552 // set FLAG_REQ_ACK and &ack_rsp_count in target descriptor 553 thread_set_req_ack( target , (void *)&rsp_count ); 554 555 // force scheduling on target thread 509 556 dev_pic_send_ipi( local_cxy , target->core->lid ); 510 557 } 511 else512 {513 hal_atomic_add( (void *)&sig_rsp_count , -1 );514 }515 558 } 516 559 } 517 560 518 // poll the reponses counter 561 // get lock protecting process th_tbl[] 562 spinlock_unlock( &process->th_lock ); 563 564 // wait all responses from schedulers 519 565 while( 1 ) 520 566 { 521 // exit loop when all responses received522 if ( sig_rsp_count == 0 ) break;567 // exit loop when all local responses received 568 if ( rsp_count == 0 ) break; 523 569 524 570 // wait 1000 cycles before retry … … 526 572 } 527 573 528 // acknowledge client thread & unblock client thread if last response529 client_cxy = GET_CXY( client_xp );530 client_ptr = (thread_t *)GET_PTR( client_xp );531 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );532 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 )533 {534 thread_unblock( client_xp , THREAD_BLOCKED_RPC);535 dev_pic_send_ipi( client_cxy , client_core->lid );536 }537 538 574 sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n", 539 575 __FUNCTION__ , process->pid , local_cxy , count ); … … 541 577 } // end process_block() 542 578 543 ////////////////////////////////////////// 544 void process_unblock( process_t * process, 545 xptr_t rsp_xp, 546 xptr_t client_xp ) 579 /////////////////////////////////////////// 580 void process_unblock( process_t * process ) 547 581 { 548 582 thread_t * target; // pointer on target thead 549 583 uint32_t ltid; // index in process th_tbl 550 thread_t * killer; // killer thread pointer 551 uint32_t req_count; // requests counter 552 cxy_t client_cxy; // client thread cluster identifier 553 thread_t * client_ptr; // client thread pointer 554 core_t * client_core; // client thread core pointer 555 556 // get local killer thread pointer 557 killer = CURRENT_THREAD; 584 uint32_t count; // requests counter 558 585 559 586 sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n", … … 564 591 565 592 // loop on process threads to unblock all threads in cluster 566 // we use both "ltid" and "req_count" because it can exist "holes" in th_tbl 567 for( ltid = 0 , req_count = 0 ; 568 req_count < process->th_nr ; 569 ltid++ ) 593 // we use both "ltid" and "count" because it can exist "holes" in th_tbl 594 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ ) 570 595 { 571 596 target = process->th_tbl[ltid]; … … 573 598 if( target != NULL ) // thread found 574 599 { 575 req_count++;600 count++; 576 601 577 602 // reset the global blocked bit in target thread descriptor. … … 580 605 } 581 606 582 // acknowledge client thread & unblock client thread if last response 583 client_cxy = GET_CXY( client_xp ); 584 client_ptr = (thread_t *)GET_PTR( client_xp ); 585 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) ); 586 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 587 { 588 thread_unblock( client_xp , THREAD_BLOCKED_RPC); 589 dev_pic_send_ipi( client_cxy , client_core->lid ); 590 } 607 // get lock protecting process th_tbl[] 608 spinlock_unlock( &process->th_lock ); 591 609 592 610 sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n", 593 __FUNCTION__ , process->pid , local_cxy , req_count );611 __FUNCTION__ , process->pid , local_cxy , count ); 594 612 595 613 } // end process_unblock() … … 597 615 ///////////////////////////////////////// 598 616 void process_delete( process_t * process, 599 xptr_t rsp_xp,600 617 xptr_t client_xp ) 601 618 { 602 thread_t * t hread; // pointer on target thread619 thread_t * target; // pointer on target thread 603 620 uint32_t ltid; // index in process th_tbl 604 621 uint32_t count; // request counter 605 pid_t pid; // process PID 606 cxy_t client_cxy; // client thread cluster identifier 607 thread_t * client_ptr; // client thread pointer 608 core_t * client_core; // client thread core pointer 609 610 // get process PID 611 pid = process->pid; 622 thread_t * requester; // pointer on calling thread 612 623 613 624 sigaction_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n", 614 __FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() ); 615 616 // loop on threads to release memory allocated to threads 625 __FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() ); 626 627 // get calling thread pointer 628 requester = CURRENT_THREAD; 629 630 // get lock protecting process th_tbl[] 631 spinlock_lock( &process->th_lock ); 632 633 // loop on threads to set the REQ_DELETE flag 634 // we use both "ltid" and "count" because it can exist "holes" in th_tbl 617 635 for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ ) 618 636 { 619 t hread= process->th_tbl[ltid];620 621 if( t hread!= NULL ) // thread found637 target = process->th_tbl[ltid]; 638 639 if( target != NULL ) // thread found 622 640 { 623 641 count++; 624 642 625 // detach thread from parent if attached 626 if( (thread->flags & THREAD_FLAG_DETACHED) == 0 ) 627 thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) ); 628 629 // detach thread from process 630 process_remove_thread( thread ); 631 632 // remove thread from scheduler 633 sched_remove_thread( thread ); 634 635 // release memory allocated to thread 636 thread_destroy( thread ); 643 // delete only if the target is not the client 644 if( XPTR( local_cxy , target ) != client_xp ) 645 { 646 hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE ); 647 } 637 648 } 638 649 } 639 650 640 // release memory allocated to process descriptors 641 // for all clusters other than the owner cluster 642 if( local_cxy != CXY_FROM_PID( process->pid ) ) process_destroy( process ); 643 644 // acknowledge client thread & unblock client thread if last response 645 client_cxy = GET_CXY( client_xp ); 646 client_ptr = (thread_t *)GET_PTR( client_xp ); 647 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) ); 648 if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 649 { 650 thread_unblock( client_xp , THREAD_BLOCKED_RPC); 651 dev_pic_send_ipi( client_cxy , client_core->lid ); 652 } 651 // get lock protecting process th_tbl[] 652 spinlock_unlock( &process->th_lock ); 653 653 654 654 sigaction_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n", 655 __FUNCTION__ , p id , local_cxy , (uint32_t)hal_get_cycles() );655 __FUNCTION__ , process->pid , local_cxy , (uint32_t)hal_get_cycles() ); 656 656 657 657 } // end process_delete() … … 951 951 952 952 // allocate a child PID from local cluster 953 error = cluster_pid_alloc( XPTR( local_cxy , process ), &new_pid );953 error = cluster_pid_alloc( process , &new_pid ); 954 954 if( (error != 0) || (new_pid == 0) ) 955 955 { … … 1037 1037 return 0; 1038 1038 1039 } // end process_make_fork() 1040 1041 /* deprecated because we don't wand to destroy the existing process descriptor 1039 } // end process_make_fork() 1040 1042 1041 1043 1042 ///////////////////////////////////////////////////// … … 1045 1044 { 1046 1045 char * path; // pathname to .elf file 1047 process_t * old; // local pointer on old process 1048 process_t * new; // local pointer on new process 1049 pid_t pid; // old process identifier 1050 thread_t * thread; // pointer on new thread 1046 process_t * old_process; // local pointer on old process 1047 process_t * new_process; // local pointer on new process 1048 pid_t old_pid; // old process identifier 1049 pid_t new_pid; // new (temporary) process identifier 1050 thread_t * old_thread; // pointer on new thread 1051 thread_t * new_thread; // pointer on new thread 1051 1052 pthread_attr_t attr; // main thread attributes 1052 1053 lid_t lid; // selected core local index … … 1054 1055 1055 1056 // get .elf pathname and PID from exec_info 1056 path = exec_info->path;1057 pid = exec_info->pid;1058 1059 // check local cluster is process owner1060 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,1061 "local cluster %x is not owner for process %x\n", local_cxy, pid );1057 path = exec_info->path; 1058 old_pid = exec_info->pid; 1059 1060 // this function must be executed by a thread running in owner cluster 1061 assert( (CXY_FROM_PID( old_pid ) == local_cxy), __FUNCTION__, 1062 "local cluster %x is not owner for process %x\n", local_cxy, old_pid ); 1062 1063 1063 1064 exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n", 1064 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path ); 1065 1066 // get old process local pointer 1067 old = (process_t *)cluster_get_local_process_from_pid( pid ); 1065 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, old_pid , path ); 1066 1067 // get old process and thread local pointers 1068 old_process = (process_t *)cluster_get_local_process_from_pid( old_pid ); 1069 old_thread = CURRENT_THREAD; 1068 1070 1069 assert( (old != NULL ) , __FUNCTION__ , 1070 "process %x not found in cluster %x\n", pid , local_cxy ); 1071 if( old_process == NULL ) 1072 { 1073 printk("\n[ERROR] in %s : cannot get old process descriptor\n", __FUNCTION__ ); 1074 return -1; 1075 } 1071 1076 1072 1077 // allocate memory for new process descriptor 1073 new = process_alloc(); 1078 new_process = process_alloc(); 1079 1080 if( new_process == NULL ) 1081 { 1082 printk("\n[ERROR] in %s : cannot allocate new process descriptor\n", __FUNCTION__ ); 1083 return -1; 1084 } 1085 1086 // get a (temporary) PID for new process 1087 error = cluster_pid_alloc( new_process , &new_pid ); 1088 1089 if( error ) 1090 { 1091 printk("\n[ERROR] in %s : cannot allocate a temporary PID\n", __FUNCTION__ ); 1092 process_destroy( new_process ); 1093 return -1; 1094 } 1074 1095 1075 1096 // initialize new process descriptor 1076 process_reference_init( new ,1077 old->pid, // same as old1078 old ->ppid, // same as old1079 XPTR( local_cxy , old ) );1097 process_reference_init( new_process, 1098 new_pid, // temporary PID 1099 old_process->ppid, // same parent 1100 XPTR( local_cxy , old_process ) ); 1080 1101 1081 1102 exec_dmsg("\n[DBG] %s : core[%x,%d] created new process %x / path = %s\n", 1082 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );1103 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, new_pid, path ); 1083 1104 1084 1105 // register "code" and "data" vsegs as well as entry-point 1085 1106 // in new process VMM, using information contained in the elf file. 1086 if( elf_load_process( path , new ) )1107 if( elf_load_process( path , new_process ) ) 1087 1108 { 1088 1109 printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n", 1089 __FUNCTION__, pid , path ); 1090 process_destroy( new ); 1110 __FUNCTION__, new_pid , path ); 1111 cluster_pid_release( new_pid ); 1112 process_destroy( new_process ); 1091 1113 return -1; 1092 1114 } … … 1104 1126 1105 1127 // create and initialize thread descriptor 1106 error = thread_user_create( pid,1107 (void *)new ->vmm.entry_point,1128 error = thread_user_create( new_pid, 1129 (void *)new_process->vmm.entry_point, 1108 1130 exec_info->args_pointers, 1109 1131 &attr, 1110 & thread );1132 &new_thread ); 1111 1133 if( error ) 1112 1134 { 1113 1135 printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n", 1114 __FUNCTION__, pid , path ); 1115 process_destroy( new ); 1136 __FUNCTION__, new_pid , path ); 1137 cluster_pid_release( new_pid ); 1138 process_destroy( new_process ); 1116 1139 return -1; 1117 1140 } 1118 1141 1119 exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n", 1120 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid ); 1121 1122 // update children list (rooted in parent process) 1123 xlist_replace( XPTR( local_cxy , &old->brothers_list ) , 1124 XPTR( local_cxy , &new->brothers_list ) ); 1125 1126 // request destruction of old process copies and threads in all clusters 1127 process_sigaction( old , SIGKILL ); 1128 1142 exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x\n", 1143 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_thread->trdid ); 1144 1145 // update children list rooted in parent process 1146 xlist_replace( XPTR( local_cxy , &old_process->brothers_list ) , 1147 XPTR( local_cxy , &new_process->brothers_list ) ); 1148 1149 // request blocking for all threads in old process (but the calling thread) 1150 process_sigaction( old_process , BLOCK_ALL_THREADS ); 1151 1152 // request destruction for all threads in old process (but the calling thread) 1153 process_sigaction( old_process , DELETE_ALL_THREADS ); 1154 1155 // update PID for both processes 1156 new_process->pid = old_pid; 1157 old_process->pid = 0xFFFFFFFF; 1158 1159 // release temporary PID 1160 cluster_pid_release( new_pid ); 1161 1129 1162 // activate new thread 1130 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );1163 thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL ); 1131 1164 1132 1165 exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n", 1133 1166 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path ); 1134 1167 1168 // set BLOCKED_GLOBAL bit 1169 thread_block( old_thread , THREAD_BLOCKED_GLOBAL ); 1170 1171 // set REQ_DELETE flag 1172 hal_atomic_or( &old_thread->flags , THREAD_FLAG_REQ_DELETE ); 1173 1174 // deschedule 1175 sched_yield("suicide after exec"); 1176 1177 // never executed but required by compiler 1135 1178 return 0; 1136 1179 1137 1180 } // end process_make_exec() 1138 1181 1139 */ 1140 1141 ///////////////////////////////////////////////////// 1142 error_t process_make_exec( exec_info_t * exec_info ) 1143 { 1144 char * path; // pathname to .elf file 1145 process_t * process; // local pointer on old process 1146 pid_t pid; // old process identifier 1147 thread_t * thread; // pointer on new main thread 1148 pthread_attr_t attr; // main thread attributes 1149 lid_t lid; // selected core local index 1150 error_t error; 1151 1152 // get .elf pathname and PID from exec_info 1153 path = exec_info->path; 1154 pid = exec_info->pid; 1155 1156 // check local cluster is process owner 1157 assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__, 1158 "local cluster %x is not owner for process %x\n", local_cxy, pid ); 1159 1160 exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n", 1161 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path ); 1162 1163 // get process local pointer 1164 process = (process_t *)cluster_get_local_process_from_pid( pid ); 1165 1166 assert( (process != NULL ) , __FUNCTION__ , 1167 "process %x not found in cluster %x\n", pid , local_cxy ); 1168 1169 // reset the existing vmm 1170 vmm_destroy( process ); 1171 1172 exec_dmsg("\n[DBG] %s : core[%x,%d] VMM cleared\n", 1173 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid ); 1174 1175 // block all existing process threads 1176 process_sigaction( process , BLOCK_ALL_THREADS ); 1177 1178 // kill all existing threads and process descriptors (other than owner) 1179 process_sigaction( process , DELETE_ALL_THREADS ); 1180 1181 // check no threads 1182 assert( (process->th_nr == 0) , __FUNCTION__ , "no threads at this point" ); 1183 1184 exec_dmsg("\n[DBG] %s : core[%x,%d] all threads deleted\n", 1185 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid ); 1186 1187 // initialize VMM 1188 error = vmm_init( process ); 1189 { 1190 printk("\n[ERROR] in %s : cannot initialize VMM for process %x / path = %s\n", 1191 __FUNCTION__, pid , path ); 1192 process_destroy( process ); 1193 return -1; 1194 } 1195 1196 if( error ) 1197 1198 // register "code" and "data" vsegs as well as entry-point and vfs_bin_xp 1199 // in VMM, using information contained in the elf file. 1200 error = elf_load_process( path , process ); 1201 1202 if( error ) 1203 { 1204 printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n", 1205 __FUNCTION__, pid , path ); 1206 process_destroy( process ); 1207 return -1; 1208 } 1209 1210 exec_dmsg("\n[DBG] %s : core[%x,%d] new vsegs registered / path = %s\n", 1211 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path ); 1212 1213 // @@@ 1214 vmm_display( process , true ); 1215 // @@@ 1216 1217 // select a core in local cluster to execute the new main thread 1218 lid = cluster_select_local_core(); 1219 1220 // initialize pthread attributes for new main thread 1221 attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED; 1222 attr.cxy = local_cxy; 1223 attr.lid = lid; 1224 1225 // create and initialize thread descriptor 1226 error = thread_user_create( pid, 1227 (void *)process->vmm.entry_point, 1228 exec_info->args_pointers, 1229 &attr, 1230 &thread ); 1231 if( error ) 1232 { 1233 printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n", 1234 __FUNCTION__, pid , path ); 1235 process_destroy( process ); 1236 return -1; 1237 } 1238 1239 exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n", 1240 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid ); 1241 1242 // activate new thread 1243 thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL ); 1244 1245 exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n", 1246 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path ); 1247 1248 return 0; 1249 1250 } // end process_make_exec() 1251 1252 //////////////////////////////////////////// 1253 void process_make_kill( process_t * process, 1254 uint32_t sig_id ) 1182 /////////////////////////////////////// 1183 void process_make_kill( pid_t pid, 1184 uint32_t sig_id ) 1255 1185 { 1256 1186 // this function must be executed by a thread running in owner cluster 1257 assert( (CXY_FROM_PID( p rocess->pid ) == local_cxy) , __FUNCTION__ ,1187 assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ , 1258 1188 "must execute in owner cluster" ); 1189 1190 kill_dmsg("\n[DBG] %s : core[%x,%d] enter / process %x / sig %d\n", 1191 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , sig_id ); 1192 1193 // get pointer on local process descriptor 1194 process_t * process = process_get_local_copy( pid ); 1195 1196 // does nothing if process does not exist 1197 if( process == NULL ) 1198 { 1199 printk("\n[WARNING] %s : process %x does not exist => do nothing\n", 1200 __FUNCTION__ , pid ); 1201 return; 1202 } 1259 1203 1260 1204 // analyse signal type 1261 1205 switch( sig_id ) 1262 1206 { 1263 case SIGSTOP: // block all threads 1207 case SIGSTOP: // block all threads in all clusters 1264 1208 { 1265 1209 process_sigaction( process , BLOCK_ALL_THREADS ); 1266 1210 } 1267 1211 break; 1268 case SIGCONT: // unblock all threads 1212 case SIGCONT: // unblock all threads in all clusters 1269 1213 { 1270 1214 process_sigaction( process , UNBLOCK_ALL_THREADS ); … … 1273 1217 case SIGKILL: // block all threads, then delete all threads 1274 1218 { 1219 // block all threads (but the calling thread) 1275 1220 process_sigaction( process , BLOCK_ALL_THREADS ); 1221 1222 // delete all threads (but the calling thread) 1276 1223 process_sigaction( process , DELETE_ALL_THREADS ); 1277 process_destroy( process ); 1224 1225 // delete the calling thread if required 1226 thread_t * this = CURRENT_THREAD; 1227 1228 if( this->process == process ) 1229 { 1230 // set REQ_DELETE flag 1231 hal_atomic_or( &this->flags , THREAD_FLAG_REQ_DELETE ); 1232 1233 // deschedule 1234 sched_yield( "suicide after kill" ); 1235 } 1278 1236 } 1279 1237 break; 1280 1238 } 1239 1240 //@@@ 1241 sched_display( 0 ); 1242 //@@@ 1243 1244 kill_dmsg("\n[DBG] %s : core[%x,%d] exit / process %x / sig %d \n", 1245 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , sig_id ); 1246 1281 1247 } // end process_make_kill() 1282 1248 1283 ///////////////////////////////////////// ///1284 void process_make_exit( p rocess_t * process,1249 ///////////////////////////////////////// 1250 void process_make_exit( pid_t pid, 1285 1251 uint32_t status ) 1286 1252 { 1287 1253 // this function must be executed by a thread running in owner cluster 1288 assert( (CXY_FROM_PID( p rocess->pid ) == local_cxy) , __FUNCTION__ ,1254 assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ , 1289 1255 "must execute in owner cluster" ); 1290 1256 1291 // block all threads in all clusters 1257 // get pointer on local process descriptor 1258 process_t * process = process_get_local_copy( pid ); 1259 1260 // does nothing if process does not exist 1261 if( process == NULL ) 1262 { 1263 printk("\n[WARNING] %s : process %x does not exist => do nothing\n", 1264 __FUNCTION__ , pid ); 1265 return; 1266 } 1267 1268 // block all threads in all clusters (but the calling thread) 1292 1269 process_sigaction( process , BLOCK_ALL_THREADS ); 1293 1270 1294 // delete all threads in all clusters 1271 // delete all threads in all clusters (but the calling thread) 1295 1272 process_sigaction( process , DELETE_ALL_THREADS ); 1296 1273 1297 // delete local process descriptor 1298 process_destroy( process ); 1274 // delete the calling thread 1275 hal_atomic_or( &CURRENT_THREAD->flags , THREAD_FLAG_REQ_DELETE ); 1276 1277 // deschedule 1278 sched_yield( "suicide after exit" ); 1299 1279 1300 1280 } // end process_make_exit() … … 1322 1302 1323 1303 // get PID from local cluster 1324 error = cluster_pid_alloc( XPTR( local_cxy , process ), &pid );1304 error = cluster_pid_alloc( process , &pid ); 1325 1305 if( error ) 1326 1306 { -
trunk/kernel/kern/process.h
r415 r416 267 267 268 268 /********************************************************************************************* 269 * This function allows any thread running in any cluster to block, unblock or delete 270 * all threads of a given process identified by the <process> argument, dependig on the 271 * <acion_type> argument. 272 * It can be called by the sys_kill() or sys_exit() functions to handle the "kill" & "exit" 273 * system calls, or by the process_make_exec() function to handle the "exec" system call. 274 * It must be executed in the owner cluster for the target process (using the relevant RPC 275 * (RPC_PROCESS_SIGNAL or RPC_PROCESS_EXEC) if the client thread in not running in the 276 * owner cluster. 277 * It uses the multicast, non blocking, RPC_PROCESS_KILL to send the signal to all process 278 * copies in parallel, block & deschedule when all signals have been sent, and finally 279 * returns only when all responses have been received and the operation is completed. 280 ********************************************************************************************* 281 * @ process : pointer on the process descriptor. 282 * @ action_type : BLOCK_ALL_THREADS / UNBLOCK_ALL_THREADS / DELETE_ALL_THREADS 269 * This function allows a client thread running in the owner cluster of a process identified 270 * by the <process> argument to block, unblock or delete all threads of the target process, 271 * depending on the <action_type> argument. The scenario is the following: 272 * - It uses the multicast, non blocking rpc_process_sigaction_client() function to send 273 * parallel requests to all remote clusters containing a process copy. Then it blocks 274 $ and deschedule to wait completion of these parrallel requests. 275 * - In each remote cluster, the rpc_process_sigaction_server() function, calls directly 276 * the relevant process_block(), process_unblock(), or process_delete() function, and 277 * decrement the responses counter to signal completion. The last server unblock 278 * the client thread. 279 * - Finally, the client thread calls directly the process_block(), process_unblock(), or 280 * process_delete() function in the owner cluster. 281 * It is used by the sys_kill() & sys_exit() functions to handle the "kill" & "exit" syscalls. 282 * It is also used by the process_make_exec() function to handle the "exec" syscall. 283 * WARNING : the DELETE and the BLOCK actions are NOT executed on the client thread. 284 ********************************************************************************************* 285 * @ process : pointer on the process descriptor in owner cluster. 286 * @ action_type : BLOCK_ALL_THREADS / UNBLOCK_ALL_THREADS / DELETE_ALL_THREADS 283 287 ********************************************************************************************/ 284 288 void process_sigaction( process_t * process, … … 287 291 /********************************************************************************************* 288 292 * This function blocks all threads of a given user process in a given cluster. 289 * It is always called by a local RPC thread, through the multicast RPC_PROCESS_KILL. 290 * It loop on all local threads of the process, requesting the relevant schedulers to 291 * block and deschedule these threads, using IPI if required. The threads are not detached 292 * from the scheduler, and not detached from the local process. 293 * It acknowledges the client thread in the owner cluster only when all process threads 294 * are descheduled and blocked on the BLOCKED_GLOBAL condition, using the <rsp_xp> argument. 293 * It loops on all local threads of the process, set the THREAD_BLOCKED_GLOBAL bit, 294 * and request the relevant schedulers to acknowledge the blocking, using IPI if required. 295 * The threads are not detached from the scheduler, and not detached from the local process. 296 * This function returns only when all blockable threads in cluster are actually blocked. 297 * WARNING : the client thread defined by the <client_xp> argument is NOT blocked. 295 298 ********************************************************************************************* 296 299 * @ process : pointer on the target process descriptor. 297 * @ rsp_xp : extended pointer on the response counter. 298 * # client_xp : extended pointer on client thread descriptor. 300 * @ client_xp : extended pointer on the client thread, that should not be blocked. 299 301 ********************************************************************************************/ 300 302 void process_block( process_t * process, 301 xptr_t rsp_xp,302 303 xptr_t client_xp ); 303 304 304 305 /********************************************************************************************* 305 306 * This function unblocks all threads of a given user process in a given cluster. 306 * It is always called by a local RPC thread, through the multicast RPC_PROCESS_KILL.307 * It loops on local threads of the process, to reset the BLOCKED_GLOBAL bit in all threads.308 * It acknowledges directly the client thread in the owner cluster when this is done,309 * using the <rsp_xp> argument.310 307 ********************************************************************************************* 311 308 * @ process : pointer on the process descriptor. 312 * @ rsp_xp : extended pointer on the response counter. 313 * # client_xp : extended pointer on client thread descriptor. 314 ********************************************************************************************/ 315 void process_unblock( process_t * process, 316 xptr_t rsp_xp, 317 xptr_t client_xp ); 318 319 /********************************************************************************************* 320 * This function delete all threads descriptors, of given user process in a given cluster. 321 * It is always called by a local RPC thread, through the multicast RPC_PROCESS_KILL. 322 * It detach all process threads from the scheduler, detach the threads from the local 323 * process, and release the local memory allocated to threads descriptors (including the 324 * associated structures such as CPU and FPU context). Finally, it release the memory 325 * allocated to the local process descriptor itself, but only when the local cluster 326 * is NOT the process owner, but only a copy. It acknowledges directly the client thread 327 * in the owner cluster, using ithe <rsp_xp> argument. 309 ********************************************************************************************/ 310 void process_unblock( process_t * process ); 311 312 /********************************************************************************************* 313 * This function delete all threads, of a given user process in a given cluster. 314 * It loops on all local threads of the process, and set the THREAD_FLAG_REQ_DELETE bit. 315 * For each marked thread, the following actions will be done by the scheduler at the next 316 * scheduling point: 317 * - the thread will be detached from the scheduler. 318 * - the thread will be detached from the local process descriptor. 319 * - the thread will be detached from parent if required. 320 * - the memory allocated to the thread descriptor is released. 321 * - the memory allocated to the process descriptor is released, if it is the last thread. 322 * WARNING : the client thread defined by the <client_xp> argument is NOT deleted. 328 323 ********************************************************************************************* 329 324 * @ process : pointer on the process descriptor. 330 * @ rsp_xp : extended pointer on the response counter. 331 * # client_xp : extended pointer on client thread descriptor. 325 * @ client_xp : extended pointer on the client thread, that should not be deleted. 332 326 ********************************************************************************************/ 333 327 void process_delete( process_t * process, 334 xptr_t rsp_xp,335 328 xptr_t client_xp ); 336 329 … … 392 385 * It must be executed by a thread running in the calling process owner cluster. 393 386 * It uses twice the multicast RPC_PROCESS_SIGNAL to first block all process threads 394 * in all clusters, and then delete all thread 395 ********************************************************************************************* 396 * @ p rocess : pointer on process descriptor in owner cluster.387 * in all clusters, and then delete all threads and process descriptors. 388 ********************************************************************************************* 389 * @ pid : process identifier. 397 390 * @ status : exit return value. 398 391 ********************************************************************************************/ 399 void process_make_exit( p rocess_t * process,392 void process_make_exit( pid_t pid, 400 393 uint32_t status ); 401 394 … … 408 401 * all process threads in all clusters, and then delete process descriptors. 409 402 ********************************************************************************************* 410 * @ p rocess : pointer on process descriptor in owner cluster.411 * @ sig_id 412 ********************************************************************************************/ 413 void process_make_kill( p rocess_t * process,414 uint32_t 403 * @ pid : process identifier. 404 * @ sig_id : signal type. 405 ********************************************************************************************/ 406 void process_make_kill( pid_t pid, 407 uint32_t sig_id ); 415 408 416 409 -
trunk/kernel/kern/rpc.c
r415 r416 94 94 /////////////////////////////////////// 95 95 void rpc_send( cxy_t server_cxy, 96 rpc_desc_t * rpc, 97 bool_t block ) 96 rpc_desc_t * rpc ) 98 97 { 99 98 error_t error; … … 106 105 rpc->lid = core->lid; 107 106 108 printk("\n @@@ enter %s : rpc_desc_cxy = %x / rpc_desc_ptr = %x / index = %d / &index = %x\n",109 __FUNCTION__ , local_cxy , rpc , rpc->index , &rpc->index);110 111 107 // build an extended pointer on the RPC descriptor 112 108 xptr_t desc_xp = XPTR( local_cxy , rpc ); … … 137 133 dev_pic_send_ipi( server_cxy , core->lid ); 138 134 139 // wait RPC completion if blocking135 // wait RPC completion before returning if blocking RPC 140 136 // - busy waiting policy during kernel_init, or if threads cannot yield 141 137 // - block and deschedule in all other cases 142 if ( block)138 if ( rpc->blocking ) 143 139 { 144 140 if( (this->type == THREAD_IDLE) || (thread_can_yield() == false) ) // busy waiting … … 178 174 dev_pic_ack_ipi(); 179 175 } 180 181 printk("\n @@@ exit %s : rpc_desc_cxy = %x / rpc_desc_ptr = %x / index = %d / &index = %x\n",182 __FUNCTION__ , local_cxy , rpc , rpc->index , &rpc->index);183 184 176 } // end rpc_send() 185 177 … … 244 236 hal_atomic_add( &LOCAL_CLUSTER->rpc_threads , 1 ); 245 237 246 grpc_dmsg("\n[DBG] %s : core [%x,%d] creates a new RPC thread %x / cycle %d\n",247 __FUNCTION__ , local_cxy , core->lid , thread ->trdid , hal_time_stamp() );238 grpc_dmsg("\n[DBG] %s : core [%x,%d] creates a new RPC thread %x / trdid %x / cycle %d\n", 239 __FUNCTION__ , local_cxy , core->lid , thread , thread->trdid , hal_time_stamp() ); 248 240 249 241 } 250 242 } 251 243 } 252 253 //@@@254 sched_display( 0 );255 //@@@256 244 257 245 grpc_dmsg("\n[DBG] %s : core[%x,%d] / interrupted thread %s deschedules / cycle %d\n", … … 279 267 rpc_desc_t * desc_ptr; // RPC request local pointer 280 268 uint32_t index; // RPC request index 281 uint32_t responses; // number of responses received by client282 269 thread_t * thread_ptr; // local pointer on client thread 283 270 lid_t core_lid; // local index of client core 271 bool_t blocking; // blocking RPC when true 284 272 285 273 // makes RPC thread not preemptable … … 319 307 desc_ptr = (rpc_desc_t *)GET_PTR( desc_xp ); 320 308 321 // get rpc index from RPC descriptor 322 index = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) ); 323 324 printk("\n @@@ in %s : rpc_desc_cxy = %x / rpc_desc_ptr = %x / index = %d / &index = %x\n", 325 __FUNCTION__ , desc_cxy , desc_ptr , index , &desc_ptr->index ); 326 309 // get RPC <index> & <blocking> fields from RPC descriptor 310 index = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->index ) ); 311 blocking = hal_remote_lw( XPTR( desc_cxy , &desc_ptr->blocking ) ); 312 327 313 grpc_dmsg("\n[DBG] %s : core[%x,%d] / RPC thread %x / starts rpc %d / cycle %d\n", 328 314 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , (uint32_t)hal_get_cycles() ); … … 334 320 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , index , hal_time_stamp() ); 335 321 336 // increment handled RPC counter322 // increment handled RPCs counter 337 323 count++; 338 324 339 // decrement response counter in RPC descriptor 340 responses = hal_remote_atomic_add(XPTR( desc_cxy, &desc_ptr->response ), -1);341 342 // unblock client thread and send IPI to client core if last response343 if( responses == 1 )344 { 345 // get pointer on client thread and unblock it325 // decrement response counter in RPC descriptor if blocking 326 if( blocking ) 327 { 328 // decrement responses counter in RPC descriptor 329 hal_remote_atomic_add(XPTR( desc_cxy, &desc_ptr->response ), -1); 330 331 // unblock client thread 346 332 thread_ptr = (thread_t *)hal_remote_lpt(XPTR(desc_cxy,&desc_ptr->thread)); 347 333 thread_unblock( XPTR(desc_cxy,thread_ptr) , THREAD_BLOCKED_RPC ); … … 363 349 // release rpc_fifo ownership if not lost 364 350 if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0; 365 } 351 352 } // end if RPC fifo 366 353 367 354 // sucide if too many RPC threads in cluster … … 412 399 rpc.index = RPC_PMEM_GET_PAGES; 413 400 rpc.response = 1; 401 rpc.blocking = true; 414 402 415 403 // set input arguments in RPC descriptor … … 417 405 418 406 // register RPC request in remote RPC fifo (blocking function) 419 rpc_send( cxy , &rpc , true);407 rpc_send( cxy , &rpc ); 420 408 421 409 // get output arguments from RPC descriptor … … 470 458 rpc.index = RPC_PMEM_RELEASE_PAGES; 471 459 rpc.response = 1; 460 rpc.blocking = true; 472 461 473 462 // set input arguments in RPC descriptor … … 475 464 476 465 // register RPC request in remote RPC fifo (blocking function) 477 rpc_send( cxy , &rpc , true);466 rpc_send( cxy , &rpc ); 478 467 479 468 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 526 515 rpc.index = RPC_PROCESS_MAKE_EXEC; 527 516 rpc.response = 1; 517 rpc.blocking = true; 528 518 529 519 // set input arguments in RPC descriptor … … 531 521 532 522 // register RPC request in remote RPC fifo (blocking function) 533 rpc_send( cxy , &rpc , true);523 rpc_send( cxy , &rpc ); 534 524 535 525 // get output arguments from RPC descriptor … … 597 587 rpc.index = RPC_PROCESS_MAKE_FORK; 598 588 rpc.response = 1; 589 rpc.blocking = true; 599 590 600 591 // set input arguments in RPC descriptor … … 603 594 604 595 // register RPC request in remote RPC fifo (blocking function) 605 rpc_send( cxy , &rpc , true);596 rpc_send( cxy , &rpc ); 606 597 607 598 // get output arguments from RPC descriptor … … 658 649 /////////////////////////////////////////////////// 659 650 void rpc_process_make_exit_client( cxy_t cxy, 660 p rocess_t * process,651 pid_t pid, 661 652 uint32_t status ) 662 653 { … … 671 662 rpc.index = RPC_PROCESS_MAKE_EXIT; 672 663 rpc.response = 1; 664 rpc.blocking = true; 673 665 674 666 // set input arguments in RPC descriptor 675 rpc.args[0] = (uint64_t) (intptr_t)process;667 rpc.args[0] = (uint64_t)pid; 676 668 rpc.args[1] = (uint64_t)status; 677 669 678 670 // register RPC request in remote RPC fifo (blocking function) 679 rpc_send( cxy , &rpc , true);671 rpc_send( cxy , &rpc ); 680 672 681 673 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 691 683 CURRENT_THREAD->core->lid , hal_time_stamp() ); 692 684 693 p rocess_t * process;694 uint32_t 685 pid_t pid; 686 uint32_t status; 695 687 696 688 // get client cluster identifier and pointer on RPC descriptor … … 699 691 700 692 // get arguments from RPC descriptor 701 p rocess = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );702 status = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );693 pid = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 694 status = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 703 695 704 696 // call local kernel function 705 process_make_exit( p rocess, status );697 process_make_exit( pid , status ); 706 698 707 699 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 716 708 /////////////////////////////////////////////////// 717 709 void rpc_process_make_kill_client( cxy_t cxy, 718 p rocess_t * process,710 pid_t pid, 719 711 uint32_t sig_id ) 720 712 { … … 729 721 rpc.index = RPC_PROCESS_MAKE_KILL; 730 722 rpc.response = 1; 723 rpc.blocking = true; 731 724 732 725 // set input arguments in RPC descriptor 733 rpc.args[0] = (uint64_t) (intptr_t)process;726 rpc.args[0] = (uint64_t)pid; 734 727 rpc.args[1] = (uint64_t)sig_id; 735 728 736 729 // register RPC request in remote RPC fifo (blocking function) 737 rpc_send( cxy , &rpc , true);730 rpc_send( cxy , &rpc ); 738 731 739 732 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 749 742 CURRENT_THREAD->core->lid , hal_time_stamp() ); 750 743 751 p rocess_t * process;744 pid_t pid; 752 745 uint32_t sig_id; 753 746 … … 757 750 758 751 // get arguments from RPC descriptor 759 p rocess = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );760 sig_id = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );752 pid = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 753 sig_id = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 761 754 762 755 // call local kernel function 763 process_make_exit( p rocess, sig_id );756 process_make_exit( pid , sig_id ); 764 757 765 758 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 791 784 rpc.index = RPC_THREAD_USER_CREATE; 792 785 rpc.response = 1; 786 rpc.blocking = true; 793 787 794 788 // set input arguments in RPC descriptor … … 799 793 800 794 // register RPC request in remote RPC fifo (blocking function) 801 rpc_send( cxy , &rpc , true);795 rpc_send( cxy , &rpc ); 802 796 803 797 // get output arguments from RPC descriptor … … 883 877 rpc.index = RPC_THREAD_KERNEL_CREATE; 884 878 rpc.response = 1; 879 rpc.blocking = true; 885 880 886 881 // set input arguments in RPC descriptor … … 890 885 891 886 // register RPC request in remote RPC fifo (blocking function) 892 rpc_send( cxy , &rpc , true);887 rpc_send( cxy , &rpc ); 893 888 894 889 // get output arguments from RPC descriptor … … 956 951 rpc.index = RPC_THREAD_KILL; 957 952 rpc.response = 1; 953 rpc.blocking = true; 958 954 959 955 // set input arguments in RPC descriptor … … 961 957 962 958 // register RPC request in remote RPC fifo (blocking function) 963 rpc_send( cxy , &rpc , true);959 rpc_send( cxy , &rpc ); 964 960 965 961 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 997 993 ///////////////////////////////////////////////////////////////////////////////////////// 998 994 999 /////////////////////////////////////////////////// 1000 void rpc_process_sigaction_client( cxy_t cxy, 1001 process_t * process, // in 1002 uint32_t sigaction, // in 1003 xptr_t rsp_xp, // in 1004 xptr_t client_xp ) // in 1005 { 1006 sigaction_dmsg("\n[DBG] %s : enter for %s (%d) / thread %x on core[%x,%d] / cycle %d\n", 1007 __FUNCTION__ , process_action_str( sigaction ) , sigaction , CURRENT_THREAD , 1008 local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() ); 1009 1010 // initialise RPC descriptor header 1011 rpc_desc_t rpc; 1012 rpc.index = RPC_PROCESS_SIGACTION; 1013 1014 // set input arguments in RPC descriptor 1015 rpc.args[0] = (uint64_t)(intptr_t)process; 1016 rpc.args[1] = (uint64_t)sigaction; 1017 rpc.args[2] = (uint64_t)rsp_xp; 1018 rpc.args[3] = (uint64_t)client_xp; 1019 1020 // register RPC request in remote RPC fifo (non blocking) 1021 rpc_send( cxy , &rpc , false ); 1022 1023 sigaction_dmsg("\n[DBG] %s : exit for %s (%d) / thread %x on core[%x,%d] / cycle %d\n", 1024 __FUNCTION__ , process_action_str( sigaction ) , sigaction , CURRENT_THREAD , 1025 local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() ); 995 //////////////////////////////////////////////////// 996 void rpc_process_sigaction_client( cxy_t cxy, 997 rpc_desc_t * rpc_ptr ) 998 { 999 sigaction_dmsg("\n[DBG] %s : enter to %s process %x in cluster %x / cycle %d\n", 1000 __FUNCTION__ , process_action_str( (uint32_t)rpc_ptr->args[0] ) , 1001 ((process_t *)(intptr_t)rpc_ptr->args[1])->pid , cxy , (uint32_t)hal_get_cycles() ); 1002 1003 // register RPC request in remote RPC fifo 1004 rpc_send( cxy , rpc_ptr ); 1005 1006 sigaction_dmsg("\n[DBG] %s : exit after %s process %x in cluster %x / cycle %d\n", 1007 __FUNCTION__ , process_action_str( (uint32_t)rpc_ptr->args[0] ) , 1008 ((process_t *)(intptr_t)rpc_ptr->args[1])->pid , cxy , (uint32_t)hal_get_cycles() ); 1026 1009 } 1027 1010 … … 1029 1012 void rpc_process_sigaction_server( xptr_t xp ) 1030 1013 { 1031 process_t * process; 1032 uint32_t action; 1033 xptr_t rsp_xp; 1034 xptr_t client_xp; 1035 1036 // get client cluster identifier and pointer on RPC descriptor 1037 cxy_t client_cxy = (cxy_t)GET_CXY( xp ); 1038 rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp ); 1014 process_t * process; // pointer on local process descriptor 1015 uint32_t action; // sigaction index 1016 thread_t * client_ptr; // local pointer on client thread in client cluster 1017 cxy_t client_cxy; // client cluster identifier 1018 xptr_t client_xp; // extended pointer on client thread 1019 core_t * client_core; // local pointer on core running the client thread 1020 rpc_desc_t * rpc; // local pointer on rpc descriptor in client cluster 1021 1022 // get client cluster identifier and pointer on RPC descriptor 1023 client_cxy = (cxy_t)GET_CXY( xp ); 1024 rpc = (rpc_desc_t *)GET_PTR( xp ); 1039 1025 1040 1026 // get arguments from RPC descriptor 1041 process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) ); 1042 action = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) ); 1043 rsp_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) ); 1044 client_xp = (xptr_t) hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) ); 1045 1046 sigaction_dmsg("\n[DBG] %s : enter for %s (%d) / thread %x on core[%x,%d] / cycle %d\n", 1047 __FUNCTION__ , process_action_str( action ) , action , CURRENT_THREAD , 1048 local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() ); 1027 action = (uint32_t) hal_remote_lwd( XPTR( client_cxy , &rpc->args[0] ) ); 1028 process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &rpc->args[1] ) ); 1029 client_ptr = (thread_t *)hal_remote_lpt( XPTR( client_cxy , &rpc->thread ) ); 1030 1031 // build extended pointer on client thread 1032 client_xp = XPTR( client_cxy , client_ptr ); 1033 1034 sigaction_dmsg("\n[DBG] %s : enter to %s process %x / cycle %d\n", 1035 __FUNCTION__ , process_action_str( action ) , process->pid , (uint32_t)hal_get_cycles() ); 1049 1036 1050 1037 // call relevant kernel function 1051 if (action == DELETE_ALL_THREADS ) process_delete ( process , rsp_xp , client_xp ); 1052 else if (action == BLOCK_ALL_THREADS ) process_block ( process , rsp_xp , client_xp ); 1053 else if (action == UNBLOCK_ALL_THREADS ) process_unblock( process , rsp_xp , client_xp ); 1054 1055 sigaction_dmsg("\n[DBG] %s : exit for %s (%d) / thread %x on core[%x,%d] / cycle %d\n", 1056 __FUNCTION__ , process_action_str( action ) , action , CURRENT_THREAD , 1057 local_cxy , CURRENT_THREAD->core->lid , hal_time_stamp() ); 1038 if (action == DELETE_ALL_THREADS ) process_delete ( process , client_xp ); 1039 else if (action == BLOCK_ALL_THREADS ) process_block ( process , client_xp ); 1040 else if (action == UNBLOCK_ALL_THREADS ) process_unblock( process ); 1041 1042 // decrement the responses counter in RPC descriptor, 1043 // unblock the client thread only if it is the last response. 1044 if( hal_remote_atomic_add( XPTR( client_cxy , &rpc->response ) , -1 ) == 1 ) 1045 { 1046 client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) ); 1047 thread_unblock( client_xp , THREAD_BLOCKED_RPC ); 1048 dev_pic_send_ipi( client_cxy , client_core->lid ); 1049 } 1050 1051 sigaction_dmsg("\n[DBG] %s : exit after %s process %x / cycle %d\n", 1052 __FUNCTION__ , process_action_str( action ) , process->pid , (uint32_t)hal_get_cycles() ); 1058 1053 } 1059 1054 … … 1085 1080 rpc.index = RPC_VFS_INODE_CREATE; 1086 1081 rpc.response = 1; 1082 rpc.blocking = true; 1087 1083 1088 1084 // set input arguments in RPC descriptor … … 1097 1093 1098 1094 // register RPC request in remote RPC fifo (blocking function) 1099 rpc_send( cxy , &rpc , true);1095 rpc_send( cxy , &rpc ); 1100 1096 1101 1097 // get output values from RPC descriptor … … 1178 1174 rpc.index = RPC_VFS_INODE_DESTROY; 1179 1175 rpc.response = 1; 1176 rpc.blocking = true; 1180 1177 1181 1178 // set input arguments in RPC descriptor … … 1183 1180 1184 1181 // register RPC request in remote RPC fifo (blocking function) 1185 rpc_send( cxy , &rpc , true);1182 rpc_send( cxy , &rpc ); 1186 1183 1187 1184 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 1236 1233 rpc.index = RPC_VFS_DENTRY_CREATE; 1237 1234 rpc.response = 1; 1235 rpc.blocking = true; 1238 1236 1239 1237 // set input arguments in RPC descriptor … … 1243 1241 1244 1242 // register RPC request in remote RPC fifo (blocking function) 1245 rpc_send( cxy , &rpc , true);1243 rpc_send( cxy , &rpc ); 1246 1244 1247 1245 // get output values from RPC descriptor … … 1315 1313 rpc.index = RPC_VFS_DENTRY_DESTROY; 1316 1314 rpc.response = 1; 1315 rpc.blocking = true; 1317 1316 1318 1317 // set input arguments in RPC descriptor … … 1320 1319 1321 1320 // register RPC request in remote RPC fifo (blocking function) 1322 rpc_send( cxy , &rpc , true);1321 rpc_send( cxy , &rpc ); 1323 1322 1324 1323 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 1373 1372 rpc.index = RPC_VFS_FILE_CREATE; 1374 1373 rpc.response = 1; 1374 rpc.blocking = true; 1375 1375 1376 1376 // set input arguments in RPC descriptor … … 1379 1379 1380 1380 // register RPC request in remote RPC fifo (blocking function) 1381 rpc_send( cxy , &rpc , true);1381 rpc_send( cxy , &rpc ); 1382 1382 1383 1383 // get output values from RPC descriptor … … 1442 1442 rpc.index = RPC_VFS_FILE_DESTROY; 1443 1443 rpc.response = 1; 1444 rpc.blocking = true; 1444 1445 1445 1446 // set input arguments in RPC descriptor … … 1447 1448 1448 1449 // register RPC request in remote RPC fifo (blocking function) 1449 rpc_send( cxy , &rpc , true);1450 rpc_send( cxy , &rpc ); 1450 1451 1451 1452 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 1499 1500 rpc.index = RPC_VFS_INODE_LOAD; 1500 1501 rpc.response = 1; 1502 rpc.blocking = true; 1501 1503 1502 1504 // set input arguments in RPC descriptor … … 1506 1508 1507 1509 // register RPC request in remote RPC fifo (blocking function) 1508 rpc_send( cxy , &rpc , true);1510 rpc_send( cxy , &rpc ); 1509 1511 1510 1512 // get output values from RPC descriptor … … 1573 1575 rpc.index = RPC_VFS_MAPPER_LOAD_ALL; 1574 1576 rpc.response = 1; 1577 rpc.blocking = true; 1575 1578 1576 1579 // set input arguments in RPC descriptor … … 1578 1581 1579 1582 // register RPC request in remote RPC fifo (blocking function) 1580 rpc_send( cxy , &rpc , true);1583 rpc_send( cxy , &rpc ); 1581 1584 1582 1585 // get output values from RPC descriptor … … 1638 1641 rpc.index = RPC_FATFS_GET_CLUSTER; 1639 1642 rpc.response = 1; 1643 rpc.blocking = true; 1640 1644 1641 1645 // set input arguments in RPC descriptor … … 1645 1649 1646 1650 // register RPC request in remote RPC fifo 1647 rpc_send( cxy , &rpc , true);1651 rpc_send( cxy , &rpc ); 1648 1652 1649 1653 // get output argument from rpc descriptor … … 1711 1715 rpc.index = RPC_VMM_GET_VSEG; 1712 1716 rpc.response = 1; 1717 rpc.blocking = true; 1713 1718 1714 1719 // set input arguments in RPC descriptor … … 1717 1722 1718 1723 // register RPC request in remote RPC fifo (blocking function) 1719 rpc_send( cxy , &rpc , true);1724 rpc_send( cxy , &rpc ); 1720 1725 1721 1726 // get output argument from rpc descriptor … … 1786 1791 rpc.index = RPC_VMM_GET_PTE; 1787 1792 rpc.response = 1; 1793 rpc.blocking = true; 1788 1794 1789 1795 // set input arguments in RPC descriptor … … 1793 1799 1794 1800 // register RPC request in remote RPC fifo (blocking function) 1795 rpc_send( cxy , &rpc , true);1801 rpc_send( cxy , &rpc ); 1796 1802 1797 1803 // get output argument from rpc descriptor … … 1860 1866 rpc.index = RPC_THREAD_USER_CREATE; 1861 1867 rpc.response = 1; 1868 rpc.blocking = true; 1862 1869 1863 1870 // set input arguments in RPC descriptor … … 1865 1872 1866 1873 // register RPC request in remote RPC fifo (blocking function) 1867 rpc_send( cxy , &rpc , true);1874 rpc_send( cxy , &rpc ); 1868 1875 1869 1876 // get output arguments from RPC descriptor … … 1923 1930 rpc.index = RPC_THREAD_USER_CREATE; 1924 1931 rpc.response = 1; 1932 rpc.blocking = true; 1925 1933 1926 1934 // set input arguments in RPC descriptor … … 1929 1937 1930 1938 // register RPC request in remote RPC fifo (blocking function) 1931 rpc_send( cxy , &rpc , true);1939 rpc_send( cxy , &rpc ); 1932 1940 1933 1941 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 1986 1994 rpc.index = RPC_MAPPER_MOVE_BUFFER; 1987 1995 rpc.response = 1; 1996 rpc.blocking = true; 1988 1997 1989 1998 // set input arguments in RPC descriptor … … 1996 2005 1997 2006 // register RPC request in remote RPC fifo (blocking function) 1998 rpc_send( cxy , &rpc , true);2007 rpc_send( cxy , &rpc ); 1999 2008 2000 2009 // get output values from RPC descriptor … … 2083 2092 rpc.index = RPC_MAPPER_GET_PAGE; 2084 2093 rpc.response = 1; 2094 rpc.blocking = true; 2085 2095 2086 2096 // set input arguments in RPC descriptor … … 2089 2099 2090 2100 // register RPC request in remote RPC fifo (blocking function) 2091 rpc_send( cxy , &rpc , true);2101 rpc_send( cxy , &rpc ); 2092 2102 2093 2103 // get output values from RPC descriptor … … 2151 2161 rpc.index = RPC_VMM_CREATE_VSEG; 2152 2162 rpc.response = 1; 2163 rpc.blocking = true; 2153 2164 2154 2165 // set input arguments in RPC descriptor … … 2163 2174 2164 2175 // register RPC request in remote RPC fifo (blocking function) 2165 rpc_send( cxy , &rpc , true);2176 rpc_send( cxy , &rpc ); 2166 2177 2167 2178 // get output values from RPC descriptor … … 2230 2241 rpc.index = RPC_SCHED_DISPLAY; 2231 2242 rpc.response = 1; 2243 rpc.blocking = true; 2232 2244 2233 2245 // set input arguments in RPC descriptor … … 2235 2247 2236 2248 // register RPC request in remote RPC fifo (blocking function) 2237 rpc_send( cxy , &rpc , true);2249 rpc_send( cxy , &rpc ); 2238 2250 2239 2251 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", … … 2282 2294 rpc.index = RPC_VMM_SET_COW; 2283 2295 rpc.response = 1; 2296 rpc.blocking = true; 2284 2297 2285 2298 // set input arguments in RPC descriptor … … 2287 2300 2288 2301 // register RPC request in remote RPC fifo (blocking function) 2289 rpc_send( cxy , &rpc , true);2302 rpc_send( cxy , &rpc ); 2290 2303 2291 2304 rpc_dmsg("\n[DBG] %s : exit / thread %x on core[%x,%d] / cycle %d\n", -
trunk/kernel/kern/rpc.h
r409 r416 109 109 { 110 110 rpc_index_t index; /*! index of requested RPC service */ 111 volatile uint32_t response; /*! response valid when 0*/111 volatile uint32_t response; /*! all responses received when 0 */ 112 112 struct thread_s * thread; /*! local pointer on client thread */ 113 113 uint32_t lid; /*! index of core running the calling thread */ 114 bool_t blocking; /*! blocking RPC when true */ 114 115 uint64_t args[10]; /*! input/output arguments buffer */ 115 116 } … … 127 128 * the caller. It exit with a Panic message if remote fifo is still full after 128 129 * (CONFIG_RPC_PUT_MAX_ITERATIONS) retries. 129 * - When the <block> argumentis true, this function blocks and deschedule.130 * - When the RPC <blocking> field is true, this function blocks and deschedule. 130 131 * It returns only when the server acknowledges the RPC by writing in the RPC 131 132 * "response" field, and unblocks the client. 132 * - When the <block > argumentis false, this function returns as soon as the RPC133 * - When the <blocking> field is false, this function returns as soon as the RPC 133 134 * has been registered in the FIFO, and the server thread must directly signal 134 135 * completion to the client thread. … … 136 137 * @ cxy : server cluster identifier 137 138 * @ desc : local pointer on RPC descriptor in client cluster 138 * @ block : boolean true when blocking behaviour is required.139 139 **********************************************************************************/ 140 140 void rpc_send( cxy_t cxy, 141 rpc_desc_t * desc, 142 bool_t block ); 141 rpc_desc_t * desc ); 143 142 144 143 … … 252 251 /*********************************************************************************** 253 252 * [4] The RPC_PROCESS_MAKE_EXIT can be called by any thread to request the owner 254 * cluster to execute the process_make_exit() function for a callingprocess.255 *********************************************************************************** 256 * @ cxy : server cluster identifier.257 * @ p rocess : local pointer on calling process in owner cluster.253 * cluster to execute the process_make_exit() function for the target process. 254 *********************************************************************************** 255 * @ cxy : owner cluster identifier. 256 * @ pid : target process identifier. 258 257 * @ status : calling process exit status. 259 258 **********************************************************************************/ 260 259 void rpc_process_make_exit_client( cxy_t cxy, 261 struct process_s * process,260 pid_t pid, 262 261 uint32_t status ); 263 262 … … 268 267 * cluster to execute the process_make_kill() function for a target process. 269 268 *********************************************************************************** 270 * @ cxy : server cluster identifier.271 * @ p rocess : local pointer on target process in owner cluster.269 * @ cxy : owner cluster identifier. 270 * @ pid : target process identifier. 272 271 * @ seg_id : signal type (only SIGKILL / SIGSTOP / SIGCONT are supported). 273 272 **********************************************************************************/ 274 273 void rpc_process_make_kill_client( cxy_t cxy, 275 struct process_s * process,274 pid_t pid, 276 275 uint32_t seg_id ); 277 276 … … 339 338 * 340 339 * WARNING : It is implemented as a NON BLOCKING multicast RPC, that can be sent 341 * in parallel to all process copies. The various server threads must decrement the 342 * responses counter defined by the <rsp_xp> argument, and the last server thread 343 * must unblock the <client_xp> thread. 340 * in parallel to all process copies. The rpc descriptor is allocated in the client 341 * thread stack by the process_sigaction() function. The various server threads 342 * must decrement the responses counter defined in the rsp descriptor, and the last 343 * server thread unblock the client thread that blocked (after sending all RPC 344 * requests) in the process_sigaction() function. 345 * - The first RPC argument is the sigaction type (BLOCK / UNBLOCK / DELETE). 346 * - The second RPC argument is the local pointer on target process. 344 347 *********************************************************************************** 345 348 * @ cxy : server cluster identifier. 346 * @ process : [in] local pointer on target process in server cluster. 347 * @ sigaction : [in] action type (BLOCK / UNBLOCK / DELETE). 348 * @ rsp_xp : [in] extended pointer on response counter. 349 * @ client_xp : [in] extended pointer on client thread. 350 **********************************************************************************/ 351 void rpc_process_sigaction_client( cxy_t cxy, 352 struct process_s * process, 353 uint32_t sigaction, 354 xptr_t rsp_xp, 355 xptr_t client_xp ); 349 * @ rpc_ptr : [in] local pointer on rpc descriptor in client cluster. 350 **********************************************************************************/ 351 void rpc_process_sigaction_client( cxy_t cxy, 352 rpc_desc_t * rpc_ptr ); 356 353 357 354 void rpc_process_sigaction_server( xptr_t xp ); -
trunk/kernel/kern/scheduler.c
r409 r416 58 58 list_root_init( &sched->k_root ); 59 59 60 sched-> sig_pending = false; // no pending signal60 sched->req_ack_pending = false; // no pending request 61 61 62 62 } // end sched_init() … … 89 89 90 90 } // end sched_register_thread() 91 92 /////////////////////////////////////////////93 void sched_remove_thread( thread_t * thread )94 {95 scheduler_t * sched = &thread->core->scheduler;96 thread_type_t type = thread->type;97 98 // take lock protecting sheduler lists99 spinlock_lock( &sched->lock );100 101 if( type == THREAD_USER )102 {103 list_unlink( &thread->sched_list );104 sched->u_threads_nr--;105 if( sched->u_threads_nr == 0 ) sched->u_last = NULL;106 }107 else // kernel thread108 {109 list_unlink( &thread->sched_list );110 sched->k_threads_nr--;111 if( sched->k_threads_nr == 0 ) sched->k_last = NULL;112 }113 114 // release lock115 spinlock_unlock( &sched->lock );116 117 } // end sched_remove_thread()118 91 119 92 ////////////////////////////////////////////// … … 203 176 } // end sched_select() 204 177 205 ////////////////////////////////////////// 206 void sched_handle_ signals( core_t * core )178 /////////////////////////////////////////// 179 void sched_handle_requests( core_t * core ) 207 180 { 208 181 list_entry_t * iter; 209 182 thread_t * thread; 210 183 184 // printk("\n@@@ %s : current thread %x enter at cycle %d\n", 185 // __FUNCTION__ , CURRENT_THREAD , hal_time_stamp() ); 186 211 187 scheduler_t * sched = &core->scheduler; 212 188 … … 214 190 spinlock_lock( &sched->lock ); 215 191 216 // handleuser threads192 // scan all user threads 217 193 LIST_FOREACH( &sched->u_root , iter ) 218 194 { 219 195 thread = LIST_ELEMENT( iter , thread_t , sched_list ); 220 196 221 if( thread->flags & THREAD_FLAG_SIGNAL ) // thread has signal 222 { 223 // decrement response counter to acknowledge signal 224 hal_atomic_add( thread->sig_rsp_count , -1 ); 225 226 // reset signal 227 thread_reset_signal( thread ); 197 // handle REQ_ACK 198 if( thread->flags & THREAD_FLAG_REQ_ACK ) 199 { 200 // check thread blocked 201 assert( (thread->blocked & THREAD_BLOCKED_GLOBAL) , 202 __FUNCTION__ , "thread not blocked" ); 203 204 // decrement response counter 205 hal_atomic_add( thread->ack_rsp_count , -1 ); 206 207 // reset REQ_ACK in thread descriptor 208 thread_reset_req_ack( thread ); 209 } 210 211 // handle REQ_DELETE 212 if( thread->flags & THREAD_FLAG_REQ_DELETE ) 213 { 214 215 sched_dmsg("\n[DBG] %s : current thread %x delete thread %x at cycle %d\n", 216 __FUNCTION__ , CURRENT_THREAD , thread , hal_time_stamp() ); 217 218 // release FPU if required 219 if( thread->core->fpu_owner == thread ) thread->core->fpu_owner = NULL; 220 221 // detach thread from parent if attached 222 if( (thread->flags & THREAD_FLAG_DETACHED) == 0 ) 223 thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) ); 224 225 // detach thread from process 226 process_remove_thread( thread ); 227 228 // remove thread from scheduler 229 list_unlink( &thread->sched_list ); 230 sched->u_threads_nr--; 231 if( sched->u_threads_nr == 0 ) sched->u_last = NULL; 232 233 // release memory allocated to thread 234 thread_destroy( thread ); 235 236 // destroy process descriptor if no more threads 237 if (thread->process->th_nr == 0) process_destroy( thread->process ); 228 238 } 229 239 } … … 232 242 spinlock_unlock( &sched->lock ); 233 243 234 } // end sched_handle_signals() 244 // printk("\n@@@ %s : current thread %x exit at cycle %d\n", 245 // __FUNCTION__ , CURRENT_THREAD , hal_time_stamp() ); 246 247 } // end sched_handle_requests() 235 248 236 249 //////////////////////////////// … … 305 318 } 306 319 307 // handle signals for all threads executing on this core.308 sched_handle_ signals( core );320 // handle pending requests for all threads executing on this core. 321 sched_handle_requests( core ); 309 322 310 323 // exit critical section / restore SR from next thread context … … 354 367 if (thread->type == THREAD_DEV) 355 368 { 356 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block ed%X / %s\n",369 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block %X / flags %X / %s\n", 357 370 thread_type_str( thread->type ), thread->process->pid, thread->trdid, 358 thread, thread->blocked 371 thread, thread->blocked, thread->flags, thread->chdev->name ); 359 372 } 360 373 else 361 374 { 362 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block ed %X\n",375 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block %X / flags %X \n", 363 376 thread_type_str( thread->type ), thread->process->pid, thread->trdid, 364 thread, thread->blocked );377 thread, thread->blocked, thread->flags ); 365 378 } 366 379 } … … 370 383 { 371 384 thread = LIST_ELEMENT( iter , thread_t , sched_list ); 372 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block ed%X\n",385 nolock_printk(" - %s / pid %X / trdid %X / desc %X / block %X / flags %X\n", 373 386 thread_type_str( thread->type ), thread->process->pid, thread->trdid, 374 thread, thread->blocked );387 thread, thread->blocked, thread->flags ); 375 388 } 376 389 -
trunk/kernel/kern/scheduler.h
r409 r416 40 40 typedef struct scheduler_s 41 41 { 42 spinlock_t lock; /*! readlock protecting lists of threads*/43 uint16_t u_threads_nr; /*! total numbre of attached user threads*/44 uint16_t k_threads_nr; /*! total number of attached kernel threads*/45 list_entry_t u_root; /*! root of list of user threads for this scheduler*/46 list_entry_t k_root; /*! root of list of kernel threads for this scheduler*/47 list_entry_t * u_last; /*! pointer on list_entry for last executed k_thread*/48 list_entry_t * k_last; /*! pointer on list entry for last executed u_thread*/49 struct thread_s * idle; /*! pointer on idle thread*/50 struct thread_s * current; /*! pointer on current running thread*/51 bool_t sig_pending; /*! signal_handller must be called when true*/42 spinlock_t lock; /*! readlock protecting lists of threads */ 43 uint16_t u_threads_nr; /*! total number of attached user threads */ 44 uint16_t k_threads_nr; /*! total number of attached kernel threads */ 45 list_entry_t u_root; /*! root of list of user threads */ 46 list_entry_t k_root; /*! root of list of kernel threads */ 47 list_entry_t * u_last; /*! pointer on list_entry for last executed k_thread */ 48 list_entry_t * k_last; /*! pointer on list entry for last executed u_thread */ 49 struct thread_s * idle; /*! pointer on idle thread */ 50 struct thread_s * current; /*! pointer on current running thread */ 51 bool_t req_ack_pending; /*! signal_handller must be called when true */ 52 52 } 53 53 scheduler_t; … … 67 67 struct thread_s * thread ); 68 68 69 /*********************************************************************************************70 * This function remove a thread from its scheduler.re scheduler.71 *********************************************************************************************72 * @ thread : local pointer on the thread descriptor.73 ********************************************************************************************/74 void sched_remove_thread( struct thread_s * thread );75 76 69 /********************************************************************************************* 77 70 * This function is the only method to make a context switch. It is called in cas of TICK, … … 87 80 88 81 /********************************************************************************************* 89 * This function scan all threads attached to a given core scheduler, and executes 90 * the relevant actions for pending KILL or EXIT signals. 91 * It is called in by the sched_yield() function, with IRQ disabled. 82 * This function scan all threads attached to a given scheduler, and executes the relevant 83 * actions for pending THREAD_FLAG_REQ_ACK or THREAD_FLAG_REQ_DELETE requests. 84 * It is called in by the sched_yield() function, with IRQ disabled. 85 * - REQ_ACK : it checks that target thread is blocked, decrements the response counter 86 * to acknowledge the client thread, and reset the pending request. 87 * - REQ_DELETE : it detach the target thread from parent if attached, detach it from 88 * the process, remove it from scheduler, release memory allocated to thread descriptor, 89 * and destroy the process descriptor it the target thread was the last thread. 92 90 ********************************************************************************************* 93 91 * @ core : local pointer on the core descriptor. 94 92 ********************************************************************************************/ 95 void sched_handle_ signals( struct core_s * core );93 void sched_handle_requests( struct core_s * core ); 96 94 97 95 /********************************************************************************************* … … 113 111 114 112 /********************************************************************************************* 115 * This function unlink a thread identified by the <thread> pointer from its process.116 * It is called by the sched_handle_signals() function when one EXIT or KILL signal is set,117 * and it implement the first step of a thread destructionebut can also be directly called by a local killer thread signal.118 * - It detach the thread from the scheduler.119 * - It detach the thread from the process.120 * - It detach the thread from the parent thread when the thread is attached.121 * - It destroys the thread descriptor.122 * - It acknowledge the killer thread if it's a kill signal123 *********************************************************************************************124 * @ thread : pointer on thread to be killed.125 ********************************************************************************************/126 void sched_kill_thread( struct thread_s * thread );127 128 /*********************************************************************************************129 113 * This function display the internal state of the local core identified by its <lid>. 130 114 ********************************************************************************************* -
trunk/kernel/kern/thread.c
r409 r416 696 696 } // thread_child_parent_unlink() 697 697 698 ///////////////////////////////////////////////// 699 inline void thread_set_ signal( thread_t * thread,700 uint32_t * sig_rsp_count )698 ////////////////////////////////////////////////// 699 inline void thread_set_req_ack( thread_t * target, 700 uint32_t * rsp_count ) 701 701 { 702 702 reg_t save_sr; // for critical section 703 703 704 // get pointer on t hreadthread scheduler705 scheduler_t * thread_sched = &thread->core->scheduler;706 707 // wait scheduler ready to handle a new signal708 while( thread_sched->sig_pending ) asm volatile( "nop" );704 // get pointer on target thread scheduler 705 scheduler_t * sched = &target->core->scheduler; 706 707 // wait scheduler ready to handle a new request 708 while( sched->req_ack_pending ) asm volatile( "nop" ); 709 709 710 710 // enter critical section 711 711 hal_disable_irq( &save_sr ); 712 712 713 // set signal inthread scheduler714 thread_sched->sig_pending = true;715 716 // set signal in threadthread "flags"717 hal_atomic_or( &t hread->flags , THREAD_FLAG_SIGNAL);718 719 // set pointer on responses counter in t hreadthread720 t hread->sig_rsp_count = sig_rsp_count;713 // set request in target thread scheduler 714 sched->req_ack_pending = true; 715 716 // set ack request in target thread "flags" 717 hal_atomic_or( &target->flags , THREAD_FLAG_REQ_ACK ); 718 719 // set pointer on responses counter in target thread 720 target->ack_rsp_count = rsp_count; 721 721 722 722 // exit critical section … … 725 725 hal_fence(); 726 726 727 } // thread_set_ signal()728 729 //////////////////////////////////////////////////// 730 inline void thread_reset_ signal( thread_t * thread)727 } // thread_set_req_ack() 728 729 ///////////////////////////////////////////////////// 730 inline void thread_reset_req_ack( thread_t * target ) 731 731 { 732 732 reg_t save_sr; // for critical section 733 733 734 734 // get pointer on target thread scheduler 735 scheduler_t * sched = &t hread->core->scheduler;735 scheduler_t * sched = &target->core->scheduler; 736 736 737 737 // check signal pending in scheduler 738 assert( sched-> sig_pending , __FUNCTION__ , "no pending signal" );738 assert( sched->req_ack_pending , __FUNCTION__ , "no pending signal" ); 739 739 740 740 // enter critical section … … 742 742 743 743 // reset signal in scheduler 744 sched-> sig_pending = false;744 sched->req_ack_pending = false; 745 745 746 746 // reset signal in thread "flags" 747 hal_atomic_and( &t hread->flags , ~THREAD_FLAG_SIGNAL);747 hal_atomic_and( &target->flags , ~THREAD_FLAG_REQ_ACK ); 748 748 749 749 // reset pointer on responses counter 750 t hread->sig_rsp_count = NULL;750 target->ack_rsp_count = NULL; 751 751 752 752 // exit critical section … … 755 755 hal_fence(); 756 756 757 } // thread_reset_ signal()757 } // thread_reset_req_ack() 758 758 759 759 //////////////////////////////// … … 809 809 void thread_kill( thread_t * target ) 810 810 { 811 volatile uint32_t sig_rsp_count = 1; // responses counter811 volatile uint32_t rsp_count = 1; // responses counter 812 812 813 813 thread_t * killer = CURRENT_THREAD; 814 814 815 kill_dmsg("\n[DBG] %s : killer thread %x enter for target thread %x\n",815 thread_dmsg("\n[DBG] %s : killer thread %x enter for target thread %x\n", 816 816 __FUNCTION__, local_cxy, killer->trdid , target trdid ); 817 817 … … 824 824 { 825 825 // set signal in target thread descriptor and in target scheduler 826 thread_set_ signal( target , (uint32_t *)(&sig_rsp_count) );826 thread_set_req_ack( target , (void *)(&rsp_count) ); 827 827 828 828 // send an IPI to the target thread core. … … 833 833 { 834 834 // exit when response received from scheduler 835 if( sig_rsp_count == 0 ) break;835 if( rsp_count == 0 ) break; 836 836 837 837 // deschedule without blocking … … 840 840 } 841 841 842 // release FPU if required 843 if( target->core->fpu_owner == target ) target->core->fpu_owner = NULL; 844 845 // detach thread from parent if attached 846 if( (target->flags & THREAD_FLAG_DETACHED) == 0 ) 847 thread_child_parent_unlink( target->parent , XPTR( local_cxy , target ) ); 848 849 // detach thread from process 850 process_remove_thread( target ); 851 852 // remove thread from scheduler 853 sched_remove_thread( target ); 854 855 // release memory allocated to target thread 856 thread_destroy( target ); 857 858 kill_dmsg("\n[DBG] %s : killer thread %x enter for target thread %x\n", 842 // set REQ_DELETE flag 843 hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE ); 844 845 thread_dmsg("\n[DBG] %s : killer thread %x exit for target thread %x\n", 859 846 __FUNCTION__, local_cxy, killer->trdid , target trdid ); 860 847 -
trunk/kernel/kern/thread.h
r409 r416 72 72 #define THREAD_FLAG_JOIN_DONE 0x0002 /*! Parent thread made a join */ 73 73 #define THREAD_FLAG_SCHED 0x0004 /*! Scheduling required for this thread */ 74 #define THREAD_FLAG_SIGNAL 0x0004 /*! Acknowledge of descheduling required */ 74 #define THREAD_FLAG_REQ_ACK 0x0008 /*! Acknowledge required from scheduler */ 75 #define THREAD_FLAG_REQ_DELETE 0x0010 /*! Destruction required by scheduler */ 75 76 76 77 /*************************************************************************************** … … 119 120 * - The TRDID 16 MSB bits contain the CXY of cluster containing the thread. 120 121 * - The LTID is used to index the th_tbl[] array in the local process descriptor. 121 * This TRDID is computed by the process_register_thread() function, when the user122 _* This TRDID is computed by the process_register_thread() function, when the user 122 123 * thread is registered in the local copy of the process descriptor. 123 124 * … … 153 154 xptr_t join_xp; /*! extended pointer on joining thread */ 154 155 155 uint32_t * sig_rsp_count; /*! pointer on signal response counter*/156 uint32_t * ack_rsp_count; /*! pointer on acknowledge response counter */ 156 157 157 158 intptr_t u_stack_base; /*! user stack base address */ … … 345 346 346 347 /*************************************************************************************** 347 * This function is used by a killer thread running in the same cluster as a target348 * thread to request the scheduler of the target t o call the thread_handle_signal()349 * at the next context switch, to confirm that the target thread is blocked and350 * not currently running.This function executes atomically the following actions :351 * - it set the sig_pending flagin the target scheduler descriptor.352 * - it set the SIGflag in the "flags" field of the target thread descriptor.348 * This function is used by a "blocker" thread running in the same cluster as a "target" 349 * thread to request the scheduler of the target thread to acknowledge that the target 350 * thread is blocked and not running, at the next context switch. 351 * This function executes atomically the following actions : 352 * - it set the request_pending boolean in the target scheduler descriptor. 353 * - it set the REQ_ACK flag in the "flags" field of the target thread descriptor. 353 354 * - It registers the responses counter pointer in the target thread descriptor. 354 * The sig_pending flag is handled as a set/reset flip-flop by the killerthread355 * and by the targetscheduler.355 * The request_pending flag is handled as a set/reset flip-flop by the "blocker" thread 356 * and by the "target" scheduler. 356 357 *************************************************************************************** 357 358 * @ target : local pointer on target thread. 358 * @ sig_rsp_count : local pointer on responses counter.359 **************************************************************************************/ 360 void thread_set_ signal( thread_t * thread,361 uint32_t * sig_rsp_count );362 363 /*************************************************************************************** 364 * This function is used by the sched_handle_signal() function executed by a scheduler365 * to reset a pending signal in both a target <thread> descriptor, and in the target366 * thread scheduler.367 *************************************************************************************** 368 * @ t hread: local pointer on target thread.369 **************************************************************************************/ 370 void thread_reset_ signal( thread_t * thread);359 * @ ack_rsp_count : local pointer on responses counter. 360 **************************************************************************************/ 361 void thread_set_req_ack( thread_t * target, 362 uint32_t * ack_rsp_count ); 363 364 /*************************************************************************************** 365 * This function is used by the sched_handle_signal() function executed by the 366 * scheduler of a "target" thread to reset a "blocked not running" acknowledge request 367 * in both the target thread descriptor, and in the target thread scheduler. 368 *************************************************************************************** 369 * @ target : local pointer on target thread. 370 **************************************************************************************/ 371 void thread_reset_req_ack( thread_t * target ); 371 372 372 373 /*************************************************************************************** … … 390 391 * If not, the client thread must use the RPC_THREAD_KILL. 391 392 * - When the killer thread is running on the same core as the target thread, 392 * This function simply detach the target thread from the scheduler, 393 * detach it from the parent thread if it is attached, detach it from the 394 * local process descriptor, and rrleases all memory allocated to the thread. 395 * - When the killer thread is running on a different core than the target thread 396 * The killer send a signal to the target thread scheduler requesting this 397 * scheduler to confirm that the target thread is blocked and not running. 398 * Then, it executes the same actions as described above. 393 * this function simply set the BLOCKED_ GLOBAL bit and the REQ_DELETE flag 394 * in the target thread descriptor and return. 395 * - When the killer thread is running on a different core than the target thread, 396 * the killer set the BLOCKED_GLOBAL bit and the REQ_ACK flag in target thread, 397 * to ask the scheduler to confirm that the target is blocked and not running. 398 * Then, it set the REQ_DELETE flag in the target thread and return. 399 * In both cases, the actual target thread destruction is done by the scheduler 400 * at the next scheduling point. 399 401 *************************************************************************************** 400 402 * @ thread : local pointer on the target thread.
Note: See TracChangeset
for help on using the changeset viewer.