Changeset 408 for trunk/kernel/syscalls/sys_fork.c
- Timestamp:
- Dec 5, 2017, 4:20:07 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_fork.c
r407 r408 41 41 int sys_fork() 42 42 { 43 process_t * parent_process; // pointer on parent process descriptor 44 pid_t parent_pid; // parent process identifier 45 thread_t * parent_thread; // pointer on parent thread descriptor 46 process_t * child_process; // pointer on child process descriptor 47 pid_t child_pid; // child process identifier 48 thread_t * child_thread; // pointer on child main thread descriptor 49 cxy_t target_cxy; // target cluster for forked child process 50 error_t error; 43 process_t * parent_process_ptr; // pointer on local parent process descriptor 44 xptr_t parent_thread_xp; // extended pointer on parent thread descriptor 45 pid_t parent_pid; // parent process identifier 46 thread_t * parent_thread_ptr; // local pointer on local parent thread descriptor 51 47 52 uint64_t tm_start; 53 uint64_t tm_end; 48 pid_t child_pid; // child process identifier 49 thread_t * child_thread_ptr; // local pointer on remote child thread descriptor 50 cxy_t target_cxy; // target cluster for forked child process 51 52 xptr_t ref_process_xp; // extended pointer on reference parent process 53 cxy_t ref_process_cxy; // cluster of reference parent process 54 process_t * ref_process_ptr; // local pointer on reference parent process 55 56 error_t error; 57 58 uint64_t tm_start; 59 uint64_t tm_end; 54 60 55 61 tm_start = hal_get_cycles(); 56 62 57 // get pointers on parent process and thread 58 parent_thread = CURRENT_THREAD; 59 parent_process = parent_thread->process; 60 parent_pid = parent_process->pid; 63 // get pointers on local parent process and thread 64 parent_thread_ptr = CURRENT_THREAD; 65 parent_thread_xp = XPTR( local_cxy , parent_thread_ptr ); 66 parent_process_ptr = parent_thread_ptr->process; 67 parent_pid = parent_process_ptr->pid; 61 68 62 fork_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x/ cycle %d\n",63 __FUNCTION__ , local_cxy , parent_thread->core->lid , parent_pid, (uint32_t)tm_start );69 fork_dmsg("\n[DBG] %s : core[%x,%d] parent process %x enters / cycle %d\n", 70 __FUNCTION__, local_cxy, parent_thread_ptr->core->lid, parent_pid, (uint32_t)tm_start ); 64 71 65 // check parent process children number 66 if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN ) 72 // get infos on reference process 73 ref_process_xp = parent_process_ptr->ref_xp; 74 ref_process_cxy = GET_CXY( ref_process_xp ); 75 ref_process_ptr = (process_t *)GET_PTR( ref_process_xp ); 76 77 // check parent process children number from reference 78 xptr_t children_xp = XPTR( ref_process_cxy , &ref_process_ptr->children_nr ); 79 if( hal_remote_atomic_add( children_xp , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN ) 67 80 { 68 81 printk("\n[ERROR] in %s : too much children processes\n", __FUNCTION__); 69 hal_atomic_add ( &parent_process->children_nr , -1 ); 70 return EAGAIN; 82 hal_remote_atomic_add ( children_xp , -1 ); 83 parent_thread_ptr->errno = EAGAIN; 84 return -1; 71 85 } 72 86 73 // Select target cluster for future migration ofchild process and main thread.87 // Select target cluster for child process and main thread. 74 88 // If placement is not user-defined, the placement is defined by the DQDT. 75 // The two first processes ("init" and "sh") on boot cluster do not migrate. 76 77 if( parent_thread->fork_user ) 89 if( parent_thread_ptr->fork_user ) // user defined placement 78 90 { 79 // user defined placement 80 target_cxy = parent_thread->fork_cxy; 81 parent_thread->fork_user = false; 91 target_cxy = parent_thread_ptr->fork_cxy; 92 parent_thread_ptr->fork_user = false; 82 93 } 83 else if( (LPID_FROM_PID(parent_process->pid) < 2) && (local_cxy == 0) ) 84 { 85 // 2 first process stay in boot cluster 86 target_cxy = local_cxy; 87 } 88 else 94 else // DQDT placement 89 95 { 90 // DQDT placement91 96 target_cxy = dqdt_get_cluster_for_process(); 92 97 } 93 98 94 //printk("\n[DBG] %s : core[%x,%d] for process %x selects target_cluster = %x\n", 95 //__FUNCTION__ , local_cxy , parent_thread->core->lid , parent_pid , target_cxy ); 96 97 // allocates memory in local cluster for the child process descriptor 98 child_process = process_alloc(); 99 100 if( child_process == NULL ) 101 { 102 printk("\n[ERROR] in %s : cannot allocate child process\n", __FUNCTION__ ); 103 hal_atomic_add ( &parent_process->children_nr , -1 ); 104 return EAGAIN; 105 } 106 107 // get a new PID for child process, 108 if( target_cxy == local_cxy ) // target cluster is local 99 // call process_make_fork in target cluster 100 if( target_cxy == local_cxy ) 109 101 { 110 error = cluster_pid_alloc( XPTR( target_cxy , child_process ) , &child_pid ); 102 error = process_make_fork( ref_process_xp, 103 parent_thread_xp, 104 &child_pid, 105 &child_thread_ptr ); 111 106 } 112 else // target cluster is remote107 else 113 108 { 114 rpc_process_pid_alloc_client( target_cxy , child_process , &error , &child_pid ); 109 rpc_process_make_fork_client( target_cxy, 110 ref_process_xp, 111 parent_thread_xp, 112 &child_pid, 113 &child_thread_ptr, 114 &error ); 115 115 } 116 116 117 117 if( error ) 118 118 { 119 printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ ); 120 hal_atomic_add ( &parent_process->children_nr , -1);121 p rocess_destroy( child_process );122 return EAGAIN;119 printk("\n[ERROR] in %s : cannot fork process %x in cluster %x\n", 120 __FUNCTION__, parent_pid, local_cxy ); 121 parent_thread_ptr->errno = EAGAIN; 122 return -1; 123 123 } 124 124 125 // initialize and register the child process descriptor 126 process_reference_init( child_process , child_pid , XPTR(local_cxy, parent_process) ); 127 128 // initialises child process standard files structures 129 // ( root / cwd / bin ) from parent process descriptor 130 131 vfs_file_count_up( parent_process->vfs_root_xp ); 132 child_process->vfs_root_xp = parent_process->vfs_root_xp; 133 134 vfs_file_count_up( parent_process->vfs_cwd_xp ); 135 child_process->vfs_cwd_xp = parent_process->vfs_cwd_xp; 136 137 vfs_file_count_up( parent_process->vfs_bin_xp ); 138 child_process->vfs_bin_xp = parent_process->vfs_bin_xp; 139 140 // copy the parent process fd_array to the child process fd_array 141 process_fd_remote_copy( XPTR( local_cxy , &child_process->fd_array ), 142 XPTR( local_cxy , &parent_process->fd_array ) ); 143 144 //printk("\n[DBG] %s : core[%x,%d] for process %x created child process %x\n", 145 //__FUNCTION__ , local_cxy , parent_thread->core->lid , parent_pid , child_pid ); 146 147 // replicate VMM 148 error = vmm_copy( child_process , parent_process ); 149 150 if( error ) 151 { 152 printk("\n[ERROR] in %s : cannot duplicate VMM\n", __FUNCTION__ ); 153 hal_atomic_add ( &parent_process->children_nr , -1 ); 154 process_destroy( child_process ); 155 return ENOMEM; 156 } 157 158 //printk("\n[DBG] %s : core[%x,%d] for process %x duplicated vmm in child process\n", 159 //__FUNCTION__ , local_cxy , parent_thread->core->lid , parent_pid ); 160 //vmm_display( parent_process , true ); 161 //vmm_display( child_process , true ); 162 163 // create child main thread in local cluster 164 error = thread_user_fork( child_process, 165 parent_thread->u_stack_size, 166 parent_thread->u_stack_base, 167 &child_thread ); 168 if( error ) 169 { 170 printk("\n[ERROR] in %s : cannot duplicate main thread\n", __FUNCTION__ ); 171 hal_atomic_add( &parent_process->children_nr , -1 ); 172 process_destroy( child_process ); 173 return ENOMEM; 174 } 175 176 //printk("\n[DBG] %s : core[%x,%d] initialised child main thread\n", 177 //__FUNCTION__ , local_cxy , parent_thread->core->lid ); 178 179 // update DQDT for the child thread 180 dqdt_local_update_threads( 1 ); 181 182 // set child_thread FPU_context from parent_thread register values 183 // only when the parent process is the FPU owner 184 if( CURRENT_THREAD->core->fpu_owner == parent_thread ) 125 // set remote child FPU_context from parent_thread register values 126 // only when the parent thread is the FPU owner 127 if( CURRENT_THREAD->core->fpu_owner == parent_thread_ptr ) 185 128 { 186 hal_fpu_context_save( child_thread->fpu_context);129 hal_fpu_context_save( XPTR( target_cxy , child_thread_ptr ) ); 187 130 } 188 131 189 // set child_thread CPU context from parent_thread register values 190 hal_do_cpu_save( child_thread->cpu_context, 191 child_thread, 192 (int)((intptr_t)child_thread - (intptr_t)parent_thread) ); 132 // set remote child CPU context from parent_thread register values 133 hal_cpu_context_fork( XPTR( target_cxy , child_thread_ptr ) ); 193 134 194 195 // from this point, both parent and child threads execute the following code 196 // but child execute it only when it has been unblocked by its parent 135 // From this point, both parent and child threads execute the following code. 136 // They can be distinguished by the CURRENT_THREAD value, and child will only 137 // execute it when it is unblocked by parent. 138 // - parent unblock child, and return child PID to user application. 139 // - child thread does nothing, and return 0 to user pplication 197 140 198 141 thread_t * current = CURRENT_THREAD; 199 142 200 if( current == parent_thread )143 if( current == parent_thread_ptr ) // current == parent thread 201 144 { 202 145 // parent_thread unblock child_thread 203 thread_unblock( XPTR( local_cxy , child_thread) , THREAD_BLOCKED_GLOBAL );146 thread_unblock( XPTR( target_cxy , child_thread_ptr ) , THREAD_BLOCKED_GLOBAL ); 204 147 205 148 tm_end = hal_get_cycles(); … … 207 150 fork_dmsg("\n[DBG] %s : core[%x,%d] parent_process %x exit / cycle %d\n" 208 151 " child_process %x / child_thread = %x / cost = %d\n", 209 __FUNCTION__, local_cxy, parent_thread ->core->lid, parent_pid, (uint32_t)tm_start,210 child_pid, child_thread ->trdid , (uint32_t)(tm_end - tm_start) );152 __FUNCTION__, local_cxy, parent_thread_ptr->core->lid, parent_pid, (uint32_t)tm_end, 153 child_pid, child_thread_ptr->trdid , (uint32_t)(tm_end - tm_start) ); 211 154 212 155 return child_pid; 213 156 } 214 else // current == child_thread157 else // current == child_thread 215 158 { 216 assert( (current == child_thread) , __FUNCTION__ , 217 "current thread %x is not the child thread %x\n", current , child_thread);159 160 tm_end = hal_get_cycles(); 218 161 219 162 fork_dmsg("\n[DBG] %s : core[%x,%d] child process %x exit / cycle %d\n", 220 __FUNCTION__, local_cxy, parent_thread ->core->lid, child_pid, (uint32_t)hal_get_cycles());163 __FUNCTION__, local_cxy, parent_thread_ptr->core->lid, child_pid, (uint32_t)tm_end ); 221 164 222 165 return 0;
Note: See TracChangeset
for help on using the changeset viewer.