Changeset 23 for trunk/kernel/syscalls/sys_fork.c
- Timestamp:
- Jun 18, 2017, 10:06:41 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_fork.c
r1 r23 1 1 /* 2 * sys_fork.c - fork the current process2 * sys_fork.c - Fork the current process. 3 3 * 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 7 5 * 8 6 * Copyright (c) UPMC Sorbonne Universites … … 24 22 */ 25 23 24 #include <kernel_config.h> 25 #include <hal_types.h> 26 #include <hal_atomic.h> 26 27 #include <errno.h> 27 #include < config.h>28 #include <c pu.h>28 #include <printk.h> 29 #include <core.h> 29 30 #include <cluster.h> 30 #include <event.h>31 31 #include <list.h> 32 32 #include <thread.h> … … 36 36 #include <process.h> 37 37 38 #if CONFIG_FORK_DEBUG 39 #define fork_debug(...) printk(__VA_ARGS__) 40 #else 41 #define fork_debug(...) /**/ 42 #endif 43 44 /*********************************************************************************************** 45 * This kernel function implement the "fork" system call. 46 * The calling process descriptor (parent process), and the associated thread descriptor are 47 * replicated in the same cluster as the calling thread, but the new process (child process) 48 * is registered in another target cluster, that will become the process owner. 49 * The child process and the associated main thread will be migrated to the target cluster 50 * later, when the child process makes an "exec" or any other system call. 51 * The target cluster depends on the "fork_user" flag and "fork_cxy" variable that can be 52 * stored in the calling thread descriptor by the specific fork_place() system call. 53 * If not, the sys_fork() function makes a query to the DQDT to select the target cluster. 54 * @ returns child process PID if success / returns -1 if failure 55 **********************************************************************************************/ 56 int sys_fork(); 38 ////////////// 39 int sys_fork() 57 40 { 58 41 process_t * parent_process; // pointer on parent process descriptor … … 63 46 thread_t * child_thread; // pointer on child main thread descriptor 64 47 trdid_t child_trdid; // child main thread identifier 65 core_t * child_core; // pointer on core for child main thread66 48 lid_t child_core_lid; // core local index for the child main thread 67 49 cxy_t target_cxy; // final target cluster for forked child process 68 50 error_t error; 69 51 70 cluster_t * parent_cluster = LOCAL_CLUSTER;71 72 52 // get pointers on parent process and thread 73 53 parent_thread = CURRENT_THREAD; 74 54 parent_process = parent_thread->process; 55 parent_pid = parent_process->pid; 75 56 76 57 // check parent process children number 77 if( hal_atomic_add( &parent_process->child s_nr , 1 ) >= CONFIG_PROCESS_CHILDS_MAX_NR)78 { 79 printk(" ERRORin %s : too much children processes\n", __FUNCTION__);80 hal_atomic_add ( &parent_process->child s_nr , -1 );81 return EAGAIN; 82 } 83 84 fork_d ebug("INFO : %senters for process %d at cycle [%d]\n",58 if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN ) 59 { 60 printk("\n[ERROR] in %s : too much children processes\n", __FUNCTION__); 61 hal_atomic_add ( &parent_process->children_nr , -1 ); 62 return EAGAIN; 63 } 64 65 fork_dmsg("\n[INFO] %s : enters for process %d at cycle [%d]\n", 85 66 __FUNCTION__, parent_process->pid, hal_time_stamp()); 86 67 … … 90 71 { 91 72 hal_fpu_context_save( parent_thread ); 92 fork_d ebug("INFO : %ssave FPU\n", __FUNCTION__);73 fork_dmsg("\n[INFO] %s : save FPU\n", __FUNCTION__); 93 74 } 94 75 95 76 // Select target cluster for future migration of child process and main thread. 96 // The placement can be specified by user. If placement is not user-defined,97 // the placement is defined by the DQDT.98 // The two first processes ("init" and "sh") on boot cluster will not migrate. 99 if( parent_thread s->fork_user )77 // If placement is not user-defined, the placement is defined by the DQDT. 78 // The two first processes ("init" and "sh") on boot cluster do not migrate. 79 80 if( parent_thread->fork_user ) 100 81 { 101 82 // user defined placement 102 target_cxy = parent->thread.fork_cxy; 103 parent->thread.fork_cxy = false; 104 } 105 else if( (LPID_FROM_PID(parent_process->pid) < 2 ) 106 && ( parent_cluster->cxy == parent_cluster->boot_cxy ) ) 83 target_cxy = parent_thread->fork_cxy; 84 parent_thread->fork_user = false; 85 } 86 else if( (LPID_FROM_PID(parent_process->pid) < 2) && (local_cxy == 0) ) 107 87 { 108 88 // 2 first process stay in boot cluster 109 target_cxy = parent_cluster->cxy;89 target_cxy = local_cxy; 110 90 } 111 91 else … … 115 95 } 116 96 117 fork_d ebug("INFO : %s select target_cluster = %x\n",97 fork_dmsg("INFO : %s select target_cluster = %x\n", 118 98 __FUNCTION__ , target_cxy ); 119 99 120 100 // allocates memory in local cluster for the child process descriptor 121 101 child_process = process_alloc(); 102 122 103 if( child_process == NULL ) 123 104 { 124 printk("ERROR in %s : cannot allocate memory for child process\n", __FUNCTION__ ); 125 hal_atomic_add ( &parent_process->childs_nr , -1 ); 126 return EAGAIN; 127 } 128 129 // get a new PID for child process 130 // it requires an RPC if target cluster is remote 131 xptr_t xp = XPTR( target_cxy , child_process ); 132 if( target_cxy == parent_cluster->cxy ) // local cluster 133 { 134 error = process_pid_alloc( xp , &child_pid ); 135 } 136 else // remote cluster 137 { 138 rpc_process_pid_alloc_server( target_cxy , xp , &error , &child_pid ); 139 } 105 printk("\n[ERROR] in %s : cannot allocate child process\n", __FUNCTION__ ); 106 hal_atomic_add ( &parent_process->children_nr , -1 ); 107 return EAGAIN; 108 } 109 110 // get a new PID for child process, 111 if( target_cxy == local_cxy ) // target cluster is local 112 { 113 error = cluster_pid_alloc( XPTR( target_cxy , child_process ) , &child_pid ); 114 } 115 else // target cluster is remote 116 { 117 rpc_process_pid_alloc_client( target_cxy , child_process , &error , &child_pid ); 118 } 119 140 120 if( error ) 141 121 { 142 printk(" ERRORin %s : cannot allocate PID\n", __FUNCTION__ );143 atomic_add ( &parent_process->childs_nr , -1 );122 printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ ); 123 hal_atomic_add ( &parent_process->children_nr , -1 ); 144 124 process_destroy( child_process ); 145 125 return EAGAIN; … … 147 127 148 128 // initialize and register the child process descriptor 149 error = process_reference_init( child_process , child_pid , parent_pid ); 150 if( error ) 151 { 152 printk("ERROR in %s : cannot initialise child process\n", __FUNCTION__ ); 153 atomic_add ( &parent_process->childs_nr , -1 ); 154 process_destroy( child_process ); 155 return EAGAIN; 156 } 157 158 fork_debug("INFO : %s created child process : pid = %x / ppid = %x\n", 129 process_reference_init( child_process , child_pid , parent_pid ); 130 131 fork_dmsg("\n[INFO] : %s created child process : pid = %x / ppid = %x\n", 159 132 __FUNCTION__, child_pid , parent_pid ); 160 161 // set IS_REFERENCE flag in child process descriptor162 child_process->flags = PDF_IS_REFERENCE;163 133 164 134 // initialises child process standard files structures 165 135 // ( root / cwd / bin ) from parent process descriptor 166 spinlock_lock( &parent_process->cwd_lock ); 167 168 vfs_file_count_up( &parent_process->vfs_root ); 169 child_process->vfs_root = parent_process->vfs_root; 170 171 vfs_file_count_up( &parent_process->vfs_cwd ); 172 child_process->vfs_cwd = parent_process->vfs_cwd; 173 174 vfs_file_count_up( &parent_process->vfs_bin ); 175 child_process->vfs_bin = parent_process->vfs_bin; 176 177 spinlock_unlock( &parent_process->cwd_lock ); 136 137 vfs_file_count_up( parent_process->vfs_root_xp ); 138 child_process->vfs_root_xp = parent_process->vfs_root_xp; 139 140 vfs_file_count_up( parent_process->vfs_cwd_xp ); 141 child_process->vfs_cwd_xp = parent_process->vfs_cwd_xp; 142 143 vfs_file_count_up( parent_process->vfs_bin_xp ); 144 child_process->vfs_bin_xp = parent_process->vfs_bin_xp; 145 146 // copy the parent process fd_array to the child process fd_array 147 process_fd_remote_copy( XPTR( local_cxy , &child_process->fd_array ), 148 XPTR( local_cxy , &parent_process->fd_array ) ); 149 150 fork_dmsg("\n[INFO] %s : duplicated child process from parent process\n", 151 __FUNCTION__ ); 152 153 // replicates virtual memory manager 154 error = vmm_copy( child_process , parent_process ); 155 156 if( error ) 157 { 158 printk("\n[ERROR] in %s : cannot duplicate VMM\n", __FUNCTION__ ); 159 hal_atomic_add ( &parent_process->children_nr , -1 ); 160 process_destroy( child_process ); 161 return ENOMEM; 162 } 178 163 179 // copy the parent process fd_array to the child process fd_array 180 process_fd_fork( child_process , parent_process ); 181 182 // initialise child process signal manager TODO ??? 183 signal_manager_init( child_process ); 184 185 fork_debug("INFO : %s duplicated child process from parent process\n", 186 __FUNCTION__ ); 187 188 // replicates virtual memory manager 189 error = vmm_dup( &child_process->vmm , &parent_process->vmm ); 164 fork_dmsg("\n[INFO] %s : parent vmm duplicated in child process\n", __FUNCTION__ ); 165 166 // create child main thread descriptor in local cluster 167 error = thread_user_fork( parent_process , &child_thread ); 168 190 169 if( error ) 191 170 { 192 printk("ERROR in %s : cannot duplicate VMM\n", __FUNCTION__ ); 193 atomic_add ( &parent_process->childs_nr , -1 ); 194 process_destroy( child_process ); 195 return EAGAIN; 196 } 197 198 fork_debug("INFO : %s: parent vmm duplicated in child process\n", __FUNCTION__ ); 199 200 // create child main thread descriptor in local cluster TODO stack ??? 201 error = thread_user_fork( &child_thread , process , parent_thread ); 202 if( error ) 203 { 204 printk("ERROR in %s : cannot duplicate thread\n", __FUNCTION__ ); 205 atomic_add ( &parent_process->childs_nr , -1 ); 206 process_destroy( child_process ); 207 return EAGAIN; 171 printk("\n[ERROR] in %s : cannot duplicate thread\n", __FUNCTION__ ); 172 hal_atomic_add( &parent_process->children_nr , -1 ); 173 process_destroy( child_process ); 174 return ENOMEM; 208 175 } 209 176 210 177 // register child thread in child process, and get a TRDID 211 spinlock_lock( &child ->process->th_lock );212 error = process_register_thread( child ->process, child->thread , &child_trdid );213 spinlock_unlock( & process->th_lock );178 spinlock_lock( &child_process->th_lock ); 179 error = process_register_thread( child_process, child_thread , &child_trdid ); 180 spinlock_unlock( &child_process->th_lock ); 214 181 215 182 if( error ) 216 183 { 217 printk(" ERRORin %s : cannot register thread\n", __FUNCTION__ );218 atomic_add ( &parent_process->childs_nr , -1 );184 printk("\n[ERROR] in %s : cannot register thread\n", __FUNCTION__ ); 185 hal_atomic_add ( &parent_process->children_nr , -1 ); 219 186 thread_destroy( child_thread ); 220 187 process_destroy( child_process ); … … 226 193 227 194 // Update child thread descriptor 228 child_thread->core = process->core_tbl[child_core_lid];195 child_thread->core = &LOCAL_CLUSTER->core_tbl[child_core_lid]; 229 196 child_thread->process = child_process; 230 child_thread->trdid = chi d_trdid;231 232 fork_d ebug("INFO : %sinitialised child main thread\n", __FUNCTION__ );197 child_thread->trdid = child_trdid; 198 199 fork_dmsg("\n[INFO] %s : initialised child main thread\n", __FUNCTION__ ); 233 200 234 201 // register local child thread into local child process th_tbl[] 235 202 // we don't use the th_lock because there is no concurrent access 236 ltid_t ltid = LTID_FROM_TRDID( trdid );237 child_process->th_tbl[ltid] = XPTR( local_cxy , child_thread );238 child_process->th reads_nr = 1;203 ltid_t ltid = LTID_FROM_TRDID( child_trdid ); 204 child_process->th_tbl[ltid] = child_thread; 205 child_process->th_nr = 1; 239 206 240 207 // register child thread in scheduler 241 sched_register ( child_thread->core , child_thread );208 sched_register_thread( child_thread->core , child_thread ); 242 209 243 fork_d ebug("INFO : %sregistered main thread in scheduler\n", __FUNCTION__);210 fork_dmsg("\n[INFO] %s : registered main thread in scheduler\n", __FUNCTION__); 244 211 245 212 // update DQDT for the child thread 246 dqdt_ update_threads_number( 1 );247 248 fork_d ebug("INFO :%scompleted / parent pid = %x / child pid = %x / at cycle [%d]\n",213 dqdt_local_update_threads( 1 ); 214 215 fork_dmsg("\n[INFO] %s : completed / parent pid = %x / child pid = %x / at cycle [%d]\n", 249 216 __FUNCTION__, parent_process->pid, child_process->pid, hal_time_stamp() ); 250 217
Note: See TracChangeset
for help on using the changeset viewer.