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

Fix several bugs in the fork() syscall.

File:
1 edited

Legend:

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

    r407 r408  
    116116// - thread_user_fork()
    117117// - thread_kernel_create()
    118 // - thread_user_init()
    119118/////////////////////////////////////////////////////////////////////////////////////
    120119// @ thread       : pointer on thread descriptor
     
    200199        thread->signature = THREAD_SIGNATURE;
    201200
     201    // FIXME call hal_thread_init() function to initialise the save_sr field
     202    thread->save_sr = 0xFF13;
     203
    202204    // update local DQDT
    203205    dqdt_local_update_threads( 1 );
     
    322324    }
    323325
     326        // update DQDT for new thread
     327    dqdt_local_update_threads( 1 );
     328
    324329thread_dmsg("\n[DBG] %s : core[%x,%d] exit / trdid = %x / process %x / core = %d\n",
    325330__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid,
     
    331336}  // end thread_user_create()
    332337
    333 ////////////////////////////////////////////////////
    334 error_t thread_user_fork( process_t * process,
    335                           intptr_t    stack_base,
    336                           uint32_t    stack_size,
    337                           thread_t ** new_thread )
     338///////////////////////////////////////////////////////
     339error_t thread_user_fork( xptr_t      parent_thread_xp,
     340                          process_t * child_process,
     341                          thread_t ** child_thread )
    338342{
    339343    error_t        error;
    340         thread_t     * child;       // pointer on new thread descriptor
    341     lid_t          core_lid;     // selected core local index
    342 
    343 thread_dmsg("\n[DBG] %s : core[%x,%d] enters\n",
    344 __FUNCTION__ , local_cxy , core_lid );
     344        thread_t     * child_ptr;        // local pointer on local child thread
     345    lid_t          core_lid;         // selected core local index
     346
     347    thread_t     * parent_ptr;       // local pointer on remote parent thread
     348    cxy_t          parent_cxy;       // parent thread cluster
     349    process_t    * parent_process;   // local pointer on parent process
     350    xptr_t         parent_gpt_xp;    // extended pointer on parent thread GPT
     351
     352    void         * func;             // parent thread entry_func
     353    void         * args;             // parent thread entry_args
     354    intptr_t       base;             // parent thread u_stack_base
     355    uint32_t       size;             // parent thread u_stack_size
     356    uint32_t       flags;            // parent_thread flags
     357    vpn_t          vpn_base;         // parent thread stack vpn_base
     358    vpn_t          vpn_size;         // parent thread stack vpn_size
     359    reg_t        * uzone;            // parent thread pointer on uzone 
     360
     361    vseg_t       * vseg;             // child thread STACK vseg
     362
     363thread_dmsg("\n[DBG] %s : core[%x,%d] enters at cycle %d\n",
     364__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , hal_get_cycles() );
    345365
    346366    // select a target core in local cluster
    347367    core_lid = cluster_select_local_core();
    348368
    349     // get pointer on parent thread descriptor
    350     thread_t * parent = CURRENT_THREAD;
    351 
    352     // allocate memory for new thread descriptor
    353     child = thread_alloc();
    354 
    355     if( child == NULL )
     369    // get cluster and local pointer on parent thread descriptor
     370    parent_cxy = GET_CXY( parent_thread_xp );
     371    parent_ptr = (thread_t *)GET_PTR( parent_thread_xp );
     372
     373    // get relevant fields from parent thread
     374    func  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_func   ) );
     375    args  = (void *)  hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->entry_args   ) );
     376    base  = (intptr_t)hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->u_stack_base ) );
     377    size  = (uint32_t)hal_remote_lw ( XPTR( parent_cxy , &parent_ptr->u_stack_size ) );
     378    flags =           hal_remote_lw ( XPTR( parent_cxy , &parent_ptr->flags        ) );
     379    uzone = (reg_t *) hal_remote_lpt( XPTR( parent_cxy , &parent_ptr->uzone        ) );
     380
     381    vpn_base = base >> CONFIG_PPM_PAGE_SHIFT;
     382    vpn_size = size >> CONFIG_PPM_PAGE_SHIFT;
     383
     384    // get pointer on parent process in parent thread cluster
     385    parent_process = (process_t *)hal_remote_lpt( XPTR( parent_cxy,
     386                                                        &parent_ptr->process ) );
     387 
     388    // get extended pointer on parent GPT in parent thread cluster
     389    parent_gpt_xp = XPTR( parent_cxy , &parent_process->vmm.gpt );
     390
     391    // allocate memory for child thread descriptor
     392    child_ptr = thread_alloc();
     393    if( child_ptr == NULL )
    356394    {
    357395        printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ );
    358         return ENOMEM;
     396        return -1;
    359397    }
    360398
    361399    // initialize thread descriptor
    362     error = thread_init( child,
    363                          process,
     400    error = thread_init( child_ptr,
     401                         child_process,
    364402                         THREAD_USER,
    365                          parent->entry_func,
    366                          parent->entry_args,
     403                         func,
     404                         args,
    367405                         core_lid,
    368                          stack_base,
    369                          stack_size );
    370 
     406                         base,
     407                         size );
    371408    if( error )
    372409    {
    373             printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
    374         thread_release( child );
     410            printk("\n[ERROR] in %s : cannot initialize child thread\n", __FUNCTION__ );
     411        thread_release( child_ptr );
    375412        return EINVAL;
    376413    }
    377414
    378415    // return child pointer
    379     *new_thread = child;
    380 
    381     // set DETACHED flag if required
    382     if( parent->flags & THREAD_FLAG_DETACHED ) child->flags = THREAD_FLAG_DETACHED;
     416    *child_thread = child_ptr;
     417
     418    // set detached flag if required
     419    if( flags & THREAD_FLAG_DETACHED ) child_ptr->flags = THREAD_FLAG_DETACHED;
     420
     421    // update uzone pointer in child thread descriptor
     422    child_ptr->uzone = (char *)((intptr_t)uzone +
     423                                (intptr_t)child_ptr -
     424                                (intptr_t)parent_ptr );
     425 
    383426
    384427    // allocate CPU context for child thread
    385         if( hal_cpu_context_alloc( child ) )
     428        if( hal_cpu_context_alloc( child_ptr ) )
    386429    {
    387430            printk("\n[ERROR] in %s : cannot allocate CPU context\n", __FUNCTION__ );
    388         thread_release( child );
    389         return ENOMEM;
     431        thread_release( child_ptr );
     432        return -1;
    390433    }
    391434
    392435    // allocate FPU context for child thread
    393         if( hal_fpu_context_alloc( child ) )
     436        if( hal_fpu_context_alloc( child_ptr ) )
    394437    {
    395438            printk("\n[ERROR] in %s : cannot allocate FPU context\n", __FUNCTION__ );
    396         thread_release( child );
    397         return ENOMEM;
    398     }
    399 
    400     // copy kernel stack content from parent to child thread descriptor
    401     void * dst = (void *)(&child->signature) + 4;
    402     void * src = (void *)(&parent->signature) + 4;
    403     memcpy( dst , src , parent->k_stack_size );
     439        thread_release( child_ptr );
     440        return -1;
     441    }
     442
     443    // create and initialize STACK vseg
     444    vseg = vseg_alloc();
     445    vseg_init( vseg,
     446               VSEG_TYPE_STACK,
     447               base,
     448               size,
     449               vpn_base,
     450               vpn_size,
     451               0, 0, XPTR_NULL,                         // not a file vseg
     452               local_cxy );
     453
     454    // register STACK vseg in local child VSL
     455    vseg_attach( &child_process->vmm , vseg );
     456
     457    // copy all valid STACK GPT entries   
     458    vpn_t          vpn;
     459    bool_t         mapped;
     460    ppn_t          ppn;
     461    for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     462    {
     463        error = hal_gpt_pte_copy( &child_process->vmm.gpt,
     464                                  parent_gpt_xp,
     465                                  vpn,
     466                                  true,                 // set cow
     467                                  &ppn,
     468                                  &mapped );
     469        if( error )
     470        {
     471            vseg_detach( &child_process->vmm , vseg );
     472            vseg_free( vseg );
     473            thread_release( child_ptr );
     474            printk("\n[ERROR] in %s : cannot update child GPT\n", __FUNCTION__ );
     475            return -1;
     476        }
     477
     478        // increment page descriptor fork_nr for the referenced page if mapped
     479        if( mapped )
     480        {
     481            xptr_t   page_xp  = ppm_ppn2page( ppn );
     482            cxy_t    page_cxy = GET_CXY( page_xp );
     483            page_t * page_ptr = (page_t *)GET_PTR( page_xp );
     484            hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->fork_nr ) , 1 );
     485
     486thread_dmsg("\n[DBG] %s : core[%x,%d] copied PTE to child GPT : vpn %x\n",
     487__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn );
     488
     489        }
     490    }
     491
     492    // set COW flag for STAK vseg in parent thread GPT
     493    hal_gpt_flip_cow( true,                               // set cow
     494                      parent_gpt_xp,
     495                      vpn_base,
     496                      vpn_size );
     497 
     498        // update DQDT for child thread
     499    dqdt_local_update_threads( 1 );
    404500
    405501thread_dmsg("\n[DBG] %s : core[%x,%d] exit / created main thread %x for process %x\n",
    406 __FUNCTION__, local_cxy , core_lid , child->trdid , process->pid );
     502__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, child_ptr->trdid, child_process->pid );
    407503
    408504        return 0;
     
    452548        hal_cpu_context_create( thread );
    453549
     550        // update DQDT for kernel thread
     551    dqdt_local_update_threads( 1 );
     552
    454553thread_dmsg("\n[DBG] %s : core = [%x,%d] exit / trdid = %x / type %s / cycle %d\n",
    455554__FUNCTION__, local_cxy, core_lid, thread->trdid, thread_type_str(type), hal_time_stamp() );
     
    511610
    512611    // update intrumentation values
    513     uint32_t pgfaults = thread->info.pgfault_nr;
    514     uint32_t u_errors = thread->info.u_err_nr;
    515     uint32_t m_errors = thread->info.m_err_nr;
    516 
    517         process->vmm.pgfault_nr += pgfaults;
    518         process->vmm.u_err_nr   += u_errors;
    519         process->vmm.m_err_nr   += m_errors;
     612        process->vmm.pgfault_nr += thread->info.pgfault_nr;
    520613
    521614    // release memory allocated for CPU context and FPU context
     
    635728    {
    636729        this->flags &= ~THREAD_FLAG_SCHED;
    637         sched_yield();
     730        sched_yield( "delayed scheduling" );
    638731    }
    639732
     
    697790
    698791    // deschedule
    699     sched_yield();
     792    sched_yield( "exit" );
    700793    return 0;
    701794
     
    721814    while( 1 )
    722815    {
     816        // unmask IRQs
     817        hal_enable_irq( NULL );
     818
    723819        if( CONFIG_THREAD_IDLE_MODE_SLEEP ) // force core to low-power mode
    724820        {
     
    740836
    741837        // force scheduling at each iteration
    742         sched_yield();
     838        sched_yield( "idle" );
    743839   }
    744840}  // end thread_idle()
     
    754850///////////////////////////////////////////////////
    755851void thread_kernel_time_update( thread_t * thread )
    756 {
    757     // TODO
    758     // printk("\n[WARNING] function %s not implemented\n", __FUNCTION__ );
    759 }
    760 
    761 ////////////////////////////////////////////////
    762 void thread_signals_handle( thread_t * thread )
    763852{
    764853    // TODO
Note: See TracChangeset for help on using the changeset viewer.