Changeset 407 for trunk/kernel/kern/thread.c
- Timestamp:
- Nov 7, 2017, 3:08:12 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/thread.c
r406 r407 57 57 else if( type == THREAD_RPC ) return "RPC"; 58 58 else if( type == THREAD_DEV ) return "DEV"; 59 else if( type == THREAD_KERNEL ) return "KER";60 59 else if( type == THREAD_IDLE ) return "IDL"; 61 60 else return "undefined"; … … 153 152 } 154 153 154 // compute thread descriptor size without kernel stack 155 uint32_t desc_size = (intptr_t)(&thread->signature) - (intptr_t)thread + 4; 156 155 157 // Initialize new thread descriptor 156 158 thread->trdid = trdid; … … 170 172 thread->u_stack_base = u_stack_base; 171 173 thread->u_stack_size = u_stack_size; 172 thread->k_stack_base = (intptr_t)thread ;173 thread->k_stack_size = CONFIG_THREAD_DESC_SIZE ;174 thread->k_stack_base = (intptr_t)thread + desc_size; 175 thread->k_stack_size = CONFIG_THREAD_DESC_SIZE - desc_size; 174 176 175 177 thread->entry_func = func; // thread entry point … … 178 180 thread->signals = 0; // no pending signal 179 181 thread->errno = 0; // no error detected 180 thread->fork_user = 0; // no fork required181 thread->fork_cxy = 0; 182 thread->fork_user = 0; // no user defined placement for fork 183 thread->fork_cxy = 0; // user defined target cluster for fork 182 184 183 185 // thread blocked … … 221 223 vseg_t * vseg; // stack vseg 222 224 223 thread_dmsg("\n[DMSG] %s : enters for process %x\n", __FUNCTION__ , pid);225 assert( (attr != NULL) , __FUNCTION__, "pthread attributes must be defined" ); 224 226 225 227 // get process descriptor local copy … … 234 236 235 237 // select a target core in local cluster 236 if( attr->attributes & PT_ATTR_CORE_DEFINED ) core_lid = attr->lid; 237 else core_lid = cluster_select_local_core(); 238 239 // check core local index 240 if( core_lid >= LOCAL_CLUSTER->cores_nr ) 241 { 242 printk("\n[ERROR] in %s : illegal core index attribute = %d\n", 243 __FUNCTION__ , core_lid ); 244 245 return EINVAL; 238 if( attr->attributes & PT_ATTR_CORE_DEFINED ) 239 { 240 core_lid = attr->lid; 241 if( core_lid >= LOCAL_CLUSTER->cores_nr ) 242 { 243 printk("\n[ERROR] in %s : illegal core index attribute = %d\n", 244 __FUNCTION__ , core_lid ); 245 return EINVAL; 246 } 247 } 248 else 249 { 250 core_lid = cluster_select_local_core(); 246 251 } 247 252 248 253 // allocate a stack from local VMM 249 vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK ); 254 vseg = vmm_create_vseg( process, 255 VSEG_TYPE_STACK, 256 0, // size unused 257 0, // length unused 258 0, // file_offset unused 259 0, // file_size unused 260 XPTR_NULL, // mapper_xp unused 261 local_cxy ); 250 262 251 263 if( vseg == NULL ) … … 287 299 288 300 // set DETACHED flag if required 289 if( attr->attributes & PT_ATTR_DETACH ) thread->flags |= THREAD_FLAG_DETACHED; 301 if( attr->attributes & PT_ATTR_DETACH ) 302 { 303 thread->flags |= THREAD_FLAG_DETACHED; 304 } 290 305 291 306 // allocate & initialize CPU context 292 error = hal_cpu_context_create( thread ); 293 294 if( error ) 307 if( hal_cpu_context_create( thread ) ) 295 308 { 296 309 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); … … 300 313 } 301 314 302 // allocate & initialize FPU context 303 error = hal_fpu_context_create( thread ); 304 305 if( error ) 315 // allocate FPU context 316 if( hal_fpu_context_alloc( thread ) ) 306 317 { 307 318 printk("\n[ERROR] in %s : cannot create FPU context\n", __FUNCTION__ ); … … 311 322 } 312 323 313 thread_dmsg("\n[DMSG] %s : exit / trdid = %x / process %x / core = %d\n", 314 __FUNCTION__ , thread->trdid , process->pid , core_lid ); 324 thread_dmsg("\n[DBG] %s : core[%x,%d] exit / trdid = %x / process %x / core = %d\n", 325 __FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, 326 thread->trdid , process->pid , core_lid ); 315 327 316 328 *new_thread = thread; … … 319 331 } // end thread_user_create() 320 332 321 ////////////////////////////////////////////// 333 //////////////////////////////////////////////////// 322 334 error_t thread_user_fork( process_t * process, 335 intptr_t stack_base, 336 uint32_t stack_size, 323 337 thread_t ** new_thread ) 324 338 { 325 339 error_t error; 326 thread_t * thread; // pointer on new thread descriptor340 thread_t * child; // pointer on new thread descriptor 327 341 lid_t core_lid; // selected core local index 328 vseg_t * vseg; // stack vseg 329 330 thread_dmsg("\n[DMSG] %s : enters\n", __FUNCTION__ ); 331 332 // allocate a stack from local VMM 333 vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK ); 334 335 if( vseg == NULL ) 336 { 337 printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ ); 338 return ENOMEM; 339 } 342 343 thread_dmsg("\n[DBG] %s : core[%x,%d] enters\n", 344 __FUNCTION__ , local_cxy , core_lid ); 340 345 341 346 // select a target core in local cluster 342 347 core_lid = cluster_select_local_core(); 343 348 344 // get pointer on callingthread descriptor345 thread_t * this= CURRENT_THREAD;349 // get pointer on parent thread descriptor 350 thread_t * parent = CURRENT_THREAD; 346 351 347 352 // allocate memory for new thread descriptor 348 thread = thread_alloc();349 350 if( thread == NULL )353 child = thread_alloc(); 354 355 if( child == NULL ) 351 356 { 352 357 printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ ); 353 vmm_remove_vseg( vseg );354 358 return ENOMEM; 355 359 } 356 360 357 361 // initialize thread descriptor 358 error = thread_init( thread,362 error = thread_init( child, 359 363 process, 360 364 THREAD_USER, 361 this->entry_func,362 this->entry_args,365 parent->entry_func, 366 parent->entry_args, 363 367 core_lid, 364 vseg->min,365 vseg->max - vseg->min);368 stack_base, 369 stack_size ); 366 370 367 371 if( error ) 368 372 { 369 373 printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ ); 370 vmm_remove_vseg( vseg ); 371 thread_release( thread ); 374 thread_release( child ); 372 375 return EINVAL; 373 376 } 374 377 375 // set ATTACHED flag if set in this thread376 if( this->flags & THREAD_FLAG_DETACHED ) thread->flags = THREAD_FLAG_DETACHED;377 378 // allocate & initialize CPU context from calling thread379 error = hal_cpu_context_copy( thread , this );380 381 if( error )382 { 383 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); 384 vmm_remove_vseg( vseg);385 thread_release( thread );378 // return child pointer 379 *new_thread = child; 380 381 // set DETACHED flag if required 382 if( parent->flags & THREAD_FLAG_DETACHED ) child->flags = THREAD_FLAG_DETACHED; 383 384 // allocate CPU context for child thread 385 if( hal_cpu_context_alloc( child ) ) 386 { 387 printk("\n[ERROR] in %s : cannot allocate CPU context\n", __FUNCTION__ ); 388 thread_release( child ); 386 389 return ENOMEM; 387 390 } 388 391 389 // allocate & initialize FPU context from calling thread 390 error = hal_fpu_context_copy( thread , this ); 391 392 if( error ) 393 { 394 printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ ); 395 vmm_remove_vseg( vseg ); 396 thread_release( thread ); 392 // allocate FPU context for child thread 393 if( hal_fpu_context_alloc( child ) ) 394 { 395 printk("\n[ERROR] in %s : cannot allocate FPU context\n", __FUNCTION__ ); 396 thread_release( child ); 397 397 return ENOMEM; 398 398 } 399 399 400 thread_dmsg("\n[DMSG] %s : exit / thread %x for process %x on core %d in cluster %x\n", 401 __FUNCTION__, thread->trdid, process->pid, core_lid, local_cxy ); 402 403 *new_thread = thread; 400 // copy kernel stack content from parent to child thread descriptor 401 void * dst = (void *)(&child->signature) + 4; 402 void * src = (void *)(&parent->signature) + 4; 403 memcpy( dst , src , parent->k_stack_size ); 404 405 thread_dmsg("\n[DBG] %s : core[%x,%d] exit / created main thread %x for process %x\n", 406 __FUNCTION__, local_cxy , core_lid , child->trdid , process->pid ); 407 404 408 return 0; 405 409 … … 416 420 thread_t * thread; // pointer on new thread descriptor 417 421 418 thread_dmsg("\n[DMSG] %s : enter / for type %s on core[%x,%d] / cycle %d\n", 419 __FUNCTION__ , thread_type_str( type ) , local_cxy , core_lid , hal_time_stamp() ); 420 421 assert( ( (type == THREAD_KERNEL) || (type == THREAD_RPC) || 422 (type == THREAD_IDLE) || (type == THREAD_DEV) ) , 423 __FUNCTION__ , "illegal thread type" ); 422 thread_dmsg("\n[DBG] %s : core[%x,%d] enters / type % / cycle %d\n", 423 __FUNCTION__ , local_cxy , core_lid , thread_type_str( type ) , hal_time_stamp() ); 424 425 assert( ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) , 426 __FUNCTION__ , "illegal thread type" ); 424 427 425 428 assert( (core_lid < LOCAL_CLUSTER->cores_nr) , … … 449 452 hal_cpu_context_create( thread ); 450 453 451 thread_dmsg("\n[DMSG] %s : exit / trdid = %x / type = %s / core = [%x,%d] / cycle %d\n", 452 __FUNCTION__ , thread->trdid , thread_type_str(type) , 453 local_cxy , core_lid , hal_time_stamp() ); 454 thread_dmsg("\n[DBG] %s : core = [%x,%d] exit / trdid = %x / type %s / cycle %d\n", 455 __FUNCTION__, local_cxy, core_lid, thread->trdid, thread_type_str(type), hal_time_stamp() ); 454 456 455 457 *new_thread = thread; … … 465 467 lid_t core_lid ) 466 468 { 467 assert( ( (type == THREAD_KERNEL) || (type == THREAD_RPC) || 468 (type == THREAD_IDLE) || (type == THREAD_DEV) ) , 469 __FUNCTION__ , "illegal thread type" ); 470 471 if( core_lid >= LOCAL_CLUSTER->cores_nr ) 472 { 473 panic("illegal core_lid / cores = %d / lid = %d / cxy = %x", 474 LOCAL_CLUSTER->cores_nr , core_lid , local_cxy ); 475 } 469 assert( (type == THREAD_IDLE) , __FUNCTION__ , "illegal thread type" ); 470 471 assert( (core_lid < LOCAL_CLUSTER->cores_nr) , __FUNCTION__ , "illegal core index" ); 476 472 477 473 error_t error = thread_init( thread, … … 487 483 488 484 return error; 489 } 485 486 } // end thread_kernel_init() 490 487 491 488 /////////////////////////////////////////////////////////////////////////////////////// … … 502 499 core_t * core = thread->core; 503 500 504 thread_dmsg("\n[D MSG] %s : enters for thread %x in process %x / type = %s\n",501 thread_dmsg("\n[DBG] %s : enters for thread %x in process %x / type = %s\n", 505 502 __FUNCTION__ , thread->trdid , process->pid , thread_type_str( thread->type ) ); 506 503 … … 556 553 tm_end = hal_get_cycles(); 557 554 558 thread_dmsg("\n[D MSG] %s : exit for thread %x in process %x / duration = %d\n",555 thread_dmsg("\n[DBG] %s : exit for thread %x in process %x / duration = %d\n", 559 556 __FUNCTION__, thread->trdid , process->pid , tm_end - tm_start ); 560 } 557 558 } // end thread_destroy() 561 559 562 560 ///////////////////////////////////////////////// … … 609 607 { 610 608 hal_atomic_or( &thread->signals , mask ); 609 hal_fence(); 611 610 } 612 611 … … 616 615 { 617 616 hal_atomic_and( &thread->signals , ~mask ); 618 } 619 620 ////////////////////////////////// 621 inline bool_t thread_is_joinable() 622 { 623 thread_t * this = CURRENT_THREAD; 624 return( (this->brothers_list.next != XPTR_NULL) && 625 (this->brothers_list.pred != XPTR_NULL) ); 626 } 627 628 ////////////////////////////////// 629 inline bool_t thread_is_runnable() 630 { 631 thread_t * this = CURRENT_THREAD; 632 return( this->blocked == 0 ); 617 hal_fence(); 633 618 } 634 619 … … 650 635 { 651 636 this->flags &= ~THREAD_FLAG_SCHED; 652 sched_yield( NULL ); 653 } 654 } 637 sched_yield(); 638 } 639 640 } // end thread_check_sched() 641 642 ///////////////////////////////////// 643 void thread_block( thread_t * thread, 644 uint32_t cause ) 645 { 646 // set blocking cause 647 hal_atomic_or( &thread->blocked , cause ); 648 hal_fence(); 649 650 } // end thread_block() 651 652 ///////////////////////////////////////// 653 uint32_t thread_unblock( xptr_t thread, 654 uint32_t cause ) 655 { 656 // get thread cluster and local pointer 657 cxy_t cxy = GET_CXY( thread ); 658 thread_t * ptr = (thread_t *)GET_PTR( thread ); 659 660 // reset blocking cause 661 uint32_t previous = hal_remote_atomic_and( XPTR( cxy , &ptr->blocked ) , ~cause ); 662 hal_fence(); 663 664 // return a non zero value if the cause bit is modified 665 return( previous & cause ); 666 667 } // end thread_unblock() 655 668 656 669 ///////////////////// … … 664 677 if( !thread_can_yield() ) 665 678 { 666 printk("ERROR in %s : thread %x in process %x on core %d in cluster %x\n" 667 " did not released all locks\n", 668 __FUNCTION__ , this->trdid , this->process->pid , 669 CURRENT_CORE->lid , local_cxy ); 679 printk("ERROR in %s : locks not released for thread %x in process %x on core[%x,%d]\n", 680 __FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid ); 670 681 return EINVAL; 671 682 } … … 686 697 687 698 // deschedule 688 sched_yield( NULL);699 sched_yield(); 689 700 return 0; 690 } 691 692 ///////////////////////////////////// 693 void thread_block( thread_t * thread, 694 uint32_t cause ) 695 { 696 // set blocking cause 697 hal_atomic_or( &thread->blocked , cause ); 698 } 699 700 //////////////////////////////////// 701 void thread_unblock( xptr_t thread, 702 uint32_t cause ) 703 { 704 // get thread cluster and local pointer 705 cxy_t cxy = GET_CXY( thread ); 706 thread_t * ptr = (thread_t *)GET_PTR( thread ); 707 708 // reset blocking cause 709 hal_remote_atomic_and( XPTR( cxy , &ptr->blocked ) , ~cause ); 710 } 701 702 } // end thread_exit() 711 703 712 704 ///////////////////////////////////// … … 721 713 // send an IPI to schedule the target thread core. 722 714 dev_pic_send_ipi( local_cxy , target->core->lid ); 723 } 715 716 } // end thread_kill() 724 717 725 718 /////////////////////// 726 719 void thread_idle_func() 727 720 { 728 #if CONFIG_IDLE_DEBUG729 lid_t lid = CURRENT_CORE->lid;730 #endif731 732 721 while( 1 ) 733 722 { 734 idle_dmsg("\n[DMSG] %s : core[%x][%d] goes to sleep at cycle %d\n", 735 __FUNCTION__ , local_cxy , lid , hal_get_cycles() ); 736 737 // force core to sleeping state 738 //hal_core_sleep(); 739 740 idle_dmsg("\n[DMSG] %s : core[%x][%d] wake up at cycle %d\n", 741 __FUNCTION__ , local_cxy , lid , hal_get_cycles() ); 742 743 // force scheduling 744 sched_yield( NULL ); 723 if( CONFIG_THREAD_IDLE_MODE_SLEEP ) // force core to low-power mode 724 { 725 726 idle_dmsg("\n[DBG] %s : core[%x][%d] goes to sleep at cycle %d\n", 727 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() ); 728 729 hal_core_sleep(); 730 731 idle_dmsg("\n[DBG] %s : core[%x][%d] wake up at cycle %d\n", 732 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() ); 733 734 } 735 else // yield each ~ 100000 cycles 736 737 { 738 hal_fixed_delay( 500000 ); 739 } 740 741 // force scheduling at each iteration 742 sched_yield(); 745 743 } 746 } 744 } // end thread_idle() 745 747 746 748 747 /////////////////////////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.