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

First implementation of fork/exec.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/kern/process.c

    r406 r407  
    3939#include <thread.h>
    4040#include <list.h>
     41#include <string.h>
    4142#include <scheduler.h>
    4243#include <remote_spinlock.h>
     
    9091    pid_t       parent_pid;
    9192
    92     process_dmsg("\n[DMSG] %s : core[%x,%d] enters for process %x\n",
    93     __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
     93        error_t     error1;
     94        error_t     error2;
     95        error_t     error3;
     96    xptr_t      stdin_xp;
     97    xptr_t      stdout_xp;
     98    xptr_t      stderr_xp;
     99    uint32_t    stdin_id;
     100    uint32_t    stdout_id;
     101    uint32_t    stderr_id;
     102
     103process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
     104__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
    94105
    95106    // get parent process cluster, local pointer, and pid
    96     // for all processes other than process_zero
    97     if( process == &process_zero )
     107    // for all processes other than kernel process
     108    if( process == &process_zero )                   // kernel process
    98109    {
    99110        assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
     
    101112        parent_cxy = 0;
    102113        parent_ptr = NULL;
    103         parent_pid = 0;      // process_zero is its own parent...
    104     }
    105     else
    106     {
    107         assert( (parent_xp != XPTR_NULL) , __FUNCTION__ , "parent_xp cannot be NULL\n");
    108 
     114        parent_pid = 0;     
     115    }
     116    else                                             // user process
     117    {
    109118        parent_cxy = GET_CXY( parent_xp );
    110119        parent_ptr = (process_t *)GET_PTR( parent_xp );
     
    112121    }
    113122
    114     // initialize PID and PPID
    115         process->pid   = pid;
    116     process->ppid  = parent_pid;
    117 
    118     // initialize reference process vmm (not for kernel process)
    119     if( pid ) vmm_init( process );
    120 
    121     // reset reference process file descriptors array
    122         process_fd_init( process );
    123 
    124     // reset reference process files structures and cwd_lock
    125         process->vfs_root_xp     = XPTR_NULL;
    126         process->vfs_bin_xp      = XPTR_NULL;
    127         process->vfs_cwd_xp      = XPTR_NULL;
    128     remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
    129 
    130     // reset children list root
    131     xlist_root_init( XPTR( local_cxy , &process->children_root ) );
    132         process->children_nr     = 0;
    133 
    134     // reset semaphore / mutex / barrier / condvar list roots
    135     xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
    136     xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
    137     xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
    138     xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
    139     remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
    140 
    141     // register new process in the parent children list (not for kernel process)
     123    // initialize PID, PPID, and REF
     124        process->pid    = pid;
     125    process->ppid   = parent_pid;
     126    process->ref_xp = XPTR( local_cxy , process );
     127
     128    // initialize vmm, fd array and others structures for user processes.
     129    // These structures are not used by the kernel process.
    142130    if( pid )
    143131    {
     132        // initialize vmm (not for kernel)
     133        vmm_init( process );
     134
     135process_dmsg("\n[DBG] %s : core[%x,%d] / vmm initialised for process %x\n",
     136__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
     137
     138        // initialize fd_array (not for kernel)
     139        process_fd_init( process );
     140
     141        // create stdin / stdout / stderr pseudo-files (not for kernel)
     142        if( parent_pid == 0 )                                              // process_init
     143        {
     144            error1 = vfs_open( process,
     145                               CONFIG_INIT_STDIN,
     146                               O_RDONLY,
     147                               0,                // FIXME chmod
     148                               &stdin_xp,
     149                               &stdin_id );
     150
     151            error2 = vfs_open( process,
     152                               CONFIG_INIT_STDOUT,
     153                               O_WRONLY,
     154                               0,                // FIXME chmod
     155                               &stdout_xp,
     156                               &stdout_id );
     157
     158            error3 = vfs_open( process,
     159                               CONFIG_INIT_STDERR,
     160                               O_WRONLY,
     161                               0,                // FIXME chmod
     162                               &stderr_xp,
     163                               &stderr_id );
     164        }
     165        else                                                               // user process
     166        {
     167            error1 = vfs_open( process,
     168                               CONFIG_USER_STDIN,
     169                               O_RDONLY,
     170                               0,                // FIXME chmod
     171                               &stdin_xp,
     172                               &stdin_id );
     173
     174            error2 = vfs_open( process,
     175                               CONFIG_USER_STDOUT,
     176                               O_WRONLY,
     177                               0,                // FIXME chmod
     178                               &stdout_xp,
     179                               &stdout_id );
     180
     181            error3 = vfs_open( process,
     182                               CONFIG_USER_STDERR,
     183                               O_WRONLY,
     184                               0,                // FIXME chmod
     185                               &stderr_xp,
     186                               &stderr_id );
     187        }
     188
     189        assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
     190        "cannot open stdin/stdout/stderr pseudo files\n");
     191
     192        assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
     193        "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
     194
     195process_dmsg("\n[DBG] %s : core[%x,%d] / fd array initialised for process %x\n",
     196__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
     197
     198
     199        // reset reference process files structures and cwd_lock (not for kernel)
     200            process->vfs_root_xp     = XPTR_NULL;
     201            process->vfs_bin_xp      = XPTR_NULL;
     202            process->vfs_cwd_xp      = XPTR_NULL;
     203        remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
     204
     205        // reset children list root (not for kernel)
     206        xlist_root_init( XPTR( local_cxy , &process->children_root ) );
     207            process->children_nr     = 0;
     208
     209        // reset semaphore / mutex / barrier / condvar list roots (nor for kernel)
     210        xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
     211        xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
     212        xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
     213        xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
     214        remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
     215
     216        // register new process in the parent children list (nor for kernel)
    144217        xptr_t entry = XPTR( local_cxy  , &process->brothers_list );
    145218        xptr_t root  = XPTR( parent_cxy , &parent_ptr->children_root );
     
    156229    spinlock_init( &process->th_lock );
    157230
    158     // set ref_xp field
    159     process->ref_xp = XPTR( local_cxy , process );
    160 
    161231    // register new process descriptor in local cluster manager local_list
    162232    cluster_process_local_link( process );
     
    169239        hal_fence();
    170240
    171     process_dmsg("\n[DMSG] %s : exit for process %x in cluster %x\n",
    172                  __FUNCTION__ , pid );
     241process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x\n",
     242__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
    173243
    174244}  // process_reference init()
     
    181251    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
    182252    process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
     253
     254    // set the pid, ppid, ref_xp fields in local process
     255    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
     256    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
     257    local_process->ref_xp = reference_process_xp;
     258
     259process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x in cluster %x\n",
     260__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
    183261
    184262    // reset local process vmm
     
    192270    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
    193271    local_process->vfs_cwd_xp  = XPTR_NULL;
    194 
    195     // set the pid, ppid, ref_xp fields
    196     local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
    197     local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
    198     local_process->ref_xp = reference_process_xp;
    199 
    200     process_dmsg("\n[DMSG] %s : enter for process %x in cluster %x\n",
    201                  __FUNCTION__ , local_process->pid );
    202272
    203273    // reset children list root (not used in a process descriptor copy)
     
    233303        hal_fence();
    234304
    235     process_dmsg("\n[DMSG] %s : exit for process %x in cluster %x\n",
    236                  __FUNCTION__ , local_process->pid );
     305process_dmsg("\n[DBG] %s : core[%x,%d] exit for process %x in cluster %x\n",
     306__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , local_process->pid );
    237307
    238308    return 0;
     
    288358    vmm_destroy( process );
    289359
    290         process_dmsg("\n[DMSG] %s for pid %d / page_faults = %d\n",
     360        process_dmsg("\n[DBG] %s for pid %d / page_faults = %d\n",
    291361                 __FUNCTION__ , process->pid, process->vmm.pgfault_nr );
    292 }
     362
     363}  // end process_destroy()
    293364
    294365////////////////////////////////////////
     
    298369    uint32_t       ltid;      // index in process th_tbl
    299370    uint32_t       count;     // thread counter
     371
     372printk("\n@@@ %s enter\n", __FUNCTION__ );
    300373
    301374    // get lock protecting th_tbl[]
     
    317390    }
    318391
    319     volatile uint32_t ko;
     392printk("\n@@@ %s : %d signal(s) sent\n", __FUNCTION__, count );
    320393
    321394    // second loop on threads to wait acknowledge from scheduler,
     
    329402        if( thread != NULL )
    330403        {
    331             // wait scheduler acknowledge
    332             do { ko = (thread->signals & THREAD_SIG_KILL); } while( ko );
    333 
    334             // unlink thread from brothers list if required
    335             if( (thread->flags & THREAD_FLAG_DETACHED) == 0 )
    336             xlist_unlink( XPTR( local_cxy , &thread->brothers_list ) );
     404
     405printk("\n@@@ %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
     406
     407            // poll the THREAD_SIG_KILL bit until reset
     408            while( thread->signals & THREAD_SIG_KILL ) asm volatile( "nop" );
     409
     410printk("\n@@@ %s exit polling\n", __FUNCTION__ );
     411
     412            // detach target thread from parent if attached
     413            if( (thread->flags & THREAD_FLAG_DETACHED) != 0 )
     414            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
    337415
    338416            // unlink thread from process
     
    346424    }
    347425
     426printk("\n@@@ %s : %d ack(s) received\n", __FUNCTION__, count );
     427
    348428    // release lock protecting th_tbl[]
    349429    spinlock_unlock( &process->th_lock );
     
    351431    // release memory allocated for process descriptor
    352432    process_destroy( process );
    353 }
     433
     434printk("\n[@@@] %s : core[%x,%d] exit\n",
     435__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
     436
     437}  // end process_kill()
    354438
    355439///////////////////////////////////////////////
     
    440524
    441525/////////////////////////////////////////////////
    442 error_t process_fd_register(  xptr_t     file_xp,
    443                               uint32_t * file_id )
     526error_t process_fd_register( process_t * process,
     527                             xptr_t      file_xp,
     528                             uint32_t  * fdid )
    444529{
    445530    bool_t    found;
     
    447532    xptr_t    xp;
    448533
    449     // get extended pointer on reference process
    450     xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
    451 
    452534    // get reference process cluster and local pointer
     535    xptr_t ref_xp = process->ref_xp;
    453536    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
    454537    cxy_t       ref_cxy = GET_CXY( ref_xp );
     
    467550            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
    468551                hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
    469                         *file_id = id;
     552                        *fdid = id;
    470553            break;
    471554        }
     
    481564////////////////////////////////////////////////
    482565xptr_t process_fd_get_xptr( process_t * process,
    483                             uint32_t    file_id )
     566                            uint32_t    fdid )
    484567{
    485568    xptr_t  file_xp;
    486569
    487570    // access local copy of process descriptor
    488     file_xp = process->fd_array.array[file_id];
     571    file_xp = process->fd_array.array[fdid];
    489572
    490573    if( file_xp == XPTR_NULL )
     
    496579
    497580        // access reference process descriptor
    498         file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[file_id] ) );
     581        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[fdid] ) );
    499582
    500583        // update local fd_array if found
    501584        if( file_xp != XPTR_NULL )
    502585        {
    503             process->fd_array.array[file_id] = file_xp;
     586            process->fd_array.array[fdid] = file_xp;
    504587        }
    505588    }
    506589
    507590    return file_xp;
    508 }
     591
     592}  // end process_fd_get_xptr()
    509593
    510594///////////////////////////////////////////
     
    543627    // release lock on source process fd_array
    544628        remote_spinlock_unlock( XPTR( src_cxy , &src_ptr->lock ) );
    545 }
     629
     630}  // end process_fd_remote_copy()
    546631
    547632////////////////////////////////////////////////////////////////////////////////////
     
    561646    assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
    562647
    563     // search a free slot in th_tbl[]
     648    // search a free slot in th_tbl[]
     649    // 0 is not a valid ltid value
    564650    found = false;
    565     for( ltid = 0 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
     651    for( ltid = 1 ; ltid < CONFIG_THREAD_MAX_PER_CLUSTER ; ltid++ )
    566652    {
    567653        if( process->th_tbl[ltid] == NULL )
     
    606692{
    607693    char           * path;                            // pathname to .elf file
     694    bool_t           keep_pid;                        // new process keep parent PID if true
    608695    process_t      * process;                         // local pointer on new process
    609696    pid_t            pid;                             // new process pid
    610697    xptr_t           parent_xp;                       // extended pointer on parent process
    611     cxy_t            parent_cxy;
    612     process_t      * parent_ptr;
    613     uint32_t         parent_pid;
     698    cxy_t            parent_cxy;                      // parent process local cluster
     699    process_t      * parent_ptr;                      // local pointer on parent process
     700    uint32_t         parent_pid;                      // parent process identifier
    614701    thread_t       * thread;                          // pointer on new thread
    615702    pthread_attr_t   attr;                            // main thread attributes
     
    618705        error_t          error;
    619706
    620         // get parent and .elf pathname from exec_info
     707        // get .elf pathname, parent_xp, and keep_pid flag from exec_info
    621708        path      = exec_info->path;
    622709    parent_xp = exec_info->parent_xp;
     710    keep_pid  = exec_info->keep_pid;
     711
     712process_dmsg("\n[DBG] %s : core[%x,%d] enters for path = %s\n",
     713__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
    623714
    624715    // get parent process cluster and local pointer
     
    627718    parent_pid = hal_remote_lw( XPTR( parent_cxy , &parent_ptr->pid ) );
    628719
    629     exec_dmsg("\n[DMSG] %s : thread %x on core[%x,%d] enters for path = %s\n",
    630     __FUNCTION__, CURRENT_THREAD->trdid, local_cxy, CURRENT_THREAD->core->lid , path );
    631 
    632     // create new process descriptor
    633     process = process_alloc();
    634 
    635     if( process == NULL )
    636     {
    637         printk("\n[ERROR] in %s : no memory / cluster = %x / ppid = %x / path = %s\n",
    638                __FUNCTION__ , local_cxy , parent_pid , path );
    639         return ENOMEM;
    640     }
    641 
    642     // get a pid from the local cluster
    643     error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
    644 
    645     if( error )
    646     {
    647         printk("\n[ERROR] in %s : cannot get PID / cluster = %x / ppid = %x / path = %s\n",
    648                __FUNCTION__ , local_cxy , parent_pid , path );
    649         process_free( process );
    650                 return ENOMEM;
    651     }
     720    // allocates memory for process descriptor
     721        process = process_alloc();
     722        if( process == NULL ) return -1;
     723
     724    // get PID
     725    if( keep_pid )    // keep parent PID
     726    {
     727        pid = parent_pid;
     728    }
     729    else              // get new PID from local cluster
     730    {
     731        error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
     732        if( error ) return -1;
     733    }
     734
     735process_dmsg("\n[DBG] %s : core[%x,%d] created process %x for path = %s\n",
     736__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
    652737
    653738    // initialize the process descriptor as the reference
    654739    process_reference_init( process , pid , parent_xp );
    655740
    656     exec_dmsg("\n[DMSG] %s : thread %x on core[%x,%d] created process %x / path = %s\n",
    657     __FUNCTION__, CURRENT_THREAD->trdid, local_cxy, CURRENT_THREAD->core->lid, pid, path );
     741process_dmsg("\n[DBG] %s : core[%x,%d] initialized process %x / path = %s\n",
     742__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
    658743
    659744    // initialize vfs_root and vfs_cwd from parent process
     
    670755                            XPTR( parent_cxy , &parent_ptr->fd_array) );
    671756
    672     exec_dmsg("\n[DMSG] %s : fd_array copied from process %x to process %x\n",
    673     __FUNCTION__, parent_pid , pid );
    674 
    675         // initialize signal manager TODO ??? [AG]
    676         // signal_manager_init( process );
     757process_dmsg("\n[DBG] %s :  core[%x,%d] copied fd_array for process %x\n",
     758__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid );
    677759
    678760    // register "code" and "data" vsegs as well as the process entry-point in VMM,
     
    682764        if( error )
    683765        {
    684                 printk("\n[ERROR] in %s : failed to access elf file for process %x / path = %s\n",
     766                printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
    685767                       __FUNCTION__, pid , path );
    686768        process_destroy( process );
     
    688770        }
    689771
    690     exec_dmsg("\n[DMSG] %s : code and data vsegs registered for process %x / path = %s\n",
    691     __FUNCTION__ , pid , path );
     772process_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs for process %x / path = %s\n",
     773__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
    692774
    693775    // select a core in cluster
     
    709791        {
    710792                printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
    711                        __FUNCTION__, pid );
     793                       __FUNCTION__, pid , path );
    712794        process_destroy( process );
    713795        return error;
    714796        }
    715797
    716         exec_dmsg("\n[DMSG] %s : thread created for process %x on core %d in cluster %x\n",
    717                __FUNCTION__ , pid , core->lid , local_cxy );
    718 
    719 #if CONFIG_EXEC_DEBUG
    720 if( hal_time_stamp() > CONFIG_EXEC_DEBUG )
    721 {
    722     grdxt_print( &process->vmm.grdxt , GRDXT_TYPE_VSEG , process->pid );
    723     hal_gpt_print( &process->vmm.gpt , process->pid );
    724 }
    725 #endif
     798process_dmsg("\n[DBG] %s : core[%x,%d] created thread %x for process %x / path = %s\n",
     799__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid, path  );
    726800
    727801    // update children list in parent process
     
    733807        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
    734808
    735     exec_dmsg("\n[DMSG] %s : exit for process %x\n",
    736                 __FUNCTION__, process->pid );
     809process_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
     810__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
    737811
    738812        return 0;
    739813
    740 }  // end proces_make_exec()
     814}  // end process_make_exec()
    741815
    742816//////////////////////////
     
    744818{
    745819    exec_info_t   exec_info;     // structure to be passed to process_make_exec()
    746 
    747         error_t   error1;
    748         error_t   error2;
    749         error_t   error3;
    750     xptr_t    stdin_xp;
    751     xptr_t    stdout_xp;
    752     xptr_t    stderr_xp;
    753     uint32_t  stdin_id;
    754     uint32_t  stdout_id;
    755     uint32_t  stderr_id;
    756 
    757         process_dmsg("\n[DMSG] %s : enters in cluster %x\n", __FUNCTION__ , local_cxy );
    758 
    759     // open stdin / stdout / stderr pseudo-files
    760         error1 = vfs_open( XPTR_NULL, CONFIG_DEV_STDIN , O_RDONLY, 0, &stdin_xp , &stdin_id  );
    761         error2 = vfs_open( XPTR_NULL, CONFIG_DEV_STDOUT, O_WRONLY, 0, &stdout_xp, &stdout_id );
    762         error3 = vfs_open( XPTR_NULL, CONFIG_DEV_STDERR, O_WRONLY, 0, &stderr_xp, &stderr_id );
    763 
    764         assert( ((error1 == 0) && (error2 == 0) && (error3 == 0)) , __FUNCTION__ ,
    765             "cannot open stdin/stdout/stderr pseudo files\n");
    766 
    767     assert( ((stdin_id == 0) && (stdout_id == 1) && (stderr_id == 2)) , __FUNCTION__ ,
    768             "bad indexes for stdin/stdout/stderr\n");
     820    xptr_t        parent_xp;     // extended pointer on parent process.
     821    error_t       error;
     822
     823process_dmsg("\n[DBG] %s : enters in cluster %x\n",
     824__FUNCTION__ , local_cxy );
     825
     826    // parent process is local kernel process
     827    parent_xp = XPTR( local_cxy , &process_zero );
    769828
    770829    // initialize the exec_info structure
    771     exec_info.parent_xp    = XPTR( local_cxy , &process_zero );
     830    exec_info.keep_pid     = false;
     831    exec_info.parent_xp    = parent_xp;
    772832    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
    773833    exec_info.args_nr      = 0;
    774834    exec_info.envs_nr      = 0;
    775835
    776     // create process_init and thread_init
    777         error1 = process_make_exec( &exec_info );
    778 
    779         assert( (error1 == 0) , __FUNCTION__ , "cannot create process_init\n");
    780 
    781         process_dmsg("\n[DMSG] %s : exit in cluster %x\n", __FUNCTION__ , local_cxy );
     836    // initialize process_init and create thread_init
     837        error = process_make_exec( &exec_info );
     838
     839        if( error ) panic("cannot initialize process_init in cluster %x", local_cxy );
     840
     841process_dmsg("\n[DBG] %s : exit in cluster %x\n",
     842__FUNCTION__ , local_cxy );
    782843               
    783844    hal_fence();
Note: See TracChangeset for help on using the changeset viewer.