Ignore:
Timestamp:
Nov 7, 2017, 3:08:12 PM (5 years ago)
Author:
alain
Message:

First implementation of fork/exec.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/syscalls/sys_exec.c

    r406 r407  
    3838
    3939////////////////////////////////////////////////i//////////////////////////////////////
    40 // This static function is called by the sys_exec() function to register the .elf
    41 // pathname in the exec_info  structure, from a string stored in user space.
    42 ////////////////////////////////////////////////i//////////////////////////////////////
    43 // @ exec_info : pointer on the exec_info structure.
    44 // @ pathname  : string containing the path to the .elf file (user space).
    45 // return 0 if success / non-zero if one string too long, or too many strings.
    46 ///////////////////////////////////////////////////////////////////////////////////////
    47 static error_t process_exec_get_path( exec_info_t  * exec_info,
    48                                       char         * pathname )
    49 {
    50     error_t error;
    51 
    52     // copy string to exec_info
    53     error = hal_strcpy_from_uspace( &exec_info->path[0] , pathname ,
    54                                     CONFIG_VFS_MAX_PATH_LENGTH );
    55     if( error )
    56         return EINVAL;
    57 
    58     return 0;
    59 }
    60 
    61 ////////////////////////////////////////////////i//////////////////////////////////////
    6240// This static function is called twice by the sys_exec() function :
    6341// - to register the main() arguments (args) in the exec_info structure.
     
    7149// to store the (args) and (envs) strings are configuration parameters.
    7250///////////////////////////////////////////////////////////////////////////////////////
    73 // @ exec_info : pointer on the exec_info structure.
    74 // @ is_args   : true if called for (args) / false if called for (envs).
    75 // @ pointers  : array of pointers on the strings (in user space).
     51// @ exec_info   : pointer on the exec_info structure.
     52// @ is_args     : true if called for (args) / false if called for (envs).
     53// @ u_pointers  : array of pointers on the strings (in user space).
    7654// @ return 0 if success / non-zero if too many strings or no more memory.
    7755///////////////////////////////////////////////////////////////////////////////////////
     
    173151// This function build an exec_info_t structure containing all informations
    174152// required to create the new process descriptor and the associated thread.
    175 // It calls the static process_exec_get_path() and process_exec_get_strings() functions
    176 // to copy the .elf pathname, the main() arguments and the environment variables from
    177 // user buffers to the exec_info_t structure, and call the process_make_exec() function.
     153// It calls the process_exec_get_strings() functions to copy the main() arguments and
     154// the environment variables from user buffers to the exec_info_t structure, allocate
     155// and call the process_make_exec() function.
     156// Finally, it destroys the calling thread and process.
     157// TODO : the args & envs arguments are not supported yet : both must be NULL
    178158/////////////////////////////////////////////////////////////////////////////////////////
    179 int sys_exec( char  * filename,     // .elf file pathname
     159int sys_exec( char  * pathname,     // .elf file pathname
    180160              char ** args,         // process arguments
    181161              char ** envs )        // environment variables
    182162{
    183     exec_info_t  exec_info;         // structure to pass to process_make_exec()
    184     error_t      error;
    185     paddr_t      paddr;
    186 
     163    exec_info_t   exec_info;        // structure to pass to process_make_exec()
     164    error_t       error;
     165
     166        uint64_t      tm_start;
     167        uint64_t      tm_end;
     168
     169        tm_start = hal_get_cycles();
     170
     171    // get pointers on parent process and thread
    187172    thread_t   * this    = CURRENT_THREAD;
    188173    process_t  * process = this->process;
    189 
    190     // check argument fileme
    191     error = vmm_v2p_translate( false , filename , &paddr );
     174    pid_t        pid     = process->pid;
     175
     176exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / cycle %d\n",
     177__FUNCTION__, local_cxy, this->core->lid, pid, (uint32_t)hal_get_cycles() );
     178
     179sched_display( 0 );
     180
     181    // check pathname length
     182    if( hal_strlen_from_uspace( pathname ) >= CONFIG_VFS_MAX_PATH_LENGTH )
     183    {
     184        printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ );
     185        this->errno = ENFILE;
     186        return -1;
     187    }
     188
     189    // copy pathname in exec_info structure (kernel space)
     190    hal_strcpy_from_uspace( exec_info.path , pathname , CONFIG_VFS_MAX_PATH_LENGTH );
     191    // check args argument
     192    assert( (args == NULL) , __FUNCTION__ ,
     193    "args not supported yet\n" );
     194
     195    // check envs argument
     196    assert( (envs == NULL) , __FUNCTION__ ,
     197    "args not supported yet\n" );
     198
     199    // compute client_cxy (local cluster) and server_cxy (target cluster)
     200    cxy_t     cxy_server = CXY_FROM_PID( pid );
     201    cxy_t     cxy_client = local_cxy;
     202
     203    // register parent process in exec_info
     204    exec_info.parent_xp   = process->ref_xp;
     205
     206    // new process keep the parent process PID
     207    exec_info.keep_pid   = true;
     208
     209    // check and store args in exec_info structure if required
     210    if( args != NULL )
     211    {
     212        if( process_exec_get_strings( &exec_info , true , args ) )
     213        {
     214            printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ );
     215            this->errno = error;
     216            return -1;
     217        }
     218    }
     219
     220    // check and store envs in exec_info structure if required
     221    if( envs != NULL )
     222    {
     223        if( process_exec_get_strings( &exec_info , false , envs ) )
     224        {
     225            printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ );
     226            this->errno = error;
     227            return -1;
     228        }
     229    }
     230
     231    // call process_make_exec (local or remote)
     232    if( cxy_server == cxy_client )
     233    {
     234        error = process_make_exec( &exec_info );
     235    }
     236    else
     237    {
     238        rpc_process_exec_client( cxy_server , &exec_info , &error );
     239    }
    192240
    193241    if( error )
    194242    {
    195         printk("\n[ERROR] in %s : filename unmapped\n", __FUNCTION__ );
    196         this->errno = EINVAL;
    197         return -1;
    198     }
    199 
    200     // check argument fileme
    201     error = vmm_v2p_translate( false , args , &paddr );
    202 
    203     if( error )
    204     {
    205         printk("\n[ERROR] in %s : args unmapped\n", __FUNCTION__ );
    206         this->errno = EINVAL;
    207         return -1;
    208     }
    209 
    210     // check argument fileme
    211     error = vmm_v2p_translate( false , envs , &paddr );
    212 
    213     if( error )
    214     {
    215         printk("\n[ERROR] in %s : envs unmapped\n", __FUNCTION__ );
    216         this->errno = EINVAL;
    217         return -1;
    218     }
    219 
    220     // compute client_cxy (local cluster) and server_cxy (target cluster)
    221     cxy_t     cxy_server = CXY_FROM_PID( process->pid );
    222     cxy_t     cxy_client = local_cxy;
    223     bool_t    is_local   = (cxy_server == cxy_client);
    224 
    225     exec_dmsg("\n[DMSG] %s starts for process %x on core %d in cluster %x"
    226                  " / target_cluster = %x / cycle %d\n",
    227                  __FUNCTION__, process->pid , CURRENT_CORE->lid,
    228                  cxy_client, cxy_server, hal_get_cycles());
    229 
    230     // register reference parent process in exec_info
    231     exec_info.parent_xp   = process->ref_xp;
    232 
    233     // check pathname and store it in exec_info structure
    234     error = process_exec_get_path( &exec_info , filename );
    235 
    236     if ( error )
    237     {
    238         printk("\n[ERROR] in %s : elf pathname too long\n", __FUNCTION__ );
     243        printk("\n[ERROR] in %s : cannot create new process %x in cluster %x\n",
     244        __FUNCTION__, pid, cxy_server );
    239245        this->errno = error;
    240246        return -1;
    241247    }
    242248
    243     // check and store args in exec_info structure
    244     error = process_exec_get_strings( &exec_info , true , args );
    245 
    246     if( error )
    247     {
    248         printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ );
    249         this->errno = error;
    250         return -1;
    251     }
    252 
    253     // check and store envs in exec_info structure
    254     error = process_exec_get_strings( &exec_info , false , envs );
    255 
    256     if( error )
    257     {
    258         printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ );
    259         this->errno = error;
    260         return -1;
    261     }
    262 
    263     exec_dmsg("\n[DMSG] %s starts exec for process %x at cycle %d\n",
    264               __FUNCTION__, process->pid, hal_get_cycles() );
    265 
    266     if( is_local )  error = process_make_exec( &exec_info );
    267     else            rpc_process_exec_client( cxy_server , &exec_info , &error );
    268 
    269     if( error )
    270     {
    271         printk("\n[ERROR] in %s : cannot create new process %x\n",
    272                __FUNCTION__ , process->pid );
    273         this->errno = error;
    274         return -1;
    275     }
    276 
    277     exec_dmsg("\n[DMSG] %s completes exec for process %x at cycle %d\n",
    278               __FUNCTION__, process->pid , hal_get_cycles() );
    279 
    280     // delete the calling thread an process
    281     thread_kill( CURRENT_THREAD );
    282     process_kill( CURRENT_THREAD->process );
     249    // FIXME delete the local process descriptor
     250    // process_kill( process );
     251
     252    tm_end = hal_get_cycles();
     253
     254exec_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x / cycle %d\n"
     255"     pathname = %s / cost = %d\n",
     256__FUNCTION__, local_cxy, this->core->lid, pid, (uint32_t)tm_start,
     257exec_info.path , (uint32_t)(tm_end - tm_start) );
    283258
    284259    return 0;
Note: See TracChangeset for help on using the changeset viewer.