Changeset 635 for trunk/kernel/libk


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

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

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

Location:
trunk/kernel/libk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • 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.
Note: See TracChangeset for help on using the changeset viewer.