Changeset 23 for trunk/kernel/syscalls/sys_exec.c
- Timestamp:
- Jun 18, 2017, 10:06:41 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/syscalls/sys_exec.c
r14 r23 1 1 /* 2 * sys_exec.c - Kernel function implementing the "exec" sys call2 * sys_exec.c - Kernel function implementing the "exec" system call. 3 3 * 4 * Authors Mohamed Lamine Karaoui (2015) 5 * Alain Greiner (2016) 4 * Authors Alain Greiner (2016,2017) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 25 24 #include <kernel_config.h> 26 25 #include <hal_types.h> 26 #include <hal_uspace.h> 27 27 #include <errno.h> 28 28 #include <printk.h> … … 51 51 52 52 // get string length 53 hal_strlen_from_uspace( pathname , &length ); 54 if( length > 255 ) 55 { 56 printk(ERROR, "%s: elf file pathname larger than 255 bytes\n", __FUNCTION__ ); 57 return EINVAL; 58 } 53 length = hal_strlen_from_uspace( pathname ); 54 55 if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) return EINVAL; 59 56 60 57 // copy string to exec_info … … 75 72 // The max number of strings is 1024 (for both args and envs). The numbers of pages 76 73 // to store the (args) and (envs) strings are configuration parameters. 77 //////////////////////////////////////////////// i//////////////////////////////////////74 /////////////////////////////////////////////////////////////////////////////////////// 78 75 // @ exec_info : pointer on the exec_info structure. 79 76 // @ is_args : true if called for (args) / false if called for (envs). … … 88 85 uint32_t found_null; // NULL pointer found in array of pointers 89 86 uint32_t length; // string length 90 uint32_t strings; // actual number of strings91 87 kmem_req_t req; // kmem request 92 88 page_t * page; // page descriptor 93 89 uint32_t order; // ln2( number of pages to store strings ) 94 char ** k_pointers; // base of kernel buffer containingarray of pointers95 char * buf_ptr;// pointer on first empty slot in kernel strings buffer96 char * buf_base;// base address of the kernel strings buffer90 char ** k_pointers; // base of kernel array of pointers 91 char * k_buf_ptr; // pointer on first empty slot in kernel strings buffer 92 char * k_buf_base; // base address of the kernel strings buffer 97 93 98 94 // compute ln2( number of pages for kernel strings buffer ) 99 if( is_args ) order = CONFIG_PROCESS_ARGS_ORDER;100 else order = CONFIG_PROCESS_ENVS_ORDER;95 if( is_args ) order = bits_log2( CONFIG_VMM_ARGS_SIZE ); 96 else order = bits_log2( CONFIG_VMM_ENVS_SIZE ); 101 97 102 98 req.type = KMEM_PAGE; … … 106 102 req.type = 0; 107 103 page = kmem_alloc( &req ); 108 if( page == NULL ) 109 { 110 printk("ERROR in %s : cannot allocate memory for pointers\n", __FUNCTION__ ); 111 return ENOMEM; 112 } 104 105 if( page == NULL ) return ENOMEM; 106 113 107 k_pointers = ppm_page2base( page ); 114 108 … … 116 110 req.type = order; 117 111 page = kmem_alloc( &req ); 118 if( page == NULL ) 119 { 120 printk("ERROR in %s : cannot allocate memory for strings\n", __FUNCTION__ ); 121 return ENOMEM; 122 } 123 buf_base = ppm_page2base( page ); 112 113 if( page == NULL ) return ENOMEM; 114 115 k_buf_base = ppm_page2base( page ); 124 116 125 117 // copy the array of pointers to kernel buffer … … 128 120 CONFIG_PPM_PAGE_SIZE ); 129 121 130 // scan local copy ofarray of pointers to copy the strings122 // scan kernel array of pointers to copy the strings 131 123 found_null = 0; 132 buf_ptr =buf_base;124 k_buf_ptr = k_buf_base; 133 125 for( index = 0 ; index < 1024 ; index++ ) 134 126 { … … 140 132 141 133 // compute string length 142 hal_strlen_from_uspace( k_pointers[index] , &length);134 length = hal_strlen_from_uspace( k_pointers[index] ); 143 135 144 136 // copy the user string to kernel buffer 145 hal_copy_from_uspace( k_ strings,146 k_pointers[index] ;137 hal_copy_from_uspace( k_buf_ptr, 138 k_pointers[index], 147 139 length ); 148 140 149 141 // update k_pointer[index] entry 150 k_pointers[index] = buf_ptr;142 k_pointers[index] = k_buf_ptr; 151 143 152 144 // increment pointer on kernel strings buffer 153 buf_ptr += (length + 1);145 k_buf_ptr += (length + 1); 154 146 } 155 147 … … 158 150 { 159 151 exec_info->args_pointers = k_pointers; 160 exec_info->args_buf_base = buf_base;152 exec_info->args_buf_base = k_buf_base; 161 153 exec_info->args_nr = index; 162 154 } … … 164 156 { 165 157 exec_info->envs_pointers = k_pointers; 166 exec_info->envs_buf_base = buf_base;167 exec_info->envs_buf_free = buf_ptr;158 exec_info->envs_buf_base = k_buf_base; 159 exec_info->envs_buf_free = k_buf_ptr; 168 160 exec_info->envs_nr = index; 169 161 } 170 162 else 171 163 { 172 printk("ERROR in %s : number of strings larger than 1024\n", __FUNCTION__ );173 164 return EINVAL; 174 165 } … … 177 168 } // end process_exec_get_strings() 178 169 179 /////////////////////////////////////////////////////////////////////////////////////////180 // This function is executed in a "client" cluster by a process whose PID can belong181 // to another "server" cluster (defined by the MSB bits of the calling process PID).182 // A new process descriptor, and the associated main thread descriptor must be created183 // in the "server" cluster, using directly the process_make_exec() function if local,184 // or the rpc_process_exec_client() function if server is remote.185 170 ///////////////////////////////////////////////////////////////////////////////////////// 186 171 // Implementation note: … … 189 174 // It calls the static process_exec_get_path() and process_exec_get_strings() functions 190 175 // to copy the .elf pathname, the main() arguments and the environment variables from 191 // user buffers to the exec_info_t , and calls the staticprocess_make_exec() function.176 // user buffers to the exec_info_t structure, and call the process_make_exec() function. 192 177 ///////////////////////////////////////////////////////////////////////////////////////// 193 178 int sys_exec( char * filename, // .elf file pathname 194 char ** arg v, // process arguments195 char ** env p) // environment variables179 char ** args, // process arguments 180 char ** envs ) // environment variables 196 181 { 197 182 exec_info_t exec_info; // structure to pass to process_make_exec() 198 thread_t * thread; // pointer on thread created in server cluster 199 error_t error = 0; 200 process_t * process = CURRENT_PROCESS; 201 202 // check arguments 203 if((filename == NULL) || (argv == NULL) || (envp == NULL)) 204 { 205 printk("\n[ERROR] in %s : missing arguments / file = %x / argv = %x / envp = %x\n", 206 __FUNCTION__ , filename , argv , envp ); 207 return EINVAL; 183 error_t error; 184 paddr_t paddr; 185 186 thread_t * this = CURRENT_THREAD; 187 process_t * process = this->process; 188 189 // check argument fileme 190 error = vmm_v2p_translate( false , filename , &paddr ); 191 192 if( error ) 193 { 194 printk("\n[ERROR] in %s : filename unmapped\n", __FUNCTION__ ); 195 this->errno = EINVAL; 196 return -1; 197 } 198 199 // check argument fileme 200 error = vmm_v2p_translate( false , args , &paddr ); 201 202 if( error ) 203 { 204 printk("\n[ERROR] in %s : args unmapped\n", __FUNCTION__ ); 205 this->errno = EINVAL; 206 return -1; 207 } 208 209 // check argument fileme 210 error = vmm_v2p_translate( false , envs , &paddr ); 211 212 if( error ) 213 { 214 printk("\n[ERROR] in %s : envs unmapped\n", __FUNCTION__ ); 215 this->errno = EINVAL; 216 return -1; 208 217 } 209 218 … … 218 227 cxy_client, cxy_server, hal_time_stamp()); 219 228 220 // Change process's state to prevent any concurent access TODO ??? [AG]221 222 229 // initialize exec_info structure 223 exec_info ->pid= process->pid;224 exec_info ->ppid= process->ppid;225 exec_info ->fd_array = &process->fd_array;226 exec_info ->vfs_root = &process->vfs_root;227 exec_info ->vfs_cwd = &process->vfs_cwd;228 exec_info ->vfs_bin = &process->vfs_bin;230 exec_info.pid = process->pid; 231 exec_info.ppid = process->ppid; 232 exec_info.fd_array_xp = XPTR( local_cxy , &process->fd_array ); 233 exec_info.vfs_root_xp = process->vfs_root_xp; 234 exec_info.vfs_cwd_xp = process->vfs_cwd_xp; 235 exec_info.vfs_bin_xp = process->vfs_bin_xp; 229 236 230 237 // check pathname and store it in exec_info structure 231 238 error = process_exec_get_path( &exec_info , filename ); 232 if ( error ) return EINVAL; 233 234 // check and store argv in exec_info structure 235 error = process_exec_get_strings( &exec_info , true , argv ); 236 if( error ) return EINVAL; 239 240 if ( error ) 241 { 242 printk("\n[ERROR] in %s : elf pathname too long\n", __FUNCTION__ ); 243 this->errno = error; 244 return -1; 245 } 246 247 // check and store args in exec_info structure 248 error = process_exec_get_strings( &exec_info , true , args ); 249 250 if( error ) 251 { 252 printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ ); 253 this->errno = error; 254 return -1; 255 } 237 256 238 // check and store envp in exec_info structure 239 error = process_exec_get_strings( &exec_info , false , envp ); 240 if( error ) return EINVAL; 257 // check and store envs in exec_info structure 258 error = process_exec_get_strings( &exec_info , false , envs ); 259 260 if( error ) 261 { 262 printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ ); 263 this->errno = error; 264 return -1; 265 } 241 266 242 if( is_local ) ////////////// local exec ////////////////////////// 243 { 244 exec_dmsg("\n[INFO] %s starts local exec for process %x at cycle %d\n", 245 __FUNCTION__, process->pid, hal_time_stamp()); 246 247 // call directly the local process_make_exec() function 248 error = process_make_exec( &exec_info , &thread ); 249 if error 250 { 251 printk("\n[ERROR] in %s : failed in local exec for process %x\n", 252 __FUNCTION__ , process->pid ); 253 return EINVAL; 254 } 255 256 exec_dmsg("\n[INFO] %s completes local exec for process %x at cycle %d\n", 257 __FUNCTION__, process->pid , hal_time_stamp() ); 258 } 259 else ///////////// remote exec ///////////////////////// 260 { 261 exec_dmsg("\n[INFO] %s starts remote exec for process %x at cycle %d\n", 262 __FUNCTION__, process->pid, hal_time_stamp() ); 263 264 // call the rpc_process_exec_client() function 265 rpc_process_exec_client( cxy_server , &exec_info , &thread , &error ); 266 267 if( error ) 268 { 269 printk("\n[ERROR] in %s : failed in remote exec for process %x\n", 270 __FUNCTION__ , process->pid ); 271 return EINVAL; 272 } 273 274 exec_dmsg("\n[INFO] %s completes remote exec for process %x at cycle %d\n", 275 __FUNCTION__, process->pid , hal_time_stamp() ); 276 } 277 278 // If no error, delete the current thread an process descriptors. 267 exec_dmsg("\n[INFO] %s starts exec for process %x at cycle %d\n", 268 __FUNCTION__, process->pid, hal_time_stamp() ); 269 270 if( is_local ) error = process_make_exec( &exec_info ); 271 else rpc_process_exec_client( cxy_server , &exec_info , &error ); 272 273 if( error ) 274 { 275 printk("\n[ERROR] in %s : cannot create new process %x\n", 276 __FUNCTION__ , process->pid ); 277 this->errno = error; 278 return -1; 279 } 280 281 exec_dmsg("\n[INFO] %s completes exec for process %x at cycle %d\n", 282 __FUNCTION__, process->pid , hal_time_stamp() ); 283 284 // delete the calling thread an process 279 285 thread_kill( CURRENT_THREAD ); 280 process_kill( CURRENT_ PROCESS);286 process_kill( CURRENT_THREAD->process ); 281 287 282 288 return 0; 289 283 290 } // end sys_exec() 284 291
Note: See TracChangeset
for help on using the changeset viewer.