Changeset 436 for trunk/kernel/syscalls/sys_thread_join.c
- Timestamp:
- Mar 7, 2018, 9:02:03 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_thread_join.c
r421 r436 25 25 #include <hal_remote.h> 26 26 #include <hal_special.h> 27 #include <hal_irqmask.h> 27 28 #include <thread.h> 28 29 #include <vmm.h> … … 36 37 void ** exit_value ) 37 38 { 39 reg_t save_sr; 38 40 xptr_t target_xp; 39 41 thread_t * target_ptr; 40 42 cxy_t target_cxy; 41 43 ltid_t target_ltid; 42 uint32_t target_blocked; // target thread blocked bit-vector 43 uint32_t target_flags; // target thread flags bit-bector 44 paddr_t paddr; // required for vmm_v2p_translate() 44 xptr_t target_join_lock_xp; 45 xptr_t target_flags_xp; 46 xptr_t target_blocked_xp; 47 xptr_t target_join_xp_xp; 48 xptr_t killer_xp; 49 xptr_t joining_xp; 50 thread_t * joining_ptr; 51 process_t * process; 45 52 46 thread_t * this = CURRENT_THREAD; 47 process_t * process = this->process; 53 // get joining thread pointers 54 joining_ptr = CURRENT_THREAD; 55 joining_xp = XPTR( local_cxy , joining_ptr ); 56 process = joining_ptr->process; 48 57 49 58 // get target thread ltid and cxy … … 51 60 target_cxy = CXY_FROM_TRDID( trdid ); 52 61 62 #if CONFIG_DEBUG_SYS_THREAD_JOIN 63 uint64_t tm_start; 64 uint64_t tm_end; 65 tm_start = hal_get_cycles(); 66 if( CONFIG_DEBUG_SYS_THREAD_JOIN < tm_start ) 67 printk("\n[DBG] %s : parent thread %x enter / process %x / target trdid %x / cycle %d\n", 68 __FUNCTION__ , joining_ptr , process->pid , trdid , (uint32_t)tm_start ); 69 #endif 70 53 71 // check trdid argument 54 72 if( (target_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || cluster_is_undefined( target_cxy ) ) 55 73 { 56 printk("\n[ERROR] in %s : illegal trdid argument\n", __FUNCTION__ ); 57 this->errno = EINVAL; 74 75 #if CONFIG_DEBUG_SYSCALLS_ERROR 76 printk("\n[ERROR] in %s : illegal trdid argument %x\n", __FUNCTION__, trdid ); 77 #endif 78 joining_ptr->errno = EINVAL; 58 79 return -1; 59 80 } 60 81 61 82 // check exit_value argument 62 if( (exit_value != NULL) && (vmm_v2p_translate( false , exit_value , &paddr ) != 0 ))83 if( exit_value != NULL ) 63 84 { 64 printk("\n[ERROR] in %s : illegal exit_value argument\n", __FUNCTION__ ); 65 this->errno = EINVAL; 85 86 #if CONFIG_DEBUG_SYSCALLS_ERROR 87 printk("\n[ERROR] in %s : exit_value argument must be NULL\n", __FUNCTION__ ); 88 #endif 89 joining_ptr->errno = EINVAL; 66 90 return -1; 67 91 } 68 92 69 93 // check target thread != this thread 70 if( this->trdid == trdid )94 if( joining_ptr->trdid == trdid ) 71 95 { 72 printk("\n[ERROR] in %s : this thread == target thread\n", __FUNCTION__ ); 73 this->errno = EDEADLK; 96 97 #if CONFIG_DEBUG_SYSCALLS_ERROR 98 printk("\n[ERROR] in %s : this thread == target thread\n", __FUNCTION__ ); 99 #endif 100 joining_ptr->errno = EDEADLK; 74 101 return -1; 75 102 } 76 103 77 // get extended pointeron target thread104 // get pointers on target thread 78 105 target_xp = thread_get_xptr( process->pid , trdid ); 106 target_ptr = GET_PTR( target_xp ); 79 107 80 108 if( target_xp == XPTR_NULL ) 81 109 { 82 printk("\n[ERROR] in %s : target thread not found\n", __FUNCTION__ ); 83 this->errno = ESRCH; 110 111 #if CONFIG_DEBUG_SYSCALLS_ERROR 112 printk("\n[ERROR] in %s : target thread %x not found\n", __FUNCTION__, trdid ); 113 #endif 114 joining_ptr->errno = ESRCH; 84 115 return -1; 85 116 } 86 117 87 // get cluster and local pointer on target thread 88 target_ptr = (thread_t *)GET_PTR( target_xp ); 118 // get extended pointers on various fields in target thread 119 target_join_lock_xp = XPTR( target_cxy , &target_ptr->join_lock ); 120 target_flags_xp = XPTR( target_cxy , &target_ptr->flags ); 121 target_blocked_xp = XPTR( target_cxy , &target_ptr->blocked ); 122 target_join_xp_xp = XPTR( target_cxy , &target_ptr->join_xp ); 89 123 90 124 // check target thread joinable 91 target_flags = hal_remote_lw( XPTR( target_cxy , &target_ptr->flags ) ); 92 if( target_flags & THREAD_FLAG_DETACHED ) 125 if( (hal_remote_lw( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0 ) 93 126 { 94 printk("\n[ERROR] in %s : target thread not joinable\n", __FUNCTION__ ); 95 this->errno = EINVAL; 127 128 #if CONFIG_DEBUG_SYSCALLS_ERROR 129 printk("\n[ERROR] in %s : target thread %x not joinable\n", __FUNCTION__, trdid ); 130 #endif 131 joining_ptr->errno = EINVAL; 96 132 return -1; 97 133 } 98 134 99 // check kernel stack overflow 100 if( target_ptr->signature != THREAD_SIGNATURE ) 135 // mask IRQs 136 hal_disable_irq( &save_sr ); 137 138 // get the lock protecting the join in target thread 139 remote_spinlock_lock( target_join_lock_xp ); 140 141 // test the kill_done flag from the target thread 142 if( hal_remote_lw( target_flags_xp ) & THREAD_FLAG_KILL_DONE ) // killer thread is first 101 143 { 102 assert( false , __FUNCTION__ , "kernel stack overflow\n" ); 144 // get pointers on killer thread 145 killer_xp = (xptr_t)hal_remote_lwd( target_join_xp_xp ); 146 147 // reset the kill_done flag in target thread 148 hal_remote_atomic_and( target_flags_xp , ~THREAD_FLAG_KILL_DONE ); 149 150 // unblock the killer thread 151 thread_unblock( killer_xp , THREAD_BLOCKED_JOIN ); 152 153 // release the lock protecting join 154 remote_spinlock_unlock( target_join_lock_xp ); 155 156 // restore IRQs 157 hal_restore_irq( save_sr ); 158 } 159 else // joining thread is first 160 { 161 // set the join_done flag in target thread 162 hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_JOIN_DONE ); 163 164 // block joining thread on BLOCKED_JOIN 165 thread_block( joining_xp , THREAD_BLOCKED_JOIN ); 166 167 // register the joining thread extended pointer in target thread 168 hal_remote_swd( target_join_xp_xp , joining_xp ); 169 170 // release the lock protecting the join 171 remote_spinlock_unlock( target_join_lock_xp ); 172 173 // deschedule 174 sched_yield( "joining thread waiting killer thread" ); 175 176 // restore IRQs 177 hal_restore_irq( save_sr ); 103 178 } 104 179 105 // get the lock protecting the join in target thread 106 remote_spinlock_lock( XPTR( target_cxy , &target_ptr->join_lock ) ); 107 108 // get the blocked bit_vector from the target thread 109 target_blocked = hal_remote_lw( XPTR( target_cxy , &target_ptr->blocked ) ); 110 111 if( target_blocked & THREAD_BLOCKED_JOIN ) // target thread arrived first 112 { 113 // unblock the target thread 114 thread_unblock( target_xp , THREAD_BLOCKED_JOIN ); 115 116 // release the lock protecting flags 117 remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) ); 118 119 // get the exit value from target thread 120 *exit_value = hal_remote_lpt( XPTR( target_cxy , &target_ptr->join_value ) ); 121 } 122 else // this thread arrived first 123 { 124 // register this thread extended pointer in target thread 125 hal_remote_swd( XPTR( target_cxy , &target_ptr->join_xp ) , 126 XPTR( local_cxy , this ) ); 127 128 // set the JOIN_DONE flag in target thread 129 hal_remote_atomic_or( XPTR( target_cxy , &target_ptr->flags ) , 130 THREAD_FLAG_JOIN_DONE ); 131 132 // block this thread on BLOCKED_EXIT 133 thread_block( this , THREAD_BLOCKED_EXIT ); 134 135 // release the lock protecting flags 136 remote_spinlock_unlock( XPTR( target_cxy , &target_ptr->join_lock ) ); 137 138 // deschedule 139 sched_yield( "WAITING_EXIT" ); 140 141 // get the exit value from target thread when resume 142 *exit_value = hal_remote_lpt( XPTR( target_cxy , &target_ptr->join_value ) ); 143 } 180 #if CONFIG_DEBUG_SYS_THREAD_JOIN 181 tm_end = hal_get_cycles(); 182 if( CONFIG_DEBUG_SYS_THREAD_JOIN < tm_end ) 183 printk("\n[DBG] %s : parent thread %x exit / process %x / target trdid %x / cycle %d\n", 184 __FUNCTION__, joining_ptr, process->pid, trdid, (uint32_t)tm_end ); 185 #endif 144 186 145 187 return 0;
Note: See TracChangeset
for help on using the changeset viewer.