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

Fix several bugs in the fork() syscall.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.