Changeset 436 for trunk/kernel/syscalls/sys_thread_exit.c
- Timestamp:
- Mar 7, 2018, 9:02:03 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_thread_exit.c
r433 r436 32 32 int sys_thread_exit( void * exit_value ) 33 33 { 34 paddr_t paddr;35 error_t error;36 37 #if CONFIG_SYSCALL_DEBUG38 uint32_t tm_start;39 uint32_t tm_end;40 tm_start = hal_get_cycles();41 #endif42 43 34 thread_t * this = CURRENT_THREAD; 44 35 process_t * process = this->process; 45 36 46 // check all locks released 47 if( !thread_can_yield() ) 48 { 49 printk("\n[ERROR] in %s : locks not released / thread %x in process %x\n", 50 __FUNCTION__, this->trdid, process->pid ); 37 // check exit_value argument 38 if( exit_value != NULL ) 39 { 40 41 #if CONFIG_DEBUG_SYSCALLS_ERROR 42 printk("\n[ERROR] in %s : exit_value argument must be NULL for thread %x in process %x\n", 43 __FUNCTION__ , exit_value, this->trdid , process->pid ); 44 #endif 51 45 this->errno = EINVAL; 52 46 return -1; 53 47 } 54 48 55 // register the exit_value pointer in this thread descriptor 56 this->join_value = exit_value; 57 58 if( (this->flags & THREAD_FLAG_DETACHED) == 0 ) // this thread is joinable 59 { 60 // check exit_value in user space 61 error = vmm_v2p_translate( false , exit_value , &paddr ); 62 if( error ) 63 { 64 printk("\n[ERROR] in %s : illegal pointer = %x / thread %x in process %x\n", 65 __FUNCTION__ , (intptr_t)exit_value, this->trdid , process->pid ); 66 this->errno = EINVAL; 67 return -1; 68 } 69 70 // take the lock protecting the join 71 remote_spinlock_lock( XPTR( local_cxy, &this->join_lock ) ); 72 73 if( this->flags & THREAD_FLAG_JOIN_DONE ) // parent thread arrived first 74 { 75 // unblock the parent thread 76 thread_unblock( this->join_xp , THREAD_BLOCKED_EXIT ); 77 78 // reset the JOIN_DONE flag in this thread 79 this->flags &= ~THREAD_FLAG_JOIN_DONE; 80 81 // release the lock protecting the flags 82 remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) ); 83 } 84 else // this thread arrived first 85 { 86 // block this thread 87 thread_block( this , THREAD_BLOCKED_JOIN ); 88 89 // release the lock protecting the join 90 remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) ); 91 92 // deschedule 93 sched_yield( "WAITING JOIN" ); 94 } 95 } 96 97 #if CONFIG_SYSCALL_DEBUG 98 tm_end = hal_get_cycles(); 99 syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n" 100 "thread %x killed / cost = %d\n", 101 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid , tm_start , 102 this->trdid , (uint32_t)(tm_end - tm_start) ); 49 #if CONFIG_DEBUG_SYS_THREAD_EXIT 50 uint64_t tm_start; 51 uint64_t tm_end; 52 tm_start = hal_get_cycles(); 53 if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_start ) 54 printk("\n[DBG] %s : thread %x enter / process %x / cycle %d\n", 55 __FUNCTION__ , this, process->pid , (uint32_t)tm_start ); 103 56 #endif 104 57 105 // suicide using a rpc because a thread cannot kill itself 106 rpc_thread_kill_client( local_cxy , this ); 58 // cal the relevant kernel function 59 thread_kill( XPTR( local_cxy , this ), 60 1, // is_exit 61 0 ); // is forced 107 62 63 #if CONFIG_DEBUG_SYS_THREAD_EXIT 64 tm_end = hal_get_cycles(); 65 if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_end ) 66 printk("\n[DBG] %s : thread %x exit / process %x / cost %d / cycle %d\n", 67 __FUNCTION__, this, this->process->pid, (uint32_t)(tm_end - tm_start), (uint32_t)tm_end ); 68 #endif 69 70 // deschedule <=> suicide, because blocked by thread_kill() 71 sched_yield( "suicide after thread_exit" ); 72 108 73 return 0; // never executed but required by compiler 109 74
Note: See TracChangeset
for help on using the changeset viewer.