Ignore:
Timestamp:
Jan 13, 2021, 12:36:17 AM (3 years ago)
Author:
alain
Message:

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File:
1 edited

Legend:

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

    r670 r683  
    3838#include <syscalls.h>
    3939
     40////////////////////////////////////////////////i////////////////////////////////////////
     41// This static function is called twice by the sys_exec() function :
     42// - to register the main() arguments (args) in the process <exec_info> structure.
     43// - to register the environment variables (envs) in the <exec_info> structure.
     44// In both cases the input is an array of NULL terminated string pointers in user space,
     45// identified by the <u_pointers> argument. The strings can be dispatched anywhere in
     46// the calling user process space. The max number of envs, and the max number of args 
     47// are defined by the CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters.
     48////////////////////////////////////////////////i////////////////////////////////////////
     49// Implementation Note:
     50// Both the array of pointers and the strings themselve are stored in kernel space in one
     51// single, dynamically allocated, kernel buffer containing an integer number of pages,
     52// defined by the CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters.
     53// These two kernel buffers contains :
     54// - in the first bytes a fixed size kernel array of kernel pointers on the strings.
     55// - in the following bytes the strings themselves.
     56// The exec_info_t structure is defined in the <process.h> file.
     57////////////////////////////////////////////////i////////////////////////////////////////
     58// @ is_args     : [in]    true if called for (args) / false if called for (envs).
     59// @ u_pointers  : [in]    array of pointers on the strings (in user space).
     60// @ exec_info   : [inout] pointer on the exec_info structure.
     61// @ return 0 if success / non-zero if too many strings or no memory.
     62////////////////////////////////////////////////i////////////////////////////////////////
     63static error_t exec_get_strings( bool_t         is_args,
     64                                 char        ** u_pointers,
     65                                 exec_info_t  * exec_info )
     66{
     67    uint32_t     index;           // slot index in pointers array
     68    uint32_t     length;          // string length (in bytes)
     69    uint32_t     pointers_bytes;  // number of bytes to store pointers
     70    uint32_t     max_index;       // max size of pointers array
     71    char      ** k_pointers;      // base of kernel array of pointers
     72    char       * k_buf_ptr;       // pointer on first empty slot in strings buffer
     73    uint32_t     k_buf_space;     // number of bytes available in string buffer
     74    char       * k_buf;           // kernel buffer for both pointers & strings
     75
     76#if DEBUG_SYS_EXEC
     77thread_t * this  = CURRENT_THREAD;
     78uint32_t   cycle = (uint32_t)hal_get_cycles();
     79#endif
     80
     81    // Allocate one block of physical memory for both the pointers and the strings
     82
     83    if( is_args )
     84    {
     85        k_buf = kmem_alloc( bits_log2(CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER), AF_ZERO );
     86
     87        pointers_bytes = (CONFIG_PROCESS_ARGS_MAX_NR + 1) * sizeof(char *);
     88        k_pointers     = (char **)k_buf;
     89        k_buf_ptr      = k_buf + pointers_bytes;
     90        k_buf_space    = (CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER) - pointers_bytes;
     91        max_index      = CONFIG_PROCESS_ARGS_MAX_NR + 1;
     92
     93#if DEBUG_SYS_EXEC
     94if( DEBUG_SYS_EXEC < cycle )
     95printk("\n[%s] thread[%x,%x] for args / u_buf %x / k_buf %x\n",
     96__FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf );
     97#endif
     98
     99    }
     100    else  // envs
     101    {
     102        k_buf = kmem_alloc( bits_log2(CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER), AF_ZERO );
     103
     104        pointers_bytes = (CONFIG_PROCESS_ENVS_MAX_NR + 1) * sizeof(char *);
     105        k_pointers     = (char **)k_buf;
     106        k_buf_ptr      = k_buf + pointers_bytes;
     107        k_buf_space    = (CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER) - pointers_bytes;
     108        max_index      = CONFIG_PROCESS_ENVS_MAX_NR + 1;
     109
     110#if DEBUG_SYS_EXEC
     111if( DEBUG_SYS_EXEC < cycle )
     112printk("\n[%s] thread[%x,%x] for envs / u_buf %x / k_buf %x\n",
     113__FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf );
     114#endif
     115
     116    }
     117
     118    // copy the user array of pointers to kernel buffer
     119    hal_copy_from_uspace( XPTR( local_cxy , k_pointers ),
     120                          u_pointers,
     121                          pointers_bytes );
     122
     123    // WARNING : the pointers copied in the k_pointers[] array are user pointers,
     124    // after the loop below, the k_pointers[] array contains kernel pointers.
     125
     126#if DEBUG_SYS_EXEC
     127if( DEBUG_SYS_EXEC < cycle )
     128printk("\n[%s] thread[%x,%x] moved u_ptr array of pointers to k_ptr array\n",
     129__FUNCTION__, this->process->pid, this->trdid );
     130#endif
     131
     132    // scan kernel array of pointers to copy strings to kernel buffer
     133    for( index = 0 ; index < max_index ; index++ )
     134    {
     135        // exit loop if (k_pointers[index] == NUll)
     136        if( k_pointers[index] == NULL ) break;
     137
     138        // compute string length (without the NUL character)
     139        length = hal_strlen_from_uspace( k_pointers[index] );
     140
     141        // return error if overflow in kernel buffer
     142        if( length > k_buf_space ) return -1;
     143
     144        // copy the string itself to kernel buffer
     145        hal_copy_from_uspace( XPTR( local_cxy , k_buf_ptr ),
     146                              k_pointers[index],
     147                              length + 1 );
     148
     149#if DEBUG_SYS_EXEC
     150if( DEBUG_SYS_EXEC < cycle )
     151printk("\n[%s] thread[%x,%x] copied string[%d] <%s> to kernel buffer / length %d\n",
     152__FUNCTION__, this->process->pid, this->trdid, index, k_buf_ptr, length );
     153#endif
     154
     155        // replace the user pointer by a kernel pointer in the k_pointer[] array
     156        k_pointers[index] = k_buf_ptr;
     157
     158        // increment loop variables
     159        k_buf_ptr   += (length + 1);
     160        k_buf_space -= (length + 1);
     161
     162#if DEBUG_SYS_EXEC
     163if( DEBUG_SYS_EXEC < cycle )
     164{
     165    if( k_pointers[0] != NULL )
     166    printk("\n[%s] thread[%x,%x] : &arg0 = %x / arg0 = <%s>\n",
     167    __FUNCTION__, this->process->pid, this->trdid, k_pointers[0], k_pointers[0] );
     168    else
     169    printk("\n[%s] thread[%x,%x] : unexpected NULL value for &arg0\n",
     170    __FUNCTION__, this->process->pid, this->trdid );
     171}
     172#endif
     173
     174    }  // end loop on index
     175
     176    // update into exec_info structure
     177    if( is_args )
     178    {
     179        exec_info->args_pointers  =  k_pointers;
     180        exec_info->args_nr        =  index;
     181    }
     182    else
     183    {
     184        exec_info->envs_pointers  =  k_pointers;
     185        exec_info->envs_buf_free  =  k_buf_ptr;
     186        exec_info->envs_nr        =  index;
     187    }
     188
     189#if DEBUG_SYS_EXEC
     190if( DEBUG_SYS_EXEC < cycle )
     191printk("\n[%s] thread[%x,%x] copied %d strings to kernel buffer\n",
     192__FUNCTION__, this->process->pid, this->trdid, index );
     193#endif
     194
     195    return 0;
     196
     197} // end exec_get_strings()
     198
     199
    40200///////////////////////////////
    41 int sys_exec( char  * pathname,       // .elf file pathname in user space
    42               char ** user_args,      // pointer on process arguments in user space
    43               char ** user_envs )     // pointer on env variables in user space
     201int sys_exec( char  * pathname,    // .elf file pathname in user space
     202              char ** user_args,   // pointer on array of process arguments in user space
     203              char ** user_envs )  // pointer on array of env variables in user space
    44204{
    45205    error_t       error;
     
    96256
    97257#if DEBUG_SYSCALLS_ERROR
     258if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
    98259printk("\n[ERROR] in %s for thread[%x,%] : user_args pointer %x unmapped\n",
    99260__FUNCTION__, pid, trdid, user_args );
     
    115276                return -1;
    116277        }
    117 
    118 #if DEBUG_SYS_EXEC
    119 if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
    120 printk("\n[%s] thread[%x,%x] enter / path <%s> / args %x / envs %x / cycle %d\n",
    121 __FUNCTION__, pid, trdid, &process->exec_info.path[0], user_args, user_envs, cycle );
    122 #endif
    123278
    124279    // 1. copy "pathname" in kernel exec_info structure
     
    127282                            CONFIG_VFS_MAX_PATH_LENGTH );
    128283
     284#if DEBUG_SYS_EXEC
     285if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
     286printk("\n[%s] thread[%x,%x] enter / path <%s> / args %x / envs %x / cycle %d\n",
     287__FUNCTION__, pid, trdid, &process->exec_info.path[0],
     288user_args, user_envs, (uint32_t)tm_start );
     289#endif
     290
    129291    // 2. copy "arguments" pointers & strings in process exec_info if required
    130292    if( user_args != NULL )
    131293    {
    132         if( process_exec_get_strings( true , user_args , &process->exec_info ) )
     294        if( exec_get_strings( true , user_args , &process->exec_info ) )
    133295        {
    134296
    135297#if DEBUG_SYSCALLS_ERROR
    136298if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
    137 printk("\n[ERROR] in %s : thread[%x,%] get arguments for <%s>\n",
     299printk("\n[ERROR] in %s : thread[%x,%] cannot get arguments for <%s>\n",
    138300__FUNCTION__, pid, trdid, pathname );
    139301#endif
     
    144306#if DEBUG_SYS_EXEC
    145307if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
    146 printk("\n[%s] thread[%x,%x] got arguments / arg[0] = <%s>\n",
     308printk("\n[%s] thread[%x,%x] set arguments in exec_info / arg[0] = <%s>\n",
    147309__FUNCTION__, pid, trdid, process->exec_info.args_pointers[0] );
    148310#endif
     
    153315    if( user_envs != NULL )
    154316    {
    155         if( process_exec_get_strings( false , user_envs , &process->exec_info ) )
     317        if( exec_get_strings( false , user_envs , &process->exec_info ) )
    156318        {
    157319
    158320#if DEBUG_SYSCALLS_ERROR
    159321if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
    160 printk("\n[ERROR] in %s : thread[%x,%] get env variables for <%s>\n",
     322printk("\n[ERROR] in %s : thread[%x,%] cannot get env variables for <%s>\n",
    161323__FUNCTION__, pid, trdid, pathname );
    162324#endif
     
    167329#if DEBUG_SYS_EXEC
    168330if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
    169 printk("\n[%s] thread[%x,%x] got envs / env[0] = <%s>\n",
     331printk("\n[%s] thread[%x,%x] set envs in exec_info / env[0] = <%s>\n",
    170332__FUNCTION__, pid, trdid, process->exec_info.envs_pointers[0] );
    171333#endif
Note: See TracChangeset for help on using the changeset viewer.