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

First implementation of fork/exec.

File:
1 edited

Legend:

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

    r406 r407  
    2424#include <kernel_config.h>
    2525#include <hal_types.h>
     26#include <hal_context.h>
     27#include <hal_switch.h>
    2628#include <hal_atomic.h>
    2729#include <errno.h>
     
    4547    pid_t                child_pid;       // child process identifier
    4648        thread_t           * child_thread;    // pointer on child main thread descriptor
    47     trdid_t              child_trdid;     // child main thread identifier
    48     lid_t                child_core_lid;  // core local index for the child main thread
    49     cxy_t                target_cxy;      // final target cluster for forked child process
     49    cxy_t                target_cxy;      // target cluster for forked child process
    5050        error_t              error;
     51
     52        uint64_t      tm_start;
     53        uint64_t      tm_end;
     54
     55        tm_start = hal_get_cycles();
    5156
    5257    // get pointers on parent process and thread
     
    5560    parent_pid     = parent_process->pid;
    5661
     62fork_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 );
     64
    5765    // check parent process children number
    5866        if( hal_atomic_add( &parent_process->children_nr , 1 ) >= CONFIG_PROCESS_MAX_CHILDREN )
     
    6169            hal_atomic_add ( &parent_process->children_nr , -1 );
    6270        return EAGAIN;
    63         }
    64 
    65         fork_dmsg("\n[DMSG] %s : enters for process %d at cycle [%d]\n",
    66                   __FUNCTION__, parent_process->pid, hal_get_cycles());
    67 
    68     // save FPU state in fpu_context if parent process is FPU owner
    69     // because we want the child process to share the FPU context
    70         if( CURRENT_CORE->fpu_owner == parent_thread )
    71         {
    72                 hal_fpu_context_save( parent_thread );
    73                 fork_dmsg("\n[DMSG] %s : save FPU\n", __FUNCTION__);
    7471        }
    7572
     
    9592        }
    9693
    97         fork_dmsg("INFO : %s select target_cluster = %x\n",
    98               __FUNCTION__ , target_cxy );
     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 );
    9996
    10097    // allocates memory in local cluster for the child process descriptor
     
    127124
    128125    // initialize and register the child process descriptor
    129     process_reference_init( child_process , child_pid , parent_pid );
    130 
    131         fork_dmsg("\n[DMSG] : %s created child process : pid = %x / ppid = %x\n",
    132               __FUNCTION__, child_pid , parent_pid );
     126    process_reference_init( child_process , child_pid , XPTR(local_cxy, parent_process) );
    133127
    134128    // initialises child process standard files structures
     
    148142                            XPTR( local_cxy , &parent_process->fd_array ) );
    149143
    150         fork_dmsg("\n[DMSG] %s : duplicated child process from parent process\n",
    151                   __FUNCTION__ );
    152 
    153     // replicates virtual memory manager
     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
    154148        error = vmm_copy( child_process , parent_process );
    155149
     
    162156    }
    163157 
    164         fork_dmsg("\n[DMSG] %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 
     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 );
    169168        if( error )
    170169    {
    171             printk("\n[ERROR] in %s : cannot duplicate thread\n", __FUNCTION__ );
     170            printk("\n[ERROR] in %s : cannot duplicate main thread\n", __FUNCTION__ );
    172171            hal_atomic_add( &parent_process->children_nr , -1 );
    173172        process_destroy( child_process );
     
    175174    }
    176175
    177     // register child thread in child process, and get a TRDID
    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 );
    181 
    182     if( error )
    183     {
    184         printk("\n[ERROR] in %s : cannot register thread\n", __FUNCTION__ );
    185             hal_atomic_add ( &parent_process->children_nr , -1 );
    186         thread_destroy( child_thread );
    187         process_destroy( child_process );
    188         return EAGAIN;
    189     }
    190  
    191     // get a local core to execute child thread
    192     child_core_lid = cluster_select_local_core();
    193 
    194         // Update child thread descriptor
    195         child_thread->core    = &LOCAL_CLUSTER->core_tbl[child_core_lid];
    196         child_thread->process = child_process;
    197     child_thread->trdid   = child_trdid;
    198 
    199         fork_dmsg("\n[DMSG] %s : initialised child main thread\n", __FUNCTION__ );
    200 
    201     // register local child thread into local child process th_tbl[]
    202     // we don't use the th_lock because there is no concurrent access
    203     ltid_t ltid = LTID_FROM_TRDID( child_trdid );
    204         child_process->th_tbl[ltid] = child_thread;
    205         child_process->th_nr = 1;
    206 
    207     // register child thread in scheduler
    208         sched_register_thread( child_thread->core , child_thread );
    209  
    210         fork_dmsg("\n[DMSG] %s : registered main thread in scheduler\n", __FUNCTION__);
     176//printk("\n[DBG] %s : core[%x,%d] initialised child main thread\n",
     177//__FUNCTION__ , local_cxy , parent_thread->core->lid );
    211178
    212179        // update DQDT for the child thread
    213180    dqdt_local_update_threads( 1 );
    214181
    215         fork_dmsg("\n[DMSG] %s : completed / parent pid = %x / child pid = %x / at cycle [%d]\n",
    216                   __FUNCTION__, parent_process->pid, child_process->pid, hal_get_cycles() );
    217 
    218         return child_process->pid;
     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 )
     185        {
     186                hal_fpu_context_save( child_thread->fpu_context );
     187        }
     188
     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) );
     193
     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
     197
     198    thread_t * current = CURRENT_THREAD;
     199
     200    if( current == parent_thread )
     201    {
     202        // parent_thread unblock child_thread
     203        thread_unblock( XPTR( local_cxy , child_thread ) , THREAD_BLOCKED_GLOBAL );
     204
     205        tm_end = hal_get_cycles();
     206
     207fork_dmsg("\n[DBG] %s : core[%x,%d] parent_process %x exit / cycle %d\n"
     208"     child_process %x / child_thread = %x / cost = %d\n",
     209__FUNCTION__, local_cxy, parent_thread->core->lid,  parent_pid, (uint32_t)tm_start,
     210child_pid, child_thread->trdid , (uint32_t)(tm_end - tm_start) );
     211
     212        return child_pid;
     213    }
     214        else  // current == child_thread
     215    {
     216        assert( (current == child_thread) , __FUNCTION__ ,
     217        "current thread %x is not the child thread %x\n", current , child_thread );
     218
     219fork_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() );
     221
     222        return 0;
     223    }
    219224
    220225}  // end sys_fork()
Note: See TracChangeset for help on using the changeset viewer.