source: trunk/kernel/mm/kcm.c @ 654

Last change on this file since 654 was 635, checked in by alain, 5 years ago

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.

File size: 21.4 KB
RevLine 
[1]1/*
[635]2 * kcm.c -  Kernel Cache Manager implementation.
[18]3 *
[635]4 * Author  Alain Greiner    (2016,2017,2018,2019)
[1]5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[14]24#include <kernel_config.h>
[457]25#include <hal_kernel_types.h>
[1]26#include <hal_special.h>
[567]27#include <busylock.h>
[1]28#include <list.h>
29#include <printk.h>
30#include <bits.h>
31#include <ppm.h>
32#include <thread.h>
33#include <page.h>
34#include <cluster.h>
[7]35#include <kmem.h>
[1]36#include <kcm.h>
37
[567]38
[635]39/////////////////////////////////////////////////////////////////////////////////////
40//        Local access functions
41/////////////////////////////////////////////////////////////////////////////////////
42
[1]43//////////////////////////////////////////////////////////////////////////////////////
[635]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.
[1]48//////////////////////////////////////////////////////////////////////////////////////
[635]49// @ kcm      : pointer on KCM allocator.
50// @ kcm_page : pointer on a non-full kcm_page.
51// @ return pointer on allocated block.
[7]52/////////////////////////////////////////////////////////////////////////////////////
[635]53static void * __attribute__((noinline)) kcm_get_block( kcm_t      * kcm,
54                                                       kcm_page_t * kcm_page )
[1]55{
[635]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;
[1]61
[635]62assert( (count < max) , "kcm_page should not be full" );
[433]63
[635]64    uint32_t index  = 1;
65    uint64_t mask   = (uint64_t)0x2;
66    uint32_t found  = 0;
[50]67
[635]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;
[1]77
[635]78            break;     
79        }
80       
81        index++;
82        mask <<= 1;
83    }
[18]84
[635]85    // change the page list if almost full
86    if( count == max-1 )
87    {
[50]88                list_unlink( &kcm_page->list);
[635]89                kcm->active_pages_nr--;
[1]90
[635]91        list_add_first( &kcm->full_root , &kcm_page->list );
92                kcm->full_pages_nr ++;
93    }
[1]94
[161]95        // compute return pointer
[635]96        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
[1]97
[635]98#if (DEBUG_KCM & 1)
99thread_t * this  = CURRENT_THREAD;
100uint32_t   cycle = (uint32_t)hal_get_cycles();
[438]101if( DEBUG_KCM < cycle )
[635]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 );
[433]104#endif
[50]105
106        return ptr;
107
[635]108}  // end kcm_get_block()
109
[1]110/////////////////////////////////////////////////////////////////////////////////////
[635]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.
[1]115/////////////////////////////////////////////////////////////////////////////////////
[635]116// @ kcm        : pointer on kcm allocator.
117// @ kcm_page   : pointer on kcm_page.
118// @ block_ptr  : pointer on block to be released.
[7]119/////////////////////////////////////////////////////////////////////////////////////
[635]120static void __attribute__((noinline)) kcm_put_block ( kcm_t      * kcm,
121                                                      kcm_page_t * kcm_page,
122                                                      void       * block_ptr )
[1]123{
[635]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   
[161]130        // compute block index from block pointer
[635]131        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
[18]132
[635]133    // compute mask in bit vector
134    uint64_t mask = ((uint64_t)0x1) << index;
[176]135
[635]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  ) );
[619]138
[635]139    // update status & count in kcm_page
140        kcm_page->status = status & ~mask;
141        kcm_page->count  = count - 1;
[50]142
[635]143        // change the page mode if page was full
144        if( count == max )
[1]145        {
[50]146                list_unlink( &kcm_page->list );
[635]147                kcm->full_pages_nr --;
[1]148
[50]149                list_add_last( &kcm->active_root, &kcm_page->list );
[1]150                kcm->active_pages_nr ++;
151        }
152
[635]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
[1]160
[635]161}  // kcm_put_block()
[1]162
163/////////////////////////////////////////////////////////////////////////////////////
[635]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.
[1]170/////////////////////////////////////////////////////////////////////////////////////
[635]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 )
[1]175{
[635]176    kcm_page_t * kcm_page;
[1]177
[635]178    uint32_t active_pages_nr = kcm->active_pages_nr;
[18]179
[635]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
[7]185        {
[635]186        // get one 4 Kbytes page from local PPM
187        page_t * page = ppm_alloc_pages( 0 );
[7]188
[635]189            if( page == NULL )
190            {
191                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
192                __FUNCTION__ , local_cxy );
[1]193
[635]194                    return NULL;
195        }
[1]196
[635]197            // get page base address
198            xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
[1]199
[635]200        // get local pointer on kcm_page
201            kcm_page = GET_PTR( base_xp );
[18]202
[635]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;
[1]208
[635]209            // introduce new page in KCM active_list
210            list_add_first( &kcm->active_root , &kcm_page->list );
211            kcm->active_pages_nr ++;
[1]212        }
213
[50]214        return kcm_page;
[1]215
[635]216}  // end kcm_get_page()
217
[7]218//////////////////////////////
219void kcm_init( kcm_t    * kcm,
[635]220                   uint32_t   order)
[1]221{
222
[635]223assert( ((order > 5) && (order < 12)) , "order must be in [6,11]" );
[619]224
[20]225        // initialize lock
[635]226        remote_busylock_init( XPTR( local_cxy , &kcm->lock ) , LOCK_KCM_STATE );
[1]227
[20]228        // initialize KCM page lists
[635]229        kcm->full_pages_nr   = 0;
[1]230        kcm->active_pages_nr = 0;
[635]231        list_root_init( &kcm->full_root );
[1]232        list_root_init( &kcm->active_root );
233
[635]234        // initialize order and max_blocks
235        kcm->order      = order;
236    kcm->max_blocks = ( CONFIG_PPM_PAGE_SIZE >> order ) - 1;
237 
[619]238#if DEBUG_KCM
239thread_t * this  = CURRENT_THREAD;
240uint32_t   cycle = (uint32_t)hal_get_cycles();
241if( DEBUG_KCM < cycle )
[635]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 );
[619]244#endif
245
[635]246}  // end kcm_init()
[1]247
248///////////////////////////////
249void kcm_destroy( kcm_t * kcm )
250{
[50]251        kcm_page_t   * kcm_page;
[18]252
[635]253    // build extended pointer on  KCM lock
254    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
255
[20]256        // get KCM lock
[635]257        remote_busylock_acquire( lock_xp );
[1]258
[635]259        // release all full pages
260        while( list_is_empty( &kcm->full_root ) == false )
[1]261        {
[635]262                kcm_page = LIST_FIRST( &kcm->full_root , kcm_page_t , list );
263                list_unlink( &kcm_page->list );
[50]264                ppm_free_pages( kcm_page->page );
[1]265        }
266
[635]267    // release all empty pages
268    while( list_is_empty( &kcm->active_root ) == false )
[1]269        {
[635]270                kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
271                list_unlink( &kcm_page->list );
[50]272                ppm_free_pages( kcm_page->page );
[1]273        }
274
[635]275        // release KCM lock
276        remote_busylock_release( lock_xp );
277}
278
279//////////////////////////////////
280void * kcm_alloc( uint32_t order )
281{
282    kcm_t      * kcm_ptr;
283        kcm_page_t * kcm_page;
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 )
[1]304        {
[635]305                remote_busylock_release( lock_xp );
306                return NULL;
[1]307        }
308
[635]309        // get a block from selected active page
310        block_ptr = kcm_get_block( kcm_ptr , kcm_page );
[1]311
[635]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 )
[1]330{
[635]331    kcm_t      * kcm_ptr;
[50]332        kcm_page_t * kcm_page;
[1]333
[635]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 );
354
[20]355        // get lock
[635]356        remote_busylock_acquire( lock_xp );
[18]357
[635]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 )
[20]414        {
[635]415                list_remote_unlink( kcm_cxy , &kcm_page->list );
416                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , -1 );
[7]417
[635]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        }
[50]421
[635]422        // compute return pointer
423        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
424
425#if DEBUG_KCM_REMOTE
426thread_t * this  = CURRENT_THREAD;
427uint32_t   cycle = (uint32_t)hal_get_cycles();
428if( DEBUG_KCM_REMOTE < cycle )
429printk("\n[%s] thread[%x,%x] get block %x in page %x / cluster %x / size %x / count %d\n",
430__FUNCTION__, this->process->pid, this->trdid, 
431ptr, kcm_page, kcm_cxy, size, count + 1 );
432#endif
433
434        return ptr;
435
436}  // end kcm_remote_get_block()
437
438/////////////////////////////////////////////////////////////////////////////////////
439// This private static function can be called by any thread running in any cluster.
440// It releases a previously allocated block to the relevant kcm_page.
441// It changes the kcm_page status as required.
442/////////////////////////////////////////////////////////////////////////////////////
443// @ kcm_cxy   : remote KCM cluster identifier
444// @ kcm_ptr   : local pointer on remote KCM.
445// @ kcm_page  : local pointer on kcm_page.
446// @ block_ptr : pointer on block to be released.
447/////////////////////////////////////////////////////////////////////////////////////
448static void __attribute__((noinline)) kcm_remote_put_block ( cxy_t        kcm_cxy,
449                                                             kcm_t      * kcm_ptr,
450                                                             kcm_page_t * kcm_page,
451                                                             void       * block_ptr )
452{
453    uint32_t max    = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->max_blocks ) );
454    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
455    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
456    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
457    uint32_t size   = 1 << order;
458   
459        // compute block index from block pointer
460        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
461
462    // compute mask in bit vector
463    uint64_t mask = 1 << index;
464
465assert( (status & mask) , "released page not allocated" );
466
467    // update status & count in kcm_page
468        hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status & ~mask );
469        hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count - 1 );
470
471        // change the page list if page was full
472        if( count == max )
473        {
474                list_remote_unlink( kcm_cxy , &kcm_page->list );
475                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , -1 );
476
477                list_remote_add_last( kcm_cxy , &kcm_ptr->active_root, &kcm_page->list );
478                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
[20]479        }
[635]480
481#if (DEBUG_KCM_REMOTE & 1)
482thread_t * this  = CURRENT_THREAD;
483uint32_t   cycle = (uint32_t)hal_get_cycles();
484if( DEBUG_KCM_REMOTE < cycle )
485printk("\n[%s] thread[%x,%x] released block %x in page %x / cluster %x / size %x / count %d\n",
486__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_page, size, count - 1 )
487#endif
488
489}  // end kcm_remote_put_block()
490
491/////////////////////////////////////////////////////////////////////////////////////
492// This private static function can be called by any thread running in any cluster.
493// It gets one non-full KCM page from the remote KCM.
494// It allocates a page from remote PPM to populate the freelist, and initialises
495// the kcm_page descriptor when required.
496/////////////////////////////////////////////////////////////////////////////////////
497static kcm_page_t * __attribute__((noinline)) kcm_remote_get_page( cxy_t    kcm_cxy,
498                                                                   kcm_t  * kcm_ptr )
499{
500    kcm_page_t * kcm_page;    // local pointer on remote KCM page
501
502    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
503
504    if( active_pages_nr > 0 )       // return first active page
505    {
506        kcm_page = LIST_REMOTE_FIRST( kcm_cxy , &kcm_ptr->active_root , kcm_page_t , list );
507    }
508    else                            // allocate a new page from PPM
[20]509        {
[635]510        // get one 4 Kbytes page from remote PPM
511        page_t * page = ppm_remote_alloc_pages( kcm_cxy , 0 );
512
513            if( page == NULL )
514            {
515                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
516                __FUNCTION__ , kcm_cxy );
517
518                    return NULL;
519        }
520
521            // get remote page base address
522            xptr_t base_xp = ppm_page2base( XPTR( kcm_cxy , page ) );
523
524        // get local pointer on kcm_page
525            kcm_page = GET_PTR( base_xp );
526
527            // initialize kcm_page descriptor
528            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count )  , 0 );
529            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , 0 );
530            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->kcm )    , kcm_ptr );
531            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->page )   , page );
532
533            // introduce new page in remote KCM active_list
534            list_remote_add_first( kcm_cxy , &kcm_ptr->active_root , &kcm_page->list );
535            hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
[20]536        }
[1]537
[635]538        return kcm_page;
539
540}  // end kcm_remote_get_page()
541
542/////////////////////////////////////////
543void * kcm_remote_alloc( cxy_t    kcm_cxy,
544                         uint32_t order )
545{
546    kcm_t      * kcm_ptr;
547    kcm_page_t * kcm_page;
548    void       * block_ptr;
549
550    if( order < 6 ) order = 6;
551
552assert( (order < 12) , "order = %d / must be less than 12" , order );
553
554    // get local pointer on relevant KCM allocator
555    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
556
557    // build extended pointer on remote KCM lock
558    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
559
560        // get lock
561        remote_busylock_acquire( lock_xp );
562
563    // get a non-full kcm_page
564    kcm_page = kcm_remote_get_page( kcm_cxy , kcm_ptr );
565
566    if( kcm_page == NULL )
567        {
568                remote_busylock_release( lock_xp );
569                return NULL;
570        }
571
[20]572        // get a block from selected active page
[635]573        block_ptr = kcm_remote_get_block( kcm_cxy , kcm_ptr , kcm_page );
[7]574
[20]575        // release lock
[635]576        remote_busylock_release( lock_xp );
[1]577
[635]578#if DEBUG_KCM_REMOTE
579thread_t * this  = CURRENT_THREAD;
580uint32_t   cycle = (uint32_t)hal_get_cycles();
581if( DEBUG_KCM_REMOTE < cycle )
582printk("\n[%s] thread[%x,%x] allocated block %x / order %d / kcm[%x,%x]\n",
583__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
584#endif
[1]585
[635]586        return block_ptr;
587
588}  // end kcm_remote_alloc()
589
590/////////////////////////////////////
591void kcm_remote_free( cxy_t  kcm_cxy,
592                      void * block_ptr )
[1]593{
[635]594        kcm_t      * kcm_ptr;
[50]595        kcm_page_t * kcm_page;
[18]596
[619]597// check argument
[635]598assert( (block_ptr != NULL) , "block pointer cannot be NULL" );
[18]599
[635]600    // get local pointer on remote KCM page
601        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~CONFIG_PPM_PAGE_MASK);
[1]602
[635]603    // get local pointer on remote KCM
604        kcm_ptr = hal_remote_lpt( XPTR( kcm_cxy , &kcm_page->kcm ) );
605
606    // build extended pointer on remote KCM lock
607    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
608
[20]609        // get lock
[635]610        remote_busylock_acquire( lock_xp );
[1]611
[20]612        // release block
[635]613        kcm_remote_put_block( kcm_cxy , kcm_ptr , kcm_page , block_ptr );
[1]614
[20]615        // release lock
[635]616        remote_busylock_release( lock_xp );
[1]617
[635]618#if DEBUG_KCM_REMOTE
619thread_t * this  = CURRENT_THREAD;
620uint32_t   cycle = (uint32_t)hal_get_cycles();
621uint32_t   order = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
622if( DEBUG_KCM_REMOTE < cycle )
623printk("\n[%s] thread[%x,%x] released block %x / order %d / kcm[%x,%x]\n",
624__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
625#endif
626
627}  // end kcm_remote_free
628
629/////////////////////////////////////////
630void kcm_remote_display( cxy_t   kcm_cxy,
631                         kcm_t * kcm_ptr )
[1]632{
[635]633    uint32_t order           = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order) );
634    uint32_t full_pages_nr   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) );
635    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
636
637        printk("*** KCM / cxy %x / order %d / full_pages %d / empty_pages %d / active_pages %d\n",
638        kcm_cxy, order, full_pages_nr, active_pages_nr );
[1]639}
Note: See TracBrowser for help on using the repository browser.