Ignore:
Timestamp:
Apr 10, 2019, 10:09:39 AM (19 months ago)
Author:
alain
Message:

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/tsar_mips32/core/hal_context.c

    r570 r625  
    152152    {
    153153        context->a0_04   = (uint32_t)thread->entry_args;
    154         context->sp_29   = (uint32_t)thread->u_stack_base + (uint32_t)thread->u_stack_size - 8;
     154        context->sp_29   = (uint32_t)thread->user_stack_vseg->max - 8;
    155155        context->ra_31   = (uint32_t)&hal_kentry_eret;
    156156        context->c0_epc  = (uint32_t)thread->entry_func;
     
    175175void hal_cpu_context_fork( xptr_t child_xp )
    176176{
    177     // allocate a local CPU context in kernel stack
    178     // It is initialized from local parent context
    179     // and from child specific values, and is copied in
    180     // in the remote child context using a remote_memcpy()
     177    // get pointer on calling thread
     178    thread_t * this = CURRENT_THREAD;
     179
     180    // allocate a local CPU context in parent kernel stack
    181181    hal_cpu_context_t  context;
    182182
    183     // get local parent thread local pointer
     183    // get local parent thread cluster and local pointer
     184    cxy_t      parent_cxy = local_cxy;
    184185    thread_t * parent_ptr = CURRENT_THREAD;
    185186
     
    188189    thread_t * child_ptr = GET_PTR( child_xp );
    189190
    190     // get remote child cpu_context local pointer
     191    // get local pointer on remote child cpu context
    191192    char * child_context_ptr = hal_remote_lpt( XPTR(child_cxy , &child_ptr->cpu_context) );
    192193
    193194    // get local pointer on remote child process
    194     process_t * process = (process_t *)hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );
     195    process_t * process = hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );
    195196
    196197    // get ppn of remote child process page table
    197     uint32_t    pt_ppn = hal_remote_l32( XPTR(child_cxy , &process->vmm.gpt.ppn) );
    198 
    199     // save CPU registers in local CPU context
     198    uint32_t pt_ppn = hal_remote_l32( XPTR(child_cxy , &process->vmm.gpt.ppn) );
     199
     200    // get local pointer on parent uzone from parent thread descriptor
     201    uint32_t * parent_uzone = parent_ptr->uzone_current;
     202
     203    // compute  local pointer on child uzone
     204    uint32_t * child_uzone  = (uint32_t *)( (intptr_t)parent_uzone +
     205                                            (intptr_t)child_ptr    -
     206                                            (intptr_t)parent_ptr  );
     207
     208    // update the uzone pointer in child thread descriptor
     209    hal_remote_spt( XPTR( child_cxy , &child_ptr->uzone_current ) , child_uzone );
     210
     211#if DEBUG_HAL_CONTEXT
     212uint32_t cycle = (uint32_t)hal_get_cycles();
     213if( DEBUG_HAL_CONTEXT < cycle )
     214printk("\n[%s] thread[%x,%x] parent_uzone %x / child_uzone %x / cycle %d\n",
     215__FUNCTION__, this->process->pid, this->trdid, parent_uzone, child_uzone, cycle );
     216#endif
     217
     218    // copy parent kernel stack to child thread descriptor
     219    // (this includes the uzone, that is allocated in the kernel stack)
     220    char * parent_ksp = (char *)hal_get_sp();
     221    char * child_ksp  = (char *)((intptr_t)parent_ksp +
     222                                 (intptr_t)child_ptr  -
     223                                 (intptr_t)parent_ptr );
     224
     225    uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_ksp;
     226
     227    hal_remote_memcpy( XPTR( child_cxy , child_ksp ),
     228                       XPTR( local_cxy , parent_ksp ),
     229                       size );
     230
     231#if DEBUG_HAL_CONTEXT
     232cycle = (uint32_t)hal_get_cycles();
     233printk("\n[%s] thread[%x,%x] copied kstack from parent %x to child %x / cycle %d\n",
     234__FUNCTION__, this->process->pid, this->trdid, parent_ptr, child_ptr, cycle );
     235#endif
     236
     237    // patch the user stack pointer slot in the child uzone[UZ_SP]
     238    // because parent and child use the same offset to access the user stack,
     239    // but parent and child do not have the same user stack base address.
     240    uint32_t parent_us_base = parent_ptr->user_stack_vseg->min;
     241    vseg_t * child_us_vseg  = hal_remote_lpt( XPTR( child_cxy , &child_ptr->user_stack_vseg ) );
     242    uint32_t child_us_base  = hal_remote_l32( XPTR( child_cxy , &child_us_vseg->min ) );
     243    uint32_t parent_usp     = parent_uzone[UZ_SP];
     244    uint32_t child_usp      = parent_usp + child_us_base - parent_us_base;
     245
     246    hal_remote_s32( XPTR( child_cxy , &child_uzone[UZ_SP] ) , child_usp );
     247
     248#if DEBUG_HAL_CONTEXT
     249cycle = (uint32_t)hal_get_cycles();
     250printk("\n[%s] thread[%x,%x] parent_usp %x / child_usp %x / cycle %d\n",
     251__FUNCTION__, this->process->pid, this->trdid, parent_usp, child_usp, cycle );
     252#endif
     253
     254    // save current values of CPU registers to local CPU context
    200255    hal_do_cpu_save( &context );
    201256
    202     // From this point, both parent and child threads execute the following code.
    203     // They can be distinguished by the CURRENT_THREAD value, and child will only
    204     // execute it when it is unblocked by parent, after return to sys_fork().
    205     // - parent thread copies user stack, and patch sp_29 / c0_th / C0_sr / c2_ptpr
    206     // - child thread does nothing
    207 
    208     thread_t * current = CURRENT_THREAD;
    209 
    210     if( current == parent_ptr )    // current == parent thread
     257    // From this point, both parent and child can execute the following code,
     258    // but child thread will only execute it after being unblocked by parent thread.
     259    // They can be distinguished by the (CURRENT_THREAD,local_cxy) values,
     260    // and we must re-initialise the calling thread pointer from c0_th register
     261
     262    this = CURRENT_THREAD;
     263
     264    if( (this == parent_ptr) && (local_cxy == parent_cxy) )   // parent thread
    211265    {
    212         // get parent and child stack pointers
    213         char * parent_sp = (char *)context.sp_29;
    214         char * child_sp  = (char *)((intptr_t)parent_sp +
    215                                     (intptr_t)child_ptr -
    216                                     (intptr_t)parent_ptr );
    217  
    218         // patch kernel_stack pointer, current thread, and status slots
    219         context.sp_29   = (uint32_t)child_sp;
     266        // patch 4 slots in the local CPU context: the sp_29 / c0_th / C0_sr / c2_ptpr
     267        // slots are not identical in parent and child
     268        context.sp_29   = context.sp_29 + (intptr_t)child_ptr - (intptr_t)parent_ptr;
    220269        context.c0_th   = (uint32_t)child_ptr;
    221270        context.c0_sr   = SR_SYS_MODE;
    222271        context.c2_ptpr = pt_ppn >> 1;
    223272
    224         // copy local context to remote child context)
     273        // copy this patched context to remote child context
    225274        hal_remote_memcpy( XPTR( child_cxy , child_context_ptr ),
    226275                           XPTR( local_cxy  , &context ) ,
    227276                           sizeof( hal_cpu_context_t ) );
    228 
    229         // copy kernel stack content from local parent thread to remote child thread
    230         uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_sp;
    231         hal_remote_memcpy( XPTR( child_cxy , child_sp ),
    232                            XPTR( local_cxy , parent_sp ),
    233                            size );
     277#if DEBUG_HAL_CONTEXT
     278cycle = (uint32_t)hal_get_cycles();
     279printk("\n[%s] thread[%x,%x] copied CPU context to child / cycle %d\n",
     280__FUNCTION__, this->process->pid, this->trdid, cycle );
     281#endif
     282
     283        // parent thread unblock child thread
     284        thread_unblock( XPTR( child_cxy , child_ptr ) , THREAD_BLOCKED_GLOBAL );
     285
     286#if DEBUG_HAL_CONTEXT
     287cycle = (uint32_t)hal_get_cycles();
     288printk("\n[%s] thread[%x,%x] unblocked child thread / cycle %d\n",
     289__FUNCTION__, this->process->pid, this->trdid, cycle );
     290#endif
     291
    234292    }
    235     else                           // current == child thread
    236     {
    237         assert( (current == child_ptr) , "current = %x / child = %x\n");
    238     }
     293
    239294}  // end hal_cpu_context_fork()
    240295
     
    285340void hal_cpu_context_destroy( thread_t * thread )
    286341{
    287     kmem_req_t  req;
    288 
    289     req.type = KMEM_CPU_CTX;
    290     req.ptr  = thread->cpu_context;
    291     kmem_free( &req );
     342    kmem_req_t          req;
     343
     344    hal_cpu_context_t * ctx = thread->cpu_context;
     345
     346    // release CPU context if required
     347    if( ctx != NULL )
     348    {   
     349        req.type = KMEM_CPU_CTX;
     350        req.ptr  = ctx;
     351        kmem_free( &req );
     352    }
    292353
    293354}  // end hal_cpu_context_destroy()
     
    348409    kmem_req_t  req;
    349410
    350     req.type = KMEM_FPU_CTX;
    351     req.ptr  = thread->fpu_context;
    352     kmem_free( &req );
     411    hal_fpu_context_t * context = thread->fpu_context;
     412
     413    // release FPU context if required
     414    if( context != NULL )
     415    {   
     416        req.type = KMEM_FPU_CTX;
     417        req.ptr  = context;
     418        kmem_free( &req );
     419    }
    353420
    354421}  // end hal_fpu_context_destroy()
Note: See TracChangeset for help on using the changeset viewer.