Changeset 635


Ignore:
Timestamp:
Jun 26, 2019, 11:42:37 AM (4 months 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,