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

Last change on this file since 680 was 672, checked in by alain, 4 years ago

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

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