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

Last change on this file since 667 was 657, checked in by alain, 5 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 23.3 KB
Line 
1/*
2 * kcm.c -  Kernel Cache Manager implementation.
3 *
4 * Author  Alain Greiner    (2016,2017,2018,2019)
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
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_special.h>
27#include <busylock.h>
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>
35#include <kmem.h>
36#include <kcm.h>
37
38
39/////////////////////////////////////////////////////////////////////////////////////
40//        Local access functions
41/////////////////////////////////////////////////////////////////////////////////////
42
43//////////////////////////////////////////////////////////////////////////////////////
44// This static function must be called by a local thread.
45// It returns a pointer on a block allocated from an active kcm_page.
46// It makes a panic if no block is available in the selected page.
47// It changes the page status as required.
48//////////////////////////////////////////////////////////////////////////////////////
49// @ kcm      : pointer on KCM allocator.
50// @ kcm_page : pointer on an active kcm_page.
51// @ return pointer on allocated block.
52/////////////////////////////////////////////////////////////////////////////////////
53static void * __attribute__((noinline)) kcm_get_block( kcm_t      * kcm,
54                                                       kcm_page_t * kcm_page )
55{
56    // initialise variables
57    uint32_t size   = 1 << kcm->order;
58    uint32_t max    = kcm->max_blocks;
59    uint32_t count  = kcm_page->count;
60    uint64_t status = kcm_page->status;
61
62assert( (count < max) , "kcm_page should not be full" );
63
64    uint32_t index  = 1;
65    uint64_t mask   = (uint64_t)0x2;
66
67        // allocate first free block in kcm_page, update status,
68    // and count , compute index of allocated block in kcm_page
69    while( index <= max )
70    {
71        if( (status & mask) == 0 )   // block found
72        {
73            // update page count and status
74            kcm_page->status = status | mask;
75            kcm_page->count  = count + 1;
76            break;     
77        }
78       
79        index++;
80        mask <<= 1;
81    }
82
83    // change the page list if found block is the last
84    if( count == max-1 )
85    {
86                list_unlink( &kcm_page->list);
87                kcm->active_pages_nr--;
88
89        list_add_first( &kcm->full_root , &kcm_page->list );
90                kcm->full_pages_nr ++;
91    }
92
93        // compute return pointer
94        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
95
96#if (DEBUG_KCM & 1)
97thread_t * this  = CURRENT_THREAD;
98uint32_t   cycle = (uint32_t)hal_get_cycles();
99if( DEBUG_KCM < cycle )
100printk("\n[%s] thread[%x,%x] allocated block %x in page %x / size %d / count %d / cycle %d\n",
101__FUNCTION__, this->process->pid, this->trdid, ptr, kcm_page, size, count + 1, cycle );
102#endif
103
104        return ptr;
105
106}  // end kcm_get_block()
107
108/////////////////////////////////////////////////////////////////////////////////////
109// This private static function must be called by a local thread.
110// It releases a previously allocated block to the relevant kcm_page.
111// It makes a panic if the released block is not allocated in this page.
112// It changes the kcm_page status as required.
113/////////////////////////////////////////////////////////////////////////////////////
114// @ kcm        : pointer on kcm allocator.
115// @ kcm_page   : pointer on kcm_page.
116// @ block_ptr  : pointer on block to be released.
117/////////////////////////////////////////////////////////////////////////////////////
118static void __attribute__((noinline)) kcm_put_block ( kcm_t      * kcm,
119                                                      kcm_page_t * kcm_page,
120                                                      void       * block_ptr )
121{
122    // initialise variables
123    uint32_t max    = kcm->max_blocks;
124    uint32_t size   = 1 << kcm->order;
125    uint32_t count  = kcm_page->count;
126    uint64_t status = kcm_page->status;
127   
128        // compute block index from block pointer
129        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
130
131    // compute mask in bit vector
132    uint64_t mask = ((uint64_t)0x1) << index;
133
134assert( (status & mask) , "released block not allocated : status (%x,%x) / mask(%x,%x)",
135GET_CXY(status), GET_PTR(status), GET_CXY(mask  ), GET_PTR(mask  ) );
136
137    // update status & count in kcm_page
138        kcm_page->status = status & ~mask;
139        kcm_page->count  = count - 1;
140
141        // change the page mode if page was full
142        if( count == max )
143        {
144                list_unlink( &kcm_page->list );
145                kcm->full_pages_nr --;
146
147                list_add_last( &kcm->active_root, &kcm_page->list );
148                kcm->active_pages_nr ++;
149        }
150
151#if (DEBUG_KCM & 1)
152thread_t * this  = CURRENT_THREAD;
153uint32_t   cycle = (uint32_t)hal_get_cycles();
154if( DEBUG_KCM < cycle )
155printk("\n[%s] thread[%x,%x] released block %x in page %x / size %d / count %d / cycle %d\n",
156__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_page, size, count - 1, cycle );
157#endif
158
159}  // kcm_put_block()
160
161/////////////////////////////////////////////////////////////////////////////////////
162// This static function must be called by a local thread.
163// It returns one non-full kcm_page with the following policy :
164// - if the "active_list" is non empty, it returns the first "active" page,
165//   without modifying the KCM state.
166// - if the "active_list" is empty, it allocates a new page from PPM, inserts
167//   this page in the active_list, and returns it.
168/////////////////////////////////////////////////////////////////////////////////////
169// @ kcm      : local pointer on local KCM allocator.
170// @ return pointer on a non-full kcm page if success / returns NULL if no memory.
171/////////////////////////////////////////////////////////////////////////////////////
172static kcm_page_t * __attribute__((noinline)) kcm_get_page( kcm_t * kcm )
173{
174    kcm_page_t * kcm_page;
175
176    uint32_t active_pages_nr = kcm->active_pages_nr;
177
178    if( active_pages_nr > 0 )       // return first active page
179    {
180        kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
181    }
182    else                            // allocate a new page from PPM
183        {
184        // get one 4 Kbytes page from local PPM
185        page_t * page = ppm_alloc_pages( 0 );
186
187            if( page == NULL )
188            {
189                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
190                __FUNCTION__ , local_cxy );
191
192                    return NULL;
193        }
194
195            // get page base address
196            xptr_t base_xp = ppm_page2base( XPTR( local_cxy , page ) );
197
198        // get local pointer on kcm_page
199            kcm_page = GET_PTR( base_xp );
200
201            // initialize kcm_page descriptor
202            kcm_page->status = 0;
203            kcm_page->count  = 0;
204            kcm_page->kcm    = kcm;
205            kcm_page->page   = page;
206
207            // introduce new page in KCM active_list
208            list_add_first( &kcm->active_root , &kcm_page->list );
209            kcm->active_pages_nr ++;
210        }
211
212        return kcm_page;
213
214}  // end kcm_get_page()
215
216//////////////////////////////
217void kcm_init( kcm_t    * kcm,
218                   uint32_t   order)
219{
220
221assert( ((order > 5) && (order < 12)) , "order must be in [6,11]" );
222
223        // initialize lock
224        remote_busylock_init( XPTR( local_cxy , &kcm->lock ) , LOCK_KCM_STATE );
225
226        // initialize KCM page lists
227        kcm->full_pages_nr   = 0;
228        kcm->active_pages_nr = 0;
229        list_root_init( &kcm->full_root );
230        list_root_init( &kcm->active_root );
231
232        // initialize order and max_blocks
233        kcm->order      = order;
234    kcm->max_blocks = ( CONFIG_PPM_PAGE_SIZE >> order ) - 1;
235 
236#if DEBUG_KCM
237thread_t * this  = CURRENT_THREAD;
238uint32_t   cycle = (uint32_t)hal_get_cycles();
239if( DEBUG_KCM < cycle )
240printk("\n[%s] thread[%x,%x] initialised KCM / order %d / max_blocks %d\n",
241__FUNCTION__, this->process->pid, this->trdid, order, kcm->max_blocks );
242#endif
243
244}  // end kcm_init()
245
246///////////////////////////////
247void kcm_destroy( kcm_t * kcm )
248{
249        kcm_page_t   * kcm_page;
250
251    // build extended pointer on  KCM lock
252    xptr_t lock_xp = XPTR( local_cxy , &kcm->lock );
253
254        // get KCM lock
255        remote_busylock_acquire( lock_xp );
256
257        // release all full pages
258        while( list_is_empty( &kcm->full_root ) == false )
259        {
260                kcm_page = LIST_FIRST( &kcm->full_root , kcm_page_t , list );
261                list_unlink( &kcm_page->list );
262                ppm_free_pages( kcm_page->page );
263        }
264
265    // release all empty pages
266    while( list_is_empty( &kcm->active_root ) == false )
267        {
268                kcm_page = LIST_FIRST( &kcm->active_root , kcm_page_t , list );
269                list_unlink( &kcm_page->list );
270                ppm_free_pages( kcm_page->page );
271        }
272
273        // release KCM lock
274        remote_busylock_release( lock_xp );
275
276}  // end kcm_destroy()
277
278//////////////////////////////////
279void * kcm_alloc( uint32_t order )
280{
281    kcm_t      * kcm_ptr;
282        kcm_page_t * kcm_page;
283        void       * block_ptr;
284
285   // min block size is 64 bytes
286    if( order < 6 ) order = 6;
287
288assert( (order < 12) , "order = %d / must be less than 12" , order );
289
290    // get local pointer on relevant KCM allocator
291    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
292
293    // build extended pointer on local KCM lock
294    xptr_t lock_xp = XPTR( local_cxy , &kcm_ptr->lock );
295
296        // get KCM lock
297        remote_busylock_acquire( lock_xp );
298
299    // get a non-full kcm_page
300    kcm_page = kcm_get_page( kcm_ptr );
301
302#if DEBUG_KCM
303thread_t * this  = CURRENT_THREAD;
304uint32_t   cycle = (uint32_t)hal_get_cycles();
305if( (DEBUG_KCM < cycle) && (local_cxy == 1) )
306{
307printk("\n[%s] thread[%x,%x] enters / order %d / page %x / kcm %x / page_status (%x|%x)\n",
308__FUNCTION__, this->process->pid, this->trdid, order, kcm_page, kcm_ptr,
309GET_CXY( kcm_page->status ), GET_PTR( kcm_page->status ) );
310kcm_remote_display( local_cxy , kcm_ptr );
311}
312#endif
313
314    if( kcm_page == NULL )
315        {
316                remote_busylock_release( lock_xp );
317                return NULL;
318        }
319
320        // get a block from selected active page
321        block_ptr = kcm_get_block( kcm_ptr , kcm_page );
322
323        // release lock
324        remote_busylock_release( lock_xp );
325
326#if DEBUG_KCM
327if( (DEBUG_KCM < cycle) && (local_cxy == 1) )
328{
329printk("\n[%s] thread[%x,%x] exit / order %d / block %x / kcm %x / page_status (%x|%x)\n",
330__FUNCTION__, this->process->pid, this->trdid, order, block_ptr, kcm_ptr,
331GET_CXY( kcm_page->status ), GET_PTR( kcm_page->status ) );
332kcm_remote_display( local_cxy , kcm_ptr );
333}
334#endif
335
336        return block_ptr;
337
338}  // end kcm_alloc()
339
340/////////////////////////////////
341void kcm_free( void * block_ptr )
342{
343    kcm_t      * kcm_ptr;
344        kcm_page_t * kcm_page;
345
346// check argument
347assert( (block_ptr != NULL) , "block pointer cannot be NULL" );
348
349    // get local pointer on KCM page
350        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~CONFIG_PPM_PAGE_MASK);
351
352    // get local pointer on KCM descriptor
353        kcm_ptr = kcm_page->kcm;
354
355#if DEBUG_KCM
356thread_t * this  = CURRENT_THREAD;
357uint32_t   cycle = (uint32_t)hal_get_cycles();
358if( (DEBUG_KCM < cycle) && (local_cxy == 1) )
359{
360printk("\n[%s] thread[%x,%x] enters / order %d / block %x / page %x / kcm %x / status [%x,%x]\n",
361__FUNCTION__, this->process->pid, this->trdid, kcm_ptr->order, block_ptr, kcm_page, kcm_ptr,
362GET_CXY(kcm_page->status), GET_PTR(kcm_page->status) );
363kcm_remote_display( local_cxy , kcm_ptr );
364}
365#endif
366
367    // build extended pointer on local KCM lock
368    xptr_t lock_xp = XPTR( local_cxy , &kcm_ptr->lock );
369
370        // get lock
371        remote_busylock_acquire( lock_xp );
372
373        // release block
374        kcm_put_block( kcm_ptr , kcm_page , block_ptr );
375
376        // release lock
377        remote_busylock_release( lock_xp );
378
379#if DEBUG_KCM
380if( (DEBUG_KCM < cycle) && (local_cxy == 1) )
381{
382printk("\n[%s] thread[%x,%x] exit / order %d / page %x / status [%x,%x]\n",
383__FUNCTION__, this->process->pid, this->trdid, kcm_ptr->order, kcm_ptr,
384GET_CXY(kcm_page->status), GET_PTR(kcm_page->status) );
385kcm_remote_display( local_cxy , kcm_ptr );
386}
387#endif
388
389}  // end kcm_free()
390
391/////////////////////////////////////////////////////////////////////////////////////
392//        Remote access functions
393/////////////////////////////////////////////////////////////////////////////////////
394
395/////////////////////////////////////////////////////////////////////////////////////
396// This static function can be called by any thread running in any cluster.
397// It returns a local pointer on a block allocated from an active kcm_page.
398// It makes a panic if no block available in the selected kcm_page.
399// It changes the page status as required.
400/////////////////////////////////////////////////////////////////////////////////////
401// @ kcm_cxy  : remote KCM cluster identifier.
402// @ kcm_ptr  : local pointer on remote KCM allocator.
403// @ kcm_page : local pointer on remote active kcm_page to use.
404// @ return a local pointer on the allocated block.
405/////////////////////////////////////////////////////////////////////////////////////
406static void * __attribute__((noinline)) kcm_remote_get_block( cxy_t        kcm_cxy,
407                                                              kcm_t      * kcm_ptr,
408                                                              kcm_page_t * kcm_page )
409{
410    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
411    uint32_t max    = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->max_blocks ) );
412    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
413    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
414    uint32_t size   = 1 << order;
415
416assert( (count < max) , "kcm_page should not be full" );
417
418    uint32_t index  = 1;
419    uint64_t mask   = (uint64_t)0x2;
420   
421        // allocate first free block in kcm_page, update status,
422    // and count , compute index of allocated block in kcm_page
423    while( index <= max )
424    {
425        if( (status & mask) == 0 )   // block found
426        {
427            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status | mask );
428            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count + 1 );
429            break;     
430        }
431       
432        index++;
433        mask <<= 1;
434    }
435
436        // change the page list if found block is the last
437        if( count == max-1 )
438        {
439                list_remote_unlink( kcm_cxy , &kcm_page->list );
440                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , -1 );
441
442                list_remote_add_first( kcm_cxy , &kcm_ptr->full_root , &kcm_page->list );
443                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , 1 );
444        }
445
446        // compute return pointer
447        void * ptr = (void *)((intptr_t)kcm_page + (index * size) );
448
449#if DEBUG_KCM_REMOTE
450thread_t * this  = CURRENT_THREAD;
451uint32_t   cycle = (uint32_t)hal_get_cycles();
452if( DEBUG_KCM_REMOTE < cycle )
453printk("\n[%s] thread[%x,%x] get block %x in page %x / cluster %x / size %x / count %d\n",
454__FUNCTION__, this->process->pid, this->trdid, 
455ptr, kcm_page, kcm_cxy, size, count + 1 );
456#endif
457
458        return ptr;
459
460}  // end kcm_remote_get_block()
461
462/////////////////////////////////////////////////////////////////////////////////////
463// This private static function can be called by any thread running in any cluster.
464// It releases a previously allocated block to the relevant kcm_page.
465// It changes the kcm_page status as required.
466/////////////////////////////////////////////////////////////////////////////////////
467// @ kcm_cxy   : remote KCM cluster identifier
468// @ kcm_ptr   : local pointer on remote KCM.
469// @ kcm_page  : local pointer on kcm_page.
470// @ block_ptr : pointer on block to be released.
471/////////////////////////////////////////////////////////////////////////////////////
472static void __attribute__((noinline)) kcm_remote_put_block ( cxy_t        kcm_cxy,
473                                                             kcm_t      * kcm_ptr,
474                                                             kcm_page_t * kcm_page,
475                                                             void       * block_ptr )
476{
477    uint32_t max    = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->max_blocks ) );
478    uint32_t order  = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
479    uint32_t count  = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
480    uint64_t status = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
481    uint32_t size   = 1 << order;
482   
483        // compute block index from block pointer
484        uint32_t index = ((intptr_t)block_ptr - (intptr_t)kcm_page) / size;
485
486    // compute mask in bit vector
487    uint64_t mask = 1 << index;
488
489assert( (status & mask) , "released page not allocated" );
490
491    // update status & count in kcm_page
492        hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , status & ~mask );
493        hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count  ) , count - 1 );
494
495        // change the page list if page was full
496        if( count == max )
497        {
498                list_remote_unlink( kcm_cxy , &kcm_page->list );
499                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) , -1 );
500
501                list_remote_add_last( kcm_cxy , &kcm_ptr->active_root, &kcm_page->list );
502                hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
503        }
504
505#if (DEBUG_KCM_REMOTE & 1)
506thread_t * this  = CURRENT_THREAD;
507uint32_t   cycle = (uint32_t)hal_get_cycles();
508if( DEBUG_KCM_REMOTE < cycle )
509printk("\n[%s] thread[%x,%x] released block %x in page %x / cluster %x / size %x / count %d\n",
510__FUNCTION__, this->process->pid, this->trdid, block_ptr, kcm_page, size, count - 1 )
511#endif
512
513}  // end kcm_remote_put_block()
514
515/////////////////////////////////////////////////////////////////////////////////////
516// This private static function can be called by any thread running in any cluster.
517// It gets one non-full KCM page from the remote KCM.
518// It allocates a page from remote PPM to populate the freelist, and initialises
519// the kcm_page descriptor when required.
520/////////////////////////////////////////////////////////////////////////////////////
521static kcm_page_t * __attribute__((noinline)) kcm_remote_get_page( cxy_t    kcm_cxy,
522                                                                   kcm_t  * kcm_ptr )
523{
524    kcm_page_t * kcm_page;    // local pointer on remote KCM page
525
526    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
527
528    if( active_pages_nr > 0 )       // return first active page
529    {
530        kcm_page = LIST_REMOTE_FIRST( kcm_cxy , &kcm_ptr->active_root , kcm_page_t , list );
531    }
532    else                            // allocate a new page from PPM
533        {
534        // get one 4 Kbytes page from remote PPM
535        xptr_t page_xp = ppm_remote_alloc_pages( kcm_cxy , 0 );
536
537            if( page_xp == XPTR_NULL )
538            {
539                    printk("\n[ERROR] in %s : failed to allocate page in cluster %x\n",
540                __FUNCTION__ , kcm_cxy );
541
542                    return NULL;
543        }
544
545            // get extended pointer on allocated buffer
546            xptr_t base_xp = ppm_page2base( page_xp );
547
548        // get local pointer on kcm_page
549            kcm_page = GET_PTR( base_xp );
550
551            // initialize kcm_page descriptor
552            hal_remote_s32( XPTR( kcm_cxy , &kcm_page->count )  , 0 );
553            hal_remote_s64( XPTR( kcm_cxy , &kcm_page->status ) , 0 );
554            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->kcm )    , kcm_ptr );
555            hal_remote_spt( XPTR( kcm_cxy , &kcm_page->page )   , GET_PTR( page_xp ) );
556
557            // introduce new page in remote KCM active_list
558            list_remote_add_first( kcm_cxy , &kcm_ptr->active_root , &kcm_page->list );
559            hal_remote_atomic_add( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) , 1 );
560        }
561
562        return kcm_page;
563
564}  // end kcm_remote_get_page()
565
566/////////////////////////////////////////
567void * kcm_remote_alloc( cxy_t    kcm_cxy,
568                         uint32_t order )
569{
570    kcm_t      * kcm_ptr;
571    kcm_page_t * kcm_page;
572    void       * block_ptr;
573
574    if( order < 6 ) order = 6;
575
576assert( (order < 12) , "order = %d / must be less than 12" , order );
577
578    // get local pointer on relevant KCM allocator
579    kcm_ptr = &LOCAL_CLUSTER->kcm[order - 6];
580
581    // build extended pointer on remote KCM lock
582    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
583
584        // get lock
585        remote_busylock_acquire( lock_xp );
586
587    // get a non-full kcm_page
588    kcm_page = kcm_remote_get_page( kcm_cxy , kcm_ptr );
589
590    if( kcm_page == NULL )
591        {
592                remote_busylock_release( lock_xp );
593                return NULL;
594        }
595
596        // get a block from selected active page
597        block_ptr = kcm_remote_get_block( kcm_cxy , kcm_ptr , kcm_page );
598
599        // release lock
600        remote_busylock_release( lock_xp );
601
602#if DEBUG_KCM_REMOTE
603thread_t * this  = CURRENT_THREAD;
604uint32_t   cycle = (uint32_t)hal_get_cycles();
605if( DEBUG_KCM_REMOTE < cycle )
606printk("\n[%s] thread[%x,%x] allocated block %x / order %d / kcm[%x,%x]\n",
607__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
608#endif
609
610        return block_ptr;
611
612}  // end kcm_remote_alloc()
613
614/////////////////////////////////////
615void kcm_remote_free( cxy_t  kcm_cxy,
616                      void * block_ptr )
617{
618        kcm_t      * kcm_ptr;
619        kcm_page_t * kcm_page;
620
621// check argument
622assert( (block_ptr != NULL) , "block pointer cannot be NULL" );
623
624    // get local pointer on remote KCM page
625        kcm_page = (kcm_page_t *)((intptr_t)block_ptr & ~CONFIG_PPM_PAGE_MASK);
626
627    // get local pointer on remote KCM
628        kcm_ptr = hal_remote_lpt( XPTR( kcm_cxy , &kcm_page->kcm ) );
629
630    // build extended pointer on remote KCM lock
631    xptr_t lock_xp = XPTR( kcm_cxy , &kcm_ptr->lock );
632
633        // get lock
634        remote_busylock_acquire( lock_xp );
635
636        // release block
637        kcm_remote_put_block( kcm_cxy , kcm_ptr , kcm_page , block_ptr );
638
639        // release lock
640        remote_busylock_release( lock_xp );
641
642#if DEBUG_KCM_REMOTE
643thread_t * this  = CURRENT_THREAD;
644uint32_t   cycle = (uint32_t)hal_get_cycles();
645uint32_t   order = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order ) );
646if( DEBUG_KCM_REMOTE < cycle )
647printk("\n[%s] thread[%x,%x] released block %x / order %d / kcm[%x,%x]\n",
648__FUNCTION__, this->process->pid, this->trdid, block_ptr, order, kcm_cxy, kcm_ptr );
649#endif
650
651}  // end kcm_remote_free
652
653/////////////////////////////////////////
654void kcm_remote_display( cxy_t   kcm_cxy,
655                         kcm_t * kcm_ptr )
656{
657    list_entry_t * iter;
658    kcm_page_t   * kcm_page;
659    uint64_t       status;
660    uint32_t       count;
661
662    uint32_t order           = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->order) );
663    uint32_t full_pages_nr   = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->full_pages_nr ) );
664    uint32_t active_pages_nr = hal_remote_l32( XPTR( kcm_cxy , &kcm_ptr->active_pages_nr ) );
665
666        printk("*** KCM : cxy %x / order %d / full_pages_nr %d / active_pages_nr %d\n",
667        kcm_cxy, order, full_pages_nr, active_pages_nr );
668
669    if( active_pages_nr )
670    {
671        LIST_REMOTE_FOREACH( kcm_cxy , &kcm_ptr->active_root , iter )
672        {
673            kcm_page = LIST_ELEMENT( iter , kcm_page_t , list );
674            status   = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
675            count    = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
676
677            printk("- active page %x / status (%x,%x) / count %d\n",
678            kcm_page, GET_CXY( status ), GET_PTR( status ), count );
679        }
680    }
681
682    if( full_pages_nr )
683    {
684        LIST_REMOTE_FOREACH( kcm_cxy , &kcm_ptr->full_root , iter )
685        {
686            kcm_page = LIST_ELEMENT( iter , kcm_page_t , list );
687            status   = hal_remote_l64( XPTR( kcm_cxy , &kcm_page->status ) );
688            count    = hal_remote_l32( XPTR( kcm_cxy , &kcm_page->count ) );
689
690            printk("- full page %x / status (%x,%x) / count %d\n",
691            kcm_page, GET_CXY( status ), GET_PTR( status ), count );
692        }
693    }
694}  // end kcm remote_display()
Note: See TracBrowser for help on using the repository browser.