Changeset 408 for trunk/kernel/syscalls


Ignore:
Timestamp:
Dec 5, 2017, 4:20:07 PM (7 years ago)
Author:
alain
Message:

Fix several bugs in the fork() syscall.

Location:
trunk/kernel/syscalls
Files:
11 edited

Legend:

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

    r407 r408  
    150150// Implementation note:
    151151// This function build an exec_info_t structure containing all informations
    152 // required to create the new process descriptor and the associated thread.
     152// required to initialize the new process descriptor and the associated thread.
     153// It includes the process PID (unchanged), main() arguments, environment variables,
     154// and the pathname to the new process .elf file.
    153155// It calls the process_exec_get_strings() functions to copy the main() arguments and
    154156// the environment variables from user buffers to the exec_info_t structure, allocate
    155157// and call the process_make_exec() function.
    156 // Finally, it destroys the calling thread and process.
     158// As it must destroy all parent process copies, and all parent threads in all clusters,
     159// the process_make_exec() function must be executed in the parent owner cluster,
     160// and this sys_exec() function uses a RPC to access the owner cluster if required.
     161//
    157162// TODO : the args & envs arguments are not supported yet : both must be NULL
    158163/////////////////////////////////////////////////////////////////////////////////////////
     
    169174        tm_start = hal_get_cycles();
    170175
    171     // get pointers on parent process and thread
     176    // get parent process pid
    172177    thread_t   * this    = CURRENT_THREAD;
    173178    process_t  * process = this->process;
     
    177182__FUNCTION__, local_cxy, this->core->lid, pid, (uint32_t)hal_get_cycles() );
    178183
    179 sched_display( 0 );
     184    // get owner cluster
     185    cxy_t  owner_cxy = CXY_FROM_PID( pid );
    180186
    181187    // check pathname length
     
    189195    // copy pathname in exec_info structure (kernel space)
    190196    hal_strcpy_from_uspace( exec_info.path , pathname , CONFIG_VFS_MAX_PATH_LENGTH );
     197
    191198    // check args argument
    192199    assert( (args == NULL) , __FUNCTION__ ,
     
    196203    assert( (envs == NULL) , __FUNCTION__ ,
    197204    "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;
    208205
    209206    // check and store args in exec_info structure if required
     
    229226    }
    230227
     228    // register PID in exec_info
     229    exec_info.pid = pid;
     230
    231231    // call process_make_exec (local or remote)
    232     if( cxy_server == cxy_client )
     232    if( owner_cxy == local_cxy )
    233233    {
    234234        error = process_make_exec( &exec_info );
     
    236236    else
    237237    {
    238         rpc_process_exec_client( cxy_server , &exec_info , &error );
     238        rpc_process_make_exec_client( owner_cxy,
     239                                      &exec_info,
     240                                      &error );
    239241    }
    240242
     
    242244    {
    243245        printk("\n[ERROR] in %s : cannot create new process %x in cluster %x\n",
    244         __FUNCTION__, pid, cxy_server );
     246        __FUNCTION__, pid, owner_cxy );
    245247        this->errno = error;
    246248        return -1;
    247249    }
    248 
    249     // FIXME delete the local process descriptor
    250     // process_kill( process );
    251250
    252251    tm_end = hal_get_cycles();
  • trunk/kernel/syscalls/sys_fork.c

    r407 r408  
    4141int sys_fork()
    4242{
    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
    5147
    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;
    5460
    5561        tm_start = hal_get_cycles();
    5662
    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;
    6168
    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 );
     69fork_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 );
    6471
    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 )
    6780        {
    6881            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;
    7185        }
    7286
    73     // Select target cluster for future migration of child process and main thread.
     87    // Select target cluster for child process and main thread.
    7488    // 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
    7890        {
    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;
    8293        }
    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
    8995        {
    90         // DQDT placement
    9196                target_cxy = dqdt_get_cluster_for_process();
    9297        }
    9398
    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 )
    109101    {
    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 );
    111106    }
    112     else                                         // target cluster is remote
     107    else
    113108    {
    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 );
    115115    }
    116116
    117117    if( error )
    118118    {
    119             printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ );
    120             hal_atomic_add ( &parent_process->children_nr , -1 );
    121         process_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;
    123123    }
    124124
    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 )
    185128        {
    186                 hal_fpu_context_save( child_thread->fpu_context );
     129                hal_fpu_context_save( XPTR( target_cxy , child_thread_ptr ) );
    187130        }
    188131
    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 ) );
    193134
    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
    197140
    198141    thread_t * current = CURRENT_THREAD;
    199142
    200     if( current == parent_thread )
     143    if( current == parent_thread_ptr )    // current == parent thread
    201144    {
    202145        // 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 );
    204147
    205148        tm_end = hal_get_cycles();
     
    207150fork_dmsg("\n[DBG] %s : core[%x,%d] parent_process %x exit / cycle %d\n"
    208151"     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,
     153child_pid, child_thread_ptr->trdid , (uint32_t)(tm_end - tm_start) );
    211154
    212155        return child_pid;
    213156    }
    214         else  // current == child_thread
     157        else                                   // current == child_thread
    215158    {
    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();
    218161
    219162fork_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 );
    221164
    222165        return 0;
  • trunk/kernel/syscalls/sys_get_cycle.c

    r407 r408  
    4848        {
    4949        printk("\n[ERROR] in %s : user buffer unmapped for thread %x in process %x\n",
    50                __FUNCTION__ , this->trdid , process->pid );
     50        __FUNCTION__ , this->trdid , process->pid );
    5151        this->errno = EFAULT;
    5252                return -1;
  • trunk/kernel/syscalls/sys_read.c

    r407 r408  
    6161        xptr_t       file_xp;     // remote file extended pointer
    6262    uint32_t     nbytes;      // number of bytes actually read
    63 
     63    reg_t        save_sr;     // required to enable IRQs during syscall
    6464        uint32_t     tm_start;
    6565        uint32_t     tm_end;
     
    9393                return -1;
    9494    }
     95
     96    // enable IRQs
     97    hal_enable_irq( &save_sr );
    9598
    9699    // get extended pointer on remote file descriptor
     
    150153        return -1;
    151154    }
     155
     156    // restore IRQs
     157    hal_restore_irq( save_sr );
    152158
    153159    hal_fence();
     
    190196#endif
    191197
    192 syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x / nbytes = %d / cycle %d\n"
    193 " first byte = %c / file_id = %d / cost = %d\n",
    194 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , nbytes , tm_start ,
    195 *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
     198syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
     199"nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
     200__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
     201tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
    196202 
    197203        return nbytes;
  • trunk/kernel/syscalls/sys_signal.c

    r407 r408  
    3333                void     * handler )
    3434
    35         thread_t  * this = CURRENT_THREAD;
     35        thread_t  * this    = CURRENT_THREAD;
    3636
     37    printk("\n[ERROR] in %s : not implemented yet\n", __FUNCTION__ );
     38    this->errno = EINVAL;
     39    return -1;
     40   
    3741        if((sig_id == 0) || (sig_id >= SIG_NR) || (sig_id == SIGKILL) || (sig_id == SIGSTOP))
    3842        {
  • trunk/kernel/syscalls/sys_thread_exit.c

    r407 r408  
    7373
    7474                // deschedule
    75                 sched_yield();
     75                sched_yield("waiting parent join");
    7676            }     
    7777        }
  • trunk/kernel/syscalls/sys_thread_join.c

    r407 r408  
    138138
    139139            // deschedule
    140             sched_yield();
     140            sched_yield("waiting child exit");
    141141        }
    142142    }
  • trunk/kernel/syscalls/sys_thread_sleep.c

    r407 r408  
    3636
    3737    thread_block( this , THREAD_BLOCKED_GLOBAL );
    38     sched_yield();
     38    sched_yield("blocked on sleep");
    3939
    4040    thread_dmsg("\n[DBG] %s : thread %x in process %x resume at cycle\n",
  • trunk/kernel/syscalls/sys_thread_yield.c

    r407 r408  
    2727int sys_thread_yield()
    2828{
    29         sched_yield();
     29        sched_yield("user request");
    3030        return 0;
    3131}
  • trunk/kernel/syscalls/sys_write.c

    r407 r408  
    4040{
    4141    error_t      error;
    42     paddr_t      paddr;                // unused, but required for user space checking
    43         xptr_t       file_xp;              // remote file extended pointer
    44     uint32_t     nbytes;               // number of bytes actually written
    45 
     42    paddr_t      paddr;           // unused, but required for user space checking
     43        xptr_t       file_xp;         // remote file extended pointer
     44    uint32_t     nbytes;          // number of bytes actually written
     45    reg_t        save_sr;         // required to enable IRQs during syscall
    4646        uint32_t     tm_start;
    4747        uint32_t     tm_end;
     
    7070                return -1;
    7171    }
     72
     73    // enable IRQs
     74    hal_enable_irq( &save_sr );
    7275
    7376    // get extended pointer on remote file descriptor
     
    128131    }
    129132
     133    // restore IRQs
     134    hal_restore_irq( save_sr );
     135
    130136    hal_fence();
    131137
    132138    tm_end = hal_get_cycles();
    133139
    134 syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x / nbytes = %d / cycle %d\n"
    135 " first byte = %c / file_id = %d / cost = %d\n",
    136 __FUNCTION__ , local_cxy , this->core->lid , this->trdid , nbytes , tm_start ,
    137 *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
     140syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
     141"nbytes = %d / first byte = %c / file_id = %d / cost = %d\n",
     142__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid ,
     143tm_start , nbytes , *((char *)(intptr_t)paddr) , file_id , tm_end - tm_start );
    138144 
    139145        return nbytes;
  • trunk/kernel/syscalls/syscalls.h

    r407 r408  
    4141 * terminating thread.
    4242 ******************************************************************************************
    43  * @ exit_vallue  : pointer to be returned to parent thread if thead is attached.
     43 * @ exit_vallue  : pointer to be returned to parent thread if thread is attached.
    4444 * @ return 0 if success / return -1 if failure.
    4545 *****************************************************************************************/
     
    154154
    155155/******************************************************************************************
    156  * [10] This slot not allocated yet
    157  ******************************************************************************************
    158  * @ return 0 if success / returns -1 if failure.
    159  *****************************************************************************************/
    160 
    161 /******************************************************************************************
    162  * [11] This function rmove an existing mapping defined by the <addr> and <size>
     156 * [10] This function implement the exit system call terminating a POSIX process.
     157 ******************************************************************************************
     158 * @ status   : terminaison status (not used in present implementation).
     159 *****************************************************************************************/
     160void sys_exit( uint32_t status );
     161
     162/******************************************************************************************
     163 * [11] This function remove an existing mapping defined by the <addr> and <size>
    163164 * arguments in user space.
    164165 ******************************************************************************************
     
    194195 * [14] This function read bytes from an open file identified by its file descriptor.
    195196 * The file can be a regular file or character oriented device.
     197 * IRQs are enabled during this system call.
    196198 ******************************************************************************************
    197199 * @ file_id  : open file index in fd_array.
     
    207209 * [15] This function writes bytes to an open file identified by its file descriptor.
    208210 * The file can be a regular file or character oriented device.
     211 * IRQs are enabled during this system call.
    209212 ******************************************************************************************
    210213 * @ file_id  : open file index in fd_array.
Note: See TracChangeset for help on using the changeset viewer.