Ignore:
Timestamp:
Jun 18, 2017, 10:06:41 PM (5 years ago)
Author:
alain
Message:

Introduce syscalls.

File:
1 edited

Legend:

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

    r1 r23  
    11/*
    2  * sys_fork.c - fork the current process
     2 * sys_fork.c - Fork the current process.
    33 *
    4  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Mohamed Lamine Karaoui (2015)
    6  *          Alain Greiner (2016)
     4 * Authors  Alain Greiner  (2016,2017)
    75 *
    86 * Copyright (c) UPMC Sorbonne Universites
     
    2422 */
    2523
     24#include <kernel_config.h>
     25#include <hal_types.h>
     26#include <hal_atomic.h>
    2627#include <errno.h>
    27 #include <config.h>
    28 #include <cpu.h>
     28#include <printk.h>
     29#include <core.h>
    2930#include <cluster.h>
    30 #include <event.h>
    3131#include <list.h>
    3232#include <thread.h>
     
    3636#include <process.h>
    3737
    38 #if CONFIG_FORK_DEBUG
    39 #define fork_debug(...) printk(__VA_ARGS__)
    40 #else
    41 #define fork_debug(...) /**/
    42 #endif
    43 
    44 /***********************************************************************************************
    45  * This kernel function implement the "fork" system call.
    46  * The calling process descriptor (parent process), and the associated thread descriptor are
    47  * replicated in the same cluster as the calling thread, but the new process (child process)
    48  * is registered in another target cluster, that will become the process owner.
    49  * The child process and the associated main thread will be migrated to the target cluster
    50  * later, when the child process makes an "exec" or any other system call.
    51  * The target cluster depends on the "fork_user" flag and "fork_cxy" variable that can be
    52  * stored in the calling thread descriptor by the specific fork_place() system call.
    53  * If not, the sys_fork() function makes a query to the DQDT to select the target cluster.
    54  * @ returns child process PID if success / returns -1 if failure
    55  **********************************************************************************************/
    56 int sys_fork();
     38//////////////
     39int sys_fork()
    5740{
    5841        process_t          * parent_process;  // pointer on parent process descriptor
     
    6346        thread_t           * child_thread;    // pointer on child main thread descriptor
    6447    trdid_t              child_trdid;     // child main thread identifier
    65     core_t             * child_core;      // pointer on core for child main thread
    6648    lid_t                child_core_lid;  // core local index for the child main thread
    6749    cxy_t                target_cxy;      // final target cluster for forked child process
    6850        error_t              error;
    6951
    70     cluster_t          * parent_cluster = LOCAL_CLUSTER;
    71 
    7252    // get pointers on parent process and thread
    7353        parent_thread  = CURRENT_THREAD;
    7454        parent_process = parent_thread->process;
     55    parent_pid     = parent_process->pid;
    7556
    7657    // check parent process children number
    77         if( hal_atomic_add( &parent_process->childs_nr , 1 ) >= CONFIG_PROCESS_CHILDS_MAX_NR )
    78         {
    79             printk("ERROR in %s : too much children processes\n", __FUNCTION__);
    80             hal_atomic_add ( &parent_process->childs_nr , -1 );
    81         return EAGAIN;
    82         }
    83 
    84         fork_debug("INFO : %s enters for process %d at cycle [%d]\n",
     58        if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN )
     59        {
     60            printk("\n[ERROR] in %s : too much children processes\n", __FUNCTION__);
     61            hal_atomic_add ( &parent_process->children_nr , -1 );
     62        return EAGAIN;
     63        }
     64
     65        fork_dmsg("\n[INFO] %s : enters for process %d at cycle [%d]\n",
    8566                  __FUNCTION__, parent_process->pid, hal_time_stamp());
    8667
     
    9071        {
    9172                hal_fpu_context_save( parent_thread );
    92                 fork_debug("INFO : %s save FPU\n", __FUNCTION__);
     73                fork_dmsg("\n[INFO] %s : save FPU\n", __FUNCTION__);
    9374        }
    9475
    9576    // Select target cluster for future migration of child process and main thread.
    96     // The placement can be specified by user. If placement is not user-defined,
    97     // the placement is defined by the DQDT.
    98     // The two first processes ("init" and "sh") on boot cluster will not migrate.
    99         if( parent_threads->fork_user )
     77    // If placement is not user-defined, the placement is defined by the DQDT.
     78    // The two first processes ("init" and "sh") on boot cluster do not migrate.
     79
     80        if( parent_thread->fork_user )
    10081        {
    10182        // user defined placement
    102         target_cxy = parent->thread.fork_cxy;
    103         parent->thread.fork_cxy = false;
    104         }
    105     else if( (LPID_FROM_PID(parent_process->pid) < 2 ) 
    106              && ( parent_cluster->cxy == parent_cluster->boot_cxy ) )
     83        target_cxy = parent_thread->fork_cxy;
     84        parent_thread->fork_user = false;
     85        }
     86    else if( (LPID_FROM_PID(parent_process->pid) < 2)  && (local_cxy == 0) )
    10787    {
    10888        // 2 first process stay in boot cluster
    109         target_cxy = parent_cluster->cxy;
     89        target_cxy = local_cxy;
    11090    }
    11191        else
     
    11595        }
    11696
    117         fork_debug("INFO : %s select target_cluster = %x\n",
     97        fork_dmsg("INFO : %s select target_cluster = %x\n",
    11898              __FUNCTION__ , target_cxy );
    11999
    120100    // allocates memory in local cluster for the child process descriptor
    121101        child_process = process_alloc();
     102
    122103        if( child_process == NULL )
    123104        {
    124             printk("ERROR in %s : cannot allocate memory for child process\n", __FUNCTION__ );
    125             hal_atomic_add ( &parent_process->childs_nr , -1 );
    126         return EAGAIN;
    127         }
    128 
    129     // get a new PID for child process
    130     // it requires an RPC if target cluster is remote
    131     xptr_t xp = XPTR( target_cxy , child_process );
    132     if( target_cxy == parent_cluster->cxy )   // local cluster
    133     {
    134         error = process_pid_alloc( xp , &child_pid );
    135     }
    136     else                            // remote cluster
    137     {
    138         rpc_process_pid_alloc_server( target_cxy , xp , &error , &child_pid );
    139     }
     105            printk("\n[ERROR] in %s : cannot allocate child process\n", __FUNCTION__ );
     106            hal_atomic_add ( &parent_process->children_nr , -1 );
     107        return EAGAIN;
     108        }
     109
     110    // get a new PID for child process,
     111    if( target_cxy == local_cxy )                // target cluster is local
     112    {
     113        error = cluster_pid_alloc( XPTR( target_cxy , child_process ) , &child_pid );
     114    }
     115    else                                         // target cluster is remote
     116    {
     117        rpc_process_pid_alloc_client( target_cxy , child_process , &error , &child_pid );
     118    }
     119
    140120    if( error )
    141121    {
    142             printk("ERROR in %s : cannot allocate PID\n", __FUNCTION__ );
    143             atomic_add ( &parent_process->childs_nr , -1 );
     122            printk("\n[ERROR] in %s : cannot allocate PID\n", __FUNCTION__ );
     123            hal_atomic_add ( &parent_process->children_nr , -1 );
    144124        process_destroy( child_process );
    145125        return EAGAIN;
     
    147127
    148128    // initialize and register the child process descriptor
    149     error = process_reference_init( child_process , child_pid , parent_pid );
    150     if( error )
    151     {
    152             printk("ERROR in %s : cannot initialise child process\n", __FUNCTION__ );
    153             atomic_add ( &parent_process->childs_nr , -1 );
    154         process_destroy( child_process );
    155         return EAGAIN;
    156     }
    157 
    158         fork_debug("INFO : %s created child process : pid = %x / ppid = %x\n",
     129    process_reference_init( child_process , child_pid , parent_pid );
     130
     131        fork_dmsg("\n[INFO] : %s created child process : pid = %x / ppid = %x\n",
    159132              __FUNCTION__, child_pid , parent_pid );
    160 
    161     // set IS_REFERENCE flag in child process descriptor
    162     child_process->flags = PDF_IS_REFERENCE;
    163133
    164134    // initialises child process standard files structures
    165135    // ( root / cwd / bin ) from parent process descriptor
    166         spinlock_lock( &parent_process->cwd_lock );
    167 
    168         vfs_file_count_up( &parent_process->vfs_root );
    169         child_process->vfs_root = parent_process->vfs_root;
    170 
    171         vfs_file_count_up( &parent_process->vfs_cwd );
    172         child_process->vfs_cwd  = parent_process->vfs_cwd;
    173 
    174         vfs_file_count_up( &parent_process->vfs_bin );
    175     child_process->vfs_bin = parent_process->vfs_bin;
    176 
    177         spinlock_unlock( &parent_process->cwd_lock );
     136
     137        vfs_file_count_up( parent_process->vfs_root_xp );
     138        child_process->vfs_root_xp = parent_process->vfs_root_xp;
     139
     140        vfs_file_count_up( parent_process->vfs_cwd_xp );
     141        child_process->vfs_cwd_xp  = parent_process->vfs_cwd_xp;
     142
     143        vfs_file_count_up( parent_process->vfs_bin_xp );
     144    child_process->vfs_bin_xp = parent_process->vfs_bin_xp;
     145
     146    // copy the parent process fd_array to the child process fd_array
     147        process_fd_remote_copy( XPTR( local_cxy , &child_process->fd_array ),
     148                            XPTR( local_cxy , &parent_process->fd_array ) );
     149
     150        fork_dmsg("\n[INFO] %s : duplicated child process from parent process\n",
     151                  __FUNCTION__ );
     152
     153    // replicates virtual memory manager
     154        error = vmm_copy( child_process , parent_process );
     155
     156        if( error )
     157    {
     158            printk("\n[ERROR] in %s : cannot duplicate VMM\n", __FUNCTION__ );
     159            hal_atomic_add ( &parent_process->children_nr , -1 );
     160        process_destroy( child_process );
     161        return ENOMEM;
     162    }
    178163 
    179     // copy the parent process fd_array to the child process fd_array
    180         process_fd_fork( child_process , parent_process );
    181 
    182     // initialise child process signal manager TODO ???
    183         signal_manager_init( child_process );
    184  
    185         fork_debug("INFO : %s duplicated child process from parent process\n",
    186                   __FUNCTION__ );
    187 
    188     // replicates virtual memory manager
    189         error = vmm_dup( &child_process->vmm , &parent_process->vmm );
     164        fork_dmsg("\n[INFO] %s : parent vmm duplicated in child process\n", __FUNCTION__ );
     165
     166    // create child main thread descriptor in local cluster
     167    error = thread_user_fork( parent_process , &child_thread );
     168
    190169        if( error )
    191170    {
    192             printk("ERROR in %s : cannot duplicate VMM\n", __FUNCTION__ );
    193             atomic_add ( &parent_process->childs_nr , -1 );
    194         process_destroy( child_process );
    195         return EAGAIN;
    196     }
    197  
    198         fork_debug("INFO : %s: parent vmm duplicated in child process\n", __FUNCTION__ );
    199 
    200     // create child main thread descriptor in local cluster TODO stack ???
    201     error = thread_user_fork( &child_thread , process , parent_thread );
    202         if( error )
    203     {
    204             printk("ERROR in %s : cannot duplicate thread\n", __FUNCTION__ );
    205             atomic_add ( &parent_process->childs_nr , -1 );
    206         process_destroy( child_process );
    207         return EAGAIN;
     171            printk("\n[ERROR] in %s : cannot duplicate thread\n", __FUNCTION__ );
     172            hal_atomic_add( &parent_process->children_nr , -1 );
     173        process_destroy( child_process );
     174        return ENOMEM;
    208175    }
    209176
    210177    // register child thread in child process, and get a TRDID
    211     spinlock_lock( &child->process->th_lock );
    212     error = process_register_thread( child->process, child->thread , &child_trdid );
    213     spinlock_unlock( &process->th_lock );
     178    spinlock_lock( &child_process->th_lock );
     179    error = process_register_thread( child_process, child_thread , &child_trdid );
     180    spinlock_unlock( &child_process->th_lock );
    214181
    215182    if( error )
    216183    {
    217         printk("ERROR in %s : cannot register thread\n", __FUNCTION__ );
    218             atomic_add ( &parent_process->childs_nr , -1 );
     184        printk("\n[ERROR] in %s : cannot register thread\n", __FUNCTION__ );
     185            hal_atomic_add ( &parent_process->children_nr , -1 );
    219186        thread_destroy( child_thread );
    220187        process_destroy( child_process );
     
    226193
    227194        // Update child thread descriptor
    228         child_thread->core    = process->core_tbl[child_core_lid];
     195        child_thread->core    = &LOCAL_CLUSTER->core_tbl[child_core_lid];
    229196        child_thread->process = child_process;
    230     child_thread->trdid   = chid_trdid;
    231 
    232         fork_debug("INFO : %s initialised child main thread\n", __FUNCTION__ );
     197    child_thread->trdid   = child_trdid;
     198
     199        fork_dmsg("\n[INFO] %s : initialised child main thread\n", __FUNCTION__ );
    233200
    234201    // register local child thread into local child process th_tbl[]
    235202    // we don't use the th_lock because there is no concurrent access
    236     ltid_t ltid = LTID_FROM_TRDID( trdid );
    237         child_process->th_tbl[ltid] = XPTR( local_cxy , child_thread );
    238         child_process->threads_nr = 1;
     203    ltid_t ltid = LTID_FROM_TRDID( child_trdid );
     204        child_process->th_tbl[ltid] = child_thread;
     205        child_process->th_nr = 1;
    239206
    240207    // register child thread in scheduler
    241         sched_register( child_thread->core , child_thread );
     208        sched_register_thread( child_thread->core , child_thread );
    242209 
    243         fork_debug("INFO : %s registered main thread in scheduler\n", __FUNCTION__);
     210        fork_dmsg("\n[INFO] %s : registered main thread in scheduler\n", __FUNCTION__);
    244211
    245212        // update DQDT for the child thread
    246     dqdt_update_threads_number( 1 );
    247 
    248         fork_debug("INFO :%s completed / parent pid = %x / child pid = %x / at cycle [%d]\n",
     213    dqdt_local_update_threads( 1 );
     214
     215        fork_dmsg("\n[INFO] %s : completed / parent pid = %x / child pid = %x / at cycle [%d]\n",
    249216                  __FUNCTION__, parent_process->pid, child_process->pid, hal_time_stamp() );
    250217
Note: See TracChangeset for help on using the changeset viewer.