Changeset 635


Ignore:
Timestamp:
Jun 26, 2019, 11:42:37 AM (5 years ago)
Author:
alain
Message:

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

Location:
trunk
Files:
81 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/generic/hal_gpt.h

    r632 r635  
    181181 * @ src_gpt_xp   : [in]  extended pointer on remote source GPT.
    182182 * @ src_vpn      : [in]  vpn defining the PTE in the source GPT.
    183  * @ cow          : [in]  activate the COPY-On-Write mechanism if true.
     183 * @ cow          : [in]  set COW flag & reset WRITABLE flag if true.
    184184 * @ ppn          : [out] PPN value (only if mapped is true).
    185185 * @ mapped       : [out] true if src_gpt[vpn] actually copied to dst_gpt[vpn].
  • trunk/hal/generic/hal_vmm.h

    r625 r635  
    6464 * It displays all valit GPT entries when the <mapping> argument is true.
    6565 ****************************************************************************************
    66  * @ process   : local pointer on user process descriptor.
    67  * @ return 0 if success / return ENOMEM if failure.
     66 * @ process_xp   : extended pointer on process descriptor.
     67 * @ mapping      : display all mapped GPT entries when true.
    6868 ***************************************************************************************/
    69 void hal_vmm_display( struct process_s * process,
    70                       bool_t             mapping );
     69void hal_vmm_display( xptr_t   process_xp,
     70                      bool_t   mapping );
    7171
    7272
  • trunk/hal/tsar_mips32/core/hal_context.c

    r625 r635  
    22 * hal_context.c - implementation of Thread Context API for TSAR-MIPS32
    33 *
    4  * Author  Alain Greiner    (2016)
     4 * Author  Alain Greiner    (2016,2017,2018,2019)
    55 *
    66 * Copyright (c)  UPMC Sorbonne Universites
     
    3030#include <printk.h>
    3131#include <vmm.h>
     32#include <bits.h>
    3233#include <core.h>
    3334#include <cluster.h>
     
    3637
    3738/////////////////////////////////////////////////////////////////////////////////////////
    38 //       Define various SR initialisation values for TSAR-MIPS32
     39//       Define various SR initialisation values for the TSAR-MIPS32 architecture.
    3940/////////////////////////////////////////////////////////////////////////////////////////
    4041
     
    4445
    4546/////////////////////////////////////////////////////////////////////////////////////////
    46 // This structure defines the CPU context for TSAR MIPS32.
     47// This structure defines the CPU context for the TSAR-MIPS32 architecture.
    4748// The following registers are saved/restored at each context switch:
    4849// - GPR : all, but (zero, k0, k1), plus (hi, lo)
     
    5152//
    5253// WARNING : check the two CONFIG_CPU_CTX_SIZE & CONFIG_FPU_CTX_SIZE configuration
    53 //           parameterss when modifying this structure.
     54//           parameters when modifying this structure.
    5455/////////////////////////////////////////////////////////////////////////////////////////
    5556
     
    101102
    102103/////////////////////////////////////////////////////////////////////////////////////////
    103 // This structure defines the fpu_context for TSAR MIPS32.
     104// This structure defines the fpu_context for the TSAR MIPS32 architecture.
    104105/////////////////////////////////////////////////////////////////////////////////////////
    105106
     
    124125    // allocate memory for cpu_context
    125126    kmem_req_t  req;
    126     req.type   = KMEM_CPU_CTX;
     127    req.type   = KMEM_KCM;
     128    req.order  = bits_log2( sizeof(hal_cpu_context_t) );
    127129    req.flags  = AF_KERNEL | AF_ZERO;
    128130
    129     hal_cpu_context_t * context = (hal_cpu_context_t *)kmem_alloc( &req );
     131    hal_cpu_context_t * context = kmem_alloc( &req );
     132
    130133    if( context == NULL ) return -1;
    131134
     
    175178void hal_cpu_context_fork( xptr_t child_xp )
    176179{
    177     // get pointer on calling thread
    178     thread_t * this = CURRENT_THREAD;
    179 
     180    cxy_t               parent_cxy;        // parent thread cluster
     181    thread_t          * parent_ptr;        // local pointer on parent thread
     182    hal_cpu_context_t * parent_context;    // local pointer on parent cpu_context
     183    uint32_t          * parent_uzone;      // local_pointer on parent uzone (in kernel stack)
     184    char              * parent_ksp;        // kernel stack pointer on parent kernel stack
     185    uint32_t            parent_us_base;    // parent user stack base value
     186
     187    cxy_t               child_cxy;         // parent thread cluster
     188    thread_t          * child_ptr;         // local pointer on child thread
     189    hal_cpu_context_t * child_context;     // local pointer on child cpu_context
     190    uint32_t          * child_uzone;       // local_pointer on child uzone (in kernel stack)
     191    char              * child_ksp;         // kernel stack pointer on child kernel stack
     192    uint32_t            child_us_base;     // child user stack base value
     193
     194    process_t         * child_process;     // local pointer on child processs
     195    uint32_t            child_pt_ppn;      // PPN of child process PT1
     196    vseg_t            * child_us_vseg;     // local pointer on child user stack vseg
     197   
    180198    // allocate a local CPU context in parent kernel stack
    181     hal_cpu_context_t  context;
    182 
    183     // get local parent thread cluster and local pointer
    184     cxy_t      parent_cxy = local_cxy;
    185     thread_t * parent_ptr = CURRENT_THREAD;
    186 
    187     // get remote child thread cluster and local pointer
    188     cxy_t      child_cxy = GET_CXY( child_xp );
    189     thread_t * child_ptr = GET_PTR( child_xp );
    190 
    191     // get local pointer on remote child cpu context
    192     char * child_context_ptr = hal_remote_lpt( XPTR(child_cxy , &child_ptr->cpu_context) );
     199    hal_cpu_context_t context;
     200
     201    // get (local) parent thread cluster and local pointer
     202    parent_cxy = local_cxy;
     203    parent_ptr = CURRENT_THREAD;
     204
     205    // get (remote) child thread cluster and local pointer
     206    child_cxy = GET_CXY( child_xp );
     207    child_ptr = GET_PTR( child_xp );
     208
     209    // get local pointer on (local) parent CPU context
     210    parent_context = parent_ptr->cpu_context;
     211
     212    // get local pointer on (remote) child CPU context
     213    child_context = hal_remote_lpt( XPTR(child_cxy , &child_ptr->cpu_context) );
    193214
    194215    // get local pointer on remote child process
    195     process_t * process = hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );
     216    child_process = hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );
    196217
    197218    // get ppn of remote child process page table
    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  );
     219    child_pt_ppn = hal_remote_l32( XPTR(child_cxy , &child_process->vmm.gpt.ppn) );
     220
     221    // get local pointer on local parent uzone (in parent kernel stack)
     222    parent_uzone = parent_ptr->uzone_current;
     223
     224    // compute local pointer on remote child uzone (in child kernel stack)
     225    child_uzone  = (uint32_t *)( (intptr_t)parent_uzone +
     226                                 (intptr_t)child_ptr    -
     227                                 (intptr_t)parent_ptr  );
    207228
    208229    // update the uzone pointer in child thread descriptor
     
    213234if( DEBUG_HAL_CONTEXT < cycle )
    214235printk("\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
     236__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid, parent_uzone, child_uzone, cycle );
     237#endif
     238
     239    // get user stack base for parent thread
     240    parent_us_base = parent_ptr->user_stack_vseg->min;
     241
     242    // get user stack base for child thread
     243    child_us_vseg  = hal_remote_lpt( XPTR( child_cxy , &child_ptr->user_stack_vseg ) );
     244    child_us_base  = hal_remote_l32( XPTR( child_cxy , &child_us_vseg->min ) );
     245
     246#if DEBUG_HAL_CONTEXT
     247if( DEBUG_HAL_CONTEXT < cycle )
     248printk("\n[%s] thread[%x,%x] parent_ustack_base %x / child_ustack_base %x\n",
     249__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid, parent_us_base, child_us_base );
     250#endif
     251
     252    // get current value of kernel stack pointer in parent kernel stack
     253    parent_ksp = (char *)hal_get_sp();
     254
     255    // compute value of kernel stack pointer in child kernel stack
     256    child_ksp  = (char *)((intptr_t)parent_ksp +
     257                          (intptr_t)child_ptr  -
     258                          (intptr_t)parent_ptr );
     259
     260#if DEBUG_HAL_CONTEXT
     261if( DEBUG_HAL_CONTEXT < cycle )
     262printk("\n[%s] thread[%x,%x] parent_ksp %x / child_ksp %x\n",
     263__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid, parent_ksp, child_ksp );
     264#endif
     265
     266    // compute number of bytes to be copied, depending on current value of parent_ksp
     267    uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_ksp;   
     268
     269    // copy parent kernel stack content to child thread descriptor
    219270    // (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 
    227271    hal_remote_memcpy( XPTR( child_cxy , child_ksp ),
    228272                       XPTR( local_cxy , parent_ksp ),
     
    230274
    231275#if DEBUG_HAL_CONTEXT
    232 cycle = (uint32_t)hal_get_cycles();
    233 printk("\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
    249 cycle = (uint32_t)hal_get_cycles();
    250 printk("\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
     276if( DEBUG_HAL_CONTEXT < cycle )
     277printk("\n[%s] thread[%x,%x] copied kstack from parent (%x) to child (%x)\n",
     278__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid, parent_ptr, child_ptr );
     279#endif
     280
     281    // save current values of CPU registers to local copy of CPU context
    255282    hal_do_cpu_save( &context );
    256283
    257     // From this point, both parent and child can execute the following code,
     284    // update  three slots in this local CPU context
     285    context.sp_29   = (uint32_t)child_ksp;
     286    context.c0_th   = (uint32_t)child_ptr;
     287    context.c2_ptpr = (uint32_t)child_pt_ppn >> 1;
     288
     289    // From this point, both parent and child execute the following code,
    258290    // but child thread will only execute it after being unblocked by parent thread.
    259291    // They can be distinguished by the (CURRENT_THREAD,local_cxy) values,
    260292    // and we must re-initialise the calling thread pointer from c0_th register
    261293
    262     this = CURRENT_THREAD;
     294    thread_t * this = CURRENT_THREAD;
    263295
    264296    if( (this == parent_ptr) && (local_cxy == parent_cxy) )   // parent thread
    265297    {
    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;
    269         context.c0_th   = (uint32_t)child_ptr;
    270         context.c0_sr   = SR_SYS_MODE;
    271         context.c2_ptpr = pt_ppn >> 1;
    272 
    273         // copy this patched context to remote child context
    274         hal_remote_memcpy( XPTR( child_cxy , child_context_ptr ),
     298        // parent thread must update four slots in child uzone
     299        // - UZ_TH   : parent and child have different threads descriptors
     300        // - UZ_SP   : parent and child have different user stack base addresses.
     301        // - UZ_PTPR : parent and child use different Generic Page Tables
     302
     303        // parent thread computes values for child thread
     304        uint32_t child_sp    = parent_uzone[UZ_SP]  + child_us_base - parent_us_base;
     305        uint32_t child_th    = (uint32_t)child_ptr;
     306        uint32_t child_ptpr  = (uint32_t)child_pt_ppn >> 1;
     307
     308#if DEBUG_HAL_CONTEXT
     309if( DEBUG_HAL_CONTEXT < cycle )
     310printk("\n[%s] thread[%x,%x] : parent_uz_sp %x / child_uz_sp %x\n",
     311__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid,
     312parent_uzone[UZ_SP], child_sp );
     313#endif
     314
     315        // parent thread updates the child uzone
     316        hal_remote_s32( XPTR( child_cxy , &child_uzone[UZ_SP]   ) , child_sp );
     317        hal_remote_s32( XPTR( child_cxy , &child_uzone[UZ_TH]   ) , child_th );
     318        hal_remote_s32( XPTR( child_cxy , &child_uzone[UZ_PTPR] ) , child_ptpr );
     319
     320        // parent thread copies the local context to remote child context
     321        hal_remote_memcpy( XPTR( child_cxy , child_context ),
    275322                           XPTR( local_cxy  , &context ) ,
    276323                           sizeof( hal_cpu_context_t ) );
    277324#if DEBUG_HAL_CONTEXT
     325if( DEBUG_HAL_CONTEXT < cycle )
     326printk("\n[%s] thread[%x,%x] copied parent CPU context to child CPU context\n",
     327__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid );
     328#endif
     329
     330        // parent thread unblocks child thread
     331        thread_unblock( XPTR( child_cxy , child_ptr ) , THREAD_BLOCKED_GLOBAL );
     332
     333#if DEBUG_HAL_CONTEXT
    278334cycle = (uint32_t)hal_get_cycles();
    279 printk("\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
    287 cycle = (uint32_t)hal_get_cycles();
    288 printk("\n[%s] thread[%x,%x] unblocked child thread / cycle %d\n",
    289 __FUNCTION__, this->process->pid, this->trdid, cycle );
     335trdid_t child_trdid = hal_remote_l32( XPTR( child_cxy , &child_ptr->trdid ) );
     336pid_t   child_pid   = hal_remote_l32( XPTR( child_cxy , &child_process->pid ) );
     337printk("\n[%s] thread[%x,%x] unblocked child thread[%x,%x] / cycle %d\n",
     338__FUNCTION__, parent_ptr->process->pid, parent_ptr->trdid, child_pid, child_trdid, cycle );
    290339#endif
    291340
     
    347396    if( ctx != NULL )
    348397    {   
    349         req.type = KMEM_CPU_CTX;
     398        req.type = KMEM_KCM;
    350399        req.ptr  = ctx;
    351400        kmem_free( &req );
     
    366415    // allocate memory for fpu_context
    367416    kmem_req_t  req;
    368     req.type   = KMEM_FPU_CTX;
     417    req.type   = KMEM_KCM;
    369418    req.flags  = AF_KERNEL | AF_ZERO;
    370 
    371     hal_fpu_context_t * context = (hal_fpu_context_t *)kmem_alloc( &req );
     419    req.order  = bits_log2( sizeof(hal_fpu_context_t) );
     420
     421    hal_fpu_context_t * context = kmem_alloc( &req );
     422
    372423    if( context == NULL ) return -1;
    373424
     
    414465    if( context != NULL )
    415466    {   
    416         req.type = KMEM_FPU_CTX;
     467        req.type = KMEM_KCM;
    417468        req.ptr  = context;
    418469        kmem_free( &req );
  • trunk/hal/tsar_mips32/core/hal_exception.c

    r632 r635  
    189189    uint32_t         excp_code;
    190190
    191     // check thread type
    192    if( CURRENT_THREAD->type != THREAD_USER )
    193     {
    194         printk("\n[PANIC] in %s : illegal thread type %s\n",
    195         __FUNCTION__, thread_type_str(CURRENT_THREAD->type) );
    196 
    197         return EXCP_KERNEL_PANIC;
    198     }
    199 
    200191    // get faulty thread process 
    201192    process = this->process;
     
    447438            else                                                // undefined coprocessor
    448439            {
    449                 printk("\n[USER_ERROR] in %s for thread[%x,%x]\n"
     440                printk("\n[USER_ERROR] in %s for thread[%x,%x] / cycle %d\n"
    450441                "   undefined coprocessor / epc %x\n",
    451                 __FUNCTION__, this->process->pid, this->trdid, excPC );
     442                __FUNCTION__, this->process->pid, this->trdid,
     443                (uint32_t)hal_get_cycles() , excPC );
    452444
    453445                        error = EXCP_USER_ERROR;
     
    457449        case XCODE_OVR:    // Arithmetic Overflow : user fatal error
    458450        {
    459             printk("\n[USER_ERROR] in %s for thread[%x,%x]\n"
     451            printk("\n[USER_ERROR] in %s for thread[%x,%x] / cycle %d\n"
    460452            "   arithmetic overflow / epc %x\n",
    461             __FUNCTION__, this->process->pid, this->trdid, excPC );
     453            __FUNCTION__, this->process->pid, this->trdid,
     454            (uint32_t)hal_get_cycles() , excPC );
    462455
    463456                    error = EXCP_USER_ERROR;
     
    466459        case XCODE_RI:     // Reserved Instruction : user fatal error
    467460        {
    468             printk("\n[USER_ERROR] in %s for thread[%x,%x]\n"
     461            printk("\n[USER_ERROR] in %s for thread[%x,%x] / cycle %d\n"
    469462            "   reserved instruction / epc %x\n",
    470             __FUNCTION__, this->process->pid, this->trdid, excPC );
     463            __FUNCTION__, this->process->pid, this->trdid,
     464            (uint32_t)hal_get_cycles() , excPC );
    471465
    472466                    error = EXCP_USER_ERROR;
     
    475469        case XCODE_ADEL:   // user fatal error
    476470        {
    477             printk("\n[USER_ERROR] in %s for thread[%x,%x]\n"
     471            printk("\n[USER_ERROR] in %s for thread[%x,%x] / cycle %d\n"
    478472            "   illegal data load address / epc %x / bad_address %x\n",
    479             __FUNCTION__, this->process->pid, this->trdid, excPC, hal_get_bad_vaddr() );
     473            __FUNCTION__, this->process->pid, this->trdid,
     474            (uint32_t)hal_get_cycles(), excPC, hal_get_bad_vaddr() );
    480475
    481476                    error = EXCP_USER_ERROR;
     
    484479        case XCODE_ADES:   //   user fatal error
    485480        {
    486             printk("\n[USER_ERROR] in %s for thread[%x,%x]\n"
     481            printk("\n[USER_ERROR] in %s for thread[%x,%x] / cycle %d\n"
    487482            "   illegal data store address / epc %x / bad_address %x\n",
    488             __FUNCTION__, this->process->pid, this->trdid, excPC, hal_get_bad_vaddr() );
     483            __FUNCTION__, this->process->pid, this->trdid,
     484            (uint32_t)hal_get_cycles(), excPC, hal_get_bad_vaddr() );
    489485
    490486                    error = EXCP_USER_ERROR;
  • trunk/hal/tsar_mips32/core/hal_gpt.c

    r633 r635  
    22 * hal_gpt.c - implementation of the Generic Page Table API for TSAR-MIPS32
    33 *
    4  * Author   Alain Greiner (2016,2017,2018)
     4 * Author   Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    7070#define TSAR_MMU_IX2_FROM_VPN( vpn )       (vpn & 0x1FF)
    7171
    72 #define TSAR_MMU_PTBA_FROM_PTE1( pte1 )    (pte1 & 0x0FFFFFFF)
    73 #define TSAR_MMU_PPN_FROM_PTE1( pte1 )     ((pte1 & 0x0007FFFF)<<9)
     72#define TSAR_MMU_PPN2_FROM_PTE1( pte1 )    (pte1 & 0x0FFFFFFF)
     73#define TSAR_MMU_PPN1_FROM_PTE1( pte1 )    ((pte1 & 0x0007FFFF)<<9)
    7474#define TSAR_MMU_ATTR_FROM_PTE1( pte1 )    (pte1 & 0xFFC00000)
    7575
     
    138138error_t hal_gpt_create( gpt_t * gpt )
    139139{
    140         page_t   * page;
    141     xptr_t     page_xp;
     140    void * base;
    142141
    143142    thread_t * this = CURRENT_THREAD;
     
    146145uint32_t cycle = (uint32_t)hal_get_cycles();
    147146if( DEBUG_HAL_GPT_CREATE < cycle )
    148 printk("\n[%s] : thread[%x,%x] enter / cycle %d\n",
     147printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    149148__FUNCTION__, this->process->pid, this->trdid, cycle );
    150149#endif
    151150
    152151// check page size
    153 assert( (CONFIG_PPM_PAGE_SIZE == 4096) , "for TSAR, the page size must be 4 Kbytes\n" );
     152assert( (CONFIG_PPM_PAGE_SIZE == 4096) , "the TSAR page size must be 4 Kbytes\n" );
    154153
    155154    // allocates 2 physical pages for PT1
    156155        kmem_req_t req;
    157         req.type  = KMEM_PAGE;
    158         req.size = 1;                     // 2 small pages
     156        req.type  = KMEM_PPM;
     157        req.order = 1;                     // 2 small pages
    159158        req.flags = AF_KERNEL | AF_ZERO;
    160         page = (page_t *)kmem_alloc( &req );
    161 
    162         if( page == NULL )
     159        base = kmem_alloc( &req );
     160
     161        if( base == NULL )
    163162    {
    164163        printk("\n[PANIC] in %s : no memory for PT1 / process %x / cluster %x\n",
     
    167166    }
    168167
    169     // initialize generic page table descriptor
    170     page_xp   = XPTR( local_cxy , page );
    171         gpt->ptr  = GET_PTR( ppm_page2base( page_xp ) );
    172         gpt->ppn  = ppm_page2ppn( page_xp );
     168    gpt->ptr = base;
     169        gpt->ppn = ppm_base2ppn( XPTR( local_cxy , base ) );
    173170
    174171#if DEBUG_HAL_GPT_CREATE
    175172cycle = (uint32_t)hal_get_cycles();
    176173if( DEBUG_HAL_GPT_CREATE < cycle )
    177 printk("\n[%s] : thread[%x,%x] exit / cycle %d\n",
    178 __FUNCTION__, this->process->pid, this->trdid, cycle );
     174printk("\n[%s] thread[%x,%x] exit / pt1_base %x / pt1_ppn %x / cycle %d\n",
     175__FUNCTION__, this->process->pid, this->trdid, gpt->ptr, gpt->ppn, cycle );
    179176#endif
    180177
     
    199196thread_t * this  = CURRENT_THREAD;
    200197if( DEBUG_HAL_GPT_DESTROY < cycle )
    201 printk("\n[%s] : thread[%x,%x] enter / cycle %d\n",
     198printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
    202199__FUNCTION__, this->process->pid, this->trdid, cycle );
    203200#endif
     
    221218            {
    222219                // get local pointer on PT2
    223                 pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    224                 xptr_t base_xp = ppm_ppn2base( pt2_ppn );
    225                 pt2     = GET_PTR( base_xp );
     220                pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
     221                pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    226222
    227223                // scan the PT2
     
    238234
    239235                // release the page allocated for the PT2
    240                 req.type = KMEM_PAGE;
    241                 req.ptr  = GET_PTR( ppm_base2page( XPTR(local_cxy , pt2 ) ) );
     236                req.type = KMEM_PPM;
     237                req.ptr  = pt2;
    242238                kmem_free( &req );
    243239            }
     
    246242
    247243    // release the PT1
    248     req.type = KMEM_PAGE;
    249     req.ptr  = GET_PTR( ppm_base2page( XPTR(local_cxy , pt1 ) ) );
     244    req.type = KMEM_PPM;
     245    req.ptr  = pt1;
    250246    kmem_free( &req );
    251247
     
    253249cycle = (uint32_t)hal_get_cycles();
    254250if( DEBUG_HAL_GPT_DESTROY < cycle )
    255 printk("\n[%s] : thread[%x,%x] exit / cycle %d\n",
     251printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    256252__FUNCTION__, this->process->pid, this->trdid, cycle );
    257253#endif
    258254
    259255} // end hal_gpt_destroy()
    260 
    261 /*
    262 
    263 /////////////////////////////////////////////////////////////////////////////////////
    264 // This static function can be used for debug.
    265 /////////////////////////////////////////////////////////////////////////////////////
    266 static void hal_gpt_display( process_t * process )
    267 {
    268     gpt_t    * gpt;
    269         uint32_t   ix1;
    270         uint32_t   ix2;
    271         uint32_t * pt1;
    272     uint32_t   pte1;
    273     ppn_t      pt2_ppn;
    274     uint32_t * pt2;
    275     uint32_t   pte2_attr;
    276     ppn_t      pte2_ppn;
    277     vpn_t      vpn;
    278 
    279 // check argument
    280 assert( (process != NULL) , "NULL process pointer\n");
    281 
    282     // get pointer on gpt
    283     gpt = &(process->vmm.gpt);
    284 
    285     // get pointer on PT1
    286     pt1 = (uint32_t *)gpt->ptr;
    287 
    288     printk("\n***** Tsar Page Table for process %x : &gpt = %x / &pt1 = %x\n\n",
    289     process->pid , gpt , pt1 );
    290 
    291     // scan the PT1
    292         for( ix1 = 0 ; ix1 < 2048 ; ix1++ )
    293         {
    294         pte1 = pt1[ix1];
    295                 if( (pte1 & TSAR_PTE_MAPPED) != 0 )
    296         {
    297             if( (pte1 & TSAR_PTE_SMALL) == 0 )  // BIG page
    298             {
    299                 vpn = ix1 << 9;
    300                 printk(" - BIG   : vpn = %x / pt1[%d] = %X\n", vpn , ix1 , pte1 );
    301             }
    302             else                           // SMALL pages
    303             {
    304                 pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    305                 xptr_t base_xp = ppm_ppn2base ( pt2_ppn );
    306                 pt2     = GET_PTR( base_xp );
    307 
    308                 // scan the PT2
    309                     for( ix2 = 0 ; ix2 < 512 ; ix2++ )
    310                 {
    311                     pte2_attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
    312                     pte2_ppn  = TSAR_MMU_PPN_FROM_PTE2( pt2[2 * ix2 + 1] );
    313 
    314                             if( (pte2_attr & TSAR_PTE_MAPPED) != 0 )
    315                     {
    316                         vpn = (ix1 << 9) | ix2;
    317                         printk(" - SMALL : vpn %X / ppn %X / attr %X\n",
    318                         vpn , pte2_ppn , tsar2gpt(pte2_attr) );
    319                     }
    320                 }
    321             }
    322         }
    323         }
    324 } // end hal_gpt_display()
    325 
    326 */
    327256
    328257////////////////////////////////////////////
     
    332261                          ppn_t    * ppn )
    333262{
    334     uint32_t          * pt1_ptr;         // local pointer on PT1 base
    335     xptr_t              ptd1_xp;         // extended pointer on PT1[x1] entry
    336         uint32_t            ptd1;            // value of PT1[x1] entry
    337 
    338     xptr_t              page_xp;
    339 
     263    uint32_t          * pt1;             // local pointer on PT1 base
     264    xptr_t              pte1_xp;         // extended pointer on PT1[x1] entry
     265        uint32_t            pte1;            // value of PT1[x1] entry
     266
     267    kmem_req_t          req;             // kmem request fro PT2 allocation
     268
     269    uint32_t          * pt2;             // local pointer on PT2 base
    340270        ppn_t               pt2_ppn;         // PPN of page containing PT2
    341     uint32_t          * pt2_ptr;         // local pointer on PT2 base
    342271        xptr_t              pte2_xp;         // extended pointer on PT2[ix2].attr
    343272    uint32_t            pte2_attr;       // PT2[ix2].attr current value   
     
    357286uint32_t   cycle = (uint32_t)hal_get_cycles();
    358287if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    359 printk("\n[%s] : thread[%x,%x] enters / vpn %x in cluster %x / cycle %d\n",
     288printk("\n[%s] thread[%x,%x] enters / vpn %x in cluster %x / cycle %d\n",
    360289__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
    361290#endif
    362291
    363292    // get indexes in PTI & PT2 from vpn
    364     uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
    365     uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
     293    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     294    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    366295
    367296    // get local pointer on PT1
    368     pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    369 
    370     // build extended pointer on PTD1 == PT1[ix1]
    371         ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     297    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     298
     299    // build extended pointer on PTE1 == PT1[ix1]
     300        pte1_xp = XPTR( gpt_cxy , &pt1[ix1] );
    372301
    373302    // get current PT1 entry value
    374     ptd1 = hal_remote_l32( ptd1_xp );
    375 
    376     // If PTD1 is unmapped and unlocked, try to atomically lock this PT1 entry.
    377     // This PTD1 lock prevent multiple concurrent PT2 allocations
    378     // - only the thread that successfully locked the PTD1 allocates a new PT2
    379     //   and updates the PTD1
    380     // - all other threads simply wait until the missing PTD1 is mapped.
    381 
    382     if( ptd1 == 0 ) 
     303    pte1 = hal_remote_l32( pte1_xp );
     304
     305    // If PTE1 is unmapped and unlocked, try to atomically lock this PT1 entry.
     306    // This PTE1 locking prevent multiple concurrent PT2 allocations
     307    // - only the thread that successfully locked the PTE1 allocates a new PT2
     308    //   and updates the PTE1
     309    // - all other threads simply wait until the missing PTE1 is mapped.
     310
     311    if( pte1 == 0 ) 
    383312        {
    384         // try to atomically lock the PTD1 to prevent concurrent PT2 allocations
    385         atomic = hal_remote_atomic_cas( ptd1_xp,
    386                                         ptd1,
    387                                         ptd1 | TSAR_PTE_LOCKED );
     313        // try to atomically lock the PTE1 to prevent concurrent PT2 allocations
     314        atomic = hal_remote_atomic_cas( pte1_xp,
     315                                        pte1,
     316                                        pte1 | TSAR_PTE_LOCKED );
    388317        if( atomic ) 
    389318                {
    390319            // allocate one 4 Kbytes physical page for PT2
    391             page_xp = ppm_remote_alloc_pages( gpt_cxy , 0 );
    392 
    393             if( page_xp == XPTR_NULL )
     320            req.type  = KMEM_PPM;
     321            req.order = 0; 
     322            req.flags = AF_ZERO | AF_KERNEL;
     323            pt2       = kmem_remote_alloc( gpt_cxy , &req );
     324
     325            if( pt2 == NULL )
    394326            {
    395                 printk("\n[ERROR] in %s : cannot allocate memory for PT2\n", __FUNCTION__ );
     327                printk("\n[ERROR] in %s : cannot allocate memory for PT2 in cluster %d\n",
     328                __FUNCTION__, gpt_cxy );
    396329                return -1;
    397330            }
    398331
    399332            // get the PT2 PPN
    400             pt2_ppn = ppm_page2ppn( page_xp );
    401 
    402             // build  PTD1
    403             ptd1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
    404 
    405             // set the PTD1 value in PT1
    406             // this unlocks the PTD1
    407             hal_remote_s32( ptd1_xp , ptd1 );
     333            pt2_ppn = ppm_base2ppn( XPTR( gpt_cxy , pt2 ) );
     334
     335            // build  PTE1
     336            pte1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | pt2_ppn;
     337
     338            // set the PTE1 value in PT1
     339            // this unlocks the PTE1
     340            hal_remote_s32( pte1_xp , pte1 );
    408341            hal_fence();
    409342
    410343#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
    411344if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    412 printk("\n[%s] : thread[%x,%x] allocates a new PT2 for vpn %x in cluster %x\n",
     345printk("\n[%s] thread[%x,%x] allocates a new PT2 for vpn %x in cluster %x\n",
    413346__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy );
    414347#endif
    415348
    416349        }  // end if atomic
    417     }  // end if (ptd1 == 0)
    418 
    419     // wait until PTD1 is mapped by another thread
    420     while( (ptd1 & TSAR_PTE_MAPPED) == 0 )
     350    }  // end if (pte1 == 0)
     351
     352    // wait until PTE1 is mapped by another thread
     353    while( (pte1 & TSAR_PTE_MAPPED) == 0 )
    421354    {
    422         ptd1 = hal_remote_l32( ptd1_xp );
     355        pte1 = hal_remote_l32( pte1_xp );
    423356
    424357#if GPT_LOCK_WATCHDOG
     
    426359{
    427360    thread_t * thread = CURRENT_THREAD;
    428     printk("\n[PANIC] in %s : thread[%x,%x] waiting PTD1 / vpn %x / cxy %x / %d iterations\n",
     361    printk("\n[PANIC] in %s : thread[%x,%x] waiting PTE1 / vpn %x / cxy %x / %d iterations\n",
    429362    __FUNCTION__, thread->process->pid, thread->trdid, vpn, gpt_cxy, count );
    430363    hal_core_sleep();
     
    435368    }
    436369
    437 // check ptd1 because only small page can be locked
    438 assert( (ptd1 & TSAR_PTE_SMALL), "cannot lock a big page\n");
     370// check pte1 because only small page can be locked
     371assert( (pte1 & TSAR_PTE_SMALL), "cannot lock a big page\n");
    439372
    440373#if (DEBUG_HAL_GPT_LOCK_PTE & 1)
    441374if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    442 printk("\n[%s] : thread[%x,%x] get ptd1 %x for vpn %x in cluster %x\n",
    443 __FUNCTION__, this->process->pid, this->trdid, ptd1, vpn, gpt_cxy );
    444 #endif
    445 
    446     // get pointer on PT2 base from PTD1
    447     pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
    448     pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     375printk("\n[%s] thread[%x,%x] get pte1 %x for vpn %x in cluster %x\n",
     376__FUNCTION__, this->process->pid, this->trdid, pte1, vpn, gpt_cxy );
     377#endif
     378
     379    // get pointer on PT2 base
     380    pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
     381    pt2    = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    449382
    450383    // build extended pointers on PT2[ix2].attr 
    451     pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     384    pte2_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
    452385
    453386    // wait until PTE2 atomically set using a remote CAS
     
    491424cycle = (uint32_t)hal_get_cycles();
    492425if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    493 printk("\n[%s] : thread[%x,%x] exit / vpn %x in cluster %x / attr %x / ppn %x / cycle %d\n",
     426printk("\n[%s] thread[%x,%x] exit / vpn %x in cluster %x / attr %x / ppn %x / cycle %d\n",
    494427__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, pte2_attr, pte2_ppn, cycle );
    495428#endif
     
    506439                         vpn_t   vpn )
    507440{
    508     uint32_t * pt1_ptr;         // local pointer on PT1 base
    509     xptr_t     ptd1_xp;         // extended pointer on PT1[ix1]
    510         uint32_t   ptd1;            // value of PT1[ix1] entry
    511 
     441    uint32_t * pt1;             // local pointer on PT1 base
     442    xptr_t     pte1_xp;         // extended pointer on PT1[ix1]
     443        uint32_t   pte1;            // value of PT1[ix1] entry
     444
     445    uint32_t * pt2;             // PT2 base address
    512446        ppn_t      pt2_ppn;         // PPN of page containing PT2
    513     uint32_t * pt2_ptr;         // PT2 base address
    514447        xptr_t     pte2_xp;         // extended pointer on PT2[ix2].attr
    515448        uint32_t   pte2_attr;       // PTE2 attribute
     
    523456uint32_t   cycle = (uint32_t)hal_get_cycles();
    524457if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    525 printk("\n[%s] : thread[%x,%x] enters for vpn %x in cluster %x / cycle %d\n",
     458printk("\n[%s] thread[%x,%x] enters for vpn %x in cluster %x / cycle %d\n",
    526459__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
    527460#endif
    528461
    529462    // compute indexes in P1 and PT2
    530     uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );    // index in PT1
    531     uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );    // index in PT2
     463    uint32_t  ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
     464    uint32_t  ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    532465
    533466    // get local pointer on PT1
    534     pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    535 
    536     // build extended pointer on PTD1 == PT1[ix1]
    537         ptd1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
    538 
    539     // get current ptd1 value
    540     ptd1 = hal_remote_l32( ptd1_xp );
    541 
    542 // check PTD1 attributes
    543 assert( ((ptd1 & TSAR_PTE_MAPPED) != 0), "unmapped PTE1\n");
    544 assert( ((ptd1 & TSAR_PTE_SMALL ) != 0), "big page PTE1\n");
    545 
    546     // get pointer on PT2 base from PTD1
    547         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( ptd1 );
    548         pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     467    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     468
     469    // build extended pointer on PTE1 == PT1[ix1]
     470        pte1_xp = XPTR( gpt_cxy , &pt1[ix1] );
     471
     472    // get current pte1 value
     473    pte1 = hal_remote_l32( pte1_xp );
     474
     475// check PTE1 attributes
     476assert( ((pte1 & TSAR_PTE_MAPPED) != 0), "unmapped PTE1\n");
     477assert( ((pte1 & TSAR_PTE_SMALL ) != 0), "big page PTE1\n");
     478
     479    // get pointer on PT2 base
     480        pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
     481        pt2    = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    549482
    550483    // build extended pointers on PT2[ix2].attr 
    551     pte2_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
     484    pte2_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
    552485
    553486    // get PT2[ix2].attr
     
    564497cycle = (uint32_t)hal_get_cycles();
    565498if( DEBUG_HAL_GPT_LOCK_PTE < cycle )
    566 printk("\n[%s] : thread[%x,%x] unlocks vpn %x in cluster %x / cycle %d\n",
     499printk("\n[%s] thread[%x,%x] unlocks vpn %x in cluster %x / cycle %d\n",
    567500__FUNCTION__, this->process->pid, this->trdid, vpn, gpt_cxy, cycle );
    568501#endif
     
    580513    gpt_t             * gpt_ptr;             // target GPT local pointer
    581514
    582     uint32_t          * pt1_ptr;             // local pointer on PT1 base
     515    uint32_t          * pt1;                 // local pointer on PT1 base
    583516        xptr_t              pte1_xp;             // extended pointer on PT1 entry
    584517        uint32_t            pte1;                // PT1 entry value if PTE1
    585518
     519        uint32_t          * pt2;                 // local pointer on PT2 base
    586520        ppn_t               pt2_ppn;             // PPN of PT2
    587         uint32_t          * pt2_ptr;             // local pointer on PT2 base
    588521    xptr_t              pte2_attr_xp;        // extended pointer on PT2[ix2].attr
    589522    xptr_t              pte2_ppn_xp;         // extended pointer on PT2[ix2].ppn
     
    604537    ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    605538
    606     pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    607         small   = attr & GPT_SMALL;
     539#if DEBUG_HAL_GPT_SET_PTE
     540thread_t * this  = CURRENT_THREAD;
     541uint32_t   cycle = (uint32_t)hal_get_cycles();
     542if( DEBUG_HAL_GPT_SET_PTE < cycle )
     543printk("\n[%s] thread[%x,%x] enter gpt (%x,%x) / vpn %x / attr %x / ppn %x\n",
     544__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, &gpt_ptr->ptr, vpn, attr, ppn );
     545#endif
     546
     547        small = attr & GPT_SMALL;
     548
     549    // get local pointer on PT1
     550    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    608551
    609552    // compute tsar attributes from generic attributes
     
    611554
    612555    // build extended pointer on PTE1 = PT1[ix1]
    613         pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     556        pte1_xp = XPTR( gpt_cxy , &pt1[ix1] );
    614557
    615558    // get current pte1 value
     
    634577
    635578#if DEBUG_HAL_GPT_SET_PTE
    636 thread_t * this  = CURRENT_THREAD;
    637 uint32_t   cycle = (uint32_t)hal_get_cycles();
    638579if( DEBUG_HAL_GPT_SET_PTE < cycle )
    639 printk("\n[%s] : thread[%x,%x] map PTE1 / cxy %x / ix1 %x / pt1 %x / pte1 %x\n",
    640 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1_ptr, pte1 );
     580printk("\n[%s] thread[%x,%x] map PTE1 / cxy %x / ix1 %x / pt1 %x / pte1 %x\n",
     581__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix1, pt1, pte1 );
    641582#endif
    642583
     
    648589assert( (pte1 & TSAR_PTE_MAPPED), "PTE1 must be mapped\n" );
    649590
    650         // get PT2 base from PTE1
    651             pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    652             pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     591        // get PT2 base
     592            pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
     593            pt2    = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    653594
    654595        // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
    655         pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
    656         pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
     596        pte2_attr_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
     597        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2[2 * ix2 + 1] );
    657598
    658599        // get current value of PTE2.attr
     
    672613uint32_t   cycle = (uint32_t)hal_get_cycles();
    673614if( DEBUG_HAL_GPT_SET_PTE < cycle )
    674 printk("\n[%s] : thread[%x,%x] map PTE2 / cxy %x / ix2 %x / pt2 %x / attr %x / ppn %x\n",
    675 __FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix2, pt2_ptr, tsar_attr, ppn );
     615printk("\n[%s] thread[%x,%x] map PTE2 / cxy %x / ix2 %x / pt2 %x / attr %x / ppn %x\n",
     616__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, ix2, pt2, tsar_attr, ppn );
    676617#endif
    677618
     
    689630    uint32_t   ix2;            // index in PT2
    690631
    691     uint32_t * pt1_ptr;        // PT1 base address
     632    uint32_t * pt1;            // PT1 base address
    692633    xptr_t     pte1_xp;        // extended pointer on PT1[ix1]
    693634    uint32_t   pte1;           // PT1 entry value
    694635
     636    uint32_t * pt2;            // PT2 base address
    695637    ppn_t      pt2_ppn;        // PPN of PT2
    696     uint32_t * pt2_ptr;        // PT2 base address
    697638    xptr_t     pte2_attr_xp;   // extended pointer on PT2[ix2].attr
    698639    xptr_t     pte2_ppn_xp;    // extended pointer on PT2[ix2].ppn
     
    707648
    708649    // get local pointer on PT1 base
    709     pt1_ptr = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
     650    pt1 = hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    710651
    711652    // build extended pointer on PTE1 = PT1[ix1]
    712         pte1_xp = XPTR( gpt_cxy , &pt1_ptr[ix1] );
     653        pte1_xp = XPTR( gpt_cxy , &pt1[ix1] );
    713654
    714655    // get current PTE1 value
     
    729670uint32_t   cycle = (uint32_t)hal_get_cycles();
    730671if( DEBUG_HAL_GPT_RESET_PTE < cycle )
    731 printk("\n[%s] : thread[%x,%x] unmap PTE1 / cxy %x / vpn %x / ix1 %x\n",
     672printk("\n[%s] thread[%x,%x] unmap PTE1 / cxy %x / vpn %x / ix1 %x\n",
    732673__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix1 );
    733674#endif
     
    737678    else                                    // it's a PTE2 => unmap it from PT2
    738679    {
    739         // compute PT2 base address
    740         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
    741         pt2_ptr = GET_PTR( ppm_ppn2base( pt2_ppn ) );
     680        // get PT2 base
     681        pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
     682        pt2    = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    742683       
    743684        // build extended pointer on PT2[ix2].attr and PT2[ix2].ppn
    744         pte2_attr_xp = XPTR( gpt_cxy , &pt2_ptr[2 * ix2] );
    745         pte2_ppn_xp  = XPTR( gpt_cxy , &pt2_ptr[2 * ix2 + 1] );
     685        pte2_attr_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
     686        pte2_ppn_xp  = XPTR( gpt_cxy , &pt2[2 * ix2 + 1] );
    746687
    747688        // unmap the PTE2
     
    755696uint32_t   cycle = (uint32_t)hal_get_cycles();
    756697if( DEBUG_HAL_GPT_RESET_PTE < cycle )
    757 printk("\n[%s] : thread[%x,%x] unmap PTE2 / cxy %x / vpn %x / ix2 %x\n",
     698printk("\n[%s] thread[%x,%x] unmap PTE2 / cxy %x / vpn %x / ix2 %x\n",
    758699__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, vpn, ix2 );
    759700#endif
     
    804745        if( (pte1 & TSAR_PTE_SMALL) == 0 )     // it's a PTE1
    805746        {
    806         // get PPN & ATTR from PT1
     747        // get PPN & ATTR
    807748                *attr = tsar2gpt( TSAR_MMU_ATTR_FROM_PTE1( pte1 ) );
    808         *ppn  = TSAR_MMU_PPN_FROM_PTE1( pte1 ) | (vpn & ((1<<TSAR_MMU_IX2_WIDTH)-1));
     749        *ppn  = TSAR_MMU_PPN1_FROM_PTE1( pte1 ) | (vpn & ((1<<TSAR_MMU_IX2_WIDTH)-1));
    809750        }
    810751    else                                  // it's a PTE2
    811752    {
    812753        // compute PT2 base address
    813         pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     754        pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
    814755        pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    815756
     
    849790        uint32_t   * src_pt1;   // local pointer on SRC PT1
    850791        uint32_t   * dst_pt1;   // local pointer on DST PT1
     792
    851793    uint32_t   * src_pt2;   // local pointer on SRC PT2
    852794    uint32_t   * dst_pt2;   // local pointer on DST PT2
     
    874816thread_t * this  = CURRENT_THREAD;
    875817if( DEBUG_HAL_GPT_COPY < cycle )
    876 printk("\n[%s] : thread[%x,%x] enter / src_cxy %x / dst_cxy %x / cycle %d\n",
     818printk("\n[%s] thread[%x,%x] enter / src_cxy %x / dst_cxy %x / cycle %d\n",
    877819__FUNCTION__, this->process->pid, this->trdid, src_cxy, local_cxy, cycle );
    878820#endif
    879 
    880     // get remote src_gpt cluster and local pointer
    881     src_cxy = GET_CXY( src_gpt_xp );
    882     src_gpt = GET_PTR( src_gpt_xp );
    883821
    884822    // get remote src_pt1 and local dst_pt1
     
    907845        dst_pte1 = dst_pt1[dst_ix1];
    908846
    909         // map dst_pte1 if required
     847        // map dst_pte1 when this entry is not mapped
    910848        if( (dst_pte1 & TSAR_PTE_MAPPED) == 0 )
    911849        {
    912850            // allocate one physical page for a new PT2
    913                 req.type  = KMEM_PAGE;
    914                 req.size = 0;                     // 1 small page
     851                req.type  = KMEM_PPM;
     852                req.order = 0;                     // 1 small page
    915853                req.flags = AF_KERNEL | AF_ZERO;
    916                 page = (page_t *)kmem_alloc( &req );
    917 
    918             if( page == NULL )
     854                dst_pt2   = kmem_alloc( &req );
     855
     856            if( dst_pt2 == NULL )
    919857            {
    920858                        printk("\n[ERROR] in %s : cannot allocate PT2\n", __FUNCTION__ );
     
    926864
    927865            // get PPN for this new PT2
    928             dst_pt2_ppn = (ppn_t)ppm_page2ppn( page_xp );
    929 
    930             // build the new dst_pte1
     866            dst_pt2_ppn = ppm_base2ppn( XPTR( local_cxy , dst_pt2 ) );
     867
     868            // build new dst_pte1
    931869            dst_pte1 = TSAR_PTE_MAPPED | TSAR_PTE_SMALL | dst_pt2_ppn;
    932870
     
    936874
    937875        // get pointer on src_pt2
    938         src_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( src_pte1 );
     876        src_pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( src_pte1 );
    939877        src_pt2     = GET_PTR( ppm_ppn2base( src_pt2_ppn ) );
    940878
    941879        // get pointer on dst_pt2
    942         dst_pt2_ppn = (ppn_t)TSAR_MMU_PTBA_FROM_PTE1( dst_pte1 );
     880        dst_pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( dst_pte1 );
    943881        dst_pt2     = GET_PTR( ppm_ppn2base( dst_pt2_ppn ) );
    944882
     
    970908cycle = (uint32_t)hal_get_cycles;
    971909if( DEBUG_HAL_GPT_COPY < cycle )
    972 printk("\n[%s] : thread[%x,%x] exit / copy done for src_vpn %x / dst_vpn %x / cycle %d\n",
     910printk("\n[%s] thread[%x,%x] exit / copy done for src_vpn %x / dst_vpn %x / cycle %d\n",
    973911__FUNCTION__, this->process->pid, this->trdid, src_vpn, dst_vpn, cycle );
    974912#endif
     
    987925cycle = (uint32_t)hal_get_cycles;
    988926if( DEBUG_HAL_GPT_COPY < cycle )
    989 printk("\n[%s] : thread[%x,%x] exit / nothing done / cycle %d\n",
     927printk("\n[%s] thread[%x,%x] exit / nothing done / cycle %d\n",
    990928__FUNCTION__, this->process->pid, this->trdid, cycle );
    991929#endif
     
    1005943    gpt_t    * gpt_ptr;
    1006944
    1007     vpn_t      vpn;
    1008 
    1009     uint32_t   ix1;
    1010     uint32_t   ix2;
     945    uint32_t   ix1;       // current
     946    uint32_t   ix2;       // current
     947
     948    vpn_t      vpn_min;
     949    vpn_t      vpn_max;   // included
     950
     951    uint32_t   ix1_min;
     952    uint32_t   ix1_max;   // included
     953
     954    uint32_t   ix2_min;
     955    uint32_t   ix2_max;   // included
    1011956
    1012957    uint32_t * pt1;
     
    1021966    gpt_ptr = GET_PTR( gpt_xp );
    1022967
    1023     // get local PT1 pointer
     968#if DEBUG_HAL_GPT_SET_COW
     969uint32_t   cycle = (uint32_t)hal_get_cycles();
     970thread_t * this  = CURRENT_THREAD;
     971if(DEBUG_HAL_GPT_SET_COW < cycle )
     972printk("\n[%s] thread[%x,%x] enter / gpt[%x,%x] / vpn_base %x / vpn_size %x / cycle %d\n",
     973__FUNCTION__, this->process->pid, this->trdid, gpt_cxy, gpt_ptr, vpn_base, vpn_size, cycle );
     974#endif
     975
     976    // get PT1 pointer
    1024977    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    1025978
    1026     // loop on pages
    1027     for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     979#if (DEBUG_HAL_GPT_SET_COW & 1)
     980if(DEBUG_HAL_GPT_SET_COW < cycle )
     981printk("\n[%s] thread[%x,%x] get pt1 = %x\n",
     982__FUNCTION__, this->process->pid, this->trdid, pt1 );
     983#endif
     984
     985    vpn_min = vpn_base;
     986    vpn_max = vpn_base + vpn_size - 1;
     987
     988    ix1_min = TSAR_MMU_IX1_FROM_VPN( vpn_base );
     989    ix1_max = TSAR_MMU_IX1_FROM_VPN( vpn_max );
     990
     991    for( ix1 = ix1_min ; ix1 <= ix1_max ; ix1++ )
    1028992    {
    1029         ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
    1030         ix2 = TSAR_MMU_IX2_FROM_VPN( vpn );
    1031 
     993
     994#if (DEBUG_HAL_GPT_SET_COW & 1)
     995if(DEBUG_HAL_GPT_SET_COW < cycle )
     996printk("\n[%s] thread[%x,%x] : &pt1[%x] = %x\n",
     997__FUNCTION__, this->process->pid, this->trdid, ix1,  &pt1[ix1] );
     998#endif
    1032999        // get PTE1 value
    10331000        pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
     1001
     1002#if (DEBUG_HAL_GPT_SET_COW & 1)
     1003if(DEBUG_HAL_GPT_SET_COW < cycle )
     1004printk("\n[%s] thread[%x,%x] : pt1[%x] = %x\n",
     1005__FUNCTION__, this->process->pid, this->trdid, ix1, pte1 );
     1006#endif
    10341007
    10351008        // only MAPPED & SMALL PTEs are modified
    10361009            if( (pte1 & TSAR_PTE_MAPPED) && (pte1 & TSAR_PTE_SMALL) )
    10371010        {
    1038             // compute PT2 base address
    1039             pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     1011            // get PT2 pointer
     1012            pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
    10401013            pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    10411014
    1042             assert( (GET_CXY( ppm_ppn2base( pt2_ppn ) ) == gpt_cxy ),
    1043             "PT2 and PT1 must be in the same cluster\n");
    1044  
    1045             // get current PTE2 attributes
    1046             attr = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) );
    1047 
    1048             // only MAPPED PTEs are modified       
    1049             if( attr & TSAR_PTE_MAPPED )
     1015#if (DEBUG_HAL_GPT_SET_COW & 1)
     1016if(DEBUG_HAL_GPT_SET_COW < cycle )
     1017printk("\n[%s] thread[%x,%x] : get pt2 = %x\n",
     1018__FUNCTION__, this->process->pid, this->trdid, pt2 );
     1019#endif
     1020            ix2_min = (ix1 == ix1_min) ? TSAR_MMU_IX2_FROM_VPN(vpn_min) : 0;
     1021            ix2_max = (ix1 == ix1_max) ? TSAR_MMU_IX2_FROM_VPN(vpn_max) : 511;
     1022 
     1023            for( ix2 = ix2_min ; ix2 <= ix2_max ; ix2++ )
    10501024            {
    1051                 attr = (attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
    1052                 hal_remote_s32( XPTR( gpt_cxy , &pt2[2*ix2] ) , attr );
    1053             }
    1054         }
    1055     }   // end loop on pages
     1025
     1026#if (DEBUG_HAL_GPT_SET_COW & 1)
     1027if(DEBUG_HAL_GPT_SET_COW < cycle )
     1028printk("\n[%s] thread[%x,%x] : &pte2[%x] = %x\n",
     1029__FUNCTION__, this->process->pid, this->trdid, 2*ix2, &pt2[2*ix2] );
     1030#endif
     1031                // get current PTE2 attributes
     1032                attr = hal_remote_l32( XPTR( gpt_cxy , &pt2[2*ix2] ) );
     1033
     1034#if (DEBUG_HAL_GPT_SET_COW & 1)
     1035if(DEBUG_HAL_GPT_SET_COW < cycle )
     1036printk("\n[%s] thread[%x,%x] : pte2[%x] (attr) = %x\n",
     1037__FUNCTION__, this->process->pid, this->trdid, 2*ix2, attr );
     1038#endif
     1039                // only MAPPED PTEs are modified       
     1040                if( attr & TSAR_PTE_MAPPED )
     1041                {
     1042                    attr = (attr | TSAR_PTE_COW) & (~TSAR_PTE_WRITABLE);
     1043                    hal_remote_s32( XPTR( gpt_cxy , &pt2[2*ix2] ) , attr );
     1044                }
     1045            }  // end loop on ix2
     1046        }
     1047    }  // end loop on ix1
     1048
     1049#if DEBUG_HAL_GPT_SET_COW
     1050cycle = (uint32_t)hal_get_cycles();
     1051if(DEBUG_HAL_GPT_SET_COW < cycle )
     1052printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
     1053__FUNCTION__, this->process->pid, this->trdid, cycle );
     1054#endif
    10561055
    10571056}  // end hal_gpt_set_cow()
     
    10681067        ppn_t               pt2_ppn;             // PPN of PT2
    10691068        uint32_t          * pt2;                 // PT2 base address
    1070     xptr_t              pte2_xp;             // exended pointer on PTE2
     1069    xptr_t              pte2_attr_xp;        // exended pointer on pte2.attr
     1070    xptr_t              pte2_ppn_xp;         // exended pointer on pte2.ppn
    10711071
    10721072    uint32_t            ix1;                 // index in PT1
    10731073    uint32_t            ix2;                 // index in PT2
    1074 
    1075 
    1076     uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
    10771074
    10781075// check MAPPED, SMALL, and not LOCKED in attr argument
     
    10921089    pt1 = (uint32_t *)hal_remote_lpt( XPTR( gpt_cxy , &gpt_ptr->ptr ) );
    10931090
    1094     // compute tsar_attr from generic attributes
    1095     tsar_attr = gpt2tsar( attr );
    1096 
    10971091    // get PTE1 value
    10981092    pte1 = hal_remote_l32( XPTR( gpt_cxy , &pt1[ix1] ) );
    10991093
    11001094// check MAPPED and SMALL in target PTE1
    1101 assert( ((pte1 & GPT_MAPPED) != 0), "attribute MAPPED must be set in target PTE1\n" );
    1102 assert( ((pte1 & GPT_SMALL ) != 0), "attribute SMALL  must be set in target PTE1\n" );
    1103 
    1104     // get PT2 base from PTE1
    1105     pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
     1095assert( ((pte1 & TSAR_PTE_MAPPED) != 0), "attribute MAPPED must be set in target PTE1\n" );
     1096assert( ((pte1 & TSAR_PTE_SMALL ) != 0), "attribute SMALL  must be set in target PTE1\n" );
     1097
     1098    // get PT2 base
     1099    pt2_ppn = TSAR_MMU_PPN2_FROM_PTE1( pte1 );
    11061100    pt2     = GET_PTR( ppm_ppn2base( pt2_ppn ) );
    11071101
    1108     // get extended pointer on PTE2
    1109     pte2_xp = XPTR( gpt_cxy , &pt2[2*ix2] );
     1102    // build extended pointers on PT2[ix2].attr and PT2[ix2].ppn
     1103    pte2_attr_xp = XPTR( gpt_cxy , &pt2[2 * ix2] );
     1104    pte2_ppn_xp  = XPTR( gpt_cxy , &pt2[2 * ix2 + 1] );
     1105
    11101106   
    11111107// check MAPPED in target PTE2
    1112 assert( ((hal_remote_l32(pte2_xp) & GPT_MAPPED) != 0),
     1108assert( ((hal_remote_l32(pte2_attr_xp) & TSAR_PTE_MAPPED) != 0),
    11131109"attribute MAPPED must be set in target PTE2\n" );
    11141110
    11151111    // set PTE2 in this order
    1116         hal_remote_s32( pte2_xp    , ppn );
     1112        hal_remote_s32( pte2_ppn_xp , ppn );
    11171113        hal_fence();
    1118         hal_remote_s32( pte2_xp + 4 , tsar_attr );
     1114        hal_remote_s32( pte2_attr_xp , gpt2tsar( attr ) );
    11191115        hal_fence();
    11201116
  • trunk/hal/tsar_mips32/core/hal_vmm.c

    r633 r635  
    4444extern process_t            process_zero;
    4545extern chdev_directory_t    chdev_dir;
     46extern char               * lock_type_str[];
    4647
    4748//////////////////////////////////////////////////////////////////////////////////////////
    4849// This function is called by the process_zero_init() function during kernel_init.
    4950// It initializes the VMM of the kernel proces_zero (containing all kernel threads)
    50 // in the local cluster: For TSAR, it registers one "kcode" vseg in kernel VSL,
    51 // and registers one big page in slot[0] of kernel GPT.
     51// in the local cluster.
     52// For TSAR, it registers one "kcode" vseg in kernel VSL, and registers one big page
     53// in slot[0] of kernel GPT.
    5254//////////////////////////////////////////////////////////////////////////////////////////
    5355error_t  hal_vmm_kernel_init( boot_info_t * info )
     
    5860    gpt_t * gpt = &process_zero.vmm.gpt;
    5961
    60     // get cluster identifier
    61     cxy_t cxy = local_cxy;
     62#if DEBUG_HAL_VMM
     63thread_t * this = CURRENT_THREAD;
     64printk("\n[%s] thread[%x,%x] enter in cluster %x\n",
     65__FUNCTION__, this->process->pid, this->trdid, local_cxy );
     66#endif
    6267
    6368    // allocate memory for kernel GPT
     
    6772    {
    6873        printk("\n[PANIC] in %s : cannot allocate kernel GPT in cluster %x\n",
    69         __FUNCTION__ , cxy );
     74        __FUNCTION__ , local_cxy );
    7075        hal_core_sleep();
    7176    }
    7277
    7378#if DEBUG_HAL_VMM
    74 thread_t * this = CURRENT_THREAD;
    75 printk("\n[%s] thread[%x,%x] enter in cluster %x / gpt %x\n",
     79printk("\n[%s] thread[%x,%x] created GPT PT1 in cluster %x / gpt %x\n",
    7680__FUNCTION__, this->process->pid, this->trdid, local_cxy, gpt );
    7781#endif
     
    7983    // compute attr and ppn for one PTE1
    8084    uint32_t attr = GPT_MAPPED | GPT_READABLE | GPT_CACHABLE | GPT_EXECUTABLE | GPT_GLOBAL;
    81     uint32_t ppn  = cxy << 20;   
     85    uint32_t ppn  = local_cxy << 20;   
    8286
    8387    // set PT1[0]
    84     hal_gpt_set_pte( XPTR( cxy , gpt ) , 0 , attr , ppn );
    85 
    86 #if DEBUG_HAL_VMM
    87 printk("\n[%s] thread[%x,%x] created PT1[0] : ppn %x / attr %x\n",
    88 __FUNCTION__, this->process->pid, this->trdid, ppn, attr );
     88    hal_gpt_set_pte( XPTR( local_cxy , gpt ) , 0 , attr , ppn );
     89
     90#if DEBUG_HAL_VMM
     91printk("\n[%s] thread[%x,%x] mapped PT1[0] in cluster %d : ppn %x / attr %x\n",
     92__FUNCTION__, this->process->pid, this->trdid, local_cxy, ppn, attr );
    8993#endif
    9094
     
    9498                                     info->kcode_base,
    9599                                     info->kcode_size,
    96                                      0, 0,                  // file ofset and file size (unused)
    97                                      XPTR_NULL,             // no mapper
     100                                     0, 0,               // file ofset and file size (unused)
     101                                     XPTR_NULL,          // no mapper
    98102                                     local_cxy );
    99103    if( vseg == NULL )
    100104    {
    101105        printk("\n[PANIC] in %s : cannot register vseg to VSL in cluster %x\n",
    102         __FUNCTION__ , cxy );
     106        __FUNCTION__ , local_cxy );
    103107        hal_core_sleep();
    104108    }
    105109
    106110#if DEBUG_HAL_VMM
    107 printk("\n[%s] thread[%x,%x] registered kcode vseg[%x,%x]\n",
    108 __FUNCTION__, this->process->pid, this->trdid, info->kcode_base, info->kcode_size );
     111printk("\n[%s] thread[%x,%x] registered kcode vseg[%x,%x] in cluster %x\n",
     112__FUNCTION__, this->process->pid, this->trdid, info->kcode_base, info->kcode_size, local_cxy );
    109113hal_vmm_display( &process_zero , true );
    110114#endif
     
    194198
    195199//////////////////////////////////////////
    196 void hal_vmm_display( process_t * process,
    197                       bool_t      mapping )
     200void hal_vmm_display( xptr_t   process_xp,
     201                      bool_t   mapping )
    198202{
    199     // get pointer on process VMM
    200     vmm_t * vmm = &process->vmm;
     203    // get target process cluster and local pointer
     204    process_t * process_ptr = GET_PTR( process_xp );
     205    cxy_t       process_cxy = GET_CXY( process_xp );
     206
     207    // get local pointer on target process VMM
     208    vmm_t * vmm = &process_ptr->vmm;
    201209
    202210    // get pointers on TXT0 chdev
     
    205213    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
    206214
    207     // build extended pointer on TXT0 lock and VSL lock
     215    // build extended pointer on TXT0 lock
    208216    xptr_t  txt_lock_xp = XPTR( txt0_cxy  , &txt0_ptr->wait_lock );
    209     xptr_t  vsl_lock_xp = XPTR( local_cxy , &vmm->vsl_lock );
    210 
    211     // get root of vsegs list
    212     xptr_t root_xp = XPTR( local_cxy , &vmm->vsegs_root );
    213 
    214     // get the locks protecting TXT0, VSL, and GPT
     217
     218    // build extended pointers on VSL lock and VSL root
     219    xptr_t vsl_root_xp = XPTR( process_cxy , &vmm->vsegs_root );
     220    xptr_t vsl_lock_xp = XPTR( process_cxy , &vmm->vsl_lock );
     221
     222    // get the locks protecting TXT0 and VSL
    215223    remote_rwlock_rd_acquire( vsl_lock_xp );
    216224    remote_busylock_acquire( txt_lock_xp );
    217225
    218     nolock_printk("\n***** VSL and GPT for process %x in cluster %x / PT1 = %x\n",
    219     process->pid , local_cxy , vmm->gpt.ptr );
    220 
    221     if( xlist_is_empty( root_xp ) )
     226    // get PID and PT1 values
     227    pid_t      pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );
     228    uint32_t * pt1 = hal_remote_lpt( XPTR( process_cxy , &vmm->gpt.ptr ) );
     229
     230    nolock_printk("\n***** VSL and GPT / process %x / cluster %x / PT1 %x / cycle %d\n",
     231    pid , process_cxy , pt1 , (uint32_t)hal_get_cycles() );
     232
     233    if( xlist_is_empty( vsl_root_xp ) )
    222234    {
    223235        nolock_printk("   ... no vsegs registered\n");
     
    227239        xptr_t         iter_xp;
    228240        xptr_t         vseg_xp;
    229         vseg_t       * vseg;
    230 
    231         XLIST_FOREACH( root_xp , iter_xp )
     241        vseg_t       * vseg_ptr;
     242        cxy_t          vseg_cxy;
     243        intptr_t       min;
     244        intptr_t       max;
     245        uint32_t       type;
     246        intptr_t       vpn_base;
     247        intptr_t       vpn_size;
     248
     249        XLIST_FOREACH( vsl_root_xp , iter_xp )
    232250        {
    233             vseg_xp = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
    234             vseg    = GET_PTR( vseg_xp );
     251            vseg_xp  = XLIST_ELEMENT( iter_xp , vseg_t , xlist );
     252            vseg_ptr = GET_PTR( vseg_xp );
     253            vseg_cxy = GET_CXY( vseg_xp );
     254
     255            type     =           hal_remote_l32( XPTR( vseg_cxy , &vseg_ptr->type ) );
     256            min      = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->min ) );
     257            max      = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->max ) );
     258            vpn_size = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->vpn_size ) );
     259            vpn_base = (intptr_t)hal_remote_lpt( XPTR( vseg_cxy , &vseg_ptr->vpn_base ) );
    235260
    236261            nolock_printk(" - %s : base = %X / size = %X / npages = %d\n",
    237             vseg_type_str(vseg->type), vseg->min, vseg->max - vseg->min, vseg->vpn_size );
     262            vseg_type_str(type), min, max - min, vpn_size );
    238263
    239264            if( mapping ) 
    240265            {
    241                 vpn_t    vpn     = vseg->vpn_base;
    242                 vpn_t    vpn_max = vpn + vseg->vpn_size;
     266                vpn_t    vpn     = vpn_base;
     267                vpn_t    vpn_max = vpn_base + vpn_size;
    243268                ppn_t    ppn;
    244269                uint32_t attr;
     
    246271                while( vpn < vpn_max )   // scan the PTEs
    247272                {
    248                     hal_gpt_get_pte( XPTR( local_cxy , &vmm->gpt ) , vpn , &attr , &ppn );
     273                    hal_gpt_get_pte( XPTR( process_cxy , &vmm->gpt ) , vpn , &attr , &ppn );
    249274
    250275                    if( attr & GPT_MAPPED )
  • trunk/hal/tsar_mips32/drivers/soclib_nic.c

    r570 r635  
    22 * soclib_nic.c - SOCLIB_NIC (Network Interface Controler) driver implementation.
    33 *
    4  * Author     Alain Greiner (2016)
     4 * Author     Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    5555            "chbuf descriptor exceeds one page" );
    5656
    57     req.type   = KMEM_PAGE;
    58     req.size   = 0;
     57    req.type   = KMEM_PPM;
     58    req.order  = 0;
    5959    req.flags  = AF_KERNEL;
    6060
    61     nic_chbuf_t * chbuf = (nic_chbuf_t *)kmem_alloc( &req );
    62 
    63     assert( (chbuf != NULL) ,
    64              "cannot allocate chbuf descriptor" );
     61    nic_chbuf_t * chbuf = kmem_alloc( &req );
     62
     63    if( chbuf == NULL )
     64    {
     65        printk("\n[PANIC] in %s : cannot allocate chbuf descriptor\n",
     66        __FUNCTION__ );
     67    }
    6568
    6669    // initialise chbuf state
     
    7679    for( i = 0 ; i < CONFIG_NIC_CHBUF_DEPTH ; i++ )
    7780    {
    78         uint32_t * container = (uint32_t *)kmem_alloc( &req );   
     81        uint32_t * container = kmem_alloc( &req );   
    7982
    8083        assert( (container != NULL) ,
  • trunk/hal/tsar_mips32/drivers/soclib_pic.c

    r629 r635  
    22 * soclib_pic.c - soclib PIC driver implementation.
    33 *
    4  * Author  Alain Greiner (2016,2017)
     4 * Author  Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    2727#include <errno.h>
    2828#include <string.h>
     29#include <bits.h>
    2930#include <vfs.h>
    3031#include <rpc.h>
     
    287288    {
    288289        // allocate memory for core extension
    289         req.type     = KMEM_GENERIC;
    290         req.size     = sizeof(soclib_pic_core_t);
     290        req.type     = KMEM_KCM;
     291        req.order    = bits_log2( sizeof(soclib_pic_core_t) );
    291292        req.flags    = AF_KERNEL;
    292293        core_ext_ptr = kmem_alloc( &req );
    293294
    294         assert( (core_ext_ptr != NULL) ,
    295                 "cannot allocate memory for core extension\n");
     295        if( core_ext_ptr == NULL )
     296        {
     297            printk("\n[PANIC] in %s : cannot allocate memory for core extension\n",
     298            __FUNCTION__ );
     299        }
    296300   
    297301        // reset the HWI / WTI  interrupt vectors
     
    304308
    305309    // allocate memory for cluster extension
    306     req.type        = KMEM_GENERIC;
    307     req.size        = sizeof(soclib_pic_cluster_t);
     310    req.type        = KMEM_KCM;
     311    req.order       = bits_log2( sizeof(soclib_pic_cluster_t) );
    308312    req.flags       = AF_KERNEL;
    309313    cluster_ext_ptr = kmem_alloc( &req );
    310314
    311     assert( (cluster_ext_ptr != NULL) ,
    312             "cannot allocate memory for cluster extension\n");
     315    if( cluster_ext_ptr == NULL )
     316    {
     317        printk("\n[PANIC] in %s : cannot allocate memory for cluster extension\n",
     318        __FUNCTION__ );
     319    }
     320   
     321assert( (cluster_ext_ptr != NULL) , "cannot allocate memory for cluster extension");
    313322
    314323    // get XCU characteristics from the XCU config register
  • trunk/hal/x86_64/core/hal_gpt.c

    r482 r635  
    282282        /* allocate a physical page for L4 */
    283283        kmem_req_t req;
    284         req.type  = KMEM_PAGE;
     284        req.type  = KMEM_PPM;
    285285        req.size  = 1;
    286286        req.flags = AF_KERNEL | AF_ZERO;
     
    330330        xptr_t page_xp;
    331331
    332         req.type  = KMEM_PAGE;
     332        req.type  = KMEM_PPM;
    333333        req.size  = 0;
    334334        req.flags = AF_KERNEL | AF_ZERO;
  • trunk/kernel/fs/devfs.c

    r624 r635  
    5858    kmem_req_t    req;
    5959
    60         req.type    = KMEM_DEVFS_CTX;
    61         req.size    = sizeof(devfs_ctx_t);
     60        req.type    = KMEM_KCM;
     61        req.order   = bits_log2( sizeof(devfs_ctx_t) );
    6262    req.flags   = AF_KERNEL | AF_ZERO;
    6363
    64         return (devfs_ctx_t *)kmem_alloc( &req );
     64        return kmem_alloc( &req );
    6565}
    6666
     
    8181    kmem_req_t    req;
    8282
    83     req.type = KMEM_DEVFS_CTX;
     83    req.type = KMEM_KCM;
    8484    req.ptr  = devfs_ctx;
    8585    kmem_free( &req );
  • trunk/kernel/fs/fatfs.c

    r633 r635  
    10691069{
    10701070    kmem_req_t    req;
    1071         req.type    = KMEM_FATFS_CTX;
    1072         req.size    = sizeof(fatfs_ctx_t);
     1071        req.type    = KMEM_KCM;
     1072        req.order   = bits_log2( sizeof(fatfs_ctx_t) );
    10731073    req.flags   = AF_KERNEL | AF_ZERO;
    10741074
    1075         return (fatfs_ctx_t *)kmem_alloc( &req );
     1075        return kmem_alloc( &req );
    10761076}
    10771077
     
    11011101    // - temporarily the BOOT sector
    11021102    // - permanently the FS_INFO sector
    1103         req.type    = KMEM_512_BYTES;
     1103        req.type    = KMEM_KCM;
     1104    req.order   = 9;                    // 512 bytes
    11041105    req.flags   = AF_KERNEL | AF_ZERO;
    1105         buffer      = (uint8_t *)kmem_alloc( &req );
    1106     buffer_xp   = XPTR( local_cxy , buffer );
     1106        buffer      = kmem_alloc( &req );
    11071107
    11081108    if( buffer == NULL )
     
    11121112    }
    11131113     
     1114    buffer_xp   = XPTR( local_cxy , buffer );
     1115
    11141116    // load the BOOT record from device
    11151117    error = dev_ioc_sync_read( buffer_xp , 0 , 1 );
     
    12421244{
    12431245    kmem_req_t    req;
    1244     req.type = KMEM_FATFS_CTX;
     1246    req.type = KMEM_KCM;
    12451247    req.ptr  = fatfs_ctx;
    12461248    kmem_free( &req );
  • trunk/kernel/fs/vfs.c

    r634 r635  
    150150    mapper_t         * mapper;     // associated mapper( to be allocated)
    151151    vfs_inode_t      * inode;      // inode descriptor (to be allocated)
     152   
    152153    uint32_t           inum;       // inode identifier (to be allocated)
    153154    vfs_ctx_t        * ctx;        // file system context
     
    155156    error_t            error;
    156157
    157 #if DEBUG_VFS_INODE_CREATE
    158 char           name[CONFIG_VFS_MAX_NAME_LENGTH];
    159 uint32_t       cycle      = (uint32_t)hal_get_cycles();
    160 cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    161 vfs_dentry_t * dentry_ptr = GET_PTR( dentry_xp );
    162 thread_t *     this       = CURRENT_THREAD;
    163 if( dentry_xp != XPTR_NULL ) hal_remote_strcpy( XPTR( local_cxy  , name ),
    164                                                 XPTR( dentry_cxy , dentry_ptr->name ) );
    165 else                         strcpy( name , "/" );
    166 if( DEBUG_VFS_INODE_CREATE < cycle )
    167 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    168 __FUNCTION__, this->process->pid, this->trdid, name, cycle );
    169 #endif
    170  
    171158    // check fs type and get pointer on context
    172159    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
     
    198185    }
    199186
    200     // allocate memory for VFS inode descriptor
    201         req.type  = KMEM_VFS_INODE;
    202         req.size  = sizeof(vfs_inode_t);
     187// check inode descriptor contained in one page
     188assert( (sizeof(vfs_inode_t) <= CONFIG_PPM_PAGE_SIZE),
     189"inode descriptor must fit in one page" );
     190
     191    // allocate one page for VFS inode descriptor
     192    // because the embedded "children xhtab footprint
     193        req.type  = KMEM_PPM;
     194        req.order = 0;
    203195    req.flags = AF_KERNEL | AF_ZERO;
    204         inode     = (vfs_inode_t *)kmem_alloc( &req );
     196        inode     = kmem_alloc( &req );
    205197
    206198    if( inode == NULL )
     
    243235
    244236#if DEBUG_VFS_INODE_CREATE
    245 cycle      = (uint32_t)hal_get_cycles();
     237char           name[CONFIG_VFS_MAX_NAME_LENGTH];
     238uint32_t       cycle      = (uint32_t)hal_get_cycles();
     239thread_t *     this       = CURRENT_THREAD;
     240vfs_inode_get_name( *inode_xp , name );
    246241if( DEBUG_VFS_INODE_CREATE < cycle )
    247 printk("\n[%s] thread[%x,%x] exit for <%s> / inode [%x,%x] / cycle %d\n",
     242printk("\n[%s] thread[%x,%x] created <%s> / inode [%x,%x] / cycle %d\n",
    248243__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, inode, cycle );
    249244#endif
     
    261256    // release memory allocate for inode descriptor
    262257        kmem_req_t req;
     258        req.type  = KMEM_PPM;
    263259        req.ptr   = inode;
    264         req.type  = KMEM_VFS_INODE;
    265260        kmem_free( &req );
    266261
     
    477472        kmem_req_t       req;        // request to kernel memory allocator
    478473
    479 #if DEBUG_VFS_DENTRY_CREATE
    480 thread_t * this = CURRENT_THREAD;
    481 uint32_t cycle = (uint32_t)hal_get_cycles();
    482 if( DEBUG_VFS_DENTRY_CREATE < cycle )
    483 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
    484 __FUNCTION__, this->process->pid, this->trdid, name, cycle );
    485 #endif
    486 
    487474    // get pointer on context
    488475    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
     
    501488
    502489    // allocate memory for dentry descriptor
    503         req.type  = KMEM_VFS_DENTRY;
    504         req.size  = sizeof(vfs_dentry_t);
     490        req.type  = KMEM_KCM;
     491        req.order = bits_log2( sizeof(vfs_dentry_t) );
    505492    req.flags = AF_KERNEL | AF_ZERO;
    506         dentry     = (vfs_dentry_t *)kmem_alloc( &req );
     493        dentry    = kmem_alloc( &req );
    507494
    508495    if( dentry == NULL )
     
    523510
    524511#if DEBUG_VFS_DENTRY_CREATE
    525 cycle = (uint32_t)hal_get_cycles();
     512thread_t * this  = CURRENT_THREAD;
     513uint32_t   cycle = (uint32_t)hal_get_cycles();
    526514if( DEBUG_VFS_DENTRY_CREATE < cycle )
    527 printk("\n[%s] thread[%x,%x] exit for <%s> / dentry [%x,%x] / cycle %d\n",
     515printk("\n[%s] thread[%x,%x] created <%s> / dentry [%x,%x] / cycle %d\n",
    528516__FUNCTION__, this->process->pid, this->trdid, name, local_cxy, dentry, cycle );
    529517#endif
     
    538526    // release memory allocated to dentry
    539527        kmem_req_t req;
     528        req.type  = KMEM_KCM;
    540529        req.ptr   = dentry;
    541         req.type  = KMEM_VFS_DENTRY;
    542530        kmem_free( &req );
    543531
     
    566554
    567555    // allocate memory for new file descriptor
    568         req.type  = KMEM_VFS_FILE;
    569         req.size  = sizeof(vfs_file_t);
     556        req.type  = KMEM_KCM;
     557        req.order = bits_log2( sizeof(vfs_file_t) );
    570558    req.flags = AF_KERNEL | AF_ZERO;
    571         file      = (vfs_file_t *)kmem_alloc( &req );
     559        file      = kmem_alloc( &req );
    572560
    573561    if( file == NULL ) return ENOMEM;
     
    602590{
    603591        kmem_req_t req;
     592        req.type  = KMEM_KCM;
    604593        req.ptr   = file;
    605         req.type  = KMEM_VFS_FILE;
    606594        kmem_free( &req );
    607595
     
    33473335#endif
    33483336
     3337
    33493338    // 3. register new_dentry in new_inode xlist of parents
    33503339    parents_root_xp  = XPTR( child_cxy , &new_inode_ptr->parents );
  • trunk/kernel/fs/vfs.h

    r633 r635  
    306306/******************************************************************************************
    307307 * This function allocates memory from local cluster for an inode descriptor and the
    308  * associated mapper. It initialise these descriptors from arguments values.
     308 * associated mapper, and partially initialise this inode from arguments values.
     309 * It does NOT link it to the Inode Tree, as this is done by add_child_in_parent().
    309310 * It must called by a local thread. Use the RPC_INODE_CREATE if client thread is remote.
    310311 ******************************************************************************************
  • trunk/kernel/kern/chdev.c

    r625 r635  
    9090
    9191    // allocate memory for chdev
    92     req.type   = KMEM_DEVICE;
    93     req.flags  = AF_ZERO;
    94     chdev      = (chdev_t *)kmem_alloc( &req );
     92    req.type   = KMEM_KCM;
     93    req.order  = bits_log2( sizeof(chdev_t) );
     94    req.flags  = AF_ZERO | AF_KERNEL;
     95    chdev      = kmem_alloc( &req );
    9596
    9697    if( chdev == NULL ) return NULL;
  • trunk/kernel/kern/cluster.c

    r627 r635  
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    55 *         Mohamed Lamine Karaoui (2015)
    6  *         Alain Greiner (2016,2017,2018)
     6 *         Alain Greiner (2016,2017,2018,2019)
    77 *
    88 * Copyright (c) UPMC Sorbonne Universites
     
    109109        cluster_t * cluster = LOCAL_CLUSTER;
    110110
    111     // initialize the lock protecting the embedded kcm allocator
    112         busylock_init( &cluster->kcm_lock , LOCK_CLUSTER_KCM );
    113 
    114111#if DEBUG_CLUSTER_INIT
    115112uint32_t   cycle = (uint32_t)hal_get_cycles();
     
    148145
    149146    // initialises embedded KCM
    150         kcm_init( &cluster->kcm , KMEM_KCM );
     147    uint32_t  i;
     148    for( i = 0 ; i < 6 ; i++ ) kcm_init( &cluster->kcm[i] , i+6 );
    151149
    152150#if( DEBUG_CLUSTER_INIT & 1 )
    153151cycle = (uint32_t)hal_get_cycles();
    154152if( DEBUG_CLUSTER_INIT < cycle )
    155 printk("\n[%s] KCM initialized in cluster %x at cycle %d\n",
     153printk("\n[%s] KCM[6:11] initialized in cluster %x at cycle %d\n",
    156154__FUNCTION__ , local_cxy , hal_get_cycles() );
    157155#endif
  • trunk/kernel/kern/cluster.h

    r611 r635  
    126126    ppm_t           ppm;               /*! embedded kernel page manager                   */
    127127    khm_t           khm;               /*! embedded kernel heap manager                   */
    128     kcm_t           kcm;               /*! embedded kernel KCMs manager                   */
    129 
    130     kcm_t         * kcm_tbl[KMEM_TYPES_NR];              /*! pointers on allocated KCMs   */
    131     busylock_t      kcm_lock;                            /*! protect kcm_tbl[] updates    */
     128    kcm_t           kcm[6];            /*! embedded kernel cache managers [6:11]          */
    132129
    133130    // RPC
  • trunk/kernel/kern/kernel_init.c

    r633 r635  
    251251           "\n\n\t\t Advanced Locality Management Operating System / Multi Kernel Hybrid\n"
    252252           "\n\n\t\t %s / %d cluster(s) / %d core(s) per cluster\n\n",
    253            CONFIG_ALMOS_VERSION , nclusters , ncores );
     253           CONFIG_VERSION , nclusters , ncores );
    254254}
    255255
     
    14281428    }
    14291429
    1430 #if( DEBUG_KERNEL_INIT & 1 )
     1430#if CONFIG_INSTRUMENTATION_FOOTPRINT
    14311431if( (core_lid ==  0) & (local_cxy == 0) )
    14321432printk("\n\n***** memory fooprint for main kernel objects\n\n"
     
    14391439                   " - rpc fifo           : %d bytes\n"
    14401440                   " - page descriptor    : %d bytes\n"
    1441                    " - mapper root        : %d bytes\n"
     1441                   " - mapper descriptor  : %d bytes\n"
     1442                   " - vseg descriptor    : %d bytes\n"
    14421443                   " - ppm manager        : %d bytes\n"
    14431444                   " - kcm manager        : %d bytes\n"
     
    14451446                   " - vmm manager        : %d bytes\n"
    14461447                   " - gpt root           : %d bytes\n"
     1448                   " - vfs inode          : %d bytes\n"
     1449                   " - vfs dentry         : %d bytes\n"
     1450                   " - vfs file           : %d bytes\n"
     1451                   " - vfs context        : %d bytes\n"
     1452                   " - xhtab root         : %d bytes\n"
    14471453                   " - list item          : %d bytes\n"
    14481454                   " - xlist item         : %d bytes\n"
     
    14621468                   sizeof( page_t             ),
    14631469                   sizeof( mapper_t           ),
     1470                   sizeof( vseg_t             ),
    14641471                   sizeof( ppm_t              ),
    14651472                   sizeof( kcm_t              ),
     
    14671474                   sizeof( vmm_t              ),
    14681475                   sizeof( gpt_t              ),
     1476                   sizeof( vfs_inode_t        ),
     1477                   sizeof( vfs_dentry_t       ),
     1478                   sizeof( vfs_file_t         ),
     1479                   sizeof( vfs_ctx_t          ),
     1480                   sizeof( xhtab_t            ),
    14691481                   sizeof( list_entry_t       ),
    14701482                   sizeof( xlist_entry_t      ),
     
    14861498    /////////////////////////////////////////////////////////////////////////////////
    14871499
    1488 #if( DEBUG_KERNEL_INIT & 1 )
     1500#if DEBUG_KERNEL_INIT
    14891501thread_t * this = CURRENT_THREAD;
    14901502printk("\n[%s] : thread[%x,%x] on core[%x,%d] jumps to thread_idle_func() / cycle %d\n",
  • trunk/kernel/kern/process.c

    r633 r635  
    7272process_t * process_alloc( void )
    7373{
    74         kmem_req_t   req;
    75 
    76     req.type  = KMEM_PROCESS;
    77         req.size  = sizeof(process_t);
     74        kmem_req_t req;
     75
     76    req.type  = KMEM_KCM;
     77        req.order = bits_log2( sizeof(process_t) );
    7878        req.flags = AF_KERNEL;
    7979
    80     return (process_t *)kmem_alloc( &req );
     80    return kmem_alloc( &req );
    8181}
    8282
     
    8686    kmem_req_t  req;
    8787
    88         req.type = KMEM_PROCESS;
     88        req.type = KMEM_KCM;
    8989        req.ptr  = process;
    9090        kmem_free( &req );
     
    166166#endif
    167167
    168     // initialize VSL locks
     168    // initialize VSL lock
    169169        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
    170170
    171     // register kernel vsegs in VMM as required by the architecture
     171    // register kernel vsegs in user process VMM as required by the architecture
    172172    error = hal_vmm_kernel_update( process );
    173173    if( error )
     
    179179#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
    180180if( DEBUG_PROCESS_REFERENCE_INIT < cycle )
    181 printk("\n[%s] thread[%x,%x] registered kernel vsegs for process %x\n",
     181printk("\n[%s] thread[%x,%x] registered kernel vsegs in VSL for process %x\n",
    182182__FUNCTION__, parent_pid, this->trdid, pid );
    183183#endif
     
    374374printk("\n[%s] thread[%x,%x] exit for process %x / cycle %d\n",
    375375__FUNCTION__, parent_pid, this->trdid, pid, cycle );
     376#endif
     377
     378#if (DEBUG_PROCESS_REFERENCE_INIT & 1)
     379hal_vmm_display( parent_xp , false );
     380hal_vmm_display( XPTR( local_cxy , process ) , false );
    376381#endif
    377382
     
    10881093    }
    10891094}
     1095
    10901096////////////////////////////////////////////////////
    10911097error_t process_fd_register( xptr_t      process_xp,
     
    13561362
    13571363#if DEBUG_PROCESS_MAKE_FORK
    1358 uint32_t cycle   = (uint32_t)hal_get_cycles();
     1364uint32_t   cycle;
    13591365thread_t * this  = CURRENT_THREAD;
    13601366trdid_t    trdid = this->trdid;
    13611367pid_t      pid   = this->process->pid;
     1368#endif
     1369
     1370#if( DEBUG_PROCESS_MAKE_FORK & 1 )
     1371cycle   = (uint32_t)hal_get_cycles();
    13621372if( DEBUG_PROCESS_MAKE_FORK < cycle )
    13631373printk("\n[%s] thread[%x,%x] enter / cluster %x / cycle %d\n",
     
    13671377    // allocate a process descriptor
    13681378    process = process_alloc();
     1379
    13691380    if( process == NULL )
    13701381    {
     
    14271438printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n",
    14281439__FUNCTION__, pid, trdid, cycle );
     1440hal_vmm_display( XPTR( local_cxy , process ) , true );
    14291441#endif
    14301442
     
    14381450cycle = (uint32_t)hal_get_cycles();
    14391451if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1440 printk("\n[%s] thread[%x,%x] / child takes TXT ownership / cycle %d\n",
    1441 __FUNCTION__ , pid, trdid, cycle );
     1452printk("\n[%s] thread[%x,%x] / child_process %x takes TXT ownership / cycle %d\n",
     1453__FUNCTION__ , pid, trdid, new_pid, cycle );
    14421454#endif
    14431455
     
    14711483#endif
    14721484
    1473     // set COW flag in DATA, ANON, REMOTE vsegs for parent process VMM
     1485    // set COW flag in DATA, ANON, REMOTE vsegs in parent process VMM
    14741486    // this includes all parent process copies in all clusters
    14751487    if( parent_process_cxy == local_cxy )   // reference is local
     
    14891501cycle = (uint32_t)hal_get_cycles();
    14901502if( DEBUG_PROCESS_MAKE_FORK < cycle )
    1491 printk("\n[%s] thread[%x,%x] set COW in parent and child / cycle %d\n",
     1503printk("\n[%s] thread[%x,%x] set COW in DATA / ANON / REMOTE for parent and child / cycle %d\n",
    14921504__FUNCTION__, pid, trdid, cycle );
    14931505#endif
     
    15461558#if DEBUG_PROCESS_MAKE_EXEC
    15471559uint32_t cycle = (uint32_t)hal_get_cycles();
    1548 if( local_cxy == 0x11 )
     1560if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    15491561printk("\n[%s] thread[%x,%x] enters for %s / cycle %d\n",
    15501562__FUNCTION__, pid, thread->trdid, path, cycle );
     
    15691581#if (DEBUG_PROCESS_MAKE_EXEC & 1)
    15701582cycle = (uint32_t)hal_get_cycles();
    1571 if( local_cxy == 0x11 )
     1583if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    15721584printk("\n[%s] thread[%x,%x] opened file <%s> / cycle %d\n",
    15731585__FUNCTION__, pid, thread->trdid, path, cycle );
     
    15791591#if (DEBUG_PROCESS_MAKE_EXEC & 1)
    15801592cycle = (uint32_t)hal_get_cycles();
    1581 if( local_cxy == 0x11 )
     1593if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    15821594printk("\n[%s] thread[%x,%x] deleted existing threads / cycle %d\n",
    15831595__FUNCTION__, pid, thread->trdid, cycle );
     
    15891601#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    15901602cycle = (uint32_t)hal_get_cycles();
    1591 if( local_cxy == 0x11 )
     1603if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    15921604printk("\n[%s] thread[%x,%x] completed VMM reset / cycle %d\n",
    15931605__FUNCTION__, pid, thread->trdid, cycle );
     
    16061618#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    16071619cycle = (uint32_t)hal_get_cycles();
    1608 if( local_cxy == 0x11 )
     1620if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    16091621printk("\n[%s] thread[%x,%x] registered args/envs vsegs / cycle %d\n",
    16101622__FUNCTION__, pid, thread->trdid, cycle );
     
    16241636#if( DEBUG_PROCESS_MAKE_EXEC & 1 )
    16251637cycle = (uint32_t)hal_get_cycles();
    1626 if( local_cxy == 0x11 )
     1638if( DEBUG_PROCESS_MAKE_EXEC < cycle )
    16271639printk("\n[%s] thread[%x,%x] registered code/data vsegs / cycle %d\n",
    16281640__FUNCTION__, pid, thread->trdid, cycle );
     
    16741686        hal_core_sleep();
    16751687    }
     1688
     1689#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1690if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1691printk("\n[%s] allocated pid %x in cluster %x\n", __FUNCTION__, pid, local_cxy );
     1692#endif
    16761693
    16771694    // initialize PID, REF_XP, PARENT_XP, and STATE
     
    16841701    process->term_state = 0;
    16851702
    1686     // initilise VSL as empty
     1703    // initialize VSL as empty
    16871704    vmm->vsegs_nr = 0;
    16881705        xlist_root_init( XPTR( local_cxy , &vmm->vsegs_root ) );
    16891706
    1690     // initialise GPT as empty
     1707#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1708if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1709printk("\n[%s] initialized VSL empty in cluster %x\n", __FUNCTION__, local_cxy );
     1710#endif
     1711
     1712    // initialize GPT as empty
    16911713    error = hal_gpt_create( &vmm->gpt );
     1714
    16921715    if( error )
    16931716    {
     
    16951718        hal_core_sleep();
    16961719    }
     1720
     1721#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1722if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1723printk("\n[%s] initialized GPT empty in cluster %x\n", __FUNCTION__, local_cxy );
     1724#endif
    16971725
    16981726    // initialize VSL and GPT locks
     
    17011729    // create kernel vsegs in GPT and VSL, as required by the hardware architecture
    17021730    error = hal_vmm_kernel_init( info );
     1731
    17031732    if( error )
    17041733    {
     
    17061735        hal_core_sleep();
    17071736    }
     1737
     1738#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1739if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1740printk("\n[%s] initialized hal specific VMM in cluster%x\n", __FUNCTION__, local_cxy );
     1741#endif
    17081742
    17091743    // reset th_tbl[] array and associated fields
     
    17161750    rwlock_init( &process->th_lock , LOCK_PROCESS_THTBL );
    17171751
     1752#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1753if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1754printk("\n[%s] initialized th_tbl[] in cluster%x\n", __FUNCTION__, local_cxy );
     1755#endif
    17181756
    17191757    // reset children list as empty
     
    17221760    remote_queuelock_init( XPTR( local_cxy , &process->children_lock ),
    17231761                           LOCK_PROCESS_CHILDREN );
     1762
     1763#if (DEBUG_PROCESS_ZERO_CREATE & 1)
     1764if( DEBUG_PROCESS_ZERO_CREATE < cycle )
     1765printk("\n[%s] initialized children list in cluster%x\n", __FUNCTION__, local_cxy );
     1766#endif
    17241767
    17251768    // register kernel process in cluster manager local_list
     
    17591802    // allocates memory for process descriptor from local cluster
    17601803        process = process_alloc();
     1804
     1805
    17611806    if( process == NULL )
    17621807    {
     
    18401885
    18411886#if (DEBUG_PROCESS_INIT_CREATE & 1)
    1842 hal_vmm_display( process , true );
     1887hal_vmm_display( XPTR( local_cxy , process ) , true );
    18431888#endif
    18441889
  • trunk/kernel/kern/process.h

    r625 r635  
    44 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    55 *          Mohamed Lamine Karaoui (2015)
    6  *          Alain Greiner (2016,2017,2018)
     6 *          Alain Greiner (2016,2017,2018,2019)
    77 *
    88 * Copyright (c) UPMC Sorbonne Universites
     
    231231 * descriptor, defined by the <parent_xp> argument. The <process> and <pid> arguments
    232232 * are previously allocated by the caller. This function can be called by two functions:
    233  * 1) process_init_create() : process is the INIT process, and parent is process-zero.
    234  * 2) process_make_fork() : the parent process descriptor is generally remote.
     233 * - process_init_create() : process is the INIT process, and parent is process-zero.
     234 * -  process_make_fork()  : the parent process descriptor is generally remote.
    235235 * The following fields are initialised :
    236236 * - It set the pid / ppid / ref_xp / parent_xp / state fields.
  • trunk/kernel/kern/rpc.c

    r632 r635  
    7575    &rpc_vmm_get_vseg_server,              // 20
    7676    &rpc_vmm_global_update_pte_server,     // 21
    77     &rpc_kcm_alloc_server,                 // 22
    78     &rpc_kcm_free_server,                  // 23
     77    &rpc_undefined,                        // 22
     78    &rpc_undefined,                        // 23
    7979    &rpc_mapper_sync_server,               // 24
    80     &rpc_mapper_handle_miss_server,        // 25
     80    &rpc_undefined,                        // 25
    8181    &rpc_vmm_delete_vseg_server,           // 26
    8282    &rpc_vmm_create_vseg_server,           // 27
    8383    &rpc_vmm_set_cow_server,               // 28
    84     &rpc_hal_vmm_display_server,           // 29
     84    &rpc_undefined,                        // 29
    8585};
    8686
     
    111111    "GET_VSEG",                  // 20
    112112    "GLOBAL_UPDATE_PTE",         // 21
    113     "KCM_ALLOC",                 // 22
    114     "KCM_FREE",                  // 23
     113    "undefined_22",              // 22
     114    "undefined_23",              // 23
    115115    "MAPPER_SYNC",               // 24
    116     "MAPPER_HANDLE_MISS",        // 25
     116    "undefined_25",              // 25
    117117    "VMM_DELETE_VSEG",           // 26
    118118    "VMM_CREATE_VSEG",           // 27
    119119    "VMM_SET_COW",               // 28
    120     "VMM_DISPLAY",               // 29
     120    "undefined_29",              // 29
    121121};
    122122
     
    557557    // release memory to local pmem
    558558    kmem_req_t req;
    559     req.type = KMEM_PAGE;
     559    req.type = KMEM_PPM;
    560560    req.ptr  = page;
    561561    kmem_free( &req );
     
    22312231/////////////////////////////////////////////////////////////////////////////////////////
    22322232
     2233/*
    22332234//////////////////////////////////////////
    22342235void rpc_kcm_alloc_client( cxy_t      cxy,
     
    23042305#endif
    23052306}   
     2307*/
    23062308
    23072309/////////////////////////////////////////////////////////////////////////////////////////
     
    23092311/////////////////////////////////////////////////////////////////////////////////////////
    23102312
     2313/*
    23112314/////////////////////////////////////////
    23122315void rpc_kcm_free_client( cxy_t      cxy,
     
    23772380#endif
    23782381}   
    2379 
    2380 /////////////////////////////////////////////////////////////////////////////////////////
    2381 // [25]          Marshaling functions attached to RPC_MAPPER_SYNC
     2382*/
     2383
     2384/////////////////////////////////////////////////////////////////////////////////////////
     2385// [24]          Marshaling functions attached to RPC_MAPPER_SYNC
    23822386/////////////////////////////////////////////////////////////////////////////////////////
    23832387
     
    24592463/////////////////////////////////////////////////////////////////////////////////////////
    24602464
     2465/*
    24612466//////////////////////////////////////////////////////////
    24622467void rpc_mapper_handle_miss_client( cxy_t             cxy,
     
    25412546#endif
    25422547}
     2548*/
    25432549
    25442550/////////////////////////////////////////////////////////////////////////////////////////
     
    27842790
    27852791/////////////////////////////////////////////////////////////////////////////////////////
    2786 // [29]          Marshaling functions attached to RPC_VMM_DISPLAY
    2787 /////////////////////////////////////////////////////////////////////////////////////////
    2788 
     2792// [29]      RPC_VMM_DISPLAY deprecated [AG] June 2019
     2793/////////////////////////////////////////////////////////////////////////////////////////
     2794
     2795/*
    27892796/////////////////////////////////////////////
    27902797void rpc_hal_vmm_display_client( cxy_t       cxy,
     
    28562863}
    28572864
    2858 
     2865*/
  • trunk/kernel/kern/rpc.h

    r632 r635  
    6060typedef enum
    6161{
    62     RPC_UNDEFINED_0               = 0,   // RPC_PMEM_GET_PAGES     deprecated [AG]
    63     RPC_UNDEFINED_1               = 1,   // RPC_PMEM_RELEASE_PAGES deprecated [AG]
    64     RPC_UNDEFINED_2               = 2,   // RPC_PMEM_DISPLAY       deprecated [AG]     
     62    RPC_UNDEFINED_0               = 0,   // RPC_PMEM_GET_PAGES       deprecated [AG]
     63    RPC_UNDEFINED_1               = 1,   // RPC_PMEM_RELEASE_PAGES   deprecated [AG]
     64    RPC_UNDEFINED_2               = 2,   // RPC_PMEM_DISPLAY         deprecated [AG]     
    6565    RPC_PROCESS_MAKE_FORK         = 3,
    6666    RPC_USER_DIR_CREATE           = 4,
     
    8484    RPC_VMM_GET_VSEG              = 20,
    8585    RPC_VMM_GLOBAL_UPDATE_PTE     = 21,
    86     RPC_KCM_ALLOC                 = 22,
    87     RPC_KCM_FREE                  = 23,
     86    RPC_UNDEFINED_22              = 22,   // RPC_KCM_ALLOC           deprecated [AG]
     87    RPC_UNDEFINED_23              = 23,   // RPC_KCM_FREE            deprecated [AG]
    8888    RPC_MAPPER_SYNC               = 24,
    89     RPC_MAPPER_HANDLE_MISS        = 25,
     89    RPC_UNDEFUNED_25              = 25,   // RPC_MAPPER_HANDLE_MISS  deprecated [AG]
    9090    RPC_VMM_DELETE_VSEG           = 26,
    9191    RPC_VMM_CREATE_VSEG           = 27,
    9292    RPC_VMM_SET_COW               = 28,
    93     RPC_VMM_DISPLAY               = 29,
     93    RPC_UNDEFINED_29              = 29,   // RPC_VMM_DISPLAY         deprecated [AG]
    9494
    9595    RPC_MAX_INDEX                 = 30,
     
    574574 * @ buf_xp    : [out] buffer for extended pointer on allocated buffer.
    575575 **********************************************************************************/
     576
     577/*
    576578void rpc_kcm_alloc_client( cxy_t      cxy,
    577579                           uint32_t   kmem_type,
     
    579581
    580582void rpc_kcm_alloc_server( xptr_t xp );
     583*/
    581584
    582585/***********************************************************************************
     
    588591 * @ kmem_type : [in]  KCM object type (as defined in kmem.h).
    589592 **********************************************************************************/
     593
     594/*
    590595void rpc_kcm_free_client( cxy_t     cxy,
    591596                          void    * buf,
     
    593598
    594599void rpc_kcm_free_server( xptr_t xp );
     600*/
    595601
    596602/***********************************************************************************
     
    621627 * @ error       : [out] error status (0 if success).
    622628 **********************************************************************************/
     629/*
    623630void rpc_mapper_handle_miss_client( cxy_t             cxy,
    624631                                    struct mapper_s * mapper,
     
    628635 
    629636void rpc_mapper_handle_miss_server( xptr_t xp );
    630 
     637*/
    631638/***********************************************************************************
    632639 * [26] The RPC_VMM_DELETE_VSEG allows any client thread  to request a remote
     
    699706 * @ detailed    : [in]  detailed display if true.
    700707 **********************************************************************************/
     708
     709/*
    701710void rpc_hal_vmm_display_client( cxy_t              cxy,
    702711                             struct process_s * process,
     
    704713
    705714void rpc_hal_vmm_display_server( xptr_t xp );
    706 
     715*/
    707716
    708717#endif
  • trunk/kernel/kern/scheduler.c

    r630 r635  
    180180    sched = &core->scheduler;
    181181
    182     ////////////////// scan user threads to handle both ACK and DELETE requests
     182    ////////////////// scan user threads to handle ACK and DELETE requests
    183183    root = &sched->u_root;
    184184    iter = root->next;
     
    195195        {
    196196
    197 // check thread blocked
     197// check target thread blocked
    198198assert( (thread->blocked & THREAD_BLOCKED_GLOBAL) , "thread not blocked" );
    199199 
     
    206206
    207207        // handle REQ_DELETE only if target thread != calling thread
    208         if( (thread->flags & THREAD_FLAG_REQ_DELETE) && (thread != CURRENT_THREAD) )
    209         {
     208        if( thread->flags & THREAD_FLAG_REQ_DELETE )
     209        {
     210
     211// check calling thread != target thread
     212assert( (thread != CURRENT_THREAD) , "calling thread cannot delete itself" );
     213 
    210214            // get thread process descriptor
    211215            process = thread->process;
     
    497501    remote_fifo_t * fifo    = &LOCAL_CLUSTER->rpc_fifo[lid];
    498502 
     503#if DEBUG_SCHED_YIELD
     504uint32_t cycle = (uint32_t)hal_get_cycles();
     505#endif
     506
    499507#if (DEBUG_SCHED_YIELD & 0x1)
    500 if( sched->trace )
     508if( sched->trace || (cycle > DEBUG_SCHED_YIELD) )
    501509sched_display( lid );
    502510#endif
     
    551559
    552560#if DEBUG_SCHED_YIELD
    553 if( sched->trace )
     561if( sched->trace || (cycle > DEBUG_SCHED_YIELD) )
    554562printk("\n[%s] core[%x,%d] / cause = %s\n"
    555563"      thread %x (%s) (%x,%x) => thread %x (%s) (%x,%x) / cycle %d\n",
    556564__FUNCTION__, local_cxy, lid, cause,
    557565current, thread_type_str(current->type), current->process->pid, current->trdid,next ,
    558 thread_type_str(next->type) , next->process->pid , next->trdid , (uint32_t)hal_get_cycles() );
     566thread_type_str(next->type) , next->process->pid , next->trdid , cycle );
    559567#endif
    560568
     
    567575        busylock_release( &sched->lock );
    568576
    569 #if (DEBUG_SCHED_YIELD & 1)
    570 if( sched->trace )
     577#if DEBUG_SCHED_YIELD
     578if( sched->trace || (cycle > DEBUG_SCHED_YIELD) )
    571579printk("\n[%s] core[%x,%d] / cause = %s\n"
    572580"      thread %x (%s) (%x,%x) continue / cycle %d\n",
  • trunk/kernel/kern/thread.c

    r633 r635  
    7878static thread_t * thread_alloc( void )
    7979{
    80         page_t       * page;   // pointer on page descriptor containing thread descriptor
    8180        kmem_req_t     req;    // kmem request
    8281
    8382        // allocates memory for thread descriptor + kernel stack
    84         req.type  = KMEM_PAGE;
    85         req.size = CONFIG_THREAD_DESC_ORDER;
     83        req.type  = KMEM_PPM;
     84        req.order = CONFIG_THREAD_DESC_ORDER;
    8685        req.flags = AF_KERNEL | AF_ZERO;
    87         page      = kmem_alloc( &req );
    88 
    89         if( page == NULL ) return NULL;
    90 
    91     // return pointer on new thread descriptor
    92     xptr_t base_xp = ppm_page2base( XPTR(local_cxy , page ) );
    93     return GET_PTR( base_xp );
     86
     87    return kmem_alloc( &req );
    9488
    9589}  // end thread_alloc()
     
    125119{
    126120
    127 // check type and trdid fields initialized
     121// check type and trdid fields are initialized
    128122assert( (thread->type == type)   , "bad type argument" );
    129123assert( (thread->trdid == trdid) , "bad trdid argument" );
     
    133127thread_t * this  = CURRENT_THREAD;
    134128if( DEBUG_THREAD_INIT < cycle )
    135 printk("\n[%s] thread[%x,%x] enter for thread %x in process %x / cycle %d\n",
    136 __FUNCTION__, this->process->pid, this->trdid, thread->trdid, process->pid , cycle );
     129printk("\n[%s] thread[%x,%x] enter for thread[%x,%x] / cycle %d\n",
     130__FUNCTION__, this->process->pid, this->trdid, process->pid, thread->trdid, cycle );
    137131#endif
    138132
     
    192186cycle = (uint32_t)hal_get_cycles();
    193187if( DEBUG_THREAD_INIT < cycle )
    194 printk("\n[%s] thread[%x,%x] exit for thread %x in process %x / cycle %d\n",
    195 __FUNCTION__, this->process->pid, this->trdid, thread, process->pid, cycle );
     188printk("\n[%s] thread[%x,%x] exit for thread[%x,%x] / cycle %d\n",
     189__FUNCTION__, this->process->pid, this->trdid, process->pid, thread->trdid, cycle );
    196190#endif
    197191
     
    580574    vpn_t  parent_vpn_size = hal_remote_l32( XPTR( parent_cxy, &parent_us_vseg->vpn_size ) );
    581575    vpn_t  child_vpn_base  = child_us_vseg->vpn_base;
     576
    582577    for( parent_vpn = parent_vpn_base , child_vpn = child_vpn_base ;
    583578         parent_vpn < (parent_vpn_base + parent_vpn_size) ;
     
    625620#if (DEBUG_THREAD_USER_FORK & 1)
    626621if( DEBUG_THREAD_USER_FORK < cycle )
    627 printk("\n[%s] thread[%x,%x] copied all stack vseg PTEs to child GPT\n",
     622printk("\n[%s] thread[%x,%x] copied STACK vseg PTEs & set COW in child GPT\n",
    628623__FUNCTION__, this->process->pid, this->trdid );
    629624#endif
     
    636631#if (DEBUG_THREAD_USER_FORK & 1)
    637632if( DEBUG_THREAD_USER_FORK < cycle )
    638 printk("\n[%s] thread[%x,%x] set the COW flag for stack vseg in parent GPT\n",
     633printk("\n[%s] thread[%x,%x] set COW for STACK vseg in parent GPT\n",
    639634__FUNCTION__, this->process->pid, this->trdid );
    640635#endif
     
    906901    thread_assert_can_yield( thread , __FUNCTION__ );
    907902
    908     // update target process instrumentation counter
    909         // process->vmm.pgfault_nr += thread->info.pgfault_nr;
     903#if CONFIG_INSTRUMENTATION_PGFAULTS
     904        process->vmm.false_pgfault_nr    += thread->info.false_pgfault_nr;
     905        process->vmm.local_pgfault_nr    += thread->info.local_pgfault_nr;
     906        process->vmm.global_pgfault_nr   += thread->info.global_pgfault_nr;
     907        process->vmm.false_pgfault_cost  += thread->info.false_pgfault_cost;
     908        process->vmm.local_pgfault_cost  += thread->info.local_pgfault_cost;
     909        process->vmm.global_pgfault_cost += thread->info.global_pgfault_cost;
     910#endif
    910911
    911912    // remove thread from process th_tbl[]
    912913    count = process_remove_thread( thread );
    913914
    914     // release memory allocated for CPU context and FPU context if required
     915    // release memory allocated for CPU context and FPU context
    915916        hal_cpu_context_destroy( thread );
    916917        hal_fpu_context_destroy( thread );
     
    933934    // release memory for thread descriptor (including kernel stack)
    934935    kmem_req_t   req;
    935     xptr_t       base_xp = ppm_base2page( XPTR(local_cxy , thread ) );
    936 
    937     req.type  = KMEM_PAGE;
    938     req.ptr   = GET_PTR( base_xp );
     936    req.type  = KMEM_PPM;
     937    req.ptr   = thread;
    939938    kmem_free( &req );
    940939
  • trunk/kernel/kern/thread.h

    r629 r635  
    101101{
    102102        uint32_t     false_pgfault_nr;       /*! number of local page fault               */
     103        uint32_t     local_pgfault_nr;       /*! number of local page fault               */
     104        uint32_t     global_pgfault_nr;      /*! number of global page fault              */
    103105    uint32_t     false_pgfault_cost;     /*! cumulated cost                           */
    104         uint32_t     local_pgfault_nr;       /*! number of local page fault               */
    105106    uint32_t     local_pgfault_cost;     /*! cumulated cost                           */
    106         uint32_t     global_pgfault_nr;      /*! number of global page fault              */
    107107    uint32_t     global_pgfault_cost;    /*! cumulated cost                           */
    108108
     
    339339 * this. This includes the thread descriptor itself, the associated CPU and FPU context,
    340340 * and the physical memory allocated for an user thread stack.
     341 * This function does not remove the thread from the scheduler, as this is done by
     342 * the scheduler itself.
    341343 ***************************************************************************************
    342344 * @ thread  : pointer on the thread descriptor to release.
     
    394396 * The calling thread can run in any cluster, as it uses remote accesses.
    395397 * This function makes a kernel panic if the target thread is the main thread,
    396  * because * the main thread deletion will cause the process deletion, and a process
     398 * because the main thread deletion will cause the process deletion, and a process
    397399 * must be deleted by the parent process, running the wait function.
    398400 * If the target thread is running in "attached" mode, and the <is_forced> argument
  • trunk/kernel/kernel_config.h

    r634 r635  
    2525#define _KERNEL_CONFIG_H_
    2626
    27 #define CONFIG_ALMOS_VERSION           "Version 2.1 / May 2019"
    28 
    2927////////////////////////////////////////////////////////////////////////////////////////////
    3028//                              KERNEL DEBUG
     
    9896#define DEBUG_HAL_GPT_DESTROY             0
    9997#define DEBUG_HAL_GPT_LOCK_PTE            0
     98#define DEBUG_HAL_GPT_SET_COW             0
    10099#define DEBUG_HAL_GPT_SET_PTE             0
    101100#define DEBUG_HAL_IOC_RX                  0
     
    109108
    110109#define DEBUG_KCM                         0
     110#define DEBUG_KCM_REMOTE                  0
     111
    111112#define DEBUG_KMEM                        0
     113#define DEBUG_KMEM_REMOTE                 0
    112114
    113115#define DEBUG_KERNEL_INIT                 0
     
    145147#define DEBUG_RPC_SERVER_GENERIC          0
    146148
    147 #define DEBUG_RPC_KCM_ALLOC               0
    148 #define DEBUG_RPC_KCM_FREE                0
    149 #define DEBUG_RPC_MAPPER_HANDLE_MISS      0
    150149#define DEBUG_RPC_MAPPER_MOVE_USER        0
    151150#define DEBUG_RPC_PROCESS_MAKE_FORK       0
     
    233232#define DEBUG_VFS_CHDIR                   0
    234233#define DEBUG_VFS_CLOSE                   0
    235 #define DEBUG_VFS_DENTRY_CREATE           0 
     234#define DEBUG_VFS_DENTRY_CREATE           0
    236235#define DEBUG_VFS_FILE_CREATE             0
    237236#define DEBUG_VFS_GET_PATH                0
     
    256255#define DEBUG_VMM_GET_ONE_PPN             0
    257256#define DEBUG_VMM_GET_PTE                 0
    258 #define DEBUG_VMM_HANDLE_PAGE_FAULT       19000000
     257#define DEBUG_VMM_HANDLE_PAGE_FAULT       0
    259258#define DEBUG_VMM_HANDLE_COW              0
    260259#define DEBUG_VMM_MMAP_ALLOC              0
     
    316315#define LOCK_FATFS_FAT        36   // remote (RW) protect exclusive access to the FATFS FAT
    317316
     317////////////////////////////////////////////////////////////////////////////////////////////
     318//                          GENERAL CONFIGURATION     
     319////////////////////////////////////////////////////////////////////////////////////////////
     320
     321#define CONFIG_VERSION           "Version 2.2 / June 2019"
    318322
    319323////////////////////////////////////////////////////////////////////////////////////////////
     
    376380#define CONFIG_VFS_ROOT_IS_EX2FS            0          // root FS is EX2FS if non zero
    377381
    378 #define CONFIG_MAPPER_GRDXT_W1              7      // number of bits for RADIX_TREE_IX1
    379 #define CONFIG_MAPPER_GRDXT_W2              7      // number of bits for RADIX_TREE_IX2
    380 #define CONFIG_MAPPER_GRDXT_W3              6      // number of bits for RADIX_TREE_IX3
     382#define CONFIG_MAPPER_GRDXT_W1              6          // number of bits for RADIX_TREE_IX1
     383#define CONFIG_MAPPER_GRDXT_W2              7          // number of bits for RADIX_TREE_IX2
     384#define CONFIG_MAPPER_GRDXT_W3              7          // number of bits for RADIX_TREE_IX3
    381385
    382386////////////////////////////////////////////////////////////////////////////////////////////
     
    445449#define CONFIG_PPM_MAX_RSVD           32           // max reserved zones on the machine
    446450
    447 #define CONFIG_KCM_SLOT_SIZE          64           // smallest allocated block (bytes)
    448 
    449451#define CONFIG_PPM_PAGE_ALIGNED       __attribute__((aligned(CONFIG_PPM_PAGE_SIZE)))
    450452
    451 
    452453////////////////////////////////////////////////////////////////////////////////////////////
    453454//                 INSTRUMENTATION
    454455////////////////////////////////////////////////////////////////////////////////////////////
    455456
    456 #define CONFIG_INSTRUMENTATION_SYSCALLS  0
    457 #define CONFIG_INSTRUMENTATION_PGFAULTS  1
    458 
     457#define CONFIG_INSTRUMENTATION_SYSCALLS    0
     458#define CONFIG_INSTRUMENTATION_PGFAULTS    1
     459#define CONFIG_INSTRUMENTATION_FOOTPRINT   1
    459460
    460461
  • trunk/kernel/libk/bits.c

    r473 r635  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner    (2016)
     5 *         Alain Greiner    (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
  • trunk/kernel/libk/bits.h

    r457 r635  
    33 *
    44 * Author   Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Alain Greiner    (2016)
     5 *          Alain Greiner    (2016,2017,2018,2019)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    189189
    190190/*********************************************************************************************
    191  * This function returns the number of bits to code a non-zero unsigned integer value.
    192  *********************************************************************************************
    193  * @ val   : value to analyse
    194  * @ returns number of bits
    195  ********************************************************************************************/
    196 static inline uint32_t bits_nr( uint32_t val )
    197 {
    198         register uint32_t i;
    199 
    200         for( i=0 ; val > 0 ; i++ )
    201                 val = val >> 1;
    202 
    203         return i;
    204 }
    205 
    206 /*********************************************************************************************
    207  * This function takes an unsigned integer value as input argument, and returns another
    208  * unsigned integer, that is the (base 2) logarithm of the smallest power of 2 contained
    209  * in the input value.
     191 * This function takes a positive integer <val> as input argument, and returns the smallest
     192 * integer <order> such as : 1<<order >= val.
     193 * In other words, <order> is the min number of bits to encode <val> values.
    210194 *********************************************************************************************
    211195 * @ val   : value to analyse
     
    214198static inline uint32_t bits_log2( uint32_t val )
    215199{
    216         return (val == 0) ? 1 : bits_nr( val ) - 1;
     200    uint32_t i;
     201
     202    if( val > 0 )
     203    {
     204        val--;
     205        for( i=0 ; val > 0 ; i++ ) val = val >> 1;
     206        return i;
     207    }
     208    return 0;
    217209}
    218210
  • trunk/kernel/libk/elf.c

    r625 r635  
    22 * elf.c - elf parser: find and map process CODE and DATA segments
    33 *
    4  * Authors   Alain Greiner    (2016)
     4 * Authors   Alain Greiner    (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    201201printk("\n[%s] thread[%x,%x] found %s vseg / base %x / size %x\n"
    202202"  file_size %x / file_offset %x / mapper_xp %l / cycle %d\n",
    203 __FUNCTION__ , this->process_pid, this->trdid,
     203__FUNCTION__ , this->process->pid, this->trdid,
    204204vseg_type_str(vseg->type) , vseg->min , vseg->max - vseg->min ,
    205 vseg->file_size , vseg->file_offset , vseg->mapper_xp );
     205vseg->file_size , vseg->file_offset , vseg->mapper_xp, cycle );
    206206#endif
    207207
     
    262262
    263263        // allocate memory for segment descriptors array
    264         req.type  = KMEM_GENERIC;
    265         req.size  = segs_size;
     264        req.type  = KMEM_KCM;
     265        req.order = bits_log2(segs_size);
    266266        req.flags = AF_KERNEL;
    267267        segs_base = kmem_alloc( &req );
  • trunk/kernel/libk/grdxt.c

    r626 r635  
    3030#include <grdxt.h>
    3131
     32////////////////////////////////////////////////////////////////////////////////////////
     33//               Local access functions
     34////////////////////////////////////////////////////////////////////////////////////////
     35
    3236/////////////////////////////////
    3337error_t grdxt_init( grdxt_t * rt,
     
    4448
    4549    // allocates first level array
    46         req.type  = KMEM_GENERIC;
    47         req.size  = sizeof(void *) << ix1_width;
     50        req.type  = KMEM_KCM;
     51        req.order = ix1_width + ( (sizeof(void*) == 4) ? 2 : 3 );
    4852        req.flags = AF_KERNEL | AF_ZERO;
    4953        root = kmem_alloc( &req );
    50         if( root == NULL ) return ENOMEM;
     54
     55        if( root == NULL )
     56    {
     57        printk("\n[ERROR] in %s : cannot allocate first level array\n", __FUNCTION__);
     58        return -1;
     59    }
    5160 
    5261        rt->root = root;
     
    7180        uint32_t   ix1;
    7281        uint32_t   ix2;
    73 
    74 // check rt
     82        uint32_t   ix3;
     83
    7584assert( (rt != NULL) , "pointer on radix tree is NULL\n" );
    76 
    77         req.type = KMEM_GENERIC;
    7885
    7986        for( ix1=0 ; ix1 < (uint32_t)(1 << w1) ; ix1++ )
     
    8996                    if( ptr3 == NULL ) continue;
    9097
     98            for( ix3=0 ; ix3 < (uint32_t)(1 << w3) ; ix3++ )
     99            {
     100                 if( ptr3[ix3] != NULL )
     101                 {
     102                     printk("\n[WARNING] in %s : ptr3[%d][%d][%d] non empty\n",
     103                     __FUNCTION__, ix1, ix2, ix3 );
     104                 }
     105            }
     106
    91107            // release level 3 array
     108            req.type = KMEM_KCM;
    92109                    req.ptr  = ptr3;
    93             req.type = KMEM_GENERIC;
    94             req.size = sizeof(void *) * (1 << w3);
    95110                    kmem_free( &req );
    96111        }
    97112
    98113        // release level 2 array
     114        req.type = KMEM_KCM;
    99115                req.ptr  = ptr2;
    100         req.type = KMEM_GENERIC;
    101         req.size = sizeof(void *) * (1 << w2);
    102116                kmem_free( &req );
    103117    }
    104118
    105119    // release level 1 array
     120    req.type = KMEM_KCM;
    106121        req.ptr  = ptr1;
    107     req.type = KMEM_GENERIC;
    108     req.size = sizeof(void *) * (1 << w1);
    109122        kmem_free( &req );
    110123
    111124}  // end grdxt_destroy()
    112 
    113 ////////////////////////////////////
    114 void grdxt_display( xptr_t    rt_xp,
    115                     char    * name )
    116 {
    117         uint32_t       ix1; 
    118         uint32_t       ix2;
    119         uint32_t       ix3;
    120 
    121 // check rt_xp
    122 assert( (rt_xp != XPTR_NULL) , "pointer on radix tree is NULL\n" );
    123 
    124     // get cluster and local pointer on remote rt descriptor
    125     grdxt_t      * rt_ptr = GET_PTR( rt_xp );
    126     cxy_t          rt_cxy = GET_CXY( rt_xp );
    127 
    128     // get widths
    129     uint32_t       w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
    130     uint32_t       w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
    131     uint32_t       w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
    132 
    133     void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
    134 
    135         printk("\n***** Generic Radix Tree for <%s>\n", name );
    136 
    137         for( ix1=0 ; ix1 < (uint32_t)(1<<w1) ; ix1++ )
    138         {
    139             void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
    140         if( ptr2 == NULL )  continue;
    141    
    142         for( ix2=0 ; ix2 < (uint32_t)(1<<w2) ; ix2++ )
    143         {
    144                 void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
    145             if( ptr3 == NULL ) continue;
    146 
    147             for( ix3=0 ; ix3 < (uint32_t)(1<<w3) ; ix3++ )
    148             {
    149                 void * value = hal_remote_lpt( XPTR( rt_cxy , &ptr3[ix3] ) );
    150                 if( value == NULL )  continue;
    151 
    152                 uint32_t key = (ix1<<(w2+w3)) + (ix2<<w3) + ix3;
    153                 printk(" - key = %x / value = %x\n", key , (intptr_t)value );
    154             }
    155         }
    156         }
    157 
    158 } // end grdxt_display()
    159125
    160126////////////////////////////////////
     
    177143        uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
    178144
    179     void         ** ptr1 = rt->root;                     // pointer on level 1 array
    180         void         ** ptr2;                                // pointer on level 2 array
    181         void         ** ptr3;                                // pointer on level 3 array
    182 
    183     // If required, we must allocate memory for the selected level 2 array,
    184     // and update the level 1 array.
    185         if( ptr1[ix1] == NULL )
     145    // get ptr1
     146    void ** ptr1 = rt->root;
     147
     148    if( ptr1 == NULL ) return -1;
     149
     150    // get ptr2
     151        void ** ptr2 = ptr1[ix1];
     152
     153    // If required, allocate memory for the missing level 2 array
     154        if( ptr2 == NULL )
    186155        {
    187156        // allocate memory for level 2 array
    188         req.type = KMEM_GENERIC;
    189         req.size = sizeof(void *) << w2;
     157        req.type  = KMEM_KCM;
     158        req.order = w2 + ( (sizeof(void*) == 4) ? 2 : 3 );
    190159        req.flags = AF_KERNEL | AF_ZERO;
    191160        ptr2 = kmem_alloc( &req );
    192         if( ptr2 == NULL) return ENOMEM;
     161
     162        if( ptr2 == NULL) return -1;
    193163
    194164        // update level 1 array
    195165        ptr1[ix1] = ptr2;
    196166        }
    197     else    // get pointer on selected level 2 array.
    198     {
    199             ptr2 = ptr1[ix1];
    200     }
    201 
    202     // If required, we must allocate memory for the selected level 3 array,
    203     // and update the level 2 array.
    204         if( ptr2[ix2] == NULL )
     167
     168    // get ptr3
     169        void ** ptr3 = ptr2[ix2];
     170
     171    // If required, allocate memory for the missing level 3 array
     172        if( ptr3 == NULL )
    205173        {
    206174        // allocate memory for level 3 array
    207         req.type = KMEM_GENERIC;
    208         req.size = sizeof(void *) << w3;
     175        req.type = KMEM_KCM;
     176        req.order = w3 + ( (sizeof(void*) == 4) ? 2 : 3 );
    209177        req.flags = AF_KERNEL | AF_ZERO;
    210178        ptr3 = kmem_alloc( &req );
    211         if( ptr3 == NULL) return ENOMEM;
     179
     180        if( ptr3 == NULL) return -1;
    212181
    213182        //  update level 3 array
    214183                ptr2[ix2] = ptr3;
    215184        }
    216     else    // get pointer on selected level 3 array.
    217     {
    218             ptr3 = ptr2[ix2];
    219     }
    220 
    221     // selected slot in level 3 array must be empty
    222         if( ptr3[ix3] != NULL ) return EEXIST;
    223185
    224186    // register the value
    225187        ptr3[ix3] = value;
     188
    226189        hal_fence();
    227190
     
    246209        uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
    247210
    248     void         ** ptr1 = rt->root;                     // pointer on level 1 array
    249         void         ** ptr2;                                // pointer on level 2 array
    250         void         ** ptr3;                                // pointer on level 3 array
     211    // get ptr1
     212    void ** ptr1 = rt->root;
     213
     214    if( ptr1 == NULL ) return NULL;
    251215
    252216    // get ptr2
    253         ptr2 = ptr1[ix1];
     217        void ** ptr2 = ptr1[ix1];
     218
    254219        if( ptr2 == NULL ) return NULL;
    255220
    256221    // get ptr3
    257         ptr3 = ptr2[ix2];
     222        void ** ptr3 = ptr2[ix2];
     223
    258224        if( ptr3 == NULL ) return NULL;
    259225
     
    303269
    304270}  // end grdxt_lookup()
    305 
    306 ////////////////////////////////////////////
    307 xptr_t grdxt_remote_lookup( xptr_t    rt_xp,
    308                             uint32_t  key )
    309 {
    310     // get cluster and local pointer on remote rt descriptor
    311     grdxt_t       * rt_ptr = GET_PTR( rt_xp );
    312     cxy_t           rt_cxy = GET_CXY( rt_xp );
    313 
    314     // get widths
    315     uint32_t        w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
    316     uint32_t        w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
    317     uint32_t        w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
    318 
    319 // Check key value
    320 assert( ((key >> (w1 + w2 + w3)) == 0 ), "illegal key value %x\n", key );
    321 
    322     // compute indexes
    323     uint32_t        ix1 = key >> (w2 + w3);              // index in level 1 array
    324         uint32_t        ix2 = (key >> w3) & ((1 << w2) -1);  // index in level 2 array
    325         uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
    326 
    327     // get ptr1
    328     void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
    329 
    330     // get ptr2
    331         void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
    332         if( ptr2 == NULL ) return XPTR_NULL;
    333 
    334     // get ptr3
    335         void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
    336         if( ptr3 == NULL ) return XPTR_NULL;
    337 
    338     // get pointer on registered item
    339     void  * item_ptr = hal_remote_lpt( XPTR( rt_cxy , &ptr3[ix3] ) );
    340 
    341     // return extended pointer on registered item
    342     if ( item_ptr == NULL )  return XPTR_NULL;
    343         else                     return XPTR( rt_cxy , item_ptr );
    344 
    345 }  // end grdxt_remote_lookup()
    346271
    347272//////////////////////////////////////
     
    400325
    401326}  // end grdxt_get_first()
     327
     328
     329
     330////////////////////////////////////////////////////////////////////////////////////////
     331//               Remote access functions
     332////////////////////////////////////////////////////////////////////////////////////////
     333
     334//////////////////////////////////////////////
     335error_t grdxt_remote_insert( xptr_t     rt_xp,
     336                             uint32_t   key,
     337                             void     * value )
     338{
     339    kmem_req_t  req;
     340
     341    // get cluster and local pointer on remote rt descriptor
     342        cxy_t     rt_cxy = GET_CXY( rt_xp );
     343    grdxt_t * rt_ptr = GET_PTR( rt_xp );
     344
     345    // get widths
     346    uint32_t        w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
     347    uint32_t        w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
     348    uint32_t        w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
     349
     350// Check key value
     351assert( ((key >> (w1 + w2 + w3)) == 0 ), "illegal key value %x\n", key );
     352
     353    // compute indexes
     354    uint32_t        ix1 = key >> (w2 + w3);              // index in level 1 array
     355        uint32_t        ix2 = (key >> w3) & ((1 << w2) -1);  // index in level 2 array
     356        uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
     357
     358    // get ptr1
     359    void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
     360
     361    if( ptr1 == NULL ) return -1;
     362
     363    // get ptr2
     364    void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
     365
     366    // allocate memory for the missing level_2 array if required
     367    if( ptr2 == NULL )
     368    {
     369        // allocate memory in remote cluster
     370        req.type  = KMEM_KCM;
     371        req.order = w2 + ((sizeof(void*) == 4) ? 2 : 3 );
     372        req.flags = AF_ZERO | AF_KERNEL;
     373        ptr2 = kmem_remote_alloc( rt_cxy , &req );
     374
     375        if( ptr2 == NULL ) return -1;
     376
     377        // update level_1 entry
     378        hal_remote_spt( XPTR( rt_cxy , &ptr1[ix1] ) , ptr2 );
     379    }
     380
     381    // get ptr3
     382    void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
     383
     384    // allocate memory for the missing level_3 array if required
     385    if( ptr3 == NULL )
     386    {
     387        // allocate memory in remote cluster
     388        req.type  = KMEM_KCM;
     389        req.order = w3 + ((sizeof(void*) == 4) ? 2 : 3 );
     390        req.flags = AF_ZERO | AF_KERNEL;
     391        ptr3 = kmem_remote_alloc( rt_cxy , &req );
     392
     393        if( ptr3 == NULL ) return -1;
     394
     395        // update level_2 entry
     396        hal_remote_spt( XPTR( rt_cxy , &ptr2[ix2] ) , ptr3 );
     397    }
     398
     399    // register value in level_3 array
     400    hal_remote_spt( XPTR( rt_cxy , &ptr3[ix3] ) , value );
     401
     402    hal_fence();
     403
     404        return 0;
     405
     406}  // end grdxt_remote_insert()
     407
     408////////////////////////////////////////////
     409void * grdxt_remote_remove( xptr_t    rt_xp,
     410                            uint32_t  key )
     411{
     412    // get cluster and local pointer on remote rt descriptor
     413        cxy_t     rt_cxy = GET_CXY( rt_xp );
     414    grdxt_t * rt_ptr = GET_PTR( rt_xp );
     415
     416    // get widths
     417    uint32_t        w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
     418    uint32_t        w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
     419    uint32_t        w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
     420
     421// Check key value
     422assert( ((key >> (w1 + w2 + w3)) == 0 ), "illegal key value %x\n", key );
     423
     424    // compute indexes
     425    uint32_t        ix1 = key >> (w2 + w3);              // index in level 1 array
     426        uint32_t        ix2 = (key >> w3) & ((1 << w2) -1);  // index in level 2 array
     427        uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
     428
     429    // get ptr1
     430    void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
     431
     432    // get ptr2
     433        void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
     434        if( ptr2 == NULL ) return NULL;
     435
     436    // get ptr3
     437        void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
     438        if( ptr3 == NULL ) return NULL;
     439
     440    // get value
     441        void * value = hal_remote_lpt( XPTR( rt_cxy , &ptr3[ix3] ) );
     442
     443    // reset selected slot
     444        hal_remote_spt( XPTR( rt_cxy, &ptr3[ix3] ) , NULL );
     445        hal_fence();
     446
     447        return value;
     448
     449}  // end grdxt_remote_remove()
     450
     451////////////////////////////////////////////
     452xptr_t grdxt_remote_lookup( xptr_t    rt_xp,
     453                            uint32_t  key )
     454{
     455    // get cluster and local pointer on remote rt descriptor
     456    grdxt_t       * rt_ptr = GET_PTR( rt_xp );
     457    cxy_t           rt_cxy = GET_CXY( rt_xp );
     458
     459    // get widths
     460    uint32_t        w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
     461    uint32_t        w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
     462    uint32_t        w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
     463
     464// Check key value
     465assert( ((key >> (w1 + w2 + w3)) == 0 ), "illegal key value %x\n", key );
     466
     467    // compute indexes
     468    uint32_t        ix1 = key >> (w2 + w3);              // index in level 1 array
     469        uint32_t        ix2 = (key >> w3) & ((1 << w2) -1);  // index in level 2 array
     470        uint32_t        ix3 = key & ((1 << w3) - 1);         // index in level 3 array
     471
     472    // get ptr1
     473    void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
     474
     475    // get ptr2
     476        void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
     477        if( ptr2 == NULL ) return XPTR_NULL;
     478
     479    // get ptr3
     480        void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
     481        if( ptr3 == NULL ) return XPTR_NULL;
     482
     483    // get pointer on registered item
     484    void  * item_ptr = hal_remote_lpt( XPTR( rt_cxy , &ptr3[ix3] ) );
     485
     486    // return extended pointer on registered item
     487    if ( item_ptr == NULL )  return XPTR_NULL;
     488        else                     return XPTR( rt_cxy , item_ptr );
     489
     490}  // end grdxt_remote_lookup()
     491
     492/////////////////////////i/////////////////
     493void grdxt_remote_display( xptr_t    rt_xp,
     494                           char    * name )
     495{
     496        uint32_t       ix1; 
     497        uint32_t       ix2;
     498        uint32_t       ix3;
     499
     500// check rt_xp
     501assert( (rt_xp != XPTR_NULL) , "pointer on radix tree is NULL\n" );
     502
     503    // get cluster and local pointer on remote rt descriptor
     504    grdxt_t      * rt_ptr = GET_PTR( rt_xp );
     505    cxy_t          rt_cxy = GET_CXY( rt_xp );
     506
     507    // get widths
     508    uint32_t       w1 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix1_width ) );
     509    uint32_t       w2 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix2_width ) );
     510    uint32_t       w3 = hal_remote_l32( XPTR( rt_cxy , &rt_ptr->ix3_width ) );
     511
     512    void ** ptr1 = hal_remote_lpt( XPTR( rt_cxy , &rt_ptr->root ) );
     513
     514        printk("\n***** Generic Radix Tree for <%s>\n", name );
     515
     516        for( ix1=0 ; ix1 < (uint32_t)(1<<w1) ; ix1++ )
     517        {
     518            void ** ptr2 = hal_remote_lpt( XPTR( rt_cxy , &ptr1[ix1] ) );
     519        if( ptr2 == NULL )  continue;
     520   
     521        for( ix2=0 ; ix2 < (uint32_t)(1<<w2) ; ix2++ )
     522        {
     523                void ** ptr3 = hal_remote_lpt( XPTR( rt_cxy , &ptr2[ix2] ) );
     524            if( ptr3 == NULL ) continue;
     525
     526            for( ix3=0 ; ix3 < (uint32_t)(1<<w3) ; ix3++ )
     527            {
     528                void * value = hal_remote_lpt( XPTR( rt_cxy , &ptr3[ix3] ) );
     529                if( value == NULL )  continue;
     530
     531                uint32_t key = (ix1<<(w2+w3)) + (ix2<<w3) + ix3;
     532                printk(" - key = %x / value = %x\n", key , (intptr_t)value );
     533            }
     534        }
     535        }
     536
     537} // end grdxt_remote_display()
     538
     539
  • trunk/kernel/libk/grdxt.h

    r626 r635  
    3636 * Memory for the second and third levels arrays is dynamically allocated by the
    3737 * grdxt_insert() function and is only released by grdxt_destroy().
    38  * - This structure is entirely contained in one single cluster.
    39  * - All modifications (insert / remove) must be done by a thread running in local cluster.
    40  * - Lookup can be done by a thread running in any cluster (local or remote).
     38 * This structure is entirely contained in one single cluster, but to allow any thread
     39 * to access it, two sets of access functions are defined:
     40 * - local threads can use access function using local pointers.
     41 * - remote threads must use the access functions using extended pointers.
    4142 ******************************************************************************************
    4243 * When it is used by the mapper implementing the file cache:
     
    5455grdxt_t;
    5556
     57////////////////////////////////////////////////////////////////////////////////////////////
     58//                       Local access functions
     59////////////////////////////////////////////////////////////////////////////////////////////
     60
    5661/*******************************************************************************************
    5762 * This function initialises the radix-tree descriptor,
     63 * It must be called by a local thread.
    5864 * and allocates memory for the first level array of pointers.
    5965 *******************************************************************************************
     
    7177/*******************************************************************************************
    7278 * This function releases all memory allocated to the radix-tree infrastructure.
    73  * The radix-tree is supposed to be empty, but this is NOT checked by this function.
     79 * It must be called by a local thread.
     80 * A warning message is printed on the kernel TXT0 if the radix tree is not empty.
    7481 *******************************************************************************************
    7582 * @ rt      : pointer on the radix-tree descriptor.
     
    7986/*******************************************************************************************
    8087 * This function insert a new item in the radix-tree.
     88 * It must be called by a local thread.
    8189 * It dynamically allocates memory for new second and third level arrays if required.
    8290 *******************************************************************************************
     
    8492 * @ key     : key value.
    8593 * @ value   : pointer on item to be registered in radix-tree.
    86  * @ returns 0 if success / returns ENOMEM if no memory, or EINVAL if illegal key.
     94 * @ returns 0 if success / returns -1 if no memory, or illegal key.
    8795 ******************************************************************************************/
    8896error_t grdxt_insert( grdxt_t  * rt,
     
    9199
    92100/*******************************************************************************************
    93  * This function removes an item identified by its key, and returns a pointer
    94  * on the removed item. No memory is released.
     101 * This function removes an item identified by its key from the radix tree,
     102 * It must be called by a local thread.
     103 * and returns a pointer on the removed item. No memory is released.
    95104 *******************************************************************************************
    96105 * @ rt      : pointer on the radix-tree descriptor.
     
    103112/*******************************************************************************************
    104113 * This function returns to a local client, a local pointer on the item identified
     114 * It must be called by a local thread.
    105115 * by the <key> argument, from the radix tree identified by the <rt> local pointer.
    106116 *******************************************************************************************
     
    113123
    114124/*******************************************************************************************
    115  * This function returns to a - possibly remote - remote client, an extended pointer
    116  * on the item identified by the <key> argument, from the radix tree identified by
    117  * the <rt_xp> remote pointer.
    118  *******************************************************************************************
    119  * @ rt_xp   : extended pointer on the radix-tree descriptor.
    120  * @ key     : key value.
    121  * @ returns an extended pointer on found item if success / returns XPTR_NULL if failure.
    122  ******************************************************************************************/
    123 xptr_t grdxt_remote_lookup( xptr_t     rt_xp,
    124                             uint32_t   key );
    125 
    126 /*******************************************************************************************
    127125 * This function scan all radix-tree entries in increasing key order, starting from
     126 * It must be called by a local thread.
    128127 * the value defined by the <key> argument, and return a pointer on the first valid
    129128 * registered item, and the found item key value.
     
    138137                        uint32_t * found_key );
    139138
     139////////////////////////////////////////////////////////////////////////////////////////////
     140//                       Remote access functions
     141////////////////////////////////////////////////////////////////////////////////////////////
     142
     143/*******************************************************************************************
     144 * This function insert a new item in a - possibly remote - radix tree.
     145 * It dynamically allocates memory for new second and third level arrays if required.
     146 *******************************************************************************************
     147 * @ rt_xp   : extended pointer on the radix-tree descriptor.
     148 * @ key     : key value.
     149 * @ value   : pointer on item to be registered in radix-tree.
     150 * @ returns 0 if success / returns -1 if no memory, or illegal key.
     151 ******************************************************************************************/
     152error_t grdxt_remote_insert( xptr_t     rt_xp,
     153                             uint32_t   key,
     154                             void     * value );
     155
     156/*******************************************************************************************
     157 * This function removes an item identified by its key from a - possibly remote - radix
     158 * tree, and returns a local pointer on the removed item. No memory is released.
     159 *******************************************************************************************
     160 * @ rt_xp   : pointer on the radix-tree descriptor.
     161 * @ key     : key value.
     162 * @ returns local pointer on removed item if success / returns NULL if failure.
     163 ******************************************************************************************/
     164void * grdxt_remote_remove( xptr_t    rt_xp,
     165                            uint32_t  key );
     166
     167/*******************************************************************************************
     168 * This function returns to a - possibly remote - client, an extended pointer
     169 * on the item identified by the <key> argument, from the radix tree identified by
     170 * the <rt_xp> remote pointer.
     171 *******************************************************************************************
     172 * @ rt_xp   : extended pointer on the radix-tree descriptor.
     173 * @ key     : key value.
     174 * @ returns an extended pointer on found item if success / returns XPTR_NULL if failure.
     175 ******************************************************************************************/
     176xptr_t grdxt_remote_lookup( xptr_t     rt_xp,
     177                            uint32_t   key );
     178
    140179/*******************************************************************************************
    141180 * This function displays the current content of a possibly remote radix_tree.
     
    144183 * @ string  : radix tree identifier.
    145184 ******************************************************************************************/
    146 void grdxt_display( xptr_t    rt_xp,
    147                     char    * string );
    148 
     185void grdxt_remote_display( xptr_t    rt_xp,
     186                           char    * string );
    149187
    150188#endif  /* _GRDXT_H_ */
  • trunk/kernel/libk/list.h

    r632 r635  
    304304 **************************************************************************/
    305305
    306 #define LIST_REMOTE_FIRST( cxy , root , type , member )                       \
    307     ({ list_entry_t * __first = hal_remote_lpt( XPTR( cxy , &root->next ) ); \
    308            LIST_ELEMENT( __first , type , member ); })
     306#define LIST_REMOTE_FIRST( cxy , root , type , member )                \
     307        LIST_ELEMENT( hal_remote_lpt( XPTR( (cxy) , &(root)->next ) ), \
     308                  type , member )
    309309
    310310/***************************************************************************
     
    314314 * item(s) from the traversed list.     
    315315 ***************************************************************************
    316  * @ cxy     : remote list cluster identifier
     316 * @ cxy     : remote cluster identifier
    317317 * @ root    : pointer on the root list_entry
    318318 * @ iter    : pointer on the current list_entry
  • trunk/kernel/libk/remote_barrier.c

    r632 r635  
    8383                                pthread_barrierattr_t * attr )
    8484{
    85     xptr_t              gen_barrier_xp;   // extended pointer on generic barrier descriptor
    8685    generic_barrier_t * gen_barrier_ptr;  // local pointer on generic barrier descriptor
    8786    void              * barrier;          // local pointer on implementation barrier descriptor     
     
    9796
    9897    // allocate memory for generic barrier descriptor
    99     if( ref_cxy == local_cxy )                         // reference cluster is local
    100     {
    101         req.type          = KMEM_GEN_BARRIER;
    102         req.flags         = AF_ZERO;
    103         gen_barrier_ptr   = kmem_alloc( &req );
    104         gen_barrier_xp    = XPTR( local_cxy , gen_barrier_ptr );
    105     }
    106     else                                               // reference cluster is remote
    107     {
    108         rpc_kcm_alloc_client( ref_cxy,
    109                               KMEM_GEN_BARRIER,
    110                               &gen_barrier_xp );
    111         gen_barrier_ptr = GET_PTR( gen_barrier_xp );
    112     }
     98    req.type   = KMEM_KCM;
     99    req.order  = bits_log2( sizeof(generic_barrier_t) );
     100    req.flags  = AF_ZERO | AF_KERNEL;
     101    gen_barrier_ptr = kmem_remote_alloc( ref_cxy , &req );
    113102
    114103    if( gen_barrier_ptr == NULL )
     
    124113         barrier = simple_barrier_create( count );
    125114
    126         if( barrier == NULL )
    127         {
    128             printk("\n[ERROR] in %s : cannot create simple barrier\n", __FUNCTION__);
    129             return -1;
    130         }
     115        if( barrier == NULL ) return -1;
    131116    }
    132117    else                                                  // QDT barrier implementation
     
    147132        barrier = dqt_barrier_create( x_size , y_size , nthreads );
    148133
    149         if( barrier == NULL )
    150         {
    151             printk("\n[ERROR] in %s : cannot create DQT barrier descriptor\n", __FUNCTION__);
    152             return -1;
    153         }
     134        if( barrier == NULL ) return -1;
    154135    }
    155136
     
    211192
    212193    // release memory allocated to barrier descriptor
    213     if( gen_barrier_cxy == local_cxy )           
    214     {
    215         req.type          = KMEM_GEN_BARRIER;
    216         req.ptr           = gen_barrier_ptr;
    217         kmem_free( &req );
    218     }
    219     else         
    220     {
    221         rpc_kcm_free_client( gen_barrier_cxy,
    222                              gen_barrier_ptr,
    223                              KMEM_GEN_BARRIER );
    224     }
     194    req.type          = KMEM_KCM;
     195    req.ptr           = gen_barrier_ptr;
     196    kmem_remote_free( ref_cxy , &req );
     197
    225198}  // end generic_barrier_destroy()
    226199
     
    273246simple_barrier_t * simple_barrier_create( uint32_t  count )
    274247{
    275     xptr_t             barrier_xp;
     248    kmem_req_t         req;
    276249    simple_barrier_t * barrier;
    277250
     
    285258
    286259    // allocate memory for simple barrier descriptor
    287     if( ref_cxy == local_cxy )                        // reference is local
    288     {
    289         kmem_req_t req;
    290         req.type      = KMEM_SMP_BARRIER;
    291         req.flags     = AF_ZERO;
    292         barrier       = kmem_alloc( &req );
    293         barrier_xp    = XPTR( local_cxy , barrier );
    294     }
    295     else                                             // reference is remote
    296     {
    297         rpc_kcm_alloc_client( ref_cxy,
    298                               KMEM_SMP_BARRIER,
    299                               &barrier_xp );
    300         barrier = GET_PTR( barrier_xp );
    301     }
    302 
    303     if( barrier == NULL ) return NULL;
     260    req.type   = KMEM_KCM;
     261    req.order  = bits_log2( sizeof(simple_barrier_t) );
     262    req.flags  = AF_ZERO | AF_KERNEL;
     263    barrier    = kmem_remote_alloc( ref_cxy , &req );
     264
     265    if( barrier == NULL )
     266    {
     267        printk("\n[ERROR] in %s : cannot create simple barrier\n", __FUNCTION__ );
     268        return NULL;
     269    }
    304270
    305271    // initialise simple barrier descriptor
     
    325291void simple_barrier_destroy( xptr_t barrier_xp )
    326292{
     293    kmem_req_t  req;
     294
    327295    // get barrier cluster and local pointer
    328296    cxy_t              barrier_cxy = GET_CXY( barrier_xp );
     
    330298
    331299    // release memory allocated for barrier descriptor
    332     if( barrier_cxy == local_cxy )
    333     {
    334         kmem_req_t  req;
    335         req.type = KMEM_SMP_BARRIER;
    336         req.ptr  = barrier_ptr;
    337         kmem_free( &req );
    338     }
    339     else 
    340     {
    341         rpc_kcm_free_client( barrier_cxy,
    342                              barrier_ptr,
    343                              KMEM_SMP_BARRIER );
    344     }
     300    req.type = KMEM_KCM;
     301    req.ptr  = barrier_ptr;
     302    kmem_remote_free( barrier_cxy , &req );
    345303
    346304#if DEBUG_BARRIER_DESTROY
     
    498456
    499457#if DEBUG_BARRIER_CREATE
    500 static void dqt_barrier_display( xptr_t  barrier_xp );
     458void dqt_barrier_display( xptr_t  barrier_xp );
    501459#endif
    502460
     
    506464                                    uint32_t    nthreads )
    507465{
    508     xptr_t          dqt_page_xp;     
    509     page_t        * rpc_page;
    510     xptr_t          rpc_page_xp;     
    511466    dqt_barrier_t * barrier;       // local pointer on DQT barrier descriptor
    512467    xptr_t          barrier_xp;    // extended pointer on DQT barrier descriptor
    513468    uint32_t        z;             // actual DQT size == max(x_size,y_size)
    514469    uint32_t        levels;        // actual number of DQT levels
    515     xptr_t          rpc_xp;        // extended pointer on RPC descriptors array
    516     rpc_desc_t    * rpc;           // pointer on RPC descriptors array
    517     uint32_t        responses;     // responses counter for parallel RPCs
    518     reg_t           save_sr;       // for critical section
    519470    uint32_t        x;             // X coordinate in QDT mesh
    520471    uint32_t        y;             // Y coordinate in QDT mesh
     
    522473    kmem_req_t      req;           // kmem request
    523474
    524     // compute size and number of DQT levels
     475    // compute number of DQT levels, depending on the mesh size
    525476    z      = (x_size > y_size) ? x_size : y_size;
    526477    levels = (z < 2) ? 1 : (z < 3) ? 2 : (z < 5) ? 3 : (z < 9) ? 4 : 5;
     
    529480assert( (z <= 16) , "DQT mesh size larger than (16*16)\n");
    530481
    531 // check RPC descriptor size
    532 assert( (sizeof(rpc_desc_t) <= 128), "RPC descriptor  larger than 128 bytes\n");
    533 
    534482// check size of an array of 5 DQT nodes
    535483assert( (sizeof(dqt_node_t) * 5 <= 512 ), "array of DQT nodes larger than 512 bytes\n");
     
    538486assert( (sizeof(dqt_barrier_t) <= 0x4000 ), "DQT barrier descriptor larger than 4 pages\n");
    539487
    540     // get pointer on local client process descriptor
     488    // get pointer on client thread and process descriptors
    541489    thread_t  * this    = CURRENT_THREAD;
    542490    process_t * process = this->process;
     
    553501    cxy_t          ref_cxy = GET_CXY( ref_xp );
    554502
    555     // 1. allocate 4 4 Kbytes pages for DQT barrier descriptor in reference cluster
    556     dqt_page_xp = ppm_remote_alloc_pages( ref_cxy , 2 );
    557 
    558     if( dqt_page_xp == XPTR_NULL ) return NULL;
    559 
    560     // get pointers on DQT barrier descriptor
    561     barrier_xp = ppm_page2base( dqt_page_xp );
    562     barrier    = GET_PTR( barrier_xp );
     503    // 1. allocate 4 small pages for the DQT barrier descriptor in reference cluster
     504    req.type   = KMEM_PPM;
     505    req.order  = 2;                     // 4 small pages == 16 Kbytes                     
     506    req.flags  = AF_ZERO | AF_KERNEL;
     507    barrier    = kmem_remote_alloc( ref_cxy , &req );
     508
     509    if( barrier == NULL )
     510    {
     511        printk("\n[ERROR] in %s : cannot create DQT barrier\n", __FUNCTION__ );
     512        return NULL;
     513    }
     514
     515    // get pointers on DQT barrier descriptor in reference cluster
     516    barrier_xp = XPTR( ref_cxy , barrier );
    563517
    564518    // initialize global parameters in DQT barrier descriptor
     
    569523#if DEBUG_BARRIER_CREATE
    570524if( cycle > DEBUG_BARRIER_CREATE )
    571 printk("\n[%s] thread[%x,%x] created DQT barrier descriptor at (%x,%x)\n",
     525printk("\n[%s] thread[%x,%x] created DQT barrier descriptor(%x,%x)\n",
    572526__FUNCTION__, process->pid, this->trdid, ref_cxy, barrier );
    573527#endif
    574528
    575     // 2. allocate memory from local cluster for an array of 256 RPCs descriptors
    576     //    cannot share the RPC descriptor, because the returned argument is not shared
    577     req.type    = KMEM_PAGE;
    578     req.size    = 3;            // 8 pages == 32 Kbytes
    579     req.flags   = AF_ZERO;
    580     rpc_page    = kmem_alloc( &req );
    581     rpc_page_xp = XPTR( local_cxy , rpc_page );
    582 
    583     // get pointers on RPC descriptors array
    584     rpc_xp    = ppm_page2base( rpc_page_xp );
    585     rpc       = GET_PTR( rpc_xp );
    586 
    587 #if DEBUG_BARRIER_CREATE
    588 if( cycle > DEBUG_BARRIER_CREATE )
    589 printk("\n[%s] thread[%x,%x] created RPC descriptors array at (%x,%s)\n",
    590 __FUNCTION__, process->pid, this->trdid, local_cxy, rpc );
    591 #endif
    592 
    593     // 3. send parallel RPCs to all existing clusters covered by the DQT
    594     //    to allocate memory for an array of 5 DQT nodes in each cluster
     529    // 2. allocate memory for an array of 5 DQT nodes 
     530    //    in all existing clusters covered by the DQDT
    595531    //    (5 nodes per cluster <= 512 bytes per cluster)
    596 
    597     responses = 0;    // initialize RPC responses counter
    598 
    599     // mask IRQs
    600     hal_disable_irq( &save_sr);
    601 
    602     // client thread blocks itself
    603     thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC );
    604 
     532    //    and complete barrier descriptor initialisation.
    605533    for ( x = 0 ; x < x_size ; x++ )
    606534    {
    607535        for ( y = 0 ; y < y_size ; y++ )
    608536        {
    609             // send RPC to existing clusters only
     537            cxy_t  cxy = HAL_CXY_FROM_XY( x , y );   // target cluster identifier
     538            xptr_t local_array_xp;                   // xptr of nodes array in cluster cxy
     539
     540            // allocate memory in existing clusters only
    610541            if( LOCAL_CLUSTER->cluster_info[x][y] )
    611542            {
    612                 cxy_t cxy = HAL_CXY_FROM_XY( x , y );   // target cluster identifier
    613 
    614                 // build a specific RPC descriptor for each target cluster
    615                 rpc[cxy].rsp       = &responses;
    616                 rpc[cxy].blocking  = false;
    617                 rpc[cxy].index     = RPC_KCM_ALLOC;
    618                 rpc[cxy].thread    = this;
    619                 rpc[cxy].lid       = this->core->lid;
    620                 rpc[cxy].args[0]   = (uint64_t)KMEM_512_BYTES; 
    621 
    622                 // atomically increment expected responses counter
    623                 hal_atomic_add( &responses , 1 );
    624 
    625                 // send a non-blocking RPC to allocate 512 bytes in target cluster
    626                 rpc_send( cxy , &rpc[cxy] );
    627             }
    628         }
    629     }
    630 
    631 #if DEBUG_BARRIER_CREATE
    632 if( cycle > DEBUG_BARRIER_CREATE )
    633 printk("\n[%s] thread[%x,%x] sent all RPC requests to allocate dqt_nodes array\n",
    634 __FUNCTION__, process->pid, this->trdid );
    635 #endif
    636 
    637     // client thread deschedule
    638     sched_yield("blocked on parallel rpc_kcm_alloc");
    639 
    640     // restore IRQs
    641     hal_restore_irq( save_sr);
    642 
    643     // 4. initialize the node_xp[x][y][l] array in DQT barrier descriptor
    644     //    the node_xp[x][y][0] value is available in rpc.args[1]
    645 
    646 #if DEBUG_BARRIER_CREATE
    647 if( cycle > DEBUG_BARRIER_CREATE )
    648 printk("\n[%s] thread[%x,%x] initialises array of pointers on dqt_nodes\n",
    649 __FUNCTION__, process->pid, this->trdid );
    650 #endif
    651 
    652     for ( x = 0 ; x < x_size ; x++ )
    653     {
    654         for ( y = 0 ; y < y_size ; y++ )
    655         {
    656             cxy_t    cxy      = HAL_CXY_FROM_XY( x , y );   // target cluster identifier
    657             xptr_t   array_xp = (xptr_t)rpc[cxy].args[1];   // x_pointer on node array
    658             uint32_t offset   = sizeof( dqt_node_t );       // size of a DQT node
    659                
    660             // set values into the node_xp[x][y][l] array
    661             for ( l = 0 ; l < levels ; l++ )
    662             {
    663                 xptr_t  node_xp = array_xp + (offset * l);
    664                 hal_remote_s64( XPTR( ref_cxy , &barrier->node_xp[x][y][l] ), node_xp );
    665 
    666 #if DEBUG_BARRIER_CREATE
     543                req.type  = KMEM_KCM;
     544                req.order = 9;                    // 512 bytes
     545                req.flags = AF_ZERO | AF_KERNEL;
     546
     547                void * ptr = kmem_remote_alloc( cxy , &req );
     548
     549                if( ptr == NULL )
     550                {
     551                    printk("\n[ERROR] in %s : cannot allocate DQT in cluster %x\n",
     552                    __FUNCTION__, cxy );
     553                    return NULL;
     554                }
     555       
     556                // build extended pointer on local node array in cluster cxy         
     557                            local_array_xp = XPTR( cxy , ptr );
     558
     559                // initialize the node_xp[x][y][l] array in barrier descriptor
     560                for ( l = 0 ; l < levels ; l++ )
     561                {
     562                    xptr_t  node_xp = local_array_xp + ( l * sizeof(dqt_node_t) );
     563                    hal_remote_s64( XPTR( ref_cxy , &barrier->node_xp[x][y][l] ), node_xp );
     564
     565#if (DEBUG_BARRIER_CREATE & 1)
    667566if( cycle > DEBUG_BARRIER_CREATE )
    668567printk(" - dqt_node_xp[%d,%d,%d] = (%x,%x) / &dqt_node_xp = %x\n",
    669568x , y , l , GET_CXY( node_xp ), GET_PTR( node_xp ), &barrier->node_xp[x][y][l] );
    670569#endif
     570                } 
    671571            }
    672         }
    673     }
    674 
    675     // 5. release memory locally allocated for the RPCs array
    676     req.type  = KMEM_PAGE;
    677     req.ptr   = rpc_page;
    678     kmem_free( &req );
     572            else   // register XPTR_NULL for all non-existing entries
     573            {
     574                for ( l = 0 ; l < levels ; l++ )
     575                {
     576                    hal_remote_s64( XPTR( ref_cxy , &barrier->node_xp[x][y][l] ), XPTR_NULL );
     577                }
     578            }
     579        }  // end for y
     580    }  // end for x
    679581
    680582#if DEBUG_BARRIER_CREATE
    681583if( cycle > DEBUG_BARRIER_CREATE )
    682 printk("\n[%s] thread[%x,%x] released memory for RPC descriptors array\n",
     584printk("\n[%s] thread[%x,%x] initialized array of pointers in DQT barrier\n",
    683585__FUNCTION__, process->pid, this->trdid );
    684586#endif
    685587
    686     // 6. initialise all distributed DQT nodes using remote accesses
     588    // 3. initialise all distributed DQT nodes using remote accesses
    687589    //    and the pointers stored in the node_xp[x][y][l] array
    688590    for ( x = 0 ; x < x_size ; x++ )
     
    827729void dqt_barrier_destroy( xptr_t   barrier_xp )
    828730{
    829     page_t     * rpc_page;
    830     xptr_t       rpc_page_xp;
    831     rpc_desc_t * rpc;                      // local pointer on RPC descriptors array
    832     xptr_t       rpc_xp;                   // extended pointer on RPC descriptor array
    833     reg_t        save_sr;                  // for critical section
    834731    kmem_req_t   req;                      // kmem request
    835 
    836     thread_t * this = CURRENT_THREAD;
     732    uint32_t     x;
     733    uint32_t     y;
     734
    837735
    838736    // get DQT barrier descriptor cluster and local pointer
     
    841739
    842740#if DEBUG_BARRIER_DESTROY
     741thread_t * this  = CURRENT_THREAD;
    843742uint32_t   cycle = (uint32_t)hal_get_cycles();
    844743if( cycle > DEBUG_BARRIER_DESTROY )
     
    851750    uint32_t y_size = hal_remote_l32( XPTR( barrier_cxy , &barrier_ptr->y_size ) );
    852751
    853     // 1. allocate memory from local cluster for an array of 256 RPCs descriptors
    854     //    cannot share the RPC descriptor, because the "buf" argument is not shared
    855     req.type    = KMEM_PAGE;
    856     req.size    = 3;            // 8 pages == 32 Kbytes
    857     req.flags   = AF_ZERO;
    858     rpc_page    = kmem_alloc( &req );
    859     rpc_page_xp = XPTR( local_cxy , rpc_page );
    860 
    861     // get pointers on RPC descriptors array
    862     rpc_xp    = ppm_page2base( rpc_page_xp );
    863     rpc       = GET_PTR( rpc_xp );
    864    
    865     // 2. send parallel RPCs to all existing clusters covered by the DQT
    866     //    to release memory allocated for the arrays of DQT nodes in each cluster
    867 
    868     uint32_t responses = 0;    // initialize RPC responses counter
    869 
    870     // mask IRQs
    871     hal_disable_irq( &save_sr);
    872 
    873     // client thread blocks itself
    874     thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_RPC );
    875 
    876     uint32_t x , y;
    877    
    878 #if DEBUG_BARRIER_DESTROY
    879 if( cycle > DEBUG_BARRIER_DESTROY )
    880 printk("\n[%s] thread[%x,%x] send RPCs to release the distributed dqt_node array\n",
    881 __FUNCTION__, this->process->pid, this->trdid );
    882 #endif
    883 
     752    // 1. release memory allocated for the DQT nodes
     753    //    in all clusters covered by the QDT mesh
    884754    for ( x = 0 ; x < x_size ; x++ )
    885755    {
    886756        for ( y = 0 ; y < y_size ; y++ )
    887757        {
    888             // send RPC to existing cluster only
     758            // compute target cluster identifier
     759            cxy_t   cxy = HAL_CXY_FROM_XY( x , y );
     760
     761            // existing cluster only
    889762            if( LOCAL_CLUSTER->cluster_info[x][y] )
    890763            {
    891                 // compute target cluster identifier
    892                 cxy_t   cxy       = HAL_CXY_FROM_XY( x , y );
    893 
    894764                // get local pointer on dqt_nodes array in target cluster 
    895765                xptr_t  buf_xp_xp = XPTR( barrier_cxy , &barrier_ptr->node_xp[x][y][0] );
     
    899769assert( (cxy == GET_CXY(buf_xp)) , "bad extended pointer on dqt_nodes array\n" );
    900770
    901                 // build a specific RPC descriptor
    902                 rpc[cxy].rsp       = &responses;
    903                 rpc[cxy].blocking  = false;
    904                 rpc[cxy].index     = RPC_KCM_FREE;
    905                 rpc[cxy].thread    = this;
    906                 rpc[cxy].lid       = this->core->lid;
    907                 rpc[cxy].args[0]   = (uint64_t)(intptr_t)buf; 
    908                 rpc[cxy].args[1]   = (uint64_t)KMEM_512_BYTES; 
    909 
    910                 // atomically increment expected responses counter
    911                 hal_atomic_add( &responses , 1 );
    912            
     771                req.type  = KMEM_KCM;
     772                req.ptr   = buf;
     773                kmem_remote_free( cxy , &req );
     774
    913775#if DEBUG_BARRIER_DESTROY
     776thread_t * this  = CURRENT_THREAD;
     777uint32_t   cycle = (uint32_t)hal_get_cycles();
    914778if( cycle > DEBUG_BARRIER_DESTROY )
    915 printk(" - target cluster(%d,%d) / buffer %x\n", x, y, buf );
    916 #endif
    917                 // send a non-blocking RPC to release 512 bytes in target cluster
    918                 rpc_send( cxy , &rpc[cxy] );
     779printk("\n[%s] thread[%x,%x] released node array %x in cluster %x / cycle %d\n",
     780__FUNCTION__, this->process->pid, this->trdid, buf, cxy, cycle );
     781#endif
    919782            }
    920783        }
    921784    }
    922785
    923     // client thread deschedule
    924     sched_yield("blocked on parallel rpc_kcm_free");
    925 
    926     // restore IRQs
    927     hal_restore_irq( save_sr);
    928 
    929     // 3. release memory locally allocated for the RPC descriptors array
    930     req.type  = KMEM_PAGE;
    931     req.ptr   = rpc_page;
    932     kmem_free( &req );
    933 
    934     // 4. release memory allocated for barrier descriptor
    935     xptr_t   page_xp  = ppm_base2page( barrier_xp );
    936     cxy_t    page_cxy = GET_CXY( page_xp );
    937     page_t * page_ptr = GET_PTR( page_xp );
    938 
    939     ppm_remote_free_pages( page_cxy , page_ptr );
     786    // 2. release memory allocated for barrier descriptor in ref cluster
     787    req.type = KMEM_PPM;
     788    req.ptr  = barrier_ptr;
     789    kmem_remote_free( barrier_cxy , &req );
    940790
    941791#if DEBUG_BARRIER_DESTROY
    942792cycle = (uint32_t)hal_get_cycles();
    943793if( cycle > DEBUG_BARRIER_DESTROY )
    944 printk("\n[%s] thread[%x,%x] exit for barrier (%x,%x) / cycle %d\n",
     794printk("\n[%s] thread[%x,%x] release barrier descriptor (%x,%x) / cycle %d\n",
    945795__FUNCTION__, this->process->pid, this->trdid, barrier_cxy, barrier_ptr, cycle );
    946796#endif
     
    1022872                {
    1023873                     uint32_t level = hal_remote_l32( XPTR( node_cxy , &node_ptr->level       ));
    1024                      uint32_t arity = hal_remote_l32( XPTR( node_cxy , &node_ptr->arity       ));
    1025                      uint32_t count = hal_remote_l32( XPTR( node_cxy , &node_ptr->current     ));
    1026874                     xptr_t   pa_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->parent_xp   ));
    1027875                     xptr_t   c0_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[0] ));
     
    1030878                     xptr_t   c3_xp = hal_remote_l32( XPTR( node_cxy , &node_ptr->child_xp[3] ));
    1031879
    1032                      printk("   . level %d : (%x,%x) / %d on %d / P(%x,%x) / C0(%x,%x)"
     880                     printk("   . level %d : (%x,%x) / P(%x,%x) / C0(%x,%x)"
    1033881                            " C1(%x,%x) / C2(%x,%x) / C3(%x,%x)\n",
    1034                      level, node_cxy, node_ptr, count, arity,
     882                     level, node_cxy, node_ptr,
    1035883                     GET_CXY(pa_xp), GET_PTR(pa_xp),
    1036884                     GET_CXY(c0_xp), GET_PTR(c0_xp),
  • trunk/kernel/libk/remote_condvar.c

    r581 r635  
    22 * remote_condvar.c - remote kernel condition variable implementation.
    33 *
    4  * Authors     Alain Greiner (2016,2017,2018)
     4 * Authors     Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    8686{
    8787    remote_condvar_t * condvar_ptr;
    88     xptr_t             condvar_xp;
     88    kmem_req_t         req;   
    8989
    9090    // get pointer on local process descriptor
     
    9898    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
    9999
    100     // allocate memory for new condvar in reference cluster
    101     if( ref_cxy == local_cxy )                              // local cluster is the reference
    102     {
    103         kmem_req_t req;   
    104         req.type    = KMEM_CONDVAR;
    105         req.flags   = AF_ZERO;
    106         condvar_ptr = kmem_alloc( &req );
    107         condvar_xp  = XPTR( local_cxy , condvar_ptr );
    108     }
    109     else                                                   // reference cluster is remote
    110     {
    111         rpc_kcm_alloc_client( ref_cxy , KMEM_CONDVAR , &condvar_xp );
    112         condvar_ptr = GET_PTR( condvar_xp );
    113     }
    114 
    115     if( condvar_xp == XPTR_NULL ) return 0xFFFFFFFF;
     100    req.type    = KMEM_KCM;
     101    req.order   = bits_log2( sizeof(remote_condvar_t) );
     102    req.flags   = AF_ZERO | AF_KERNEL;
     103    condvar_ptr = kmem_alloc( &req );
     104
     105    if( condvar_ptr == NULL )
     106    {
     107        printk("\n[ERROR] in %s : cannot create condvar\n", __FUNCTION__ );
     108        return -1;
     109    }
    116110
    117111    // initialise condvar
     
    136130void remote_condvar_destroy( xptr_t condvar_xp )
    137131{
     132    kmem_req_t  req;
     133
    138134    // get pointer on local process descriptor
    139135    process_t * process = CURRENT_THREAD->process;
     
    166162
    167163    // release memory allocated for condvar descriptor
    168     if( condvar_cxy == local_cxy )                            // reference is local
    169     {
    170         kmem_req_t  req;
    171         req.type = KMEM_SEM;
    172         req.ptr  = condvar_ptr;
    173         kmem_free( &req );
    174     }
    175     else                                                  // reference is remote
    176     {
    177         rpc_kcm_free_client( condvar_cxy , condvar_ptr , KMEM_CONDVAR );
    178     }
     164    req.type = KMEM_KCM;
     165    req.ptr  = condvar_ptr;
     166    kmem_remote_free( ref_cxy , &req );
    179167
    180168}  // end remote_convar_destroy()
  • trunk/kernel/libk/remote_condvar.h

    r581 r635  
    22 * remote_condvar.h: POSIX condition variable definition.     
    33 *
    4  * Authors  Alain Greiner (2016,2017,2018)
     4 * Authors  Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    7878 * This function implements the CONVAR_INIT operation.
    7979 * This function creates and initializes a remote_condvar, identified by its virtual
    80  * address <vaddr> in the client process reference cluster, using RPC if required.
     80 * address <vaddr> in the client process reference cluster, using remote access.
    8181 * It registers this user condvar in the reference process descriptor.
    8282 *******************************************************************************************
  • trunk/kernel/libk/remote_mutex.c

    r619 r635  
    22 * remote_mutex.c - POSIX mutex implementation.
    33 *
    4  * Authors   Alain   Greiner (2016,2017,2018)
     4 * Authors   Alain   Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    8484error_t remote_mutex_create( intptr_t ident )
    8585{
    86     xptr_t           mutex_xp;
    8786    remote_mutex_t * mutex_ptr;
     87    kmem_req_t       req;   
    8888
    8989    // get pointer on local process descriptor
     
    9797    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
    9898
    99     // allocate memory for mutex descriptor
    100     if( ref_cxy == local_cxy )                  // local cluster is the reference
    101     {
    102         kmem_req_t req;   
    103         req.type    = KMEM_MUTEX;
    104         req.flags   = AF_ZERO;
    105         mutex_ptr   = kmem_alloc( &req );
    106         mutex_xp    = XPTR( local_cxy , mutex_ptr );
    107     }
    108     else                                       // reference is remote
    109     {
    110         rpc_kcm_alloc_client( ref_cxy , KMEM_MUTEX , &mutex_xp );
    111         mutex_ptr = GET_PTR( mutex_xp );
    112     }
    113 
    114     if( mutex_ptr == NULL ) return 0xFFFFFFFF;
     99    // allocate memory for mutex descriptor in reference cluster
     100    req.type    = KMEM_KCM;
     101    req.order   = bits_log2( sizeof(remote_mutex_t) );
     102    req.flags   = AF_ZERO | AF_KERNEL;
     103    mutex_ptr   = kmem_remote_alloc( ref_cxy , &req );
     104
     105    if( mutex_ptr == NULL )
     106    {
     107       printk("\n[ERROR] in %s : cannot create mutex\n", __FUNCTION__);
     108       return -1;
     109    }
    115110
    116111    // initialise mutex
     
    150145void remote_mutex_destroy( xptr_t mutex_xp )
    151146{
     147    kmem_req_t  req;
     148
    152149    // get pointer on local process descriptor
    153150    process_t * process = CURRENT_THREAD->process;
     
    174171
    175172    // release memory allocated for mutex descriptor
    176     if( mutex_cxy == local_cxy )                            // reference is local
    177     {
    178         kmem_req_t  req;
    179         req.type = KMEM_MUTEX;
    180         req.ptr  = mutex_ptr;
    181         kmem_free( &req );
    182     }
    183     else                                                  // reference is remote
    184     {
    185         rpc_kcm_free_client( mutex_cxy , mutex_ptr , KMEM_MUTEX );
    186     }
     173    req.type = KMEM_KCM;
     174    req.ptr  = mutex_ptr;
     175    kmem_remote_free( mutex_cxy , &req );
    187176
    188177}  // end remote_mutex_destroy()
  • trunk/kernel/libk/remote_sem.c

    r563 r635  
    22 * remote_sem.c - POSIX unnamed semaphore implementation.
    33 *
    4  * Author   Alain Greiner  (2016,2017,2018)
     4 * Author   Alain Greiner  (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    8686                           uint32_t   value )
    8787{
     88    kmem_req_t     req;   
    8889    remote_sem_t * sem_ptr;
    89     xptr_t         sem_xp;
    9090
    9191    // get pointer on local process descriptor
     
    100100
    101101    // allocate memory for new semaphore in reference cluster
    102     if( ref_cxy == local_cxy )  // local cluster is the reference
    103     {
    104         kmem_req_t req;   
    105         req.type  = KMEM_SEM;
    106         req.flags = AF_ZERO;
    107         sem_ptr   = kmem_alloc( &req );
    108         sem_xp    = XPTR( local_cxy , sem_ptr );
     102    req.type  = KMEM_KCM;
     103    req.order = bits_log2( sizeof(remote_sem_t) );
     104    req.flags = AF_ZERO | AF_KERNEL;
     105    sem_ptr   = kmem_remote_alloc( ref_cxy, &req );
     106
     107    if( sem_ptr == NULL )
     108    {
     109        printk("\n[ERROR] in %s : cannot create semaphore\n", __FUNCTION__ );
     110        return -1;
    109111    }
    110     else                         // reference is remote
    111     {
    112         rpc_kcm_alloc_client( ref_cxy , KMEM_SEM , &sem_xp );
    113         sem_ptr = GET_PTR( sem_xp );
    114     }
    115 
    116     if( sem_xp == XPTR_NULL ) return 0xFFFFFFFF;
    117112
    118113    // initialise semaphore
     
    149144void remote_sem_destroy( xptr_t sem_xp )
    150145{
     146    kmem_req_t  req;
     147
    151148    // get pointer on local process descriptor
    152149    process_t * process = CURRENT_THREAD->process;
     
    179176
    180177    // release memory allocated for semaphore descriptor
    181     if( sem_cxy == local_cxy )                            // reference is local
    182     {
    183         kmem_req_t  req;
    184         req.type = KMEM_SEM;
    185         req.ptr  = sem_ptr;
    186         kmem_free( &req );
    187     }
    188     else                                                  // reference is remote
    189     {
    190         rpc_kcm_free_client( sem_cxy , sem_ptr , KMEM_SEM );
    191     }
     178    req.type = KMEM_KCM;
     179    req.ptr  = sem_ptr;
     180    kmem_remote_free( sem_cxy , &req );
    192181
    193182}  // end remote_sem_destroy()
  • trunk/kernel/libk/user_dir.c

    r633 r635  
    9393    uint32_t        attr;              // attributes for all GPT entries
    9494    uint32_t        dirents_per_page;  // number of dirent descriptors per page
    95     xptr_t          page_xp;           // extended pointer on page descriptor 
    9695    page_t        * page;              // local pointer on page descriptor
    97     xptr_t          base_xp;           // extended pointer on physical page base
    9896    struct dirent * base;              // local pointer on physical page base
    9997    uint32_t        total_dirents;     // total number of dirents in dirent array
     
    126124
    127125// check dirent size
    128 assert( ( sizeof(struct dirent) == 64), "sizeof(dirent) != 64\n");
     126assert( ( sizeof(struct dirent) == 64), "sizeof(dirent) must be 64\n");
    129127
    130128    // compute number of dirent per page
     
    135133
    136134    // allocate memory for a local user_dir descriptor
    137     req.type  = KMEM_DIR;
    138     req.flags = AF_ZERO;
     135    req.type  = KMEM_KCM;
     136    req.order = bits_log2( sizeof(user_dir_t) );
     137    req.flags = AF_ZERO | AF_KERNEL;
    139138    dir       = kmem_alloc( &req );
    140139
     
    146145    }
    147146
    148     // Build an initialize the dirent array as a list of physical pages.
     147    // Build an initialize the dirent array as a list of pages.
    149148    // For each iteration in this while loop:
    150149    // - allocate one physical 4 Kbytes (64 dirent slots)
     
    163162    {
    164163        // allocate one physical page
    165         req.type  = KMEM_PAGE;
    166         req.size = 0;
     164        req.type  = KMEM_PPM;
     165        req.order = 0;
    167166        req.flags = AF_ZERO;
    168         page      = kmem_alloc( &req );
    169 
    170         if( page == NULL )
     167        base      = kmem_alloc( &req );
     168
     169        if( base == NULL )
    171170        {
    172171            printk("\n[ERROR] in %s : cannot allocate page in cluster %x\n",
     
    174173            goto user_dir_create_failure;
    175174        }
    176 
    177         // get pointer on page base (array of dirents)
    178         page_xp  = XPTR( local_cxy , page );
    179         base_xp  = ppm_page2base( page_xp );
    180         base     = GET_PTR( base_xp );
    181175
    182176        // call the relevant FS specific function to copy up to 64 dirents in page
     
    198192        total_dirents += entries;
    199193
     194        // get page descriptor pointer from base
     195        page = GET_PTR( ppm_base2page( XPTR( local_cxy , base ) ) );
     196
    200197        // register page in temporary list
    201198        list_add_last( &root , &page->list );
     
    303300
    304301            // release the user_dir descriptor
    305             req.type = KMEM_DIR;
     302            req.type = KMEM_KCM;
    306303            req.ptr  = dir;
    307304            kmem_free( &req );
     
    364361
    365362    // release local user_dir_t structure
    366     req.type = KMEM_DIR;
     363    req.type = KMEM_KCM;
    367364    req.ptr  = dir;
    368365    kmem_free( &req );
     
    372369    {
    373370        page = LIST_FIRST( &root , page_t , list );
    374         req.type  = KMEM_PAGE;
    375         req.ptr   = page;
     371
     372        // get base from page descriptor pointer
     373        base = GET_PTR( ppm_page2base( XPTR( local_cxy , page ) ) );
     374 
     375        req.type  = KMEM_PPM;
     376        req.ptr   = base;
    376377        kmem_free( &req );
    377378    }
     
    492493    // release local user_dir_t structure
    493494    kmem_req_t  req;
    494     req.type = KMEM_DIR;
     495    req.type = KMEM_KCM;
    495496    req.ptr  = dir;
    496497    kmem_free( &req );
  • trunk/kernel/libk/user_dir.h

    r629 r635  
    7878 * This function allocates memory and initializes a user_dir_t structure in the cluster
    7979 * containing the directory inode identified by the <inode> argument and map the
    80  * user accessible dirent array in the reference user process VMM, identified by the
     80 * user accessible dirent array in the reference user process VSL, identified by the
    8181 * <ref_xp> argument.
    8282 * It must be executed by a thread running in the cluster containing the target inode.
  • trunk/kernel/libk/xhtab.c

    r614 r635  
    22 * xhtab.c - Remote access embedded hash table implementation.
    33 *
    4  * Author     Alain Greiner          (2016,2017)
     4 * Author     Alain Greiner   (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    134134        uint32_t i;
    135135
    136     // initialize readlock
     136    // initialize lock
    137137    remote_busylock_init( XPTR( local_cxy , &xhtab->lock), LOCK_XHTAB_STATE );
    138138
     
    153153    }
    154154
    155         for( i=0 ; i < XHASHTAB_SIZE ; i++ )
    156     {
    157                 xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );
    158     } 
    159 
    160 #if DEBUG_XHTAB
    161 printk("\n@@@ %s for xhtab (%x,%x)\n"
     155#if DEBUG_XHTAB
     156printk("\n[%s] for xhtab (%x,%x)\n"
    162157" - index_from_key  = %x (@ %x)\n"
    163158" - item_match_key  = %x (@ %x)\n"
     
    169164#endif
    170165
     166        for( i=0 ; i < XHASHTAB_SIZE ; i++ )
     167    {
     168                xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );
     169
     170#if (DEBUG_XHTAB & 1)
     171printk("\n - initialize root[%d] / %x\n", i , &xhtab->roots[i] );
     172#endif
     173
     174    } 
     175
    171176}  // end xhtab_init()
    172177
    173 //////////////////////////////////////
    174 xptr_t xhtab_scan( xptr_t    xhtab_xp,
    175                    uint32_t  index,
    176                    void    * key )
     178/////////////////////////////////////////////////////////////////////////////////////////////
     179// This static function traverse the subset identified by the <index> argument
     180// to find an item identified by the <key> argument.
     181/////////////////////////////////////////////////////////////////////////////////////////////
     182// @ xhtab_xp  : extended pointer on the xhtab descriptor.
     183// @ index     : subset index.
     184// @ key       : searched key value.
     185// @ return  extended pointer on the found item if success / return XPTR_NULL if not found.
     186/////////////////////////////////////////////////////////////////////////////////////////////
     187static xptr_t xhtab_scan( xptr_t    xhtab_xp,
     188                          uint32_t  index,
     189                          void    * key )
    177190{
    178191    xptr_t              xlist_xp;           // xlist_entry_t (iterator)
     
    220233    index_from_key_t * index_from_key;     // function pointer
    221234   
    222 #if DEBUG_XHTAB
    223 printk("\n[%s] enter / key %s\n", __FUNCTION__, key );
    224 #endif
    225 
    226     // get xhtab cluster and local pointer
    227     xhtab_cxy = GET_CXY( xhtab_xp );
    228     xhtab_ptr = GET_PTR( xhtab_xp );
     235    // get xhtab cluster and local pointer
     236    xhtab_cxy = GET_CXY( xhtab_xp );
     237    xhtab_ptr = GET_PTR( xhtab_xp );
     238
     239#if DEBUG_XHTAB
     240printk("\n[%s] enter / xhtab (%x,%x) / key = <%s> / cycle %d\n",
     241__FUNCTION__, xhtab_cxy, xhtab_ptr, key, (uint32_t)hal_get_cycles() );
     242#endif
     243
     244    // build extended pointer on xhtab lock
     245    xptr_t lock_xp = XPTR( xhtab_cxy , &xhtab_ptr->lock );
    229246
    230247    // get pointer on "index_from_key" function
    231248    index_from_key = (index_from_key_t *)hal_remote_lpt( XPTR( xhtab_cxy ,
    232249                                                         &xhtab_ptr->index_from_key ) );
     250#if DEBUG_XHTAB
     251printk("\n[%s] remote = %x / direct = %x / @ = %x\n",
     252__FUNCTION__, index_from_key, xhtab_ptr->index_from_key, &xhtab_ptr->index_from_key );
     253#endif
     254
    233255    // compute index from key
    234256        index = index_from_key( key );
    235257
     258#if DEBUG_XHTAB
     259printk("\n[%s] index = %x\n", __FUNCTION__, index );
     260#endif
     261
    236262    // take the lock protecting hash table
    237     remote_busylock_acquire( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
    238 
    239     // search a matching item
     263    remote_busylock_acquire( lock_xp );
     264
     265    // search a matching item in subset
    240266    item_xp = xhtab_scan( xhtab_xp , index , key );
    241267
    242     if( item_xp != XPTR_NULL )    // error if found
     268    if( item_xp != XPTR_NULL )    // error if item already registered
    243269    {
    244270        // release the lock protecting hash table
    245         remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
     271        remote_busylock_release( lock_xp );
    246272
    247273        return -1;
     
    256282
    257283        // release the lock protecting hash table
    258         remote_busylock_release( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
     284        remote_busylock_release( lock_xp );
    259285   
    260286#if DEBUG_XHTAB
    261 printk("\n[%s] success / %s\n", __FUNCTION__, key );
     287printk("\n[%s] success / <%s>\n", __FUNCTION__, key );
    262288#endif
    263289
  • trunk/kernel/libk/xhtab.h

    r614 r635  
    22 * xhtab.h - Remote access embedded hash table definition.
    33 *
    4  * Author     Alain Greiner  (2016,2017,2018)
     4 * Author     Alain Greiner  (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    3838// The main goal is to speedup search by key in a large number of items of same type.
    3939// For this purpose the set of all registered items is split in several subsets.
    40 // Each subset is organised as an embedded double linked xlists.
     40// Each subset is organised as an embedded double linked xlist.
    4141// - an item is uniquely identified by a <key>, that is a item specific pointer,
    4242//   that can be a - for example - a char* defining the item "name".
     
    6464
    6565/******************************************************************************************
    66  * This define the four item_type_specific function prototypes that must be defined
     66 * Here are the four item_type_specific function prototypes that must be defined
    6767 * for each item type.
    6868 *****************************************************************************************/
     
    7474
    7575/******************************************************************************************
    76  * This define the supported item types.
     76 * This define the currently supported item types.
    7777 * - The XHTAB_DENTRY_TYPE is used to implement the set of directory entries for a
    7878 *   directory inode : the "children" inode field is an embedded xhtab.
  • trunk/kernel/mm/kcm.c

    r619 r635  
    11/*
    2  * kcm.c - Per cluster Kernel Cache Manager implementation.
     2 * kcm.c - Kernel Cache Manager implementation.
    33 *
    4  * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner    (2016,2017,2018,2019)
     4 * Author  Alain Greiner    (2016,2017,2018,2019)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    3837
    3938
     39/////////////////////////////////////////////////////////////////////////////////////
     40//        Local access functions
     41/////////////////////////////////////////////////////////////////////////////////////
     42
    4043//////////////////////////////////////////////////////////////////////////////////////
    41 // This static function returns pointer on an allocated block from an active page.
    42 // It returns NULL if no block available in selected page.
    43 // It changes the page status if required.
     44// This static function must be called by a local thread.
     45// It returns a pointer on a block allocated from a non-full kcm_page.
     46// It makes a panic if no block is available in selected page.
     47// It changes the page status as required.
    4448//////////////////////////////////////////////////////////////////////////////////////
    45 // @ kcm      : pointer on kcm allocator.
    46 // @ kcm_page : pointer on active kcm page to use.
    47 /////////////////////////////////////////////////////////////////////////////////////
    48 static void * kcm_get_block( kcm_t      * kcm,
    49                              kcm_page_t * kcm_page )
    50 {
    51 
    52 #if DEBUG_KCM
    53 thread_t * this = CURRENT_THREAD;
    54 uint32_t cycle = (uint32_t)hal_get_cycles();
     49// @ kcm      : pointer on KCM allocator.
     50// @ kcm_page : pointer on a non-full kcm_page.
     51// @ return pointer on allocated block.
     52/////////////////////////////////////////////////////////////////////////////////////
     53static void * __attribute__((noinline)) kcm_get_block( kcm_t      * kcm,
     54                                                       kcm_page_t * kcm_page )
     55{
     56    // initialise variables
     57    uint32_t size   = 1 << kcm->order;
     58    uint32_t max    = kcm->max_blocks;
     59    uint32_t count  = kcm_page->count;
     60    uint64_t status = kcm_page->status;
     61
     62assert( (count < max) , "kcm_page should not be full" );
     63
     64    uint32_t index  = 1;
     65    uint64_t mask   = (uint64_t)0x2;
     66    uint32_t found  = 0;
     67
     68        // allocate first free block in kcm_page, update status,
     69    // and count , compute index of allocated block in kcm_page
     70    while( index <= max )
     71    {
     72        if( (status & mask) == 0 )   // block non allocated
     73        {
     74            kcm_page->status = status | mask;
     75            kcm_page->count  = count + 1;
     76            found  = 1;
     77
     78            break;     
     79        }
     80       
     81        index++;
     82        mask <<= 1;
     83    }
     84
     85    // change the page list if almost full
     86    if( count == max-1 )
     87    {
     88                list_unlink( &kcm_page->list);
     89                kcm->active_pages_nr--;
     90
     91        list_add_first( &kcm->full_root , &kcm_page->list );
     92                kcm->full_pages_nr ++;
     93    }
     94
     95        // compute return pointer
     96        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
     97
     98#if (DEBUG_KCM & 1)
     99thread_t * this  = CURRENT_THREAD;
     100uint32_t   cycle = (uint32_t)hal_get_cycles();
    55101if( DEBUG_KCM < cycle )
    56 printk("\n[%s] thread[%x,%x] enters for %s / page %x / count %d / active %d\n",
    57 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(kcm->type),
    58 (intptr_t)kcm_page , kcm_page->count , kcm_page->active );
    59 #endif
    60 
    61 assert( kcm_page->active , "kcm_page should be active" );
    62 
    63         // get first block available
    64         int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr );
    65 
    66 assert( (index != -1) , "kcm_page should not be full" );
    67 
    68         // allocate block
    69         bitmap_clear( kcm_page->bitmap , index );
    70 
    71         // increase kcm_page count
    72         kcm_page->count ++;
    73 
    74         // change the kcm_page to busy if no more free block in page
    75         if( kcm_page->count >= kcm->blocks_nr )
    76         {
    77                 kcm_page->active = 0;
    78                 list_unlink( &kcm_page->list);
    79                 kcm->active_pages_nr --;
    80 
    81                 list_add_first( &kcm->busy_root , &kcm_page->list);
    82                 kcm->busy_pages_nr ++;
    83                 kcm_page->busy = 1;
    84         }
    85 
    86         // compute return pointer
    87         void * ptr = (void *)((intptr_t)kcm_page + CONFIG_KCM_SLOT_SIZE
    88                      + (index * kcm->block_size) );
    89 
    90 #if DEBUG_KCM
    91 cycle = (uint32_t)hal_get_cycles();
    92 if( DEBUG_KCM < cycle )
    93 printk("\n[%s] thread[%x,%x] exit for %s / ptr %x / page %x / count %d\n",
    94 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(kcm->type),
    95 (intptr_t)ptr, (intptr_t)kcm_page, kcm_page->count );
     102printk("\n[%s] thread[%x,%x] allocated block %x in page %x / size %d / count %d / cycle %d\n",
     103__FUNCTION__, this->process->pid, this->trdid, ptr, kcm_page, size, count + 1, cycle );
    96104#endif
    97105
    98106        return ptr;
    99 }
    100 
    101 /////////////////////////////////////////////////////////////////////////////////////
    102 // This static function releases a previously allocated block.
    103 // It changes the kcm_page status if required.
    104 /////////////////////////////////////////////////////////////////////////////////////
    105 // @ kcm      : pointer on kcm allocator.
    106 // @ kcm_page : pointer on kcm_page.
    107 // @ ptr      : pointer on block to be released.
    108 /////////////////////////////////////////////////////////////////////////////////////
    109 static void kcm_put_block ( kcm_t      * kcm,
    110                             kcm_page_t * kcm_page,
    111                             void       * ptr )
    112 {
    113         uint32_t     index;
    114 
     107
     108}  // end kcm_get_block()
     109
     110/////////////////////////////////////////////////////////////////////////////////////
     111// This private static function must be called by a local thread.
     112// It releases a previously allocated block to the relevant kcm_page.
     113// It makes a panic if the released block is not allocated in this page.
     114// It changes the kcm_page status as required.
     115/////////////////////////////////////////////////////////////////////////////////////
     116// @ kcm        : pointer on kcm allocator.
     117// @ kcm_page   : pointer on kcm_page.
     118// @ block_ptr  : pointer on block to be released.
     119/////////////////////////////////////////////////////////////////////////////////////
     120static void __attribute__((noinline)) kcm_put_block ( kcm_t      * kcm,
     121                                                      kcm_page_t * kcm_page,
     122                                                      void       * block_ptr )
     123{
     124    // initialise variables
     125    uint32_t max    = kcm->max_blocks;
     126    uint32_t size   = 1 << kcm->order;
     127    uint32_t count  = kcm_page->count;
     128    uint64_t status = kcm_page->status;
     129   
    115130        // compute block index from block pointer
    116         index = ((uint8_t *)ptr - (uint8_t *)kcm_page - CONFIG_KCM_SLOT_SIZE) / kcm->block_size;
    117 
    118 assert( !bitmap_state( kcm_page->bitmap , index ) , "page already freed" );
    119 
    120 assert( (kcm_page->count > 0) , "count already zero" );
    121 
    122         bitmap_set( kcm_page->bitmap , index );
    123         kcm_page->count --;
    124 
    125         // change the page to active if it was busy
    126         if( kcm_page->busy )
    127         {
    128                 kcm_page->busy = 0;
     131        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
     132
     133    // compute mask in bit vector
     134    uint64_t mask = ((uint64_t)0x1) << index;
     135
     136assert( (status & mask) , "released block not allocated : status (%x,%x) / mask(%x,%x)",
     137GET_CXY(status), GET_PTR(status), GET_CXY(mask  ), GET_PTR(mask  ) );
     138
     139    // update status & count in kcm_page
     140        kcm_page->status = status & ~mask;
     141        kcm_page->count  = count - 1;
     142
     143        // change the page mode if page was full
     144        if( count == max )
     145        {
    129146                list_unlink( &kcm_page->list );
    130                 kcm->busy_pages_nr --;
     147                kcm->full_pages_nr --;
    131148
    132149                list_add_last( &kcm->active_root, &kcm_page->list );
    133150                kcm->active_pages_nr ++;
    134                 kcm_page->active = 1;
    135         }
    136 
    137         // change the kcm_page to free if last block in active page
    138         if( (kcm_page->active) && (kcm_page->count == 0) )
    139         {
    140                 kcm_page->active = 0;
    141                 list_unlink( &kcm_page->list);
    142                 kcm->active_pages_nr --;
    143 
    144                 list_add_first( &kcm->free_root , &kcm_page->list);
    145                 kcm->free_pages_nr ++;
    146         }
    147 }
    148 
    149 /////////////////////////////////////////////////////////////////////////////////////
    150 // This static function allocates one page from PPM. It initializes
    151 // the kcm_page descriptor, and introduces the new kcm_page into freelist.
    152 /////////////////////////////////////////////////////////////////////////////////////
    153 static error_t freelist_populate( kcm_t * kcm )
    154 {
    155         page_t     * page;
    156         kcm_page_t * kcm_page;
    157         kmem_req_t   req;
    158 
    159         // get one page from local PPM
    160         req.type  = KMEM_PAGE;
    161         req.size  = 0;
    162         req.flags = AF_KERNEL;
    163         page = kmem_alloc( &req );
    164 
    165         if( page == NULL )
    166         {
    167                 printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
    168             __FUNCTION__ , local_cxy );
    169                 return ENOMEM;
    170         }
    171 
    172         // get page base address
    173         xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    174         kcm_page = (kcm_page_t *)GET_PTR( base_xp );
    175 
    176         // initialize KCM-page descriptor
    177         bitmap_set_range( kcm_page->bitmap , 0 , kcm->blocks_nr );
    178 
    179         kcm_page->busy          = 0;
    180         kcm_page->active        = 0;
    181         kcm_page->count      = 0;
    182         kcm_page->kcm           = kcm;
    183         kcm_page->page          = page;
    184 
    185         // introduce new page in free-list
    186         list_add_first( &kcm->free_root , &kcm_page->list );
    187         kcm->free_pages_nr ++;
    188 
    189         return 0;
    190 }
    191 
    192 /////////////////////////////////////////////////////////////////////////////////////
    193 // This private function gets one KCM page from the KCM freelist.
    194 // It populates the freelist if required.
    195 /////////////////////////////////////////////////////////////////////////////////////
    196 static kcm_page_t * freelist_get( kcm_t * kcm )
    197 {
    198         error_t      error;
    199         kcm_page_t * kcm_page;
    200 
    201         // get a new page from PPM if freelist empty
    202         if( kcm->free_pages_nr == 0 )
    203         {
    204                 error = freelist_populate( kcm );
    205                 if( error ) return NULL;
    206         }
    207 
    208         // get first KCM page from freelist and unlink it
    209         kcm_page = LIST_FIRST( &kcm->free_root, kcm_page_t , list );
    210         list_unlink( &kcm_page->list );
    211         kcm->free_pages_nr --;
     151        }
     152
     153#if (DEBUG_KCM & 1)
     154thread_t * this  = CURRENT_THREAD;
     155uint32_t   cycle = (uint32_t)hal_get_cycles();
     156if( DEBUG_KCM < cycle )
     157printk("\n[%s] thread[%x,%x] released block %x in page %x / size %d / count %d / cycle %d\n",
     158__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_page, size, count - 1, cycle );
     159#endif
     160
     161}  // kcm_put_block()
     162
     163/////////////////////////////////////////////////////////////////////////////////////
     164// This private static function must be called by a local thread.
     165// It returns one non-full kcm_page with te following policy :
     166// - if the "active_list" is non empty, it returns the first "active" page,
     167//   without modifying the KCM state.
     168// - if the "active_list" is empty, it allocates a new page fromm PPM, inserts
     169//   this page in the active_list, and returns it.
     170/////////////////////////////////////////////////////////////////////////////////////
     171// @ kcm      : local pointer on local KCM allocator.
     172// @ return pointer on a non-full kcm page if success / returns NULL if no memory.
     173/////////////////////////////////////////////////////////////////////////////////////
     174static kcm_page_t * __attribute__((noinline)) kcm_get_page( kcm_t * kcm )
     175{
     176    kcm_page_t * kcm_page;
     177
     178    uint32_t active_pages_nr = kcm->active_pages_nr;
     179
     180    if( active_pages_nr > 0 )       // return first active page
     181    {
     182        kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
     183    }
     184    else                            // allocate a new page from PPM
     185        {
     186        // get one 4 Kbytes page from local PPM
     187        page_t * page = ppm_alloc_pages( 0 );
     188
     189            if( page == NULL )
     190            {
     191                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
     192                __FUNCTION__ , local_cxy );
     193
     194                    return NULL;
     195        }
     196
     197            // get page base address
     198            xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
     199
     200        // get local pointer on kcm_page
     201            kcm_page = GET_PTR( base_xp );
     202
     203            // initialize kcm_page descriptor
     204            kcm_page->status = 0;
     205            kcm_page->count  = 0;
     206            kcm_page->kcm    = kcm;
     207            kcm_page->page   = page;
     208
     209            // introduce new page in KCM active_list
     210            list_add_first( &kcm->active_root , &kcm_page->list );
     211            kcm->active_pages_nr ++;
     212        }
    212213
    213214        return kcm_page;
    214 }
     215
     216}  // end kcm_get_page()
    215217
    216218//////////////////////////////
    217219void kcm_init( kcm_t    * kcm,
    218                    uint32_t   type )
    219 {
    220 
    221 // the kcm_page descriptor must fit in the KCM slot
    222 assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) , "KCM slot too small\n" );
    223 
    224 // the allocated object must fit in one single page
    225 assert( (kmem_type_size(type) <= (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE)),
    226 "allocated object requires more than one single page\n" );
     220                   uint32_t   order)
     221{
     222
     223assert( ((order > 5) && (order < 12)) , "order must be in [6,11]" );
    227224
    228225        // initialize lock
    229         busylock_init( &kcm->lock , LOCK_KCM_STATE );
    230 
    231         // initialize KCM type
    232         kcm->type = type;
     226        remote_busylock_init( XPTR( local_cxy , &kcm->lock ) , LOCK_KCM_STATE );
    233227
    234228        // initialize KCM page lists
    235         kcm->free_pages_nr   = 0;
    236         kcm->busy_pages_nr   = 0;
     229        kcm->full_pages_nr   = 0;
    237230        kcm->active_pages_nr = 0;
    238         list_root_init( &kcm->free_root );
    239         list_root_init( &kcm->busy_root );
     231        list_root_init( &kcm->full_root );
    240232        list_root_init( &kcm->active_root );
    241233
    242         // initialize block size
    243         uint32_t block_size = ARROUND_UP( kmem_type_size( type ) , CONFIG_KCM_SLOT_SIZE );
    244         kcm->block_size = block_size;
    245 
    246         // initialize number of blocks per page
    247         uint32_t  blocks_nr = (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE) / block_size;
    248         kcm->blocks_nr = blocks_nr;
    249 
     234        // initialize order and max_blocks
     235        kcm->order      = order;
     236    kcm->max_blocks = ( CONFIG_PPM_PAGE_SIZE >> order ) - 1;
     237 
    250238#if DEBUG_KCM
    251239thread_t * this  = CURRENT_THREAD;
    252240uint32_t   cycle = (uint32_t)hal_get_cycles();
    253241if( DEBUG_KCM < cycle )
    254 printk("\n[%s] thread[%x,%x] initialised KCM %s : block_size %d / blocks_nr %d\n",
    255 __FUNCTION__, this->process->pid, this->trdid,
    256 kmem_type_str( kcm->type ), block_size, blocks_nr );
    257 #endif
    258 
    259 }
     242printk("\n[%s] thread[%x,%x] initialised KCM / order %d / max_blocks %d\n",
     243__FUNCTION__, this->process->pid, this->trdid, order, kcm->max_blocks );
     244#endif
     245
     246}  // end kcm_init()
    260247
    261248///////////////////////////////
     
    263250{
    264251        kcm_page_t   * kcm_page;
    265         list_entry_t * iter;
     252
     253    // build extended pointer on  KCM lock
     254    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
    266255
    267256        // get KCM lock
    268         busylock_acquire( &kcm->lock );
    269 
    270         // release all free pages
    271         LIST_FOREACH( &kcm->free_root , iter )
    272         {
    273                 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
    274                 list_unlink( iter );
    275                 kcm->free_pages_nr --;
     257        remote_busylock_acquire( lock_xp );
     258
     259        // release all full pages
     260        while( list_is_empty( &kcm->full_root ) == false )
     261        {
     262                kcm_page = LIST_FIRST( &kcm->full_root , kcm_page_t , list );
     263                list_unlink( &kcm_page->list );
    276264                ppm_free_pages( kcm_page->page );
    277265        }
    278266
    279         // release all active pages
    280         LIST_FOREACH( &kcm->active_root , iter )
    281         {
    282                 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
    283                 list_unlink( iter );
    284                 kcm->free_pages_nr --;
     267    // release all empty pages
     268    while( list_is_empty( &kcm->active_root ) == false )
     269        {
     270                kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
     271                list_unlink( &kcm_page->list );
    285272                ppm_free_pages( kcm_page->page );
    286273        }
    287274
    288         // release all busy pages
    289         LIST_FOREACH( &kcm->busy_root , iter )
    290         {
    291                 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
    292                 list_unlink( iter );
    293                 kcm->free_pages_nr --;
    294                 ppm_free_pages( kcm_page->page );
    295         }
    296 
    297275        // release KCM lock
    298         busylock_release( &kcm->lock );
     276        remote_busylock_release( lock_xp );
    299277}
    300278
    301 ///////////////////////////////
    302 void * kcm_alloc( kcm_t * kcm )
    303 {
     279//////////////////////////////////
     280void * kcm_alloc( uint32_t order )
     281{
     282    kcm_t      * kcm_ptr;
    304283        kcm_page_t * kcm_page;
    305         void       * ptr = NULL;   // pointer on block
     284        void       * block_ptr;
     285
     286    // min block size is 64 bytes
     287    if( order < 6 ) order = 6;
     288
     289assert( (order < 12) , "order = %d / must be less than 12" , order );
     290
     291    // get local pointer on relevant KCM allocator
     292    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
     293
     294    // build extended pointer on local KCM lock
     295    xptr_t lock_xp = XPTR( local_cxy , &kcm_ptr->lock );
     296
     297        // get KCM lock
     298        remote_busylock_acquire( lock_xp );
     299
     300    // get a non-full kcm_page
     301    kcm_page = kcm_get_page( kcm_ptr );
     302
     303    if( kcm_page == NULL )
     304        {
     305                remote_busylock_release( lock_xp );
     306                return NULL;
     307        }
     308
     309        // get a block from selected active page
     310        block_ptr = kcm_get_block( kcm_ptr , kcm_page );
     311
     312        // release lock
     313        remote_busylock_release( lock_xp );
     314
     315#if DEBUG_KCM
     316thread_t * this  = CURRENT_THREAD;
     317uint32_t   cycle = (uint32_t)hal_get_cycles();
     318if( DEBUG_KCM < cycle )
     319printk("\n[%s] thread[%x,%x] allocated block %x / order %d / kcm %x / status[%x,%x] / count %d\n",
     320__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_ptr,
     321GET_CXY(kcm_page->status), GET_PTR(kcm_page->status), kcm_page->count );
     322#endif
     323
     324        return block_ptr;
     325
     326}  // end kcm_alloc()
     327
     328/////////////////////////////////
     329void kcm_free( void * block_ptr )
     330{
     331    kcm_t      * kcm_ptr;
     332        kcm_page_t * kcm_page;
     333
     334// check argument
     335assert( (block_ptr != NULL) , "block pointer cannot be NULL" );
     336
     337    // get local pointer on KCM page
     338        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~CONFIG_PPM_PAGE_MASK);
     339
     340    // get local pointer on KCM descriptor
     341        kcm_ptr = kcm_page->kcm;
     342
     343#if DEBUG_KCM
     344thread_t * this  = CURRENT_THREAD;
     345uint32_t   cycle = (uint32_t)hal_get_cycles();
     346if( DEBUG_KCM < cycle )
     347printk("\n[%s] thread[%x,%x] release block %x / order %d / kcm %x / status [%x,%x] / count %d\n",
     348__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_ptr->order, kcm_ptr,
     349GET_CXY(kcm_page->status), GET_PTR(kcm_page->status), kcm_page->count );
     350#endif
     351
     352    // build extended pointer on local KCM lock
     353    xptr_t lock_xp = XPTR( local_cxy , &kcm_ptr->lock );
    306354
    307355        // get lock
    308         busylock_acquire( &kcm->lock );
    309 
    310         // get an active page
    311         if( list_is_empty( &kcm->active_root ) )  // no active page => get one
    312         {
    313                 // get a page from free list
    314                 kcm_page = freelist_get( kcm );
    315 
    316                 if( kcm_page == NULL )
    317                 {
    318                         busylock_release( &kcm->lock );
    319                         return NULL;
    320                 }
    321 
    322                 // insert page in active list
    323                 list_add_first( &kcm->active_root , &kcm_page->list );
    324                 kcm->active_pages_nr ++;
    325                 kcm_page->active = 1;
    326         }
    327         else                                    // get first page from active list
    328         {
    329                 // get page pointer from active list
    330                 kcm_page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list );
     356        remote_busylock_acquire( lock_xp );
     357
     358        // release block
     359        kcm_put_block( kcm_ptr , kcm_page , block_ptr );
     360
     361        // release lock
     362        remote_busylock_release( lock_xp );
     363}
     364
     365/////////////////////////////////////////////////////////////////////////////////////
     366//        Remote access functions
     367/////////////////////////////////////////////////////////////////////////////////////
     368
     369/////////////////////////////////////////////////////////////////////////////////////
     370// This static function can be called by any thread running in any cluster.
     371// It returns a local pointer on a block allocated from an non-full kcm_page.
     372// It makes a panic if no block available in selected page.
     373// It changes the page status as required.
     374/////////////////////////////////////////////////////////////////////////////////////
     375// @ kcm_cxy  : remote KCM cluster identidfier.
     376// @ kcm_ptr  : local pointer on remote KCM allocator.
     377// @ kcm_page : pointer on active kcm page to use.
     378// @ return a local pointer on the allocated block.
     379/////////////////////////////////////////////////////////////////////////////////////
     380static void * __attribute__((noinline)) kcm_remote_get_block( cxy_t        kcm_cxy,
     381                                                              kcm_t      * kcm_ptr,
     382                                                              kcm_page_t * kcm_page )
     383{
     384    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
     385    uint32_t max    = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->max_blocks ) );
     386    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
     387    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
     388    uint32_t size   = 1 << order;
     389
     390assert( (count < max) , "kcm_page should not be full" );
     391
     392    uint32_t index  = 1;
     393    uint64_t mask   = (uint64_t)0x2;
     394    uint32_t found  = 0;
     395   
     396        // allocate first free block in kcm_page, update status,
     397    // and count , compute index of allocated block in kcm_page
     398    while( index <= max )
     399    {
     400        if( (status & mask) == 0 )   // block non allocated
     401        {
     402            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status | mask );
     403            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->count  ) , count + 1 );
     404            found  = 1;
     405            break;     
     406        }
     407       
     408        index++;
     409        mask <<= 1;
     410    }
     411
     412        // change the page list if almost full
     413        if( count == max-1 )
     414        {
     415                list_remote_unlink( kcm_cxy , &kcm_page->list );
     416                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , -1 );
     417
     418                list_remote_add_first( kcm_cxy , &kcm_ptr->full_root , &kcm_page->list );
     419                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , 1 );
     420        }
     421
     422        // compute return pointer
     423        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
     424
     425#if DEBUG_KCM_REMOTE
     426thread_t * this  = CURRENT_THREAD;
     427uint32_t   cycle = (uint32_t)hal_get_cycles();
     428if( DEBUG_KCM_REMOTE < cycle )
     429printk("\n[%s] thread[%x,%x] get block %x in page %x / cluster %x / size %x / count %d\n",
     430__FUNCTION__, this->process->pid, this->trdid,
     431ptr, kcm_page, kcm_cxy, size, count + 1 );
     432#endif
     433
     434        return ptr;
     435
     436}  // end kcm_remote_get_block()
     437
     438/////////////////////////////////////////////////////////////////////////////////////
     439// This private static function can be called by any thread running in any cluster.
     440// It releases a previously allocated block to the relevant kcm_page.
     441// It changes the kcm_page status as required.
     442/////////////////////////////////////////////////////////////////////////////////////
     443// @ kcm_cxy   : remote KCM cluster identifier
     444// @ kcm_ptr   : local pointer on remote KCM.
     445// @ kcm_page  : local pointer on kcm_page.
     446// @ block_ptr : pointer on block to be released.
     447/////////////////////////////////////////////////////////////////////////////////////
     448static void __attribute__((noinline)) kcm_remote_put_block ( cxy_t        kcm_cxy,
     449                                                             kcm_t      * kcm_ptr,
     450                                                             kcm_page_t * kcm_page,
     451                                                             void       * block_ptr )
     452{
     453    uint32_t max    = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->max_blocks ) );
     454    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
     455    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
     456    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
     457    uint32_t size   = 1 << order;
     458   
     459        // compute block index from block pointer
     460        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
     461
     462    // compute mask in bit vector
     463    uint64_t mask = 1 << index;
     464
     465assert( (status & mask) , "released page not allocated" );
     466
     467    // update status & count in kcm_page
     468        hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status & ~mask );
     469        hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count - 1 );
     470
     471        // change the page list if page was full
     472        if( count == max )
     473        {
     474                list_remote_unlink( kcm_cxy , &kcm_page->list );
     475                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , -1 );
     476
     477                list_remote_add_last( kcm_cxy , &kcm_ptr->active_root, &kcm_page->list );
     478                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
     479        }
     480
     481#if (DEBUG_KCM_REMOTE & 1)
     482thread_t * this  = CURRENT_THREAD;
     483uint32_t   cycle = (uint32_t)hal_get_cycles();
     484if( DEBUG_KCM_REMOTE < cycle )
     485printk("\n[%s] thread[%x,%x] released block %x in page %x / cluster %x / size %x / count %d\n",
     486__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_page, size, count - 1 )
     487#endif
     488
     489}  // end kcm_remote_put_block()
     490
     491/////////////////////////////////////////////////////////////////////////////////////
     492// This private static function can be called by any thread running in any cluster.
     493// It gets one non-full KCM page from the remote KCM.
     494// It allocates a page from remote PPM to populate the freelist, and initialises
     495// the kcm_page descriptor when required.
     496/////////////////////////////////////////////////////////////////////////////////////
     497static kcm_page_t * __attribute__((noinline)) kcm_remote_get_page( cxy_t    kcm_cxy,
     498                                                                   kcm_t  * kcm_ptr )
     499{
     500    kcm_page_t * kcm_page;    // local pointer on remote KCM page
     501
     502    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
     503
     504    if( active_pages_nr > 0 )       // return first active page
     505    {
     506        kcm_page = LIST_REMOTE_FIRST( kcm_cxy , &kcm_ptr->active_root , kcm_page_t , list );
     507    }
     508    else                            // allocate a new page from PPM
     509        {
     510        // get one 4 Kbytes page from remote PPM
     511        page_t * page = ppm_remote_alloc_pages( kcm_cxy , 0 );
     512
     513            if( page == NULL )
     514            {
     515                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
     516                __FUNCTION__ , kcm_cxy );
     517
     518                    return NULL;
     519        }
     520
     521            // get remote page base address
     522            xptr_t base_xp = ppm_page2base( XPTR( kcm_cxy , page ) );
     523
     524        // get local pointer on kcm_page
     525            kcm_page = GET_PTR( base_xp );
     526
     527            // initialize kcm_page descriptor
     528            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count )  , 0 );
     529            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , 0 );
     530            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->kcm )    , kcm_ptr );
     531            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->page )   , page );
     532
     533            // introduce new page in remote KCM active_list
     534            list_remote_add_first( kcm_cxy , &kcm_ptr->active_root , &kcm_page->list );
     535            hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
     536        }
     537
     538        return kcm_page;
     539
     540}  // end kcm_remote_get_page()
     541
     542/////////////////////////////////////////
     543void * kcm_remote_alloc( cxy_t    kcm_cxy,
     544                         uint32_t order )
     545{
     546    kcm_t      * kcm_ptr;
     547    kcm_page_t * kcm_page;
     548    void       * block_ptr;
     549
     550    if( order < 6 ) order = 6;
     551
     552assert( (order < 12) , "order = %d / must be less than 12" , order );
     553
     554    // get local pointer on relevant KCM allocator
     555    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
     556
     557    // build extended pointer on remote KCM lock
     558    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
     559
     560        // get lock
     561        remote_busylock_acquire( lock_xp );
     562
     563    // get a non-full kcm_page
     564    kcm_page = kcm_remote_get_page( kcm_cxy , kcm_ptr );
     565
     566    if( kcm_page == NULL )
     567        {
     568                remote_busylock_release( lock_xp );
     569                return NULL;
    331570        }
    332571
    333572        // get a block from selected active page
    334         // cannot fail, as an active page cannot be full...
    335         ptr  = kcm_get_block( kcm , kcm_page );
     573        block_ptr = kcm_remote_get_block( kcm_cxy , kcm_ptr , kcm_page );
    336574
    337575        // release lock
    338         busylock_release( &kcm->lock );
    339 
    340         return ptr;
     576        remote_busylock_release( lock_xp );
     577
     578#if DEBUG_KCM_REMOTE
     579thread_t * this  = CURRENT_THREAD;
     580uint32_t   cycle = (uint32_t)hal_get_cycles();
     581if( DEBUG_KCM_REMOTE < cycle )
     582printk("\n[%s] thread[%x,%x] allocated block %x / order %d / kcm[%x,%x]\n",
     583__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
     584#endif
     585
     586        return block_ptr;
     587
     588}  // end kcm_remote_alloc()
     589
     590/////////////////////////////////////
     591void kcm_remote_free( cxy_t  kcm_cxy,
     592                      void * block_ptr )
     593{
     594        kcm_t      * kcm_ptr;
     595        kcm_page_t * kcm_page;
     596
     597// check argument
     598assert( (block_ptr != NULL) , "block pointer cannot be NULL" );
     599
     600    // get local pointer on remote KCM page
     601        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~CONFIG_PPM_PAGE_MASK);
     602
     603    // get local pointer on remote KCM
     604        kcm_ptr = hal_remote_lpt( XPTR( kcm_cxy , &kcm_page->kcm ) );
     605
     606    // build extended pointer on remote KCM lock
     607    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
     608
     609        // get lock
     610        remote_busylock_acquire( lock_xp );
     611
     612        // release block
     613        kcm_remote_put_block( kcm_cxy , kcm_ptr , kcm_page , block_ptr );
     614
     615        // release lock
     616        remote_busylock_release( lock_xp );
     617
     618#if DEBUG_KCM_REMOTE
     619thread_t * this  = CURRENT_THREAD;
     620uint32_t   cycle = (uint32_t)hal_get_cycles();
     621uint32_t   order = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
     622if( DEBUG_KCM_REMOTE < cycle )
     623printk("\n[%s] thread[%x,%x] released block %x / order %d / kcm[%x,%x]\n",
     624__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
     625#endif
     626
     627}  // end kcm_remote_free
     628
     629/////////////////////////////////////////
     630void kcm_remote_display( cxy_t   kcm_cxy,
     631                         kcm_t * kcm_ptr )
     632{
     633    uint32_t order           = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order) );
     634    uint32_t full_pages_nr   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) );
     635    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
     636
     637        printk("*** KCM / cxy %x / order %d / full_pages %d / empty_pages %d / active_pages %d\n",
     638        kcm_cxy, order, full_pages_nr, active_pages_nr );
    341639}
    342 
    343 ///////////////////////////
    344 void kcm_free( void * ptr )
    345 {
    346         kcm_page_t * kcm_page;
    347         kcm_t      * kcm;
    348 
    349 // check argument
    350 assert( (ptr != NULL) , "pointer cannot be NULL" );
    351 
    352         kcm_page = (kcm_page_t *)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK);
    353         kcm      = kcm_page->kcm;
    354 
    355         // get lock
    356         busylock_acquire( &kcm->lock );
    357 
    358         // release block
    359         kcm_put_block( kcm , kcm_page , ptr );
    360 
    361         // release lock
    362         busylock_release( &kcm->lock );
    363 }
    364 
    365 ////////////////////////////
    366 void kcm_print (kcm_t * kcm)
    367 {
    368         printk("*** KCM type = %s / free_pages = %d / busy_pages = %d / active_pages = %d\n",
    369                kmem_type_str( kcm->type ) ,
    370                kcm->free_pages_nr ,
    371                kcm->busy_pages_nr ,
    372                kcm->active_pages_nr );
    373 }
  • trunk/kernel/mm/kcm.h

    r619 r635  
    11/*
    2  * kcm.h - Per-cluster Kernel Cache Manager definition.
     2 * kcm.h - Kernel Cache Manager definition.
    33 *
    4  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Alain Greiner    (2016,2017,2018)
     4 * Authors    Alain Greiner (2016,2017,2018,2019)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    3332#include <kmem.h>
    3433
     34
     35#define KCM_PAGE_FULL     0
     36#define KCM_PAGE_EMPTY    1
     37#define KCM_PAGE_ACTIVE   2
     38
    3539/****************************************************************************************
    3640 * This structure defines a generic Kernel Cache Manager, that is a block allocator,
    37  * for fixed size objects. It exists a specific KCM allocator for each object type.
    38  * The actual allocated block size is the smallest multiple of the KCM slot, that
    39  * contain one single object. The KCM slot is 64 bytes, as it must be large enough
    40  * to store the kcm_page descriptor, defined below.
    41  * The various KCM allocators themselves are not statically allocated in the cluster
    42  * manager, but are dynamically allocated when required, using the embedded KCM
    43  * allocator defined in the cluster manager, to allocate the other ones...
     41 * for fixed size objects. It exists in each cluster a specific KCM allocator for
     42 * the following block sizes: 64, 128, 256, 512, 1024, 2048 bytes.
     43 * These six KCM allocators are initialized by the cluster_init() function.
     44 *
     45 * Each KCM cache is implemented as a set o 4 Kbytes pages. A kcm_page is split in slots,
     46 * where each slot can contain one block. in each kcm_page, the first slot (that cannot
     47 * be smaller than 64 bytes) contains the kcm page descriptor, defined below
     48 *
     49 * To allow any thread running in any cluster to directly access the KCM of any cluster,
     50 * ALMOS-MKH defines two sets of access functions, for local or remote access.
    4451 ***************************************************************************************/
    4552
    4653typedef struct kcm_s
    4754{
    48         busylock_t           lock;             /*! protect KCM ammocator                   */
    49         uint32_t             block_size;       /*! rounded block size (bytes)              */
    50         uint32_t             blocks_nr;        /*! max number of blocks per page           */
     55        remote_busylock_t    lock;             /*! protect KCM allocator                   */
    5156
     57        list_entry_t         full_root;        /*! root of full pages list                 */
    5258        list_entry_t         active_root;      /*! root of active pages list               */
    53         list_entry_t         busy_root;        /*! root of busy pages list                 */
    54         list_entry_t         free_root;        /*! root of free pages list                 */
    5559
    56         uint32_t             free_pages_nr;    /*! number of free pages                    */
    57         uint32_t             busy_pages_nr;    /*! number of busy pages                    */
     60        uint32_t             full_pages_nr;    /*! number of busy pages                    */
    5861        uint32_t             active_pages_nr;  /*! number of active pages                  */
    5962
    60         uint32_t             type;             /*! KCM type                                */
     63        uint32_t             order;            /*! ln( block_size )                        */
     64        uint32_t             max_blocks;       /*! max number of blocks per page           */
    6165}
    6266kcm_t;
     
    6569/****************************************************************************************
    6670 * This structure defines a KCM-page descriptor.
    67  * A KCM-page contains at most (CONFIG_PPM_PAGE_SIZE / CONFIG_KCM_SLOT_SIZE) blocks.
    68  * This kcm page descriptor is stored in the first slot of the page.
     71 * A KCM-page contains at most (CONFIG_PPM_PAGE_SIZE / CONFIG_KCM_SLOT_SIZE) slots,
     72 * and each slot contains one block. The kcm page descriptor is stored in first slot.
     73 * The current allocation status is defined by the 64 bits "status" bit vector: each
     74 * non zero bit defines an allocated block / "counts is the number of allocated blocks.
     75 * Each kcm_page is registered in one of the two following page_list:
     76 * - full   : when count == max
     77 * - active : count < max
    6978 ***************************************************************************************/
    7079
    7180typedef struct kcm_page_s
    7281{
    73         uint32_t        bitmap[2];             /*! at most 64 blocks in a single page      */
    74         list_entry_t    list;                  /*! [active / busy / free] list member      */
    75         kcm_t         * kcm;                   /*! pointer on kcm allocator                */
    76         page_t        * page;                  /*! pointer on the physical page descriptor */
    77         uint32_t        count;                 /*! number of allocated blocks              */
    78         uint32_t        busy;                  /*! page busy if non zero                   */
    79         uint32_t        active;                /*! page active if non zero                 */
     82        uint64_t            status;            /*! bit vector: non-zero == allocated       */
     83        uint32_t            count;             /*! number of allocated blocks in page      */
     84        list_entry_t        list;              /*! [active / busy / free] list member      */
     85        kcm_t             * kcm;               /*! pointer on kcm allocator                */
     86        page_t            * page;              /*! pointer on the physical page descriptor */
    8087}
    8188kcm_page_t;
    8289
    8390/****************************************************************************************
    84  * This function initializes a generic Kernel Cache Manager.
     91 * This function must be called by a local thread.
     92 * It initializes a Kernel Cache Manager, depending on block size.
    8593 ****************************************************************************************
    8694 * @ kcm      : pointer on KCM manager to initialize.
    87  * @ type     : KCM allocator type.
     95 * @ order    : ln(block_size).
    8896 ***************************************************************************************/
    8997void kcm_init( kcm_t    * kcm,
    90                uint32_t   type );
     98               uint32_t   order );
    9199
    92100/****************************************************************************************
    93  * This function releases all memory allocated to a generic Kernel Cache Manager.
     101 * This function must be called by a local thread.
     102 * It releases all memory allocated to a Kernel Cache Manager.
    94103 ****************************************************************************************
    95104 * @ kcm      : pointer on KCM manager to destroy.
     
    98107
    99108/****************************************************************************************
    100  * This function allocates one single object from a Kernel Cache Manager
    101  * The object size must be smaller than one page size.
     109 * This function must be called by a local thread.
     110 * It allocates one block from the local Kernel Cache Manager.
    102111 ****************************************************************************************
    103  * @ kcm      :  pointer on the selected KCM allocator
     112 * @ order     :  ln( block-size ) == KCM allocator identifier.
    104113 * @ return pointer on allocated block if success / return NULL if failure
    105114 ***************************************************************************************/
    106 void * kcm_alloc( kcm_t * kcm );
     115void * kcm_alloc( uint32_t order );
    107116
    108117/****************************************************************************************
    109  * This function releases a previouly allocated block containing one object.
     118 * This function must be called by a local thread.
     119 * It releases a previouly allocated block to the local Kernel Cache Manager.
    110120 ****************************************************************************************
    111  * @ ptr   : local pointer on the allocated buffer.
     121 * @ block_ptr   : local pointer on the released block.
    112122 ***************************************************************************************/
    113 void kcm_free( void * ptr );
     123void kcm_free( void    * block_ptr );
    114124
    115125/****************************************************************************************
    116  * This function prints KCM allocator state (for debug only).
     126 * This function can be called by any thread running in any cluster.
     127 * It allocates one fixed size block from a remote Kernel Cache Manager.
    117128 ****************************************************************************************
    118  * @ kcm   : local pointer on the selected KCM allocator.
     129 * @ kcm_cxy   : remote KCM cluster identifier.
     130 * @ order     :  ln( block-size ) == KCM allocator identifier.
     131 * @ return a local pointer on allocated block if success / return NULL if failure
    119132 ***************************************************************************************/
    120 void kcm_print( kcm_t * kcm );
     133void * kcm_remote_alloc( cxy_t    kcm_cxy,
     134                         uint32_t order );
     135
     136/****************************************************************************************
     137 * This function can be called by any thread running in any cluster.
     138 * It releases a previouly allocated block to a remote Kernel Cache Manager.
     139 ****************************************************************************************
     140 * @ kcm_cxy     : remote KCM cluster identifier.
     141 * @ block_ptr   : local pointer on the released buffer in remote cluster.
     142 ***************************************************************************************/
     143void kcm_remote_free( cxy_t     kcm_cxy,
     144                      void    * block_ptr );
     145
     146/****************************************************************************************
     147 * This debug function can be called by any thread running in any cluster.
     148 * It diplays on TXT0 the current state of a local KCM allocator.
     149 ****************************************************************************************
     150 * @ kcm_cxy : remote KCM cluster identifier.
     151 * @ kcm_ptr : local pointer on remote KCM.
     152 ***************************************************************************************/
     153void kcm_remote_display( cxy_t   kcm_cxy,
     154                         kcm_t * kcm_ptr );
    121155
    122156#endif  /* _KCM_H_ */
  • trunk/kernel/mm/khm.h

    r619 r635  
    3232/*******************************************************************************************
    3333 * This structure defines a Kernel Heap Manager (KHM) in a given cluster.
    34  * It is used to allocate memory objects, that too large, or not enough replicated
     34 * It is used to allocate memory objects, that are too large, or not enough replicated
    3535 * to use a dedicated KCM allocator.
    3636 ******************************************************************************************/
     
    5454{
    5555        uint32_t   busy;           /*! free block if zero                                     */
    56         uint32_t   size;           /*! block size                                                   */
     56        uint32_t   size;           /*! block size                                             */
    5757}
    5858khm_block_t;
  • trunk/kernel/mm/kmem.c

    r619 r635  
    22 * kmem.c - kernel memory allocator implementation.
    33 *
    4  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Alain Greiner (2016,2017,2018)
     4 * Authors  Alain Greiner (2016,2017,2018,2019)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    2726#include <hal_special.h>
    2827#include <printk.h>
    29 #include <busylock.h>
     28#include <cluster.h>
    3029#include <memcpy.h>
    3130#include <khm.h>
    3231#include <ppm.h>
     32#include <kcm.h>
    3333#include <page.h>
    34 #include <cluster.h>
    35 #include <thread.h>
    36 #include <process.h>
    37 #include <chdev.h>
    38 #include <mapper.h>
    39 #include <vfs.h>
    40 #include <fatfs.h>
    41 #include <ramfs.h>
    42 #include <user_dir.h>
    43 #include <remote_sem.h>
    44 #include <remote_barrier.h>
    45 #include <remote_mutex.h>
    46 #include <remote_condvar.h>
    47 #include <mapper.h>
    48 #include <grdxt.h>
    49 #include <vseg.h>
    5034#include <kmem.h>
    51 
    52 /////////////////////////////////
    53 void kmem_print_kcm_table( void )
    54 {
    55         uint32_t    index;
    56         kcm_t     * kcm;
    57         cluster_t * cluster = LOCAL_CLUSTER;
    58 
    59         printk("\n    *** KCM Pointers Table ***\n");
    60 
    61         for( index = 0 ; index < KMEM_TYPES_NR ; index++ )
    62         {
    63                 kcm = cluster->kcm_tbl[index];
    64                 if( kcm != NULL )
    65                 {
    66                         if( index == kcm->type )
    67                         {
    68                                 printk("     - KCM[%s] (at address %x) is OK\n",
    69                                        kmem_type_str( index ) , (intptr_t)kcm );
    70                         }
    71                         else
    72                         {
    73                                 printk("     - KCM[%s] (at address %x) is KO : has type %s\n",
    74                                        kmem_type_str( index ) , (intptr_t)kcm , kmem_type_str( kcm->type ) );
    75                         }
    76                 }
    77         }
    78 }
    79 
    80 /////////////////////////////////////////
    81 uint32_t  kmem_type_size( uint32_t type )
    82 {
    83     if     ( type == KMEM_PAGE )          return CONFIG_PPM_PAGE_SIZE;
    84     else if( type == KMEM_GENERIC )       return 0;
    85     else if( type == KMEM_KCM )           return sizeof( kcm_t );
    86     else if( type == KMEM_VSEG )          return sizeof( vseg_t );
    87     else if( type == KMEM_DEVICE )        return sizeof( chdev_t );
    88     else if( type == KMEM_MAPPER )        return sizeof( mapper_t );
    89     else if( type == KMEM_PROCESS )       return sizeof( process_t );
    90     else if( type == KMEM_CPU_CTX )       return CONFIG_CPU_CTX_SIZE;
    91     else if( type == KMEM_FPU_CTX )       return CONFIG_FPU_CTX_SIZE;
    92     else if( type == KMEM_GEN_BARRIER )   return sizeof( generic_barrier_t );
    93 
    94     else if( type == KMEM_SMP_BARRIER )   return sizeof( simple_barrier_t );
    95     else if( type == KMEM_DEVFS_CTX )     return sizeof( fatfs_ctx_t );
    96     else if( type == KMEM_FATFS_CTX )     return sizeof( fatfs_ctx_t );
    97     else if( type == KMEM_VFS_CTX )       return sizeof( vfs_ctx_t );
    98     else if( type == KMEM_VFS_INODE )     return sizeof( vfs_inode_t );
    99     else if( type == KMEM_VFS_DENTRY )    return sizeof( vfs_dentry_t );
    100     else if( type == KMEM_VFS_FILE )      return sizeof( vfs_file_t );
    101     else if( type == KMEM_SEM )           return sizeof( remote_sem_t );
    102     else if( type == KMEM_CONDVAR )       return sizeof( remote_condvar_t );
    103     else if( type == KMEM_MUTEX )         return sizeof( remote_mutex_t );
    104 
    105     else if( type == KMEM_DIR )           return sizeof( user_dir_t );
    106         else if( type == KMEM_512_BYTES )     return 512;
    107 
    108         else                                  return 0;
    109 }
    110 
    111 /////////////////////////////////////
    112 char * kmem_type_str( uint32_t type )
    113 {
    114         if     ( type == KMEM_PAGE )          return "KMEM_PAGE";
    115         else if( type == KMEM_GENERIC )       return "KMEM_GENERIC";
    116         else if( type == KMEM_KCM )           return "KMEM_KCM";
    117         else if( type == KMEM_VSEG )          return "KMEM_VSEG";
    118         else if( type == KMEM_DEVICE )        return "KMEM_DEVICE";
    119         else if( type == KMEM_MAPPER )        return "KMEM_MAPPER";
    120         else if( type == KMEM_PROCESS )       return "KMEM_PROCESS";
    121         else if( type == KMEM_CPU_CTX )       return "KMEM_CPU_CTX";
    122         else if( type == KMEM_FPU_CTX )       return "KMEM_FPU_CTX";
    123         else if( type == KMEM_GEN_BARRIER )   return "KMEM_GEN_BARRIER";
    124 
    125     else if( type == KMEM_SMP_BARRIER )   return "KMEM_SMP_BARRIER";
    126     else if( type == KMEM_DEVFS_CTX )     return "KMEM_DEVFS_CTX";
    127     else if( type == KMEM_FATFS_CTX )     return "KMEM_FATFS_CTX";
    128     else if( type == KMEM_VFS_CTX )       return "KMEM_VFS_CTX";
    129     else if( type == KMEM_VFS_INODE )     return "KMEM_VFS_INODE";
    130     else if( type == KMEM_VFS_DENTRY )    return "KMEM_VFS_DENTRY";
    131     else if( type == KMEM_VFS_FILE )      return "KMEM_VFS_FILE";
    132     else if( type == KMEM_SEM )           return "KMEM_SEM";
    133     else if( type == KMEM_CONDVAR )       return "KMEM_CONDVAR";
    134     else if( type == KMEM_MUTEX )         return "KMEM_MUTEX";
    135 
    136     else if( type == KMEM_DIR )           return "KMEM_DIR";
    137         else if( type == KMEM_512_BYTES )     return "KMEM_512_BYTES";
    138 
    139         else                                  return "undefined";
    140 }
    141 
    142 /////////////////////////////////////////////////////////////////////////////////////////////
    143 // This static function dynamically allocates and initializes a specific KCM allocator.
    144 // It uses the KCM allocator embedded in cluster manager, initialized by cluster_init().
    145 /////////////////////////////////////////////////////////////////////////////////////////////
    146 static error_t kmem_create_kcm( uint32_t type )
    147 {
    148         kcm_t    * kcm;
    149 
    150         assert( ((type > 1) && (type < KMEM_TYPES_NR) ) , "illegal KCM type" );
    151 
    152 #if DEBUG_KMEM
    153 thread_t * this = CURRENT_THREAD;
    154 uint32_t cycle = (uint32_t)hal_get_cycles();
    155 if( DEBUG_KMEM < cycle )
    156 printk("\n[%s] thread[%x,%x] enter / KCM type %s missing in cluster %x / cycle %d\n",
    157 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str( type ), local_cxy, cycle );
    158 #endif
    159 
    160         cluster_t * cluster = LOCAL_CLUSTER;
    161 
    162         // allocate memory for the requested KCM allocator
    163         // from the KCM allocator embedded in cluster descriptor
    164         kcm = kcm_alloc( &cluster->kcm );
    165 
    166         if( kcm == NULL )
    167         {
    168                 printk("\n[ERROR] in %s : failed to create KCM type %d in cluster %x\n",
    169                        __FUNCTION__ , type , local_cxy );
    170                 return ENOMEM;
    171         }
    172 
    173         // initialize the new KCM allocator
    174         kcm_init( kcm , type );
    175 
    176         // register it in the KCM pointers Table
    177         cluster->kcm_tbl[type] = kcm;
    178 
    179         hal_fence();
    180 
    181 #if DEBUG_KMEM
    182 cycle = (uint32_t)hal_get_cycles();
    183 if( DEBUG_KMEM < cycle )
    184 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
    185 __FUNCTION__, this->process->pid, this->trdid, cycle );
    186 #endif
    187 
    188         return 0;
    189 }
    19035
    19136/////////////////////////////////////
    19237void * kmem_alloc( kmem_req_t * req )
    19338{
    194         cluster_t * cluster = LOCAL_CLUSTER;
    195 
    196         uint32_t    type;
    197         uint32_t    flags;
    198         uint32_t    size;    // ln( pages ) if PPM / bytes if KHM / unused if KCM
    199         void      * ptr;     // memory buffer if KHM or KCM / page descriptor if PPM
     39        uint32_t    type;    // KMEM_PPM / KMEM_KCM / KMEM_KHM
     40        uint32_t    flags;   // AF_NONE / AF_ZERO / AF_KERNEL
     41        uint32_t    order;   // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes
    20042
    20143        type  = req->type;
    202         size  = req->size;
     44        order = req->order;
    20345        flags = req->flags;
    20446
    205         assert( (type < KMEM_TYPES_NR) , "illegal KMEM request type" );
     47    ////////////////////////////////// PPM
     48        if( type == KMEM_PPM )
     49        {
     50                // allocate the number of requested pages
     51                page_t * page_ptr = (void *)ppm_alloc_pages( order );
     52
     53                if( page_ptr == NULL )
     54                {
     55                        printk("\n[ERROR] in %s : PPM failed / order %d / cluster %x\n",
     56                        __FUNCTION__ , order , local_cxy );
     57                        return NULL;
     58                }
     59
     60        xptr_t page_xp = XPTR( local_cxy , page_ptr );
     61
     62                // reset page if requested
     63                if( flags & AF_ZERO ) page_zero( page_ptr );
     64
     65        // get pointer on buffer from the page descriptor
     66        void * ptr = GET_PTR( ppm_page2base( page_xp ) );
    20667
    20768#if DEBUG_KMEM
    208 thread_t * this = CURRENT_THREAD;
    209 uint32_t cycle = (uint32_t)hal_get_cycles();
     69thread_t * this  = CURRENT_THREAD;
     70uint32_t   cycle = (uint32_t)hal_get_cycles();
    21071if( DEBUG_KMEM < cycle )
    211 printk("\n[%s] thread [%x,%x] enter / %s / size %d / cluster %x / cycle %d\n",
     72printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n",
     73__FUNCTION__, this->process->pid, this->trdid,
     741<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), local_cxy, cycle );
     75#endif
     76        return ptr;
     77        }
     78    ///////////////////////////////////// KCM
     79        else if( type == KMEM_KCM )
     80        {
     81                // allocate memory from KCM
     82                void * ptr = kcm_alloc( order );
     83
     84                if( ptr == NULL )
     85                {
     86                        printk("\n[ERROR] in %s : KCM failed / order %d / cluster %x\n",
     87                    __FUNCTION__ , order , local_cxy );
     88                        return NULL;
     89                }
     90
     91                // reset memory if requested
     92                if( flags & AF_ZERO ) memset( ptr , 0 , 1<<order );
     93
     94#if DEBUG_KMEM
     95thread_t * this  = CURRENT_THREAD;
     96uint32_t   cycle = (uint32_t)hal_get_cycles();
     97if( DEBUG_KMEM < cycle )
     98printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n",
     99__FUNCTION__, this->process->pid, this->trdid,
     1001<<order, ptr, local_cxy, cycle );
     101#endif
     102        return ptr;
     103        }
     104    //////////////////////////////////// KHM
     105        else if( type == KMEM_KHM )
     106        {
     107                // allocate memory from KHM
     108                void * ptr = khm_alloc( &LOCAL_CLUSTER->khm , order );
     109
     110                if( ptr == NULL )
     111                {
     112                        printk("\n[ERROR] in %s : KHM failed / order %d / cluster %x\n",
     113                        __FUNCTION__ , order , local_cxy );
     114                        return NULL;
     115                }
     116
     117                // reset memory if requested
     118                if( flags & AF_ZERO ) memset( ptr , 0 , order );
     119
     120#if DEBUG_KMEM
     121thread_t * this  = CURRENT_THREAD;
     122uint32_t   cycle = (uint32_t)hal_get_cycles();
     123if( DEBUG_KMEM < cycle )
     124printk("\n[%s] thread[%x,%x] from KHM / %d bytes / base %x / cxy %x / cycle %d\n",
    212125__FUNCTION__, this->process->pid, this->trdid,
    213 kmem_type_str( type ), size, local_cxy, cycle );
    214 #endif
    215 
    216         // analyse request type
    217         if( type == KMEM_PAGE )                        // PPM allocator
    218         {
    219                 // allocate the number of requested pages
    220                 ptr = (void *)ppm_alloc_pages( size );
    221                 if( ptr == NULL )
    222                 {
    223                         printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n",
    224                             __FUNCTION__ , type , size , local_cxy );
    225                         return NULL;
    226                 }
    227 
    228                 // reset page if requested
    229                 if( flags & AF_ZERO ) page_zero( (page_t *)ptr );
    230 
    231 #if DEBUG_KMEM
    232 cycle = (uint32_t)hal_get_cycles();
    233 if( DEBUG_KMEM < cycle )
    234 printk("\n[%s] thread[%x,%x] exit / %d page(s) allocated / ppn %x / cycle %d\n",
    235 __FUNCTION__, this->process->pid, this->trdid,
    236 1<<size, ppm_page2ppn(XPTR(local_cxy,ptr)), cycle );
    237 #endif
    238 
    239         }
    240         else if( type == KMEM_GENERIC )                // KHM allocator
    241         {
    242                 // allocate memory from KHM
    243                 ptr = khm_alloc( &cluster->khm , size );
    244                 if( ptr == NULL )
    245                 {
    246                         printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n",
    247                             __FUNCTION__ , type , size , local_cxy );
    248                         return NULL;
    249                 }
    250 
    251                 // reset memory if requested
    252                 if( flags & AF_ZERO ) memset( ptr , 0 , size );
    253 
    254 #if DEBUG_KMEM
    255 cycle = (uint32_t)hal_get_cycles();
    256 if( DEBUG_KMEM < cycle )
    257 printk("\n[%s] thread[%x,%x] exit / type %s allocated / base %x / size %d / cycle %d\n",
    258 __FUNCTION__, this->process->pid, this->trdid,
    259 kmem_type_str( type ), (intptr_t)ptr, size, cycle );
    260 #endif
    261 
    262         }
    263         else                                           // KCM allocator
    264         {
    265                 // initialize the KCM allocator if not already done
    266                 if( cluster->kcm_tbl[type] == NULL )
    267                 {
    268             // get lock protecting local kcm_tbl[] array
    269                         busylock_acquire( &cluster->kcm_lock );
    270 
    271             // create missing KCM
    272                         error_t error = kmem_create_kcm( type );
    273 
    274             // release lock protecting local kcm_tbl[] array
    275                         busylock_release( &cluster->kcm_lock );
    276 
    277                         if ( error )
    278             {
    279                  printk("\n[ERROR] in %s : cannot create KCM type %d in cluster %x\n",
    280                  __FUNCTION__, type, local_cxy );
    281                  return NULL;
    282             }
    283                 }
    284 
    285                 // allocate memory from KCM
    286                 ptr = kcm_alloc( cluster->kcm_tbl[type] );
    287                 if( ptr == NULL )
    288                 {
    289                         printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n",
    290                     __FUNCTION__ , type , size , local_cxy );
    291                         return NULL;
    292                 }
    293 
    294                 // reset memory if requested
    295                 if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) );
    296 
    297 #if DEBUG_KMEM
    298 cycle = (uint32_t)hal_get_cycles();
    299 if( DEBUG_KMEM < cycle )
    300 printk("\n[%s] thread [%x,%x] exit / type %s allocated / base %x / size %d / cycle %d\n",
    301 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(type), (intptr_t)ptr,
    302 kmem_type_size(type), cycle );
    303 #endif
    304 
    305         }
    306 
    307         return ptr;
    308 }
     126order, ptr, local_cxy, cycle );
     127#endif
     128        return ptr;
     129        }
     130    else
     131    {
     132        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
     133        return NULL;
     134    }
     135}  // end kmem_alloc()
    309136
    310137//////////////////////////////////
    311138void kmem_free( kmem_req_t * req )
    312139{
    313         if( req->type >= KMEM_TYPES_NR )
    314         {
    315                 assert( false , "illegal request type\n" );
    316         }
    317 
    318         switch(req->type)
    319         {
    320                 case KMEM_PAGE:
    321                         ppm_free_pages( (page_t*)req->ptr );
    322                         return;
    323 
    324                 case KMEM_GENERIC:
    325                         khm_free( req->ptr );
    326                         return;
    327 
    328                 default:
    329                         kcm_free( req->ptr );
    330                         return;
    331         }
    332 }
    333 
     140    uint32_t type = req->type;
     141
     142        if( type == KMEM_PPM )
     143        {
     144        page_t * page = GET_PTR( ppm_base2page( XPTR( local_cxy , req->ptr ) ) );
     145
     146        ppm_free_pages( page );
     147    }
     148    else if( type == KMEM_KCM )
     149    {
     150        kcm_free( req->ptr );
     151        }
     152    else if( type == KMEM_KHM )
     153    {
     154        khm_free( req->ptr );
     155    }
     156    else
     157    {
     158        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
     159    }
     160}  // end kmem_free()
     161
     162///////////////////////////////////////////
     163void * kmem_remote_alloc( cxy_t        cxy,
     164                          kmem_req_t * req )
     165{
     166        uint32_t    type;    // KMEM_PPM / KMEM_KCM / KMEM_KHM
     167        uint32_t    flags;   // AF_ZERO / AF_KERNEL / AF_NONE
     168        uint32_t    order;   // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes
     169
     170        type  = req->type;
     171        order = req->order;
     172        flags = req->flags;
     173
     174        ///////////////////////////////// PPM
     175        if( type == KMEM_PPM )
     176        {
     177                // allocate the number of requested pages
     178                page_t * page_ptr = ppm_remote_alloc_pages( cxy , order );
     179
     180                if( page_ptr == NULL )
     181                {
     182                        printk("\n[ERROR] in %s : failed for PPM / order %d in cluster %x\n",
     183                        __FUNCTION__ , order , cxy );
     184                        return NULL;
     185                }
     186
     187        xptr_t page_xp = XPTR( cxy , page_ptr );
     188
     189        // get pointer on buffer from the page descriptor
     190        xptr_t base_xp = ppm_page2base( page_xp );
     191
     192                // reset page if requested
     193                if( flags & AF_ZERO ) hal_remote_memset( base_xp , 0 , CONFIG_PPM_PAGE_SIZE );
     194
     195        void * ptr = GET_PTR( base_xp );
     196
     197#if DEBUG_KMEM_REMOTE
     198thread_t * this = CURRENT_THREAD;
     199uint32_t   cycle = (uint32_t)hal_get_cycles();
     200if( DEBUG_KMEM_REMOTE < cycle )
     201printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n",
     202__FUNCTION__, this->process->pid, this->trdid,
     2031<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), cxy, cycle );
     204#endif
     205        return ptr;
     206        }
     207    /////////////////////////////////// KCM
     208        else if( type == KMEM_KCM )
     209        {
     210                // allocate memory from KCM
     211                void * ptr = kcm_remote_alloc( cxy , order );
     212
     213                if( ptr == NULL )
     214                {
     215                        printk("\n[ERROR] in %s : failed for KCM / order %d in cluster %x\n",
     216                    __FUNCTION__ , order , cxy );
     217                        return NULL;
     218                }
     219
     220                // reset memory if requested
     221                if( flags & AF_ZERO )  hal_remote_memset( XPTR( cxy , ptr ) , 0 , 1<<order );
     222
     223#if DEBUG_KMEM_REMOTE
     224thread_t * this = CURRENT_THREAD;
     225uint32_t   cycle = (uint32_t)hal_get_cycles();
     226if( DEBUG_KMEM_REMOTE < cycle )
     227printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n",
     228__FUNCTION__, this->process->pid, this->trdid,
     2291<<order, ptr, cxy, cycle );
     230#endif
     231        return ptr;
     232        }
     233        /////////////////////////////////// KHM
     234        else if( type == KMEM_KHM )               
     235        {
     236        printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__  );
     237                return NULL;
     238        }
     239    else
     240    {
     241        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
     242        return NULL;
     243    }
     244}  // kmem_remote_malloc()
     245
     246////////////////////////////////////////
     247void kmem_remote_free( cxy_t        cxy,
     248                       kmem_req_t * req )
     249{
     250    uint32_t type = req->type;
     251
     252        if( type == KMEM_PPM )
     253        {
     254        page_t * page = GET_PTR( ppm_base2page( XPTR( cxy , req->ptr ) ) );
     255
     256        ppm_remote_free_pages( cxy , page );
     257    }
     258    else if( type == KMEM_KCM )
     259    {
     260        kcm_remote_free( cxy , req->ptr );
     261        }
     262    else if( type == KMEM_KHM )
     263    {
     264        printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__ );
     265    }
     266    else
     267    {
     268        printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__);
     269    }
     270}  // end kmem_remote_free()
     271
     272
     273
  • trunk/kernel/mm/kmem.h

    r619 r635  
    22 * kmem.h - kernel unified memory allocator interface
    33 *
    4  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *          Alain Greiner (2016,2017,2018)
     4 * Authors  Alain Greiner (2016,2017,2018,2019)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    3029
    3130/*************************************************************************************
    32  * This enum defines the Kernel Memory Types for dynamically allocated objects.
    33  * WARNING : this enum must be kepts consistent with use in kmem.c file.
     31 * This enum defines the three Kernel Memory Allocaror types:
    3432 ************************************************************************************/
    3533
    3634enum
    3735{
    38     KMEM_PAGE             = 0,   /*! reserved for PPM allocator                     */
    39     KMEM_GENERIC          = 1,   /*! reserved for KHM allocator                     */
    40     KMEM_KCM              = 2,   /*! kcm_t                                          */
    41     KMEM_VSEG             = 3,   /*! vseg_t                                         */
    42     KMEM_DEVICE           = 4,   /*! device_t                                       */
    43     KMEM_MAPPER           = 5,   /*! mapper_t                                       */
    44     KMEM_PROCESS          = 6,   /*! process_t                                      */
    45     KMEM_CPU_CTX          = 7,   /*! hal_cpu_context_t                              */
    46     KMEM_FPU_CTX          = 8,   /*! hal_fpu_context_t                              */
    47     KMEM_GEN_BARRIER      = 9,   /*! generi_cbarrier_t                              */
    48 
    49     KMEM_SMP_BARRIER      = 10,  /*! simple_barrier_t                               */
    50     KMEM_DEVFS_CTX        = 11,  /*! fatfs_inode_t                                  */
    51     KMEM_FATFS_CTX        = 12,  /*! fatfs_ctx_t                                    */
    52     KMEM_VFS_CTX          = 13,  /*! vfs_context_t                                  */
    53     KMEM_VFS_INODE        = 14,  /*! vfs_inode_t                                    */
    54     KMEM_VFS_DENTRY       = 15,  /*! vfs_dentry_t                                   */
    55     KMEM_VFS_FILE         = 16,  /*! vfs_file_t                                     */
    56     KMEM_SEM              = 17,  /*! remote_sem_t                                   */
    57     KMEM_CONDVAR          = 18,  /*! remote_condvar_t                               */
    58     KMEM_MUTEX            = 19,  /*! remote_mutex_t                                 */
    59 
    60     KMEM_DIR              = 20,  /*! remote_dir_t                                   */
    61     KMEM_512_BYTES        = 21,  /*! 512 bytes aligned                              */
    62 
    63     KMEM_TYPES_NR         = 22,
     36    KMEM_PPM              = 0,   /*! PPM allocator                                  */
     37    KMEM_KCM              = 1,   /*! KCM allocator                                  */
     38    KMEM_KHM              = 2,   /*! KHM allocator                                  */
    6439};
    6540
     
    7954typedef struct kmem_req_s
    8055{
    81     uint32_t      type;   /*! request type                                          */
    82     uint32_t      size;   /*! ln2(nb_pages) if PPM / bytes if KHM / unused by KCM   */
     56    uint32_t      type;   /*! KMEM_PPM / KMEM_KCM / KMEM_KHM                        */
     57    uint32_t      order;  /*! PPM: ln2(pages) / KCM: ln2(bytes) / KHM: bytes        */
    8358    uint32_t      flags;  /*! request attributes                                    */
    8459    void        * ptr;    /*! local pointer on allocated buffer (only used by free) */
     
    8762
    8863/*************************************************************************************
    89  * This generic function allocates physical memory in the local cluster
    90  * as specified by the request descriptor.
    91  * It uses three specialised physical memory allocators, depending on request type:
    92  * - PPM (Physical Pages Manager) allocates N contiguous physical pages,
    93  *       N must be a power of 2.
    94  * - KHM (Kernel Heap Manager) allocates a physical memory buffer,
    95  *       that can have any size.
    96  * - KCM (Kernel Cache Manager) allocates various fixed size objects,
    97  *       handling a dedicated cache for each object type.
     64 * These two functions allocate physical memory in a local or remote cluster
     65 * as specified by the kmem_req_t request descriptor, and return a local pointer
     66 * on the allocated buffer. It uses three specialised physical memory allocators:
     67 * - PPM (Physical Pages Manager) allocates N contiguous small physical pages.
     68 *       N is a power of 2, and req.order = ln(N). Implement the buddy algorithm.
     69 * - KCM (Kernel Cache Manager) allocates aligned blocks of M bytes from a cache.
     70 *       M is a power of 2, and req.order = ln( M ). One cache per block size.
     71 * - KHM (Kernel Heap Manager) allocates physical memory buffers of M bytes,
     72 *       M can have any value, and req.order = M.
    9873 *************************************************************************************
    99  * @ req   : local pointer to allocation request.
    100  * @ return a local pointer on page descriptor if KMEM_PAGE.
    101  *   return a local pointer to allocated buffer if KCM or KHM.
    102  *   return NULL if no physical memory available.
     74 * @ cxy   : target cluster identifier for a remote access.
     75 * @ req   : local pointer on allocation request.
     76 * @ return local pointer on allocated buffer if success / return NULL if no memory.
    10377 ************************************************************************************/
    10478void * kmem_alloc( kmem_req_t * req );
    10579
     80void * kmem_remote_alloc( cxy_t        cxy,
     81                          kmem_req_t * req );
     82
    10683/*************************************************************************************
    107  * This function releases previously allocated physical memory, as specified
    108  * by the "type" and "ptr" fiels of the kmem-req_t request.
     84 * These two functions release previously allocated physical memory, as specified
     85 * by the <type> and <ptr> fields of the kmem_req_t request descriptor.
    10986 *************************************************************************************
     87 * @ cxy   : target cluster identifier for a remote access.
    11088 * @ req : local pointer to request descriptor.
    11189 ************************************************************************************/
    11290void  kmem_free ( kmem_req_t * req );
    11391
    114 /*************************************************************************************
    115  * This function returns a printable string for a kmem object type.
    116  *************************************************************************************
    117  * @ type   : kmem object type.
    118  ************************************************************************************/
    119 char * kmem_type_str( uint32_t type );
    120 
    121 /*************************************************************************************
    122  * This function returns the size (bytes) for a kmem object type.
    123  *************************************************************************************
    124  * @ type   : kmem object type.
    125  ************************************************************************************/
    126 uint32_t kmem_type_size( uint32_t type );
    127 
    128 /*************************************************************************************
    129  * This function displays the content of the KCM pointers Table
    130  ************************************************************************************/
    131 void kmem_print_kcm_table( void );
     92void  kmem_remote_free( cxy_t        cxy,
     93                        kmem_req_t * req );
    13294
    13395
  • trunk/kernel/mm/mapper.c

    r628 r635  
    5252    error_t    error;
    5353
    54     // allocate memory for mapper
    55     req.type  = KMEM_MAPPER;
    56     req.size  = sizeof(mapper_t);
     54    // allocate memory for mapper descriptor
     55    req.type  = KMEM_KCM;
     56    req.order = bits_log2( sizeof(mapper_t) );
    5757    req.flags = AF_KERNEL | AF_ZERO;
    58     mapper    = (mapper_t *)kmem_alloc( &req );
     58    mapper    = kmem_alloc( &req );
    5959
    6060    if( mapper == NULL )
     
    7373                        CONFIG_MAPPER_GRDXT_W2,
    7474                        CONFIG_MAPPER_GRDXT_W3 );
    75 
    7675    if( error )
    7776    {
    7877        printk("\n[ERROR] in %s : cannot initialize radix tree\n", __FUNCTION__ );
    79         req.type  = KMEM_MAPPER;
     78        req.type  = KMEM_KCM;
    8079        req.ptr   = mapper;
    8180        kmem_free( &req );
     
    117116        {
    118117            // remove page from mapper and release to PPM
    119             mapper_release_page( mapper , page );
     118            mapper_remote_release_page( XPTR( local_cxy , mapper ) , page );
    120119
    121120            // update start_key value for next page
     
    129128
    130129    // release memory for mapper descriptor
    131     req.type = KMEM_MAPPER;
     130    req.type = KMEM_KCM;
    132131    req.ptr  = mapper;
    133132    kmem_free( &req );
    134133
    135134}  // end mapper_destroy()
     135
     136////////////////////////////////////////////////////////
     137error_t mapper_remote_handle_miss( xptr_t     mapper_xp,
     138                                   uint32_t   page_id,
     139                                   xptr_t   * page_xp_ptr )
     140{
     141    error_t    error;
     142
     143    thread_t * this = CURRENT_THREAD;
     144
     145    // get target mapper cluster and local pointer
     146    cxy_t      mapper_cxy = GET_CXY( mapper_xp );
     147    mapper_t * mapper_ptr = GET_PTR( mapper_xp );
     148
     149#if DEBUG_MAPPER_HANDLE_MISS
     150uint32_t      cycle = (uint32_t)hal_get_cycles();
     151char          name[CONFIG_VFS_MAX_NAME_LENGTH];
     152vfs_inode_t * inode = mapper->inode;
     153if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode != NULL) )
     154{
     155    vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
     156    printk("\n[%s] thread[%x,%x] enter for page %d in <%s> / cluster %x / cycle %d",
     157    __FUNCTION__, this->process->pid, this->trdid, page_id, name, mapper_cxy, cycle );
     158    if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt), name );
     159}
     160if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode == NULL) )
     161{
     162    printk("\n[%s] thread[%x,%x] enter for page %d in FAT / cluster %x / cycle %d",
     163    __FUNCTION__, this->process->pid, this->trdid, page_id, mapper_cxy, cycle );
     164    if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt), "FAT" );
     165}
     166#endif
     167
     168    // allocate one 4 Kbytes page from the remote mapper cluster
     169    page_t * page_ptr = ppm_remote_alloc_pages( mapper_cxy , 0 );
     170                           
     171    if( page_ptr == NULL )
     172    {
     173        printk("\n[ERROR] in %s : thread [%x,%x] cannot allocate page in cluster %x\n",
     174        __FUNCTION__ , this->process->pid, this->trdid , mapper_cxy );
     175        return -1;
     176    }
     177
     178    // build extended pointer on new page descriptor
     179    xptr_t page_xp = XPTR( mapper_cxy , page_ptr );
     180
     181    // initialize the page descriptor
     182    page_remote_init( page_xp );
     183
     184    hal_remote_s32( XPTR( mapper_cxy , &page_ptr->refcount ) , 1          );
     185    hal_remote_s32( XPTR( mapper_cxy , &page_ptr->index )    , page_id    );
     186    hal_remote_spt( XPTR( mapper_cxy , &page_ptr->mapper )   , mapper_ptr );
     187    hal_remote_s32( XPTR( mapper_cxy , &page_ptr->flags )    , PG_INIT    );
     188
     189    // insert page in mapper radix tree
     190    error = grdxt_remote_insert( XPTR( mapper_cxy , &mapper_ptr->rt),
     191                                 page_id,
     192                                 page_ptr );
     193
     194    if( error )
     195    {
     196        printk("\n[ERROR] in %s : thread[%x,%x] cannot insert page in mapper\n",
     197        __FUNCTION__ , this->process->pid, this->trdid );
     198        ppm_remote_free_pages( mapper_cxy , page_ptr );
     199        return -1;
     200    }
     201
     202    // launch I/O operation to load page from IOC device to mapper
     203    error = vfs_fs_move_page( page_xp , IOC_SYNC_READ );
     204
     205    if( error )
     206    {
     207        printk("\n[ERROR] in %s : thread[%x,%x] cannot load page from device\n",
     208        __FUNCTION__ , this->process->pid, this->trdid );
     209        mapper_remote_release_page( mapper_xp , page_ptr );
     210        return -1;
     211    }
     212
     213    // return extended pointer on allocated page
     214    *page_xp_ptr = page_xp;
     215
     216#if DEBUG_MAPPER_HANDLE_MISS
     217cycle = (uint32_t)hal_get_cycles();
     218if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode != NULL) )
     219{
     220    printk("\n[%s] thread[%x,%x] exit for page %d in <%s> / ppn %x / cycle %d",
     221    __FUNCTION__, this->process->pid, this->trdid,
     222    page_id, name, ppm_page2ppn( page_xp ), cycle );
     223    if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt) , name );
     224}
     225if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode == NULL) )
     226{
     227    printk("\n[%s] thread[%x,%x] exit for page %d in FAT / ppn %x / cycle %d",
     228    __FUNCTION__, this->process->pid, this->trdid,
     229    page_id, ppm_page2ppn( page_xp ), cycle );
     230    if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt ), "FAT" );
     231}
     232#endif
     233
     234    return 0;
     235
     236}  // end mapper_remote_handle_miss()
    136237
    137238////////////////////////////////////////////////////
     
    183284
    184285    // test mapper miss
    185     if( page_xp == XPTR_NULL )                  // miss => try to handle it
     286    if( page_xp == XPTR_NULL )                  // miss => handle it
    186287    {
    187288        // release the lock in READ_MODE and take it in WRITE_MODE
     
    196297        if ( page_xp == XPTR_NULL )  // miss confirmed => handle it
    197298        {
    198 
    199             if( mapper_cxy == local_cxy )   // mapper is local
    200             {
    201 
    202 #if (DEBUG_MAPPER_GET_PAGE & 1)
    203 if( DEBUG_MAPPER_GET_PAGE < cycle )
    204 printk("\n[%s] missing page => load it from FS / local access \n", __FUNCTION__ );
    205 #endif
    206                  error = mapper_handle_miss( mapper_ptr,
    207                                              page_id,
    208                                              &page_xp );
    209             }
    210             else
    211             {
    212 
    213 #if (DEBUG_MAPPER_GET_PAGE & 1)
    214 if( DEBUG_MAPPER_GET_PAGE < cycle )
    215 printk("\n[%s] missing page => load it from FS / RPC access \n", __FUNCTION__ );
    216 #endif
    217                  rpc_mapper_handle_miss_client( mapper_cxy,
    218                                                 mapper_ptr,
    219                                                 page_id,
    220                                                 &page_xp,
    221                                                 &error );
    222             }
    223 
    224             if ( error )
     299            error = mapper_remote_handle_miss( mapper_xp,
     300                                               page_id,
     301                                               &page_xp );
     302            if( error )
    225303            {
    226304                printk("\n[ERROR] in %s : thread[%x,%x] cannot handle mapper miss\n",
     
    230308            }
    231309        }
     310
     311#if (DEBUG_MAPPER_GET_PAGE & 1)
     312if( DEBUG_MAPPER_GET_PAGE < cycle )
     313printk("\n[%s] thread[%x,%x] load missing page from FS : ppn %x\n",
     314__FUNCTION__, this->process->pid, this->trdid, ppm_page2ppn(page_xp) );
     315#endif
    232316       
    233317        // release mapper lock from WRITE_MODE
     
    260344}  // end mapper_remote_get_page()
    261345
    262 //////////////////////////////////////////////
    263 error_t mapper_handle_miss( mapper_t * mapper,
    264                             uint32_t   page_id,
    265                             xptr_t   * page_xp )
    266 {
    267     kmem_req_t   req;
    268     page_t     * page;
    269     error_t      error;
    270 
    271     thread_t * this = CURRENT_THREAD;
    272 
    273 #if DEBUG_MAPPER_HANDLE_MISS
    274 uint32_t      cycle = (uint32_t)hal_get_cycles();
    275 char          name[CONFIG_VFS_MAX_NAME_LENGTH];
    276 vfs_inode_t * inode = mapper->inode;
    277 if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode != NULL) )
    278 {
    279     vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
    280     printk("\n[%s] thread[%x,%x] enter for page %d in <%s> / cycle %d",
    281     __FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
    282     if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt), name );
    283 }
    284 if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode == NULL) )
    285 {
    286     printk("\n[%s] thread[%x,%x] enter for page %d in FAT / cycle %d",
    287     __FUNCTION__, this->process->pid, this->trdid, page_id, cycle );
    288     if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt), "FAT" );
    289 }
    290 #endif
    291 
    292     // allocate one page from the local cluster
    293     req.type  = KMEM_PAGE;
    294     req.size  = 0;
    295     req.flags = AF_NONE;
    296     page = kmem_alloc( &req );
    297 
    298     if( page == NULL )
    299     {
    300         printk("\n[ERROR] in %s : thread [%x,%x] cannot allocate page in cluster %x\n",
    301         __FUNCTION__ , this->process->pid, this->trdid , local_cxy );
    302         return -1;
    303     }
    304 
    305     // initialize the page descriptor
    306     page_init( page );
    307     page_set_flag( page , PG_INIT );
    308     page_refcount_up( page );
    309     page->mapper = mapper;
    310     page->index  = page_id;
    311 
    312     // insert page in mapper radix tree
    313     error = grdxt_insert( &mapper->rt , page_id , page );
    314 
    315     if( error )
    316     {
    317         printk("\n[ERROR] in %s : thread[%x,%x] cannot insert page in mapper\n",
    318         __FUNCTION__ , this->process->pid, this->trdid );
    319         mapper_release_page( mapper , page );
    320         req.ptr  = page;
    321         req.type = KMEM_PAGE;
    322         kmem_free(&req);
    323         return -1;
    324     }
    325 
    326     // launch I/O operation to load page from IOC device to mapper
    327     error = vfs_fs_move_page( XPTR( local_cxy , page ) , IOC_SYNC_READ );
    328 
    329     if( error )
    330     {
    331         printk("\n[ERROR] in %s : thread[%x,%x] cannot load page from device\n",
    332         __FUNCTION__ , this->process->pid, this->trdid );
    333         mapper_release_page( mapper , page );
    334         req.ptr  = page;
    335         req.type = KMEM_PAGE;
    336         kmem_free( &req );
    337         return -1;
    338     }
    339 
    340     // set extended pointer on allocated page
    341     *page_xp = XPTR( local_cxy , page );
    342 
    343 #if DEBUG_MAPPER_HANDLE_MISS
    344 cycle = (uint32_t)hal_get_cycles();
    345 if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode != NULL) )
    346 {
    347     printk("\n[%s] thread[%x,%x] exit for page %d in <%s> / ppn %x / cycle %d",
    348     __FUNCTION__, this->process->pid, this->trdid,
    349     page_id, name, ppm_page2ppn( *page_xp ), cycle );
    350     if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt) , name );
    351 }
    352 if( (DEBUG_MAPPER_HANDLE_MISS < cycle) && (inode == NULL) )
    353 {
    354     printk("\n[%s] thread[%x,%x] exit for page %d in FAT / ppn %x / cycle %d",
    355     __FUNCTION__, this->process->pid, this->trdid,
    356     page_id, ppm_page2ppn( *page_xp ), cycle );
    357     if( DEBUG_MAPPER_HANDLE_MISS & 1 ) grdxt_display( XPTR(local_cxy,&mapper->rt ), "FAT" );
    358 }
    359 #endif
    360 
    361     return 0;
    362 
    363 }  // end mapper_handle_miss()
    364 
    365 ////////////////////////////////////////////
    366 void mapper_release_page( mapper_t * mapper,
    367                           page_t   * page )
    368 {
     346////////////////////////////////////////////////////
     347void mapper_remote_release_page( xptr_t   mapper_xp,
     348                                 page_t * page )
     349{
     350    // get mapper cluster an local pointer
     351    cxy_t      mapper_cxy = GET_CXY( mapper_xp );
     352    mapper_t * mapper_ptr = GET_PTR( mapper_xp );
     353
    369354    // build extended pointer on mapper lock
    370     xptr_t mapper_lock_xp = XPTR( local_cxy , &mapper->lock );
     355    xptr_t lock_xp = XPTR( mapper_cxy , &mapper_ptr->lock );
    371356
    372357    // take mapper lock in WRITE_MODE
    373     remote_rwlock_wr_acquire( mapper_lock_xp );
     358    remote_rwlock_wr_acquire( lock_xp );
    374359
    375360    // remove physical page from radix tree
    376     grdxt_remove( &mapper->rt , page->index );
     361    grdxt_remote_remove( XPTR( mapper_cxy , &mapper_ptr->rt ) , page->index );
    377362
    378363    // release mapper lock from WRITE_MODE
    379     remote_rwlock_wr_release( mapper_lock_xp );
     364    remote_rwlock_wr_release( lock_xp );
    380365
    381366    // release page to PPM
    382     kmem_req_t   req;
    383     req.type  = KMEM_PAGE;
    384     req.ptr   = page;
    385     kmem_free( &req );
    386 
     367    ppm_remote_free_pages( mapper_cxy , page );
     368                           
    387369}  // end mapper_release_page()
    388370
  • trunk/kernel/mm/mapper.h

    r628 r635  
    6464 * TODO (1) the mapper being only used to implement the VFS cache(s), the mapper.c
    6565 *          and mapper.h file should be trandfered to the fs directory.
    66  * TODO (2) the "type" field is probably unused...
     66 * TODO (2) the "type" field in mapper descriptor is redundant and probably unused.
    6767 ******************************************************************************************/
    6868
     
    106106
    107107/*******************************************************************************************
    108  * This function load from device a missing page identified by the <page_id> argument
    109  * into the mapper identified by the <mapper> local pointer.
    110  * It allocates a physical page from the local cluster, initialise by accessing device,
    111  * and register the page in the mapper radix tree.
    112  * It must be executed by a thread running in the cluster containing the mapper.
     108 * This function load from the IOC device a missing page identified by the <page_id>
     109 * argument into a - possibly remote - mapper identified by the <mapper_xp> argument.
     110 * It can be executed by a thread running in any cluster.
     111 * It allocates a physical page from the remote cluster PPM, initialises it by accessing
     112 * the IOC device, and registers the page in the remote mapper radix tree.
    113113 * WARNING : the calling function mapper_remote_get_page() is supposed to take and release
    114114 * the lock protecting the mapper in WRITE_MODE.
    115115 *******************************************************************************************
    116  * @ mapper      : [in]  target mapper.
    117  * @ page_id : [in]  missing page index in file.
    118  * @ page_xp : [out] buffer for extended pointer on missing page descriptor.
    119  * @ return 0 if success / return -1 if a dirty page cannot be updated on device.
    120  ******************************************************************************************/
    121 error_t mapper_handle_miss( mapper_t * mapper,
    122                             uint32_t   page_id,
    123                             xptr_t   * page_xp );
     116 * @ mapper_xp   : [in]  extended pointer on remote mapper.
     117 * @ page_id     : [in]  missing page index in file.
     118 * @ page_xp     : [out] buffer for extended pointer on missing page descriptor.
     119 * @ return 0 if success / return -1 if IOC cannot be accessed.
     120 ******************************************************************************************/
     121error_t mapper_remote_handle_miss( xptr_t     mapper_xp,
     122                                   uint32_t   page_id,
     123                                   xptr_t   * page_xp );
     124
     125/*******************************************************************************************
     126 * This function removes a physical page from a - possibly remote - mapper,
     127 * and releases the page to the remote PPM.
     128 * It can be executed by any thread running in any cluster.
     129 * It takes the mapper lock in WRITE_MODE to update the mapper.
     130 *******************************************************************************************
     131 * @ mapper     : extended pointer on the remote mapper.
     132 * @ page       : local pointer on the page in remote mapper.
     133 ******************************************************************************************/
     134void mapper_remote_release_page( xptr_t          mapper_xp,
     135                                 struct page_s * page );
    124136
    125137/*******************************************************************************************
     
    170182
    171183/*******************************************************************************************
    172  * This function removes a physical page from the mapper, and releases
    173  * the page to the local PPM. It is called by the mapper_destroy() function.
    174  * It must be executed by a thread running in the cluster containing the mapper.
    175  * It takes the mapper lock in WRITE_MODE to update the mapper.
    176  *******************************************************************************************
    177  * @ mapper     : local pointer on the mapper.
    178  * @ page       : pointer on page to remove.
    179  ******************************************************************************************/
    180 void mapper_release_page( mapper_t      * mapper,
    181                           struct page_s * page );
    182 
    183 /*******************************************************************************************
    184184 * This function returns an extended pointer on a page descriptor.
    185185 * The - possibly remote - mapper is identified by the <mapper_xp> argument.
     
    237237/*******************************************************************************************
    238238 * This function scan all pages present in the mapper identified by the <mapper> argument,
    239  * and synchronize all pages maked as dirty" on disk.
     239 * and synchronize all pages marked as "dirty" on disk.
    240240 * These pages are unmarked and removed from the local PPM dirty_list.
    241241 * This function must be called by a local thread running in same cluster as the mapper.
  • trunk/kernel/mm/page.c

    r634 r635  
    4646
    4747        remote_busylock_init( XPTR( local_cxy , &page->lock ), LOCK_PAGE_STATE );
    48 
    49         list_entry_init( &page->list );
    5048}
    5149
     
    9391}
    9492
     93
     94
     95
     96///////////////////////////////////////////////
     97inline void page_remote_init( xptr_t  page_xp )
     98{
     99        hal_remote_memset( page_xp , 0 , sizeof(page_t) );
     100
     101    cxy_t    page_cxy = GET_CXY( page_xp );
     102    page_t * page_ptr = GET_PTR( page_xp );
     103
     104        remote_busylock_init( XPTR( page_cxy , &page_ptr->lock ), LOCK_PAGE_STATE );
     105}
    95106
    96107////////////////////////////////////////////////////
  • trunk/kernel/mm/page.h

    r632 r635  
    4848 * This structure defines a physical page descriptor.
    4949 * - The remote_busylock is used to allows any remote thread to atomically
    50  *   test/modify the forks counter or the page flags.
     50 *   test/modify the forks counter or the flags.
    5151 * - The list entry is used to register the page in a free list or in dirty list.
    5252 *   The refcount is used for page release to KMEM.
     
    133133
    134134
     135
     136/*************************************************************************************
     137 * This function must be called by a thread running in the local cluster.
     138 * It initializes the page descriptor.
     139 *************************************************************************************
     140 * @ page_xp    : extended pointer to page descriptor.
     141 ************************************************************************************/
     142inline void page_remote_init( xptr_t  page_xp );
     143
    135144/*************************************************************************************
    136145 * This function can be called by any thread running in any cluster.
  • trunk/kernel/mm/ppm.c

    r634 r635  
    212212        page_t   * found_block; 
    213213
     214    thread_t * this = CURRENT_THREAD;
     215
    214216#if DEBUG_PPM_ALLOC_PAGES
    215 thread_t * this = CURRENT_THREAD;
    216217uint32_t cycle = (uint32_t)hal_get_cycles();
    217218if( DEBUG_PPM_ALLOC_PAGES < cycle )
     
    237238
    238239        current_block = NULL;
    239 
    240         // find a free block equal or larger to requested size
    241         for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ )
    242         {
    243                 if( !list_is_empty( &ppm->free_pages_root[current_order] ) )
     240    current_order = order;
     241
     242        // search a free block equal or larger than requested size
     243        while( current_order < CONFIG_PPM_MAX_ORDER )
     244        {
     245        // get local pointer on the root of relevant free_list (same in all clusters)
     246        list_entry_t * root = &ppm->free_pages_root[current_order];
     247
     248                if( !list_is_empty( root ) )
    244249                {
    245250            // get first free block in this free_list
    246                         current_block = LIST_FIRST( &ppm->free_pages_root[current_order] , page_t , list );
     251                        current_block = LIST_FIRST( root , page_t , list );
    247252
    248253            // remove this block from this free_list
    249254                        list_unlink( &current_block->list );
     255                ppm->free_pages_nr[current_order] --;
    250256
    251257            // register pointer on found block
    252258            found_block = current_block;
    253259
    254             // update this free-list number of blocks
    255                 ppm->free_pages_nr[current_order] --;
    256 
    257260            // compute found block size
    258261                current_size = (1 << current_order);
     
    260263                        break; 
    261264                }
     265
     266        // increment loop index
     267        current_order++;
    262268        }
    263269
     
    267273                remote_busylock_release( lock_xp );
    268274
    269 #if DEBUG_PPM_ALLOC_PAGES
    270 cycle = (uint32_t)hal_get_cycles();
    271 if( DEBUG_PPM_ALLOC_PAGES < cycle )
    272 printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) in cluster %x / cycle %d\n",
    273 __FUNCTION__, this->process->pid, this->trdid, 1<<order, local_cxy, cycle );
    274 #endif
     275        printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) in cluster %x\n",
     276        __FUNCTION__, this->process->pid, this->trdid, 1<<order, local_cxy );
    275277
    276278                return NULL;
     
    282284        while( current_order > order )
    283285        {
     286        // update size and order
    284287                current_order --;
    285 
    286         // update pointer, size, and order fiels for new free block
    287288                current_size >>= 1;
     289
     290        // update order fiels in new free block
    288291                current_block = found_block + current_size;
    289292                current_block->order = current_order;
     
    291294        // insert new free block in relevant free_list
    292295                list_add_first( &ppm->free_pages_root[current_order] , &current_block->list );
    293 
    294         // update number of blocks in free list
    295296                ppm->free_pages_nr[current_order] ++;
    296297        }
     
    312313printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn = %x / cycle %d\n",
    313314__FUNCTION__, this->process->pid, this->trdid,
    314 1<<order, ppm_page2ppn(XPTR( local_cxy , found_block )), local_cxy, cycle );
     3151<<order, local_cxy, ppm_page2ppn(XPTR( local_cxy , found_block )), cycle );
    315316#endif
    316317
     
    374375
    375376/////////////////////////////////////////////
    376 xptr_t ppm_remote_alloc_pages( cxy_t     cxy,
     377void * ppm_remote_alloc_pages( cxy_t     cxy,
    377378                               uint32_t  order )
    378379{
     
    382383    page_t   * found_block;
    383384
     385    thread_t * this  = CURRENT_THREAD;
     386
    384387#if DEBUG_PPM_REMOTE_ALLOC_PAGES
    385 thread_t * this  = CURRENT_THREAD;
    386388uint32_t   cycle = (uint32_t)hal_get_cycles();
    387389if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
     
    408410
    409411    current_block = NULL;   
    410 
    411         // find in remote cluster a free block equal or larger to requested size
    412         for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ )
    413         {
    414         // get local pointer on the root of relevant free_list in remote cluster
     412    current_order = order;
     413
     414    // search a free block equal or larger than requested size
     415    while( current_order < CONFIG_PPM_MAX_ORDER )
     416    {
     417        // get local pointer on the root of relevant free_list (same in all clusters)
    415418        list_entry_t * root = &ppm->free_pages_root[current_order];
    416419
    417                 if( !list_remote_is_empty( cxy , root ) )
     420                if( !list_remote_is_empty( cxy , root ) )  // list non empty => success
    418421                {
    419422            // get local pointer on first free page descriptor in remote cluster
     
    422425            // remove first free page from the free-list in remote cluster
    423426                        list_remote_unlink( cxy , &current_block->list );
     427                hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ), -1 );
    424428
    425429            // register found block
    426430            found_block = current_block;
    427431
    428                 // decrement relevant free-list number of items in remote cluster
    429                 hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ), -1 );
    430 
    431432            // compute found block size
    432433                current_size = (1 << current_order);
     
    434435                        break;
    435436                }
     437
     438        // increment loop index
     439        current_order++;
    436440        }
    437441
     
    441445                remote_busylock_release( lock_xp );
    442446
    443 #if DEBUG_REMOTE_PPM_ALLOC_PAGES
    444 cycle = (uint32_t)hal_get_cycles();
    445 if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
    446 printk("\n[%s] thread[%x,%x] cannot allocate %d page(s) in cluster %x / cycle %d\n",
    447 __FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
    448 #endif
     447        printk("\n[ERROR] in %s : thread[%x,%x] cannot allocate %d page(s) in cluster %x\n",
     448        __FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy );
    449449
    450450                return XPTR_NULL;
     
    455455        while( current_order > order )
    456456        {
    457         // update order, size, and local pointer for new free block
     457        // update order and size
    458458                current_order --;
    459459                current_size >>= 1;
     460
     461        // update new free block order field in remote cluster
    460462                current_block = found_block + current_size;
    461 
    462         // update new free block order field in remote cluster
    463463                hal_remote_s32( XPTR( cxy , &current_block->order ) , current_order );
    464464
     
    497497#endif
    498498
    499         return XPTR( cxy , found_block );
     499        return found_block;
    500500
    501501}  // end ppm_remote_alloc_pages()
  • trunk/kernel/mm/ppm.h

    r632 r635  
    123123 * @ cxy       : remote cluster identifier.
    124124 * @ order     : ln2( number of 4 Kbytes pages)
    125  * @ returns an extended pointer on the page descriptor if success / XPTR_NULL if error.
    126  ****************************************************************************************/
    127 xptr_t  ppm_remote_alloc_pages( cxy_t    cxy,
     125 * @ returns a local pointer on remote page descriptor if success / XPTR_NULL if error.
     126 ****************************************************************************************/
     127void *  ppm_remote_alloc_pages( cxy_t    cxy,
    128128                                uint32_t order );
    129129
  • trunk/kernel/mm/vmm.c

    r634 r635  
    4949#include <hal_exception.h>
    5050
    51 //////////////////////////////////////////////////////////////////////////////////
     51////////////////////////////////////////////////////////////////////////////////////////////
    5252//   Extern global variables
    53 //////////////////////////////////////////////////////////////////////////////////
     53////////////////////////////////////////////////////////////////////////////////////////////
    5454
    5555extern  process_t  process_zero;      // allocated in cluster.c
     
    286286}  // end vmm_detach_from_vsl()
    287287
    288 
    289 
    290 
    291288////////////////////////////////////////////
    292289error_t vmm_user_init( process_t * process )
    293290{
    294     vseg_t  * vseg_args;
    295     vseg_t  * vseg_envs;
    296     intptr_t  base;
    297     intptr_t  size;
    298291    uint32_t  i;
    299292
     
    319312"STACK zone too small\n");
    320313
     314    // initialize the lock protecting the VSL
     315        remote_rwlock_init( XPTR( local_cxy , &vmm->vsl_lock ) , LOCK_VMM_VSL );
     316
     317
     318/*
    321319    // register "args" vseg in VSL
    322320    base = CONFIG_VMM_UTILS_BASE << CONFIG_PPM_PAGE_SHIFT;
     
    358356
    359357    vmm->envs_vpn_base = base;
    360 
     358*/
    361359    // initialize STACK allocator
    362360    vmm->stack_mgr.bitmap   = 0;
     
    375373
    376374    // initialize instrumentation counters
    377         vmm->pgfault_nr = 0;
     375        vmm->false_pgfault_nr    = 0;
     376        vmm->local_pgfault_nr    = 0;
     377        vmm->global_pgfault_nr   = 0;
     378        vmm->false_pgfault_cost  = 0;
     379        vmm->local_pgfault_cost  = 0;
     380        vmm->global_pgfault_cost = 0;
    378381
    379382    hal_fence();
     
    398401
    399402#if DEBUG_VMM_USER_RESET
    400 uint32_t cycle = (uint32_t)hal_get_cycles();
     403uint32_t   cycle;
    401404thread_t * this = CURRENT_THREAD;
     405#endif
     406
     407#if (DEBUG_VMM_USER_RESET & 1 )
     408cycle = (uint32_t)hal_get_cycles();
    402409if( DEBUG_VMM_USER_RESET < cycle )
    403410printk("\n[%s] thread[%x,%x] enter for process %x in cluster %x / cycle %d\n",
     
    407414#if (DEBUG_VMM_USER_RESET & 1 )
    408415if( DEBUG_VMM_USER_RESET < cycle )
    409 hal_vmm_display( process , true );
     416hal_vmm_display( XPTR( local_cxy , process ) , true );
    410417#endif
    411418
     
    478485#endif
    479486
     487#if (DEBUG_VMM_USER_RESET & 1 )
     488if( DEBUG_VMM_USER_RESET < cycle )
     489hal_vmm_display( XPTR( local_cxy , process ) , true );
     490#endif
     491
    480492}  // end vmm_user_reset()
    481493
     
    503515thread_t * this = CURRENT_THREAD;
    504516if( DEBUG_VMM_UPDATE_PTE < cycle )
    505 printk("\n[%s] thread[%x,%x] enter for process %x / vpn %x / cycle %d\n",
    506 __FUNCTION__, this->process->pid, this->trdid, process->pid , vpn , cycle );
    507 #endif
    508 
    509 // check cluster is reference
    510 assert( (GET_CXY( process->ref_xp ) == local_cxy) , "not called in reference cluster\n");
     517printk("\n[%s] thread[%x,%x] enter for process %x / vpn %x / attr %x / ppn %x / ycle %d\n",
     518__FUNCTION__, this->process->pid, this->trdid, process->pid, vpn, attr, ppn, cycle );
     519#endif
    511520
    512521    // get extended pointer on root of process copies xlist in owner cluster
     
    517526    process_root_xp  = XPTR( owner_cxy , process_root_ptr );
    518527
     528// check local cluster is owner cluster
     529assert( (owner_cxy == local_cxy) , "must be called in owner cluster\n");
     530
    519531    // loop on destination process copies
    520532    XLIST_FOREACH( process_root_xp , process_iter_xp )
     
    525537        remote_process_cxy = GET_CXY( remote_process_xp );
    526538
    527 #if (DEBUG_VMM_UPDATE_PTE & 0x1)
     539#if (DEBUG_VMM_UPDATE_PTE & 1)
    528540if( DEBUG_VMM_UPDATE_PTE < cycle )
    529 printk("\n[%s] threadr[%x,%x] handling vpn %x for process %x in cluster %x\n",
     541printk("\n[%s] thread[%x,%x] handling vpn %x for process %x in cluster %x\n",
    530542__FUNCTION__, this->process->pid, this->trdid, vpn, process->pid, remote_process_cxy );
    531543#endif
     
    545557#endif
    546558
     559#if (DEBUG_VMM_UPDATE_PTE & 1)
     560hal_vmm_display( process , true );
     561#endif
     562
    547563}  // end vmm_global_update_pte()
    548564
     
    570586    cxy_t           owner_cxy;
    571587    lpid_t          owner_lpid;
     588
     589    // get target process PID
     590    pid = process->pid;
    572591
    573592#if DEBUG_VMM_SET_COW
     
    576595if( DEBUG_VMM_SET_COW < cycle )
    577596printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n",
    578 __FUNCTION__, this->process->pid, this->trdid, process->pid , cycle );
     597__FUNCTION__, this->process->pid, this->trdid, pid , cycle );
     598#endif
     599
     600#if (DEBUG_VMM_SET_COW & 1)
     601if( DEBUG_VMM_SET_COW < cycle )
     602hal_vmm_display( process , true );
    579603#endif
    580604
    581605// check cluster is reference
    582 assert( (GET_CXY( process->ref_xp ) == local_cxy) ,
    583 "local cluster is not process reference cluster\n");
     606assert( (XPTR( local_cxy , process ) == process->ref_xp),
     607"local cluster must be process reference cluster\n");
    584608
    585609    // get pointer on reference VMM
     
    587611
    588612    // get extended pointer on root of process copies xlist in owner cluster
    589     pid              = process->pid;
    590613    owner_cxy        = CXY_FROM_PID( pid );
    591614    owner_lpid       = LPID_FROM_PID( pid );
     
    596619    vseg_root_xp  = XPTR( local_cxy , &vmm->vsegs_root );
    597620
    598     // loop on destination process copies
     621    // loop on target process copies
    599622    XLIST_FOREACH( process_root_xp , process_iter_xp )
    600623    {
    601         // get cluster and local pointer on remote process
     624        // get cluster and local pointer on remote process copy
    602625        remote_process_xp  = XLIST_ELEMENT( process_iter_xp , process_t , copies_list );
    603626        remote_process_ptr = GET_PTR( remote_process_xp );
     
    606629#if (DEBUG_VMM_SET_COW & 1)
    607630if( DEBUG_VMM_SET_COW < cycle )
    608 printk("\n[%s] thread[%x,%x] handling process %x in cluster %x\n",
    609 __FUNCTION__, this->process->pid, this->trdid, process->pid , remote_process_cxy );
     631printk("\n[%s] thread[%x,%x] (%x) handles process %x in cluster %x\n",
     632__FUNCTION__, this->process->pid, this->trdid, this, pid, remote_process_cxy );
    610633#endif
    611634
     
    620643            vseg     = GET_PTR( vseg_xp );
    621644
    622 assert( (GET_CXY( vseg_xp ) == local_cxy) ,
    623 "all vsegs in reference VSL must be local\n" );
    624 
    625645            // get vseg type, base and size
    626646            uint32_t type     = vseg->type;
     
    630650#if (DEBUG_VMM_SET_COW & 1)
    631651if( DEBUG_VMM_SET_COW < cycle )
    632 printk("\n[%s] thread[%x,%x] handling vseg %s / vpn_base = %x / vpn_size = %x\n",
     652printk("\n[%s] thread[%x,%x] found vseg %s / vpn_base = %x / vpn_size = %x\n",
    633653__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(type), vpn_base, vpn_size );
    634654#endif
     
    653673
    654674                // atomically increment pending forks counter in physical pages,
    655                 // for all vseg pages that are mapped in reference cluster
     675                // this is only done once, when handling the reference copy
    656676                if( remote_process_cxy == local_cxy )
    657677                {
     678
     679#if (DEBUG_VMM_SET_COW & 1)
     680if( DEBUG_VMM_SET_COW < cycle )
     681printk("\n[%s] thread[%x,%x] handles vseg %s / vpn_base = %x / vpn_size = %x\n",
     682__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(type), vpn_base, vpn_size );
     683#endif
    658684                    // scan all pages in vseg
    659685                    for( vpn = vpn_base ; vpn < (vpn_base + vpn_size) ; vpn++ )
     
    684710                        }
    685711                    }   // end loop on vpn
     712
     713#if (DEBUG_VMM_SET_COW & 1)
     714if( DEBUG_VMM_SET_COW < cycle )
     715printk("\n[%s] thread[%x,%x] completes vseg %s / vpn_base = %x / vpn_size = %x\n",
     716__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(type), vpn_base, vpn_size );
     717#endif
    686718                }   // end if local
    687719            }   // end if vseg type
     
    713745    vseg_t    * child_vseg;
    714746    uint32_t    type;
    715     bool_t      cow;
    716747    vpn_t       vpn;           
    717748    vpn_t       vpn_base;
    718749    vpn_t       vpn_size;
    719     xptr_t      page_xp;        // extended pointer on page descriptor
    720     page_t    * page_ptr;
    721     cxy_t       page_cxy;
    722     xptr_t      forks_xp;       // extended pointer on forks counter in page descriptor
    723750    xptr_t      parent_root_xp;
    724751    bool_t      mapped;
     
    740767    parent_vmm = &parent_process->vmm;
    741768    child_vmm  = &child_process->vmm;
    742 
    743     // initialize the lock protecting the child VSL
    744         remote_rwlock_init( XPTR( local_cxy , &child_vmm->vsl_lock ) , LOCK_VMM_VSL );
    745 
    746     // initialize the child VSL as empty
    747     xlist_root_init( XPTR( local_cxy, &child_vmm->vsegs_root ) );
    748     child_vmm->vsegs_nr = 0;
    749 
    750     // create an empty child GPT
    751     error = hal_gpt_create( &child_vmm->gpt );
    752     if( error )
    753     {
    754         printk("\n[ERROR] in %s : cannot create GPT\n", __FUNCTION__ );
    755         return -1;
    756     }
    757769
    758770    // build extended pointer on parent VSL root and lock
     
    820832            {
    821833                // activate the COW for DATA, ANON, REMOTE vsegs only
    822                 cow = ( type != VSEG_TYPE_FILE );
     834                // cow = ( type != VSEG_TYPE_FILE );
    823835
    824836                vpn_base = child_vseg->vpn_base;
     
    832844                                              XPTR( parent_cxy , &parent_vmm->gpt ),
    833845                                              vpn,
    834                                               cow,
    835                                               &ppn,
    836                                               &mapped );
     846                                              false,      // does not handle COW flag
     847                                              &ppn,       // unused
     848                                              &mapped );  // unused
    837849                    if( error )
    838850                    {
     
    842854                    }
    843855
    844                     // increment pending forks counter in page if mapped
    845                     if( mapped )
    846                     {
    847                         // get pointers and cluster on page descriptor
    848                         page_xp  = ppm_ppn2page( ppn );
    849                         page_cxy = GET_CXY( page_xp );
    850                         page_ptr = GET_PTR( page_xp );
    851 
    852                         // get extended pointers on "forks" and "lock"
    853                         forks_xp = XPTR( page_cxy , &page_ptr->forks );
    854                         lock_xp  = XPTR( page_cxy , &page_ptr->lock );
    855 
    856                         // get lock protecting "forks" counter
    857                         remote_busylock_acquire( lock_xp );
    858 
    859                         // increment "forks"
    860                         hal_remote_atomic_add( forks_xp , 1 );
    861 
    862                         // release lock protecting "forks" counter
    863                         remote_busylock_release( lock_xp );
    864 
    865856#if DEBUG_VMM_FORK_COPY
    866857cycle = (uint32_t)hal_get_cycles();
     
    869860__FUNCTION__ , this->process->pid, this->trdid , vpn , cycle );
    870861#endif
    871                     }
    872862                }
    873863            }   // end if no code & no stack
     
    877867    // release the parent VSL lock in read mode
    878868    remote_rwlock_rd_release( parent_lock_xp );
    879 
    880     // update child VMM with kernel vsegs
    881     error = hal_vmm_kernel_update( child_process );
    882 
    883     if( error )
    884     {
    885         printk("\n[ERROR] in %s : cannot update child VMM\n", __FUNCTION__ );
    886         return -1;
    887     }
    888869
    889870    // initialize the child VMM STACK allocator
     
    902883
    903884    // initialize instrumentation counters
    904         child_vmm->pgfault_nr    = 0;
     885        child_vmm->false_pgfault_nr    = 0;
     886        child_vmm->local_pgfault_nr    = 0;
     887        child_vmm->global_pgfault_nr   = 0;
     888        child_vmm->false_pgfault_cost  = 0;
     889        child_vmm->local_pgfault_cost  = 0;
     890        child_vmm->global_pgfault_cost = 0;
    905891
    906892    // copy base addresses from parent VMM to child VMM
     
    933919
    934920#if DEBUG_VMM_DESTROY
    935 uint32_t cycle = (uint32_t)hal_get_cycles();
    936 thread_t * this = CURRENT_THREAD;
     921uint32_t   cycle = (uint32_t)hal_get_cycles();
     922thread_t * this  = CURRENT_THREAD;
    937923if( DEBUG_VMM_DESTROY < cycle )
    938924printk("\n[%s] thread[%x,%x] enter for process %x in cluster %x / cycle %d\n",
     
    942928#if (DEBUG_VMM_DESTROY & 1 )
    943929if( DEBUG_VMM_DESTROY < cycle )
    944 hal_vmm_display( process , true );
     930hal_vmm_display( XPTR( local_cxy, process ) , true );
    945931#endif
    946932
     
    10621048vseg_t * vmm_create_vseg( process_t   * process,
    10631049                              vseg_type_t   type,
    1064                           intptr_t      base,
     1050                          intptr_t      base,         // ltid for VSEG_TYPE_STACK
    10651051                              uint32_t      size,
    10661052                          uint32_t      file_offset,
     
    10741060        error_t      error;
    10751061
    1076 #if DEBUG_VMM_CREATE_VSEG
     1062#if (DEBUG_VMM_CREATE_VSEG & 1)
    10771063thread_t * this  = CURRENT_THREAD;
    10781064uint32_t   cycle = (uint32_t)hal_get_cycles();
    10791065if( DEBUG_VMM_CREATE_VSEG < cycle )
    1080 printk("\n[%s] thread[%x,%x] enter for process %x / %s / cxy %x / cycle %d\n",
    1081 __FUNCTION__, this->process->pid, this->trdid, process->pid, vseg_type_str(type), cxy, cycle );
     1066printk("\n[%s] thread[%x,%x] enter / process %x / %s / base %x / cxy %x / cycle %d\n",
     1067__FUNCTION__, this->process->pid, this->trdid,
     1068process->pid, vseg_type_str(type), base, cxy, cycle );
    10821069#endif
    10831070
     
    11711158        }
    11721159
    1173 #if DEBUG_VMM_CREATE_VSEG
     1160#if (DEBUG_VMM_CREATE_VSEG & 1)
    11741161if( DEBUG_VMM_CREATE_VSEG < cycle )
    11751162printk("\n[%s] thread[%x,%x] : base %x / size %x / vpn_base %x / vpn_size %x\n",
     
    12041191cycle = (uint32_t)hal_get_cycles();
    12051192if( DEBUG_VMM_CREATE_VSEG < cycle )
    1206 printk("\n[%s] thread[%x,%x] exit / %s / cxy %x / cycle %d\n",
    1207 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(type), cxy, cycle );
     1193printk("\n[%s] thread[%x,%x] exit / process %x / %s / base %x / cxy %x / cycle %d\n",
     1194__FUNCTION__, this->process->pid, this->trdid,
     1195process->pid, vseg_type_str(type), base, cxy, cycle );
    12081196#endif
    12091197
     
    16851673    xptr_t       page_xp;
    16861674    cxy_t        page_cxy;
     1675    page_t     * page_ptr;
    16871676    uint32_t     index;
    16881677
     
    17111700    }
    17121701
    1713     // allocate a 4 Kbytes physical page from target cluster
    1714     page_xp = ppm_remote_alloc_pages( page_cxy , 0 );
     1702    // allocate one small physical page from target cluster
     1703    page_ptr = ppm_remote_alloc_pages( page_cxy , 0 );
     1704
     1705    page_xp = XPTR( page_cxy , page_ptr );
    17151706
    17161707#if DEBUG_VMM_PAGE_ALLOCATE
    17171708cycle = (uint32_t)hal_get_cycles();
    17181709if( DEBUG_VMM_PAGE_ALLOCATE < cycle )
    1719 printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cluster %x / cycle %d\n",
    1720 __FUNCTION__ , this->process->pid, this->trdid, vpn, ppm_page2ppn(page_xp), page_cxy, cycle );
     1710printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle %d\n",
     1711__FUNCTION__ , this->process->pid, this->trdid, vpn, ppm_page2ppn(page_xp), cycle );
    17211712#endif
    17221713
     
    17411732uint32_t   cycle = (uint32_t)hal_get_cycles();
    17421733thread_t * this  = CURRENT_THREAD;
    1743 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1744 if( vpn == 0x40B )
     1734if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
    17451735printk("\n[%s] thread[%x,%x] enter for vpn %x / type %s / page_id  %d / cycle %d\n",
    17461736__FUNCTION__, this->process->pid, this->trdid, vpn, vseg_type_str(type), page_id, cycle );
     
    17691759        page_xp = vmm_page_allocate( vseg , vpn );
    17701760
    1771         if( page_xp == XPTR_NULL ) return ENOMEM;
     1761        if( page_xp == XPTR_NULL ) return -1;
    17721762
    17731763        // initialise missing page from .elf file mapper for DATA and CODE types
     
    17881778
    17891779#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1790 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1791 if( vpn == 0x40B )
     1780if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
    17921781printk("\n[%s] thread[%x,%x] for vpn = %x / elf_offset = %x\n",
    17931782__FUNCTION__, this->process->pid, this->trdid, vpn, elf_offset );
     
    18031792
    18041793#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1805 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1806 if( vpn == 0x40B )
     1794if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
    18071795printk("\n[%s] thread[%x,%x] for vpn  %x / fully in BSS\n",
    18081796__FUNCTION__, this->process->pid, this->trdid, vpn );
     
    18211809
    18221810#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1823 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1824 if( vpn == 0x40B )
     1811if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
    18251812printk("\n[%s] thread[%x,%x] for vpn  %x / fully in mapper\n",
    18261813__FUNCTION__, this->process->pid, this->trdid, vpn );
     
    18391826
    18401827#if (DEBUG_VMM_GET_ONE_PPN & 0x1)
    1841 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1842 if( vpn == 0x40B )
     1828if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
    18431829printk("\n[%s] thread[%x,%x] for vpn  %x / both mapper & BSS\n"
    18441830"      %d bytes from mapper / %d bytes from BSS\n",
     
    18741860#if DEBUG_VMM_GET_ONE_PPN
    18751861cycle = (uint32_t)hal_get_cycles();
    1876 // if( DEBUG_VMM_GET_ONE_PPN < cycle )
    1877 if( vpn == 0x40B )
    1878 printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle\n",
     1862if( (DEBUG_VMM_GET_ONE_PPN < cycle) && (vpn == 0x40b) )
     1863printk("\n[%s] thread[%x,%x] exit for vpn %x / ppn %x / cycle %d\n",
    18791864__FUNCTION__ , this->process->pid, this->trdid , vpn , *ppn, cycle );
    18801865#endif
     
    19061891
    19071892#if DEBUG_VMM_HANDLE_PAGE_FAULT
    1908 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     1893if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    19091894printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n",
    19101895__FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle );
     
    19121897
    19131898#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
    1914 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
    1915 hal_vmm_display( this->process , false );
     1899if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
     1900hal_vmm_display( this->process , true );
    19161901#endif
    19171902
     
    19281913    }
    19291914
    1930 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    1931 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     1915#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     1916if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    19321917printk("\n[%s] thread[%x,%x] found vseg %s\n",
    19331918__FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) );
     
    19501935    }
    19511936
    1952 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    1953 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
    1954 printk("\n[%s] thread[%x,%x] locked vpn %x in cluster %x / cycle %d\n",
     1937#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     1938if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
     1939printk("\n[%s] thread[%x,%x] locked vpn %x in cluster %x\n",
    19551940__FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy );
    19561941#endif
     
    19701955        {
    19711956
    1972 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    1973 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
    1974 printk("\n[%s] thread[%x,%x] access local gpt : cxy %x / ref_cxy %x / type %s\n",
    1975 __FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
     1957#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     1958if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
     1959printk("\n[%s] thread[%x,%x] access local gpt : cxy %x / ref_cxy %x / type %s / cycle %d\n",
     1960__FUNCTION__, this->process->pid, this->trdid,
     1961local_cxy, ref_cxy, vseg_type_str(vseg->type), (uint32_t)hal_get_cycles() );
    19761962#endif
    19771963            // allocate and initialise a physical page
     
    20081994
    20091995#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2010 if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     1996if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    20111997printk("\n[%s] thread[%x,%x] handled local pgfault / ppn %x / attr %x / cycle %d\n",
    20121998__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
     
    20262012        {
    20272013
    2028 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2029 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
    2030 printk("\n[%s] thread[%x,%x] access ref gpt : cxy %x / ref_cxy %x / type %s\n",
    2031 __FUNCTION__, this->process->pid, this->trdid, local_cxy, ref_cxy, vseg_type_str(vseg->type) );
     2014#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2015if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
     2016printk("\n[%s] thread[%x,%x] access ref gpt : cxy %x / ref_cxy %x / type %s / cycle %d\n",
     2017__FUNCTION__, this->process->pid, this->trdid,
     2018local_cxy, ref_cxy, vseg_type_str(vseg->type), (uint32_t)hal_get_cycles() );
    20322019#endif
    20332020            // build extended pointer on reference GPT
     
    20502037            }
    20512038
    2052 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2053 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2039#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2040if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    20542041printk("\n[%s] thread[%x,%x] get pte from ref gpt / attr %x / ppn %x\n",
    20552042__FUNCTION__, this->process->pid, this->trdid, ref_attr, ref_ppn );
     
    20652052                                 ref_ppn );
    20662053
    2067 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2068 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2054#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2055if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    20692056printk("\n[%s] thread[%x,%x] updated local gpt for a false pgfault\n",
    20702057__FUNCTION__, this->process->pid, this->trdid );
     
    20742061                hal_gpt_unlock_pte( ref_gpt_xp, vpn );
    20752062                             
    2076 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2077 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2063#if (DEBUG_VMM_HANDLE_PAGE_FAULT &1)
     2064if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    20782065printk("\n[%s] thread[%x,%x] unlock the ref gpt after a false pgfault\n",
    20792066__FUNCTION__, this->process->pid, this->trdid );
     
    20852072
    20862073#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2087 if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2074if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    20882075printk("\n[%s] thread[%x,%x] handled false pgfault / ppn %x / attr %x / cycle %d\n",
    20892076__FUNCTION__, this->process->pid, this->trdid, ref_ppn, ref_attr, end_cycle );
     
    21202107                if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE;
    21212108
    2122 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2123 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2109#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2110if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    21242111printk("\n[%s] thread[%x,%x] build a new PTE for a true pgfault\n",
    21252112__FUNCTION__, this->process->pid, this->trdid );
     
    21322119                                 ppn );
    21332120
    2134 #if DEBUG_VMM_HANDLE_PAGE_FAULT
    2135 if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2121#if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2122if( (start_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    21362123printk("\n[%s] thread[%x,%x] set new PTE in ref gpt for a true page fault\n",
    21372124__FUNCTION__, this->process->pid, this->trdid );
     
    21502137
    21512138#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2152 if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2139if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    21532140printk("\n[%s] thread[%x,%x] handled global pgfault / ppn %x / attr %x / cycle %d\n",
    21542141__FUNCTION__, this->process->pid, this->trdid, ppn, attr, end_cycle );
     
    21732160
    21742161#if DEBUG_VMM_HANDLE_PAGE_FAULT
    2175 if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn == vpn) )
     2162if( (end_cycle > DEBUG_VMM_HANDLE_PAGE_FAULT) && (vpn > 0) )
    21762163printk("\n[%s] handled by another thread / vpn %x / ppn %x / attr %x / cycle %d\n",
    21772164__FUNCTION__, vpn, ppn, attr, end_cycle );
     
    22122199#endif
    22132200
    2214 #if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1)
     2201#if ((DEBUG_VMM_HANDLE_COW & 3) == 3 )
    22152202hal_vmm_display( process , true );
    22162203#endif
     
    23522339#if(DEBUG_VMM_HANDLE_COW & 1)
    23532340if( DEBUG_VMM_HANDLE_COW < cycle )
    2354 printk("\n[%s] thread[%x,%x]  no pending forks / keep existing PPN %x\n",
     2341printk("\n[%s] thread[%x,%x] no pending forks / keep existing PPN %x\n",
    23552342__FUNCTION__, this->process->pid, this->trdid, old_ppn );
    23562343#endif
     
    23602347    // build new_attr : set WRITABLE, reset COW, reset LOCKED
    23612348    new_attr = (((old_attr | GPT_WRITABLE) & (~GPT_COW)) & (~GPT_LOCKED));
     2349
     2350#if(DEBUG_VMM_HANDLE_COW & 1)
     2351if( DEBUG_VMM_HANDLE_COW < cycle )
     2352printk("\n[%s] thread[%x,%x] new_attr %x / new_ppn %x\n",
     2353__FUNCTION__, this->process->pid, this->trdid, new_attr, new_ppn );
     2354#endif
    23622355
    23632356    // update the relevant GPT(s)
     
    23662359    if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) )
    23672360    {
    2368         // set the new PTE2
     2361        // set new PTE in local gpt
    23692362        hal_gpt_set_pte( gpt_xp,
    23702363                         vpn,
     
    23982391#endif
    23992392
     2393#if ((DEBUG_VMM_HANDLE_COW & 3) == 3)
     2394hal_vmm_display( process , true );
     2395#endif
     2396
    24002397     return EXCP_NON_FATAL;
    24012398
  • trunk/kernel/mm/vmm.h

    r632 r635  
    5252 * - The allocator checks that the requested slot has not been already allocated, and set the
    5353 *   corresponding bit in the bitmap.
    54  * - The de-allocator function reset the corresponding bit in the bitmap.
     54 * - The de-allocator reset the corresponding bit in the bitmap.
    5555 ********************************************************************************************/
    5656
     
    112112typedef struct vmm_s
    113113{
    114         remote_rwlock_t  vsl_lock;           /*! lock protecting the local VSL                  */
    115         xlist_entry_t    vsegs_root;         /*! Virtual Segment List (complete in reference)   */
    116         uint32_t         vsegs_nr;           /*! total number of local vsegs                    */
    117 
    118     gpt_t            gpt;                /*! Generic Page Table (complete in reference)     */
    119 
    120     stack_mgr_t      stack_mgr;          /*! embedded STACK vsegs allocator                 */
    121     mmap_mgr_t       mmap_mgr;           /*! embedded MMAP vsegs allocator                  */
    122 
    123         uint32_t         pgfault_nr;         /*! page fault counter (instrumentation)           */
    124 
    125     vpn_t            args_vpn_base;      /*! args vseg first page                           */
    126     vpn_t            envs_vpn_base;      /*! envs vseg first page                           */
    127         vpn_t            code_vpn_base;      /*! code vseg first page                           */
    128         vpn_t            data_vpn_base;      /*! data vseg first page                           */
    129     vpn_t            heap_vpn_base;      /*! heap zone first page                           */
    130 
    131         intptr_t         entry_point;        /*! main thread entry point                        */
     114        remote_rwlock_t  vsl_lock;            /*! lock protecting the local VSL                 */
     115        xlist_entry_t    vsegs_root;          /*! Virtual Segment List (complete in reference)  */
     116        uint32_t         vsegs_nr;            /*! total number of local vsegs                   */
     117
     118    gpt_t            gpt;                 /*! Generic Page Table (complete in reference)    */
     119
     120    stack_mgr_t      stack_mgr;           /*! embedded STACK vsegs allocator                */
     121    mmap_mgr_t       mmap_mgr;            /*! embedded MMAP vsegs allocator                 */
     122
     123        uint32_t         false_pgfault_nr;    /*! false page fault counter (for all threads)    */
     124        uint32_t         local_pgfault_nr;    /*! false page fault counter (for all threads)    */
     125        uint32_t         global_pgfault_nr;   /*! false page fault counter (for all threads)    */
     126    uint32_t         false_pgfault_cost;  /*! cumulated cost (for all threads)              */
     127    uint32_t         local_pgfault_cost;  /*! cumulated cost (for all threads)              */
     128    uint32_t         global_pgfault_cost; /*! cumulated cost (for all threads)              */
     129
     130    vpn_t            args_vpn_base;       /*! args vseg first page                          */
     131    vpn_t            envs_vpn_base;       /*! envs vseg first page                          */
     132        vpn_t            code_vpn_base;       /*! code vseg first page                          */
     133        vpn_t            data_vpn_base;       /*! data vseg first page                          */
     134    vpn_t            heap_vpn_base;       /*! heap zone first page                          */
     135
     136        intptr_t         entry_point;         /*! main thread entry point                       */
    132137}
    133138vmm_t;
    134139
    135140/*********************************************************************************************
    136  * This function mkkes a partial initialisation of the VMM attached to an user process.
    137  * The GPT must have been previously created, with the hal_gpt_create() function.
    138  * - It registers "args", "envs" vsegs in the VSL.
    139  * - It initializes the STACK and MMAP allocators.
    140  * Note:
     141 * This function makes only a partial initialisation of the VMM attached to an user
     142 * process: It intializes the STACK and MMAP allocators, and the VSL lock.
     143 * - The GPT has been previously created, with the hal_gpt_create() function.
     144 * - The "kernel" vsegs are previously registered, by the hal_vmm_kernel_update() function.
    141145 * - The "code" and "data" vsegs are registered by the elf_load_process() function.
    142146 * - The "stack" vsegs are dynamically registered by the thread_user_create() function.
     
    165169 * This function is called by the process_make_fork() function. It partially copies
    166170 * the content of a remote parent process VMM to the local child process VMM:
     171 * - The KERNEL vsegs required by the architecture must have been previously
     172 *   created in the child VMM, using the hal_vmm_kernel_update() function.
    167173 * - The DATA, ANON, REMOTE vsegs registered in the parent VSL are registered in the
    168  *   child VSL. All valid PTEs in parent GPT are copied to the child GPT, but the
    169  *   WRITABLE flag is reset and the COW flag is set.
     174 *   child VSL. All valid PTEs in parent GPT are copied to the child GPT.
     175 *   The WRITABLE  and COW flags are not modified, as it will be done later for those
     176 *   shared pages by the vmm_set_cow() function.
    170177 * - The CODE vsegs registered in the parent VSL are registered in the child VSL, but the
    171178 *   GPT entries are not copied in the child GPT, and will be dynamically updated from
     
    173180 * - The FILE vsegs registered in the parent VSL are registered in the child VSL, and all
    174181 *   valid GPT entries in parent GPT are copied to the child GPT. The COW flag is not set.
    175  * - No STACK vseg is copied from  parent VMM to child VMM, because the child stack vseg
    176  *   must be copied later from the cluster containing the user thread requesting the fork().
    177  * - The KERNEL vsegs required by the target architecture are re-created in the child
    178  *   VMM, from the local kernel process VMM, using the hal_vmm_kernel_update() function.
     182 * - No STACK vseg is copied from  parent VMM to child VMM: the child stack vseg is copied
     183 *   later from the cluster containing the user thread requesting the fork().
    179184 *********************************************************************************************
    180185 * @ child_process     : local pointer on local child process descriptor.
     
    203208 * This function modifies one GPT entry identified by the <process> and <vpn> arguments
    204209 * in all clusters containing a process copy. It is used to maintain coherence in GPT
    205  * copies, using the list of copies stored in the owner process, and remote_write accesses.
     210 * copies, using remote_write accesses.
    206211 * It must be called by a thread running in the process owner cluster.
    207212 * Use the RPC_VMM_GLOBAL_UPDATE_PTE if required.
     
    248253 * - For the FILE, ANON, & REMOTE types, it does not use the <base> and <size> arguments,
    249254 *   but uses the specific MMAP virtual memory allocator.
    250  * - For the STACK type, it does not use the <size> argument, and the <base> argument
    251  *   defines the user thread LTID used by the specific STACK virtual memory allocator.
    252  * It checks collision with all pre-existing vsegs.
     255 * - For the STACK type, it does not use the <base> and <size> arguments,  but uses the
     256 *   and the <base> argument the specific STACK virtual memory allocator.
     257 * It checks collision with pre-existing vsegs.
    253258 * To comply with the "on-demand" paging policy, this function does NOT modify the GPT,
    254259 * and does not allocate physical memory for vseg data.
  • trunk/kernel/mm/vseg.c

    r625 r635  
    22 * vseg.c - virtual segment (vseg) related operations
    33 *
    4  * Authors   Ghassan Almaless (2008,2009,2010,2011, 2012)
    5  *           Mohamed Lamine Karaoui (2015)
    6  *           Alain Greiner (2016,2017,2018,2019)
     4 * Authors   Alain Greiner (2016,2017,2018,2019)
    75 *
    86 * Copyright (c) UPMC Sorbonne Universites
     
    6664    kmem_req_t   req;
    6765
    68     req.type  = KMEM_VSEG;
    69         req.size  = sizeof(vseg_t);
    70         req.flags = AF_KERNEL;
    71 
    72     return (vseg_t *)kmem_alloc( &req );
     66    req.type  = KMEM_KCM;
     67        req.order = bits_log2( sizeof(vseg_t) );
     68        req.flags = AF_KERNEL | AF_ZERO;
     69
     70    return kmem_alloc( &req );
    7371}
    7472
     
    7876    kmem_req_t  req;
    7977
    80         req.type = KMEM_VSEG;
     78        req.type = KMEM_KCM;
    8179        req.ptr  = vseg;
    8280        kmem_free( &req );
  • trunk/kernel/syscalls/sys_barrier.c

    r629 r635  
    7676printk("\n[ERROR] in %s : unmapped barrier %x / thread %x / process %x\n",
    7777__FUNCTION__ , vaddr , this->trdid , process->pid );
    78 hal_vmm_display( process , false );
    7978#endif
    8079        this->errno = error;
     
    9796printk("\n[ERROR] in %s : unmapped barrier attributes %x / thread %x / process %x\n",
    9897__FUNCTION__ , attr , this->trdid , process->pid );
    99 hal_vmm_display( process , false );
    10098#endif
    10199                    this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_condvar.c

    r624 r635  
    7676printk("\n[ERROR] in %s : unmapped condvar %x / thread %x / process %x\n",
    7777__FUNCTION__ , (intptr_t)condvar , this->trdid , process->pid );
    78 hal_vmm_display( process , false );
    7978#endif
    8079        this->errno = error;
  • trunk/kernel/syscalls/sys_display.c

    r626 r635  
    160160            }
    161161
    162             // get local pointer on process
    163             process_t * process = (process_t *)GET_PTR( process_xp );
    164 
    165162            // call kernel function
    166             if( cxy == local_cxy )
    167             {
    168                     hal_vmm_display( process , true );
    169             }
    170             else
    171             {
    172                 rpc_hal_vmm_display_client( cxy , process , true );
    173             }
     163                hal_vmm_display( process_xp , true );
    174164
    175165            break;
  • trunk/kernel/syscalls/sys_exec.c

    r626 r635  
    6363    uint32_t     length;      // string length
    6464    kmem_req_t   req;         // kmem request
    65     page_t     * page;        // page descriptor
    66     xptr_t       base_xp;     // extended pointer on page base
    6765    uint32_t     order;       // ln2( number of pages to store strings )
    6866    char      ** k_pointers;  // base of kernel array of pointers
     67    char       * k_buf_base;  // base address of the kernel strings buffer
    6968    char       * k_buf_ptr;   // pointer on first empty slot in kernel strings buffer
    70     char       * k_buf_base;  // base address of the kernel strings buffer
    7169
    7270    // compute ln2( number of pages for kernel strings buffer )
     
    7472    else          order = bits_log2( CONFIG_VMM_ENVS_SIZE );
    7573
    76     req.type   = KMEM_PAGE;
     74    // allocate one physical page for kernel array of pointers
     75    req.type   = KMEM_PPM;
     76    req.order  = 0;
    7777    req.flags  = AF_KERNEL | AF_ZERO;
    78 
    79     // allocate one physical page for kernel array of pointers
    80     req.type   = 0;
    81     page       = kmem_alloc( &req );
    82 
    83     if( page == NULL ) return ENOMEM;
    84 
    85     base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    86     k_pointers = (char **)GET_PTR( base_xp );
     78    k_pointers = kmem_alloc( &req );
     79
     80    if( k_pointers == NULL ) return ENOMEM;
    8781
    8882    // allocate several physical pages to store the strings themselve
    89     req.type   = order;
    90     page       = kmem_alloc( &req );
    91 
    92     if( page == NULL ) return ENOMEM;
    93 
    94     base_xp = ppm_page2base( XPTR( local_cxy , page ) );
    95     k_buf_base = (char *)GET_PTR( base_xp );
     83    req.type   = KMEM_PPM;
     84    req.order  = order;
     85    req.flags  = AF_KERNEL | AF_ZERO;
     86    k_buf_base = kmem_alloc( &req );
     87
     88    if( k_buf_base == NULL ) return ENOMEM;
    9689
    9790    // copy the array of pointers to kernel buffer
  • trunk/kernel/syscalls/sys_fork.c

    r625 r635  
    7272
    7373#if DEBUG_SYS_FORK
    74 if( DEBUG_SYS_FORK < tm_start )
     74if( DEBUG_SYS_FORK < (uint32_t)tm_start )
    7575printk("\n[%s] thread[%x,%x] enter / cycle =  %d\n",
    7676__FUNCTION__, parent_pid, parent_thread_ptr->trdid, (uint32_t)tm_start );
     
    109109
    110110#if (DEBUG_SYS_FORK & 1 )
    111 if( DEBUG_SYS_FORK < tm_start )
     111if( DEBUG_SYS_FORK < (uint32_t)tm_start )
    112112printk("\n[%s] thread[%x,%x] selected cluster %x\n",
    113113__FUNCTION__, parent_pid, parent_thread_ptr->trdid, child_cxy );
     
    150150        }
    151151
    152     // set remote child CPU context from parent_thread register values
     152    // set the remote child CPU context from parent register values,
     153    // set the remote child uzone from
    153154    // replicates the parent thread kernel stack to the child thread descriptor,
    154155    // and finally unblock the child thread.
     
    171172
    172173#if DEBUG_SYS_FORK
    173 if( DEBUG_SYS_FORK < tm_end )
     174if( DEBUG_SYS_FORK < (uint32_t)tm_end )
    174175printk("\n[%s] parent thread[%x,%x] exit / child_pid %x / cycle %d\n",
    175176__FUNCTION__, current->process->pid, current->trdid, child_pid, (uint32_t)tm_end );
    176177#endif
    177178
    178 // only parent contribute to instrumentation
     179// only parent display the parent and child VMM
     180#if (DEBUG_SYS_FORK & 1 )
     181if( DEBUG_SYS_FORK < (uint32_t)tm_end )
     182{
     183    process_t * child_process_ptr = hal_remote_lpt( XPTR( child_cxy ,
     184                                                          &child_thread_ptr->process ) );
     185    xptr_t      child_process_xp  = XPTR( child_cxy , child_process_ptr );
     186
     187    hal_vmm_display( ref_process_xp , true );
     188    hal_vmm_display( child_process_xp , true );
     189}
     190#endif
     191
     192// only parent contribute to syscalls instrumentation
    179193#if CONFIG_INSTRUMENTATION_SYSCALLS
    180194hal_atomic_add( &syscalls_cumul_cost[SYS_FORK] , tm_end - tm_start );
     
    187201
    188202#if DEBUG_SYS_FORK
    189 if( DEBUG_SYS_FORK < tm_end )
     203if( DEBUG_SYS_FORK < (uint32_t)tm_end )
    190204printk("\n[%s] child thread[%x,%x] exit / child_pid %x / cycle %d\n",
    191205__FUNCTION__, current->process->pid, current->trdid, child_pid, (uint32_t)tm_end );
  • trunk/kernel/syscalls/sys_get_config.c

    r626 r635  
    6969printk("\n[ERROR] in %s : x_size buffer unmapped / thread %x / process %x\n",
    7070__FUNCTION__ , (intptr_t)x_size , this->trdid , process->pid );
    71 hal_vmm_display( process , false );
    7271#endif
    7372        this->errno = EINVAL;
     
    8483printk("\n[ERROR] in %s : y_size buffer unmapped / thread %x / process %x\n",
    8584__FUNCTION__ , (intptr_t)y_size , this->trdid , process->pid );
    86 hal_vmm_display( process , false );
    8785#endif
    8886        this->errno = EINVAL;
     
    9997printk("\n[ERROR] in %s : ncores buffer unmapped / thread %x / process %x\n",
    10098__FUNCTION__ , (intptr_t)ncores , this->trdid , process->pid );
    101 hal_vmm_display( process , false );
    10299#endif
    103100        this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_get_core.c

    r626 r635  
    5656printk("\n[ERROR] in %s : cxy buffer unmapped %x / thread %x / process %x\n",
    5757__FUNCTION__ , (intptr_t)cxy , this->trdid , process->pid );
    58 hal_vmm_display( process , false );
    5958#endif
    6059        this->errno = EFAULT;
     
    7170printk("\n[ERROR] in %s : lid buffer unmapped %x / thread %x / process %x\n",
    7271__FUNCTION__ , (intptr_t)lid , this->trdid , process->pid );
    73 hal_vmm_display( process , false );
    7472#endif
    7573        this->errno = EFAULT;
  • trunk/kernel/syscalls/sys_get_cycle.c

    r626 r635  
    5454printk("\n[ERROR] in %s : user buffer unmapped %x / thread %x / process %x\n",
    5555__FUNCTION__ , (intptr_t)cycle , this->trdid , process->pid );
    56 hal_vmm_display( process , false );
    5756#endif
    5857        this->errno = EFAULT;
  • trunk/kernel/syscalls/sys_is_fg.c

    r626 r635  
    6868printk("\n[ERROR] in %s : unmapped owner buffer %x / thread %x in process %x\n",
    6969__FUNCTION__ , (intptr_t)is_fg, this->trdid, process->pid );
    70 hal_vmm_display( process , false );
    7170#endif
    7271         this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_mmap.c

    r626 r635  
    7070printk("\n[ERROR] in %s : thread[%x,%x] / mmap attributes unmapped %x\n",
    7171__FUNCTION__ , process->pid, this->trdid, (intptr_t)attr );
    72 hal_vmm_display( process , false );
    7372#endif
    7473                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_munmap.c

    r625 r635  
    6767printk("\n[ERROR] in %s : thread[%x,%x] / user buffer unmapped %x\n",
    6868__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
    69 hal_vmm_display( process , false );
    7069#endif
    7170                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_mutex.c

    r625 r635  
    7676printk("\n[ERROR] in %s : mutex unmapped %x / thread %x / process %x\n",
    7777__FUNCTION__ , (intptr_t)vaddr , this->trdid , process->pid );
    78 hal_vmm_display( process , false );
    7978#endif
    8079        this->errno = error;
  • trunk/kernel/syscalls/sys_opendir.c

    r626 r635  
    6767printk("\n[ERROR] in %s / thread[%x,%x] : DIR buffer %x unmapped\n",
    6868__FUNCTION__ , process->pid , this->trdid, dirp );
    69 hal_vmm_display( process , false );
    7069#endif
    7170                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_read.c

    r633 r635  
    106106printk("\n[ERROR] in %s : thread[%x,%x] user buffer unmapped %x\n",
    107107__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
    108 hal_vmm_display( process , false );
    109108#endif
    110109                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_readdir.c

    r626 r635  
    7070printk("\n[ERROR] in %s / thread[%x,%x] : user buffer %x unmapped\n",
    7171__FUNCTION__ , process->pid , this->trdid, buffer );
    72 hal_vmm_display( process , false );
    7372#endif
    7473                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_sem.c

    r626 r635  
    7575printk("\n[ERROR] in %s : unmapped semaphore pointer %x / thread %x in process %x / cycle %d\n",
    7676__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
    77 hal_vmm_display( process , false );
    7877#endif
    7978        this->errno = EINVAL;
     
    113112printk("\n[ERROR] in %s GETVALUE: unmapped buffer %x / thread %x in process %x / cycle %d\n",
    114113__FUNCTION__ , (intptr_t)current_value, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
    115 hal_vmm_display( process , false );
    116114#endif
    117115                this->errno = EINVAL;
     
    158156printk("\n[ERROR] in %s WAIT: semaphore %x not found / thread %x in process %x / cycle %d\n",
    159157__FUNCTION__ , (intptr_t)vaddr, this->trdid, process->pid, (uint32_t)hal_get_cycles() );
    160 hal_vmm_display( process , true );
    161158#endif
    162159                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_stat.c

    r626 r635  
    6262printk("\n[ERROR] in %s / thread[%x,%x] : stat structure %x unmapped\n",
    6363__FUNCTION__ , process->pid , this->trdid, u_stat );
    64 hal_vmm_display( process , false );
    6564#endif
    6665                this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_thread_create.c

    r633 r635  
    8181printk("\n[ERROR] in %s : thread[%x,%x] / trdid buffer %x unmapped %x\n",
    8282__FUNCTION__, process->pid, parent->trdid, (intptr_t)trdid_ptr );
    83 hal_vmm_display( process , false );
    8483#endif
    8584                parent->errno = EINVAL;
     
    9897printk("\n[ERROR] in %s : thread[%x,%x] / user_attr buffer unmapped %x\n",
    9998__FUNCTION__, process->pid, parent->trdid, (intptr_t)user_attr );
    100 hal_vmm_display( process , false );
    10199#endif
    102100                    parent->errno = EINVAL;
     
    119117printk("\n[ERROR] in %s : thread[%x,%x] / start_func unmapped %x\n",
    120118__FUNCTION__, process->pid, parent->trdid, (intptr_t)start_func );
    121 hal_vmm_display( process , false );
    122119#endif
    123120        parent->errno = EINVAL;
     
    136133printk("\n[ERROR] in %s : thread[%x,%x] / start_args buffer unmapped %x\n",
    137134__FUNCTION__, process->pid, parent->trdid, (intptr_t)start_args );
    138 hal_vmm_display( process , false );
    139135#endif
    140136                    parent->errno = EINVAL;
  • trunk/kernel/syscalls/sys_thread_exit.c

    r625 r635  
    22 * sys_thread_exit.c - terminates the execution of calling thread
    33 *
    4  * Authors   Alain Greiner (2016,2017,2018)
     4 * Authors   Alain Greiner (2016,2017,2018,2019)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    4646
    4747#if DEBUG_SYSCALLS_ERROR
    48 printk("\n[ERROR] in %s : exit_value argument must be NULL / thread %x in process %x\n",
    49 __FUNCTION__ , this , pid );
     48printk("\n[ERROR] in %s : thread[%x,%x] / exit_value argument %x must be NULL\n",
     49__FUNCTION__ , pid, trdid , exit_value );
    5050#endif
    5151        this->errno = EINVAL;
    5252        return -1;
    5353    }
    54 
    5554
    5655    // If calling thread is the main thread, the process must be deleted.
  • trunk/kernel/syscalls/sys_timeofday.c

    r626 r635  
    7171printk("\n[ERROR] in %s : user buffer tz unmapped / thread %x / process %x\n",
    7272__FUNCTION__ , (intptr_t)tz , this->trdid , process->pid );
    73 hal_vmm_display( process , false );
    7473#endif
    7574        this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_wait.c

    r626 r635  
    6969printk("\n[ERROR] in %s : status buffer %x unmapped for thread[%x,%x]\n",
    7070__FUNCTION__ , (intptr_t)status, pid, this->trdid );
    71 hal_vmm_display( process , false );
    7271#endif
    7372        this->errno = EINVAL;
  • trunk/kernel/syscalls/sys_write.c

    r625 r635  
    106106printk("\n[ERROR] in %s : thread[%x,%x] user buffer unmapped %x\n",
    107107__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
    108 hal_vmm_display( process , false );
    109108#endif
    110109                this->errno = EINVAL;
  • trunk/params-hard.mk

    r634 r635  
    22
    33ARCH      = /Users/alain/soc/tsar-trunk-svn-2013/platforms/tsar_generic_iob
    4 X_SIZE    = 1
     4X_SIZE    = 2
    55Y_SIZE    = 2
    6 NB_PROCS  = 1
     6NB_PROCS  = 2
    77NB_TTYS   = 2
    88IOC_TYPE  = IOC_BDV
  • trunk/user/fft/fft.c

    r630 r635  
    8787// parameters
    8888
    89 #define DEFAULT_M               12              // 4096 data points
     89#define DEFAULT_M               8               // 256 data points
    9090#define USE_DQT_BARRIER         0               // use DDT barrier if non zero
    9191#define MODE                    COSIN           // DATA array initialisation mode
     
    291291    main_tid = (((main_x * y_size) + main_y) * ncores) + main_lid;
    292292
    293     printf("\n[fft] starts on core[%x,%d] / %d complex points / %d thread(s) / PID %x\n",
    294     main_cxy, main_lid, N, nthreads, getpid() );
     293    printf("\n[fft] starts / core[%x,%d] / %d points / %d thread(s) / PID %x / cycle %d\n",
     294    main_cxy, main_lid, N, nthreads, getpid(), (unsigned int)start_init_cycle );
    295295
    296296    // allocate memory for the distributed data[i], trans[i], umain[i], twid[i] buffers
     
    312312    }
    313313
    314     printf("\n[fft] main completes remote_malloc\n");
     314#if DEBUG_MAIN
     315printf("\n[fft] main completes remote_malloc\n");
     316#endif
    315317
    316318    // arrays initialisation
     
    319321    InitT( twid );
    320322
    321     printf("\n[fft] main completes arrays init\n");
     323#if DEBUG_MAIN
     324printf("\n[fft] main completes arrays init\n");
     325#endif
    322326
    323327#if CHECK
     
    357361    }
    358362
    359     printf("\n[fft] main completes barrier init\n");
     363#if DEBUG_MAIN
     364printf("\n[fft] main completes barrier init\n");
     365#endif
    360366
    361367    // launch other threads to execute the slave() function
     
    393399                        exit( 0 );
    394400                    }
     401
    395402#if (DEBUG_MAIN & 1)
    396403unsigned long long debug_cycle;
     
    404411    }
    405412
    406     printf("\n[fft] main completes threads creation\n");
     413#if DEBUG_MAIN
     414printf("\n[fft] main completes threads creation\n");
     415#endif
    407416
    408417    get_cycle( &end_init_cycle );
  • trunk/user/init/init.c

    r625 r635  
    105105        {
    106106            cxy = HAL_CXY_FROM_XY( x , y );
    107             display_cluster_processes( cxy );
     107            display_cluster_processes( cxy , 0 );
    108108            for( lid = 0 ; lid < ncores ; lid++ )
    109109            {
  • trunk/user/ksh/ksh.c

    r633 r635  
    108108char            pathnew[PATH_MAX_SIZE];     // used by the rename command
    109109 
     110char            string[128];                // used by snprintf() for debug
     111
    110112//////////////////////////////////////////////////////////////////////////////////////////
    111113//         Shell  Commands
     
    121123
    122124#if DEBUG_CMD_CAT
    123 char string[64];
     125snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__);
     126display_string( string );
    124127#endif
    125128
     
    133136
    134137    strcpy( pathname , argv[1] );
     138
     139#if DEBUG_CMD_CAT
     140snprintf( string , 128 , "[ksh] in %s : after strcpy" , __FUNCTION__ );
     141display_string( string );
     142#endif
    135143
    136144    // open the file
     
    145153
    146154#if DEBUG_CMD_CAT
    147 snprintf( string , 64 , "[ksh] %s : file %s open", __FUNCTION__, pathname );
     155snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, pathname );
    148156display_string( string );
    149157#endif
     
    172180
    173181#if DEBUG_CMD_CAT
    174 snprintf( string , 64 , "[ksh] %s : size = %d", __FUNCTION__, size );
     182snprintf( string , 128 , "[ksh] %s : size = %d", __FUNCTION__, size );
    175183display_string( string );
    176184#endif
     
    198206
    199207#if DEBUG_CMD_CAT
    200 snprintf( string , 64 , "[ksh] %s : maped file %d to buffer %x", __FUNCTION__, fd , buf );
     208snprintf( string , 128 , "[ksh] %s : maped file %d to buffer %x", __FUNCTION__, fd , buf );
    201209display_string( string );
    202210#endif
     
    212220
    213221#if DEBUG_CMD_CAT
    214 snprintf( string , 64 , "[ksh] %s : unmaped file %d from buffer %x", __FUNCTION__, fd , buf );
     222snprintf( string , 128 , "[ksh] %s : unmaped file %d from buffer %x", __FUNCTION__, fd , buf );
    215223display_string( string );
    216224#endif
     
    261269
    262270#if DEBUG_CMD_CP
    263 char string[64];
     271snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__);
     272display_string( string );
    264273#endif
    265274
     
    284293
    285294#if DEBUG_CMD_CP
    286 snprintf( string , 64 , "[ksh] %s : file %s open", __FUNCTION__, argv[1] );
     295snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, argv[1] );
    287296display_string( string );
    288297#endif
     
    297306
    298307#if DEBUG_CMD_CP
    299 snprintf( string , 64 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[1] );
     308snprintf( string , 128 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[1] );
    300309display_string( string );
    301310#endif
     
    322331
    323332#if DEBUG_CMD_CP
    324 snprintf( string , 64 , "[ksh] %s : file %s open", __FUNCTION__, argv[2] );
     333snprintf( string , 128 , "[ksh] %s : file %s open", __FUNCTION__, argv[2] );
    325334display_string( string );
    326335#endif
     
    333342
    334343#if DEBUG_CMD_CP
    335 snprintf( string , 64 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[2] );
     344snprintf( string , 128 , "[ksh] %s : got stats for %s", __FUNCTION__, argv[2] );
    336345display_string( string );
    337346#endif
     
    357366
    358367#if DEBUG_CMD_CP
    359 snprintf( string , 64 , "[ksh] %s : read %d bytes from %s", __FUNCTION__, len, argv[1] );
     368snprintf( string , 128 , "[ksh] %s : read %d bytes from %s", __FUNCTION__, len, argv[1] );
    360369display_string( string );
    361370#endif
     
    369378
    370379#if DEBUG_CMD_CP
    371 snprintf( string , 64 , "[ksh] %s : write %d bytes to %s", __FUNCTION__, len, argv[2] );
     380snprintf( string , 128 , "[ksh] %s : write %d bytes to %s", __FUNCTION__, len, argv[2] );
    372381display_string( string );
    373382#endif
     
    682691
    683692#if DEBUG_CMD_LOAD
    684 char string[64];
     693snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__);
     694display_string( string );
    685695#endif
    686696
     
    725735
    726736#if DEBUG_CMD_LOAD
    727 snprintf( string , 64 , "[ksh] %s : ksh_pid %x / path %s / bg %d / place %d (%x)\n",
    728 __FUNCTION__, ksh_pid, argv[1], background, placement, cxy );
     737snprintf( string , 128 , "[ksh] %s : <%s> / bg %d / place %d / cxy %x",
     738__FUNCTION__, argv[1], background, placement, cxy );
    729739display_string( string );
    730740#endif
     
    744754
    745755#if DEBUG_CMD_LOAD
    746 snprintf( string , 64 , "[ksh] %s : child_pid %x after fork, before exec\n",
     756snprintf( string , 128 , "[ksh] %s : child (%x) after fork, before exec",
    747757__FUNCTION__ , getpid() );
    748758display_string( string );
     
    753763
    754764#if DEBUG_CMD_LOAD
    755 snprintf( string , 64 , "[ksh] %s : child_pid %x after exec / ret_exec %x\n",
     765snprintf( string , 128 , "[ksh] %s : child (%x) after exec / ret_exec %x",
    756766__FUNCTION__ , getpid(), ret_exec );
    757767display_string( string );
     
    769779
    770780#if DEBUG_CMD_LOAD
    771 snprintf( string , 64 , "[ksh] %s : ksh_pid %x after fork / ret_fork %x\n",
     781snprintf( string , 128 , "[ksh] %s : ksh (%x) after fork / ret_fork %x",
    772782__FUNCTION__, getpid(), ret_fork );
    773783display_string( string );
     
    821831
    822832#if DEBUG_CMD_LS
    823 char string[64];
     833snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__);
     834display_string( string );
    824835#endif
    825836
     
    840851
    841852#if DEBUG_CMD_LS
    842 snprintf( string , 64 , "[ksh] %s : directory <%s> open / DIR %x\n",
     853snprintf( string , 128 , "[ksh] %s : directory <%s> open / DIR %x\n",
    843854__FUNCTION__, pathname , dir );
    844855display_string( string );
     
    863874
    864875#if DEBUG_CMD_LS
    865 snprintf( string , 64 , "[ksh] %s : directory <%s> closed\n",
     876snprintf( string , 128 , "[ksh] %s : directory <%s> closed\n",
    866877__FUNCTION__, pathname );
    867878display_string( string );
     
    929940
    930941#if DEBUG_CMD_PS
    931 char string[64];
     942snprintf( string , 128 , "[ksh] enter %s" , __FUNCTION__);
     943display_string( string );
    932944#endif
    933945
     
    948960
    949961#if DEBUG_CMD_PS
    950 snprintf( string , 64 , "\n[ksh] %s : call display_cluster_process()", __FUNCTION__ );
     962snprintf( string , 128 , "\n[ksh] %s : call display_cluster_process()", __FUNCTION__ );
    951963display_string( string );
    952964#endif
     
    11061118
    11071119#if DEBUG_EXECUTE
    1108 printf("\n[ksh] %s : command <%s>\n",
    1109 __FUNCTION__ , buf );
     1120snprintf( string , 128 , "[ksh] enter %s for command <%s>" , __FUNCTION__ , buf );
     1121display_string( string );
    11101122#endif
    11111123
     
    11361148
    11371149#if DEBUG_EXECUTE
    1138 printf("\n[ksh] %s : argc %d / arg0 %s / arg1 %s\n",
     1150snprintf( string , 128 , "\n[ksh] in %s : argc = %d / arg0 = %s / arg1 = %s\n",
    11391151__FUNCTION__ , argc , argv[0], argv[1] );
    11401152#endif
     
    11741186        char           cmd[CMD_MAX_SIZE];               // buffer for one command
    11751187
    1176 #if DEBUG_INTER
    1177 char string[128];
    1178 #endif
    1179 
    1180 
    1181 // 1. first direct command
     1188/* 1. first direct command
    11821189if( sem_wait( &semaphore ) )
    11831190{
     
    11871194else
    11881195{
    1189     printf("\n[ksh] load bin/user/fft.elf\n");
     1196    printf("\n[ksh] load bin/user/sort.elf\n");
    11901197}
    11911198
    1192 strcpy( cmd , "load bin/user/fft.elf" );
     1199strcpy( cmd , "load bin/user/sort.elf" );
    11931200execute( cmd );
    1194 //
     1201*/
    11951202
    11961203
     
    12041211else
    12051212{
    1206     printf("\n[ksh] rm home/fft_1_2_1_4096\n");
     1213    printf("\n[ksh] load bin/user/fft.elf\n");
    12071214}
    12081215
    1209 strcpy( cmd , "rm home/fft_1_2_1_4096" );
     1216strcpy( cmd , "load bin/user/fft.elf" );
    12101217execute( cmd );
    12111218*/
     
    12521259#if DEBUG_INTER
    12531260unsigned int pid = getpid();
    1254 snprintf( string , 128 , "\n[ksh] %s : request a new command", __FUNCTION__ );
     1261snprintf( string , 128 , "[ksh] %s : request a new command", __FUNCTION__ );
    12551262display_string( string );
    12561263#endif
     
    12821289                        count++;
    12831290#if DEBUG_INTER
    1284 snprintf( string , 128 , "[ksh] %s : get command <%s> / &log = %x / ptw = %d / &ptw = %x",
    1285 __FUNCTION__, cmd , log_entries[ptw].buf , ptw , &ptw );
     1291snprintf( string , 128 , "[ksh] %s : get command <%s>", __FUNCTION__, cmd );
    12861292display_string( string );
    12871293display_vmm( 0 , 2 );
     
    14521458
    14531459#if DEBUG_MAIN
    1454 printf("\n[ksh] main thread started on core[%x,%d]\n", cxy , lid );
     1460snprintf( string , 128 , "\n[ksh] main thread started on core[%x,%d]\n", cxy , lid );
     1461display_string( string );
    14551462#endif
    14561463   
     
    14631470
    14641471#if DEBUG_MAIN
    1465 printf("\n[ksh] main initialized semaphore\n" );
     1472snprintf( string , 128 , "\n[ksh] main initialized semaphore\n" );
     1473display_string( string );
    14661474#endif
    14671475   
     
    14761484                    NULL );
    14771485#if DEBUG_MAIN
    1478 printf("\n[ksh] main thread launched interactive thread %x\n", trdid );
     1486snprintf( string , 128 , "\n[ksh] main thread launched interactive thread %x\n", trdid );
     1487display_string( string );
    14791488#endif
    14801489
  • trunk/user/sort/sort.c

    r629 r635  
     1/*
     2 * sort.c - Parallel sort
     3 *
     4 * Author     Cesar Fuguet Tortolero (2013)
     5 *            Alain Greiner (2019)
     6 *
     7 * Copyright (c) UPMC Sorbonne Universites
     8 *
     9 * This is free software; you can redistribute it and/or modify it
     10 * under the terms of the GNU General Public License as published by
     11 * the Free Software Foundation; version 2.0 of the License.
     12 *
     13 * It is distributed in the hope that it will be useful, but
     14 * WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16 * General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU General Public License
     19 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
     20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     21 */
     22
    123///////////////////////////////////////////////////////////////////////////////
    2 // File   :  sort.c
    3 // Date   :  November 2013
    4 // Author :  Cesar Fuguet Tortolero <cesar.fuguet-tortolero@lip6.fr>
    5 ///////////////////////////////////////////////////////////////////////////////
    6 // This multi-threaded application implement a multi-stage sort application.
    7 // The various stages are separated by synchronisation barriers.
     24// This multi-threaded application implement a multi-stage sort.
     25// It has been writen by Cesar Fuget Tortolero in 2013.
     26// It has been ported on ALMOS-MKH by Alain Greiner in 2019.
     27//
    828// There is one thread per physical cores.
    929// Computation is organised as a binary tree:
     
    1535//       Number_of_stages = number of barriers = log2(Number_of_threads)
    1636//
     37// The various stages are separated by synchronisation barriers, and the
     38// main thread uses the join syscall to check that all threads completed
     39// before printing the computation time (sequencial & parallel).
     40// These results can be - optionnaly - registered in an instrumentation file.
     41//
    1742// Constraints :
    1843// - It supports up to 1024 cores: x_size, y_size, and ncores must be
     
    2954#include <hal_macros.h>
    3055
    31 #define ARRAY_LENGTH        4096       // number of items
     56#define ARRAY_LENGTH        128        // number of items
    3257#define MAX_THREADS         1024       // 16 * 16 * 4
    3358
    3459#define USE_DQT_BARRIER     1          // use DQT barrier if non zero
    3560#define DISPLAY_ARRAY       0          // display items values before and after
    36 #define DEBUG_MAIN          1          // trace main function
    37 #define DEBUG_SORT          1          // trace sort function
    38 #define INTERACTIVE_MODE    0          // activate idbg() during instrumentation
     61#define DEBUG_MAIN          0          // trace main function
     62#define DEBUG_SORT          0          // trace sort function
    3963#define CHECK_RESULT        0          // for debug
    4064#define INSTRUMENTATION     1          // register computation times on file
    41 #define IDBG                0          // activate interactive debug in main
    4265
    4366/////////////////////////////////////////////////////////////
     
    6285pthread_barrier_t   barrier;                 // synchronisation variables
    6386
    64 pthread_attr_t      attr[MAX_THREADS];       // thread attributes (one per thread)
    65 args_t              arg[MAX_THREADS];        // sort function arguments (one per thread)
     87pthread_t           trdid[MAX_THREADS];      // kernel identifiers
     88pthread_attr_t      attr[MAX_THREADS];       // thread attributes
     89args_t              arg[MAX_THREADS];        // sort function arguments
    6690
    6791////////////////////////////////////
     
    277301    unsigned int           lid;                // core local index for a thread
    278302    unsigned int           n;                  // index in array to sort
    279     pthread_t              trdid;              // kernel allocated thread index (unused)
    280303    pthread_barrierattr_t  barrier_attr;       // barrier attributes
    281304
     
    353376    // launch other threads to execute sort() function
    354377    // on cores other than the core running the main thread
    355     for ( x=0 ; x<x_size ; x++ )
    356     {
    357         for ( y=0 ; y<y_size ; y++ )
    358         {
    359             for ( lid=0 ; lid<ncores ; lid++ )
     378    for ( x = 0 ; x < x_size ; x++ )
     379    {
     380        for ( y = 0 ; y < y_size ; y++ )
     381        {
     382            for ( lid = 0 ; lid < ncores ; lid++ )
    360383            {
     384                // compute thread user index (continuous index)
    361385                thread_uid = (((x * y_size) + y) * ncores) + lid;
    362386
    363                 // set sort arguments for all threads
     387                // set arguments for all threads
    364388                arg[thread_uid].threads      = total_threads;
    365389                arg[thread_uid].thread_uid   = thread_uid;
     
    367391
    368392                // set thread attributes for all threads
    369                 attr[thread_uid].attributes = PT_ATTR_DETACH          |
    370                                               PT_ATTR_CLUSTER_DEFINED |
    371                                               PT_ATTR_CORE_DEFINED;
     393                attr[thread_uid].attributes = PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
    372394                attr[thread_uid].cxy        = HAL_CXY_FROM_XY( x , y );
    373395                attr[thread_uid].lid        = lid;
     
    375397                if( thread_uid != main_uid )
    376398                {
    377                     if ( pthread_create( &trdid,              // not used because no join
     399                    if ( pthread_create( &trdid[thread_uid],  // buffer for kernel identifier
    378400                                         &attr[thread_uid],   // thread attributes
    379401                                         &sort,               // entry function
     
    383405                        exit( 0 );
    384406                    }
    385                     else
    386                     {
    387 #if DEBUG_MAIN
     407
     408#if (DEBUG_MAIN & 1)
    388409printf("\n[sort] main created thread %x \n", thread_uid );
    389410#endif
    390                     }
    391411                }
    392412            }
     
    402422#endif
    403423
    404 #if INTERACTIVE_MODE
    405 idbg();
    406 #endif
    407    
    408424    // the main thread run also the sort() function
    409425    sort( &arg[main_uid] );
    410426
     427    // wait other threads completion
     428    for ( x = 0 ; x < x_size ; x++ )
     429    {
     430        for ( y = 0 ; y < y_size ; y++ )
     431        {
     432            for ( lid = 0 ; lid < ncores ; lid++ )
     433            {
     434                // compute thread continuous index
     435                thread_uid = (((x * y_size) + y) * ncores) + lid;
     436
     437                if( thread_uid != main_uid )
     438                {
     439                    if( pthread_join( trdid[thread_uid] , NULL ) )
     440                    {
     441                        printf("\n[fft error] in main thread %d joining thread %d\n",
     442                        main_uid , thread_uid );
     443                        exit( 0 );
     444                    }
     445                   
     446#if (DEBUG_MAIN & 1)
     447printf("\n[fft] main thread %d joined thread %d\n", main_uid, thread_uid );
     448#endif
     449
     450                }
     451            }
     452        }
     453    }
     454
    411455    ////////////////////////////
    412456    get_cycle( &para_end_cycle );
     
    417461    // destroy barrier
    418462    pthread_barrier_destroy( &barrier );
    419 
    420 #if INTERACTIVE_MODE
    421 idbg();
    422 #endif
    423463
    424464#if CHECK_RESULT
Note: See TracChangeset for help on using the changeset viewer.