Ignore:
Timestamp:
Jun 18, 2017, 10:06:41 PM (4 years ago)
Author:
alain
Message:

Introduce syscalls.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/libk/remote_barrier.c

    r14 r23  
    11/*
    2  * remote_barrier.c - distributed kernel barrier implementaion
     2 * remote_barrier.c - Access a POSIX barrier.
    33 *
    4  * Author   Alain Greiner (2016)
     4 * Author   Alain Greiner (2016,2017)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    2424#include <hal_types.h>
    2525#include <hal_remote.h>
     26#include <hal_irqmask.h>
     27#include <remote_spinlock.h>
     28#include <thread.h>
     29#include <kmem.h>
     30#include <printk.h>
     31#include <process.h>
     32#include <vmm.h>
    2633#include <remote_barrier.h>
    2734
    28 /////////////////////////////////////////
    29 inline void remote_barrier( xptr_t    xp,
     35/////////////////////////////////////////////////
     36inline void remote_barrier( xptr_t    barrier_xp,
    3037                            uint32_t  count )
    3138{
    3239    uint32_t  expected;
    3340
    34     remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( xp );
    35     cxy_t              cxy = GET_CXY( xp );
     41    remote_barrier_t * ptr = (remote_barrier_t *)GET_PTR( barrier_xp );
     42    cxy_t              cxy = GET_CXY( barrier_xp );
    3643
    3744    // get barrier sense value
     
    5764}
    5865
    59 
     66///////////////////////////////////////////////////
     67xptr_t remote_barrier_from_ident( intptr_t  ident )
     68{
     69    // get pointer on local process_descriptor
     70    process_t * process = CURRENT_THREAD->process;
     71
     72    // get extended pointer on reference process
     73    xptr_t      ref_xp = process->ref_xp;
     74
     75    // get cluster and local pointer on reference process
     76    cxy_t          ref_cxy = GET_CXY( ref_xp );
     77    process_t    * ref_ptr = (process_t *)GET_PTR( ref_xp );
     78
     79    // get extended pointer on root of barriers list
     80    xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->barrier_root );
     81   
     82    // scan reference process barriers list
     83    xptr_t             iter_xp;
     84    xptr_t             barrier_xp;
     85    cxy_t              barrier_cxy;
     86    remote_barrier_t * barrier_ptr;
     87    intptr_t           current;
     88    bool_t             found = false;
     89           
     90    XLIST_FOREACH( root_xp , iter_xp )
     91    {
     92        barrier_xp  = XLIST_ELEMENT( iter_xp , remote_barrier_t , list );
     93        barrier_cxy = GET_CXY( barrier_xp );
     94        barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp );
     95        current     = (intptr_t)hal_remote_lpt( XPTR( barrier_cxy , &barrier_ptr->ident ) );   
     96        if( ident == current )
     97        {
     98            found = true;
     99            break;
     100        }
     101    }
     102
     103    if( found == false )  return XPTR_NULL;
     104    else                  return barrier_xp;
     105
     106}  // end remote_barrier_from_ident()
     107
     108//////////////////////////////////////////////
     109error_t remote_barrier_create( intptr_t ident,
     110                               uint32_t count )
     111{
     112    xptr_t             barrier_xp;
     113    remote_barrier_t * barrier_ptr;
     114
     115    // get pointer on local process descriptor
     116    process_t * process = CURRENT_THREAD->process;
     117
     118    // get extended pointer on reference process
     119    xptr_t      ref_xp = process->ref_xp;
     120
     121    // get reference process cluster and local pointer
     122    cxy_t       ref_cxy = GET_CXY( ref_xp );
     123    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
     124
     125    // allocate memory for barrier descriptor
     126    if( ref_cxy == local_cxy )                  // local cluster is the reference
     127    {
     128        kmem_req_t req;   
     129        req.type      = KMEM_BARRIER;
     130        req.flags     = AF_ZERO;
     131        barrier_ptr   = kmem_alloc( &req );
     132        barrier_xp    = XPTR( local_cxy , barrier_ptr );
     133    }
     134    else                                       // reference is remote
     135    {
     136        rpc_kcm_alloc_client( ref_cxy , KMEM_BARRIER , &barrier_xp );
     137        barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp );
     138    }
     139
     140    if( barrier_ptr == NULL ) return ENOMEM;
     141
     142    // initialise barrier
     143    hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->nb_threads ) , count );
     144    hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->current    ) , 0 );
     145    hal_remote_sw ( XPTR( ref_cxy , &barrier_ptr->sense      ) , 0 );
     146    hal_remote_spt( XPTR( ref_cxy , &barrier_ptr->ident      ) , (void*)ident );
     147
     148    xlist_entry_init( XPTR( ref_cxy , &barrier_ptr->list ) );
     149
     150    // register  barrier in reference process xlist
     151    xptr_t root_xp  = XPTR( ref_cxy , &ref_ptr->barrier_root );
     152    xptr_t entry_xp = XPTR( ref_cxy , &barrier_ptr->list );
     153
     154    remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     155    xlist_add_first( root_xp , entry_xp );
     156    remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     157
     158    return 0;
     159
     160}  // end remote_barrier_create()
     161
     162////////////////////////////////////////////////
     163void remote_barrier_destroy( xptr_t barrier_xp )
     164{
     165    // get pointer on local process descriptor
     166    process_t * process = CURRENT_THREAD->process;
     167
     168    // get extended pointer on reference process
     169    xptr_t      ref_xp = process->ref_xp;
     170
     171    // get reference process cluster and local pointer
     172    cxy_t       ref_cxy = GET_CXY( ref_xp );
     173    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
     174
     175    // get barrier cluster and local pointer
     176    cxy_t              barrier_cxy = GET_CXY( barrier_xp );
     177    remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp );
     178
     179    // remove barrier from reference process xlist
     180    remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     181    xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) );
     182    remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     183
     184    // release memory allocated for barrier descriptor
     185    if( barrier_cxy == local_cxy )                        // reference is local
     186    {
     187        kmem_req_t  req;
     188        req.type = KMEM_BARRIER;
     189        req.ptr  = barrier_ptr;
     190        kmem_free( &req );
     191    }
     192    else                                                  // reference is remote
     193    {
     194        rpc_kcm_free_client( barrier_cxy , barrier_ptr , KMEM_BARRIER );
     195    }
     196
     197}  // end remote_barrier_destroy()
     198
     199/////////////////////////////////////////////
     200void remote_barrier_wait( xptr_t barrier_xp )
     201{
     202    uint32_t  expected;
     203    uint32_t  current;
     204    uint32_t  count;
     205    uint32_t  sense;
     206    uint32_t  irq_state;
     207    xptr_t    root_xp;
     208
     209    // get cluster and local pointer on calling thread
     210    cxy_t              thread_cxy = local_cxy;
     211    thread_t         * thread_ptr = CURRENT_THREAD;
     212
     213    // get cluster and local pointer on remote barrier
     214    remote_barrier_t * barrier_ptr = (remote_barrier_t *)GET_PTR( barrier_xp );
     215    cxy_t              barrier_cxy = GET_CXY( barrier_xp );
     216
     217    // get count and root fields from barrier descriptor
     218    count   = hal_remote_lw ( XPTR( barrier_cxy , &barrier_ptr->nb_threads ) );
     219    root_xp = hal_remote_lwd( XPTR( barrier_cxy , &barrier_ptr->root ) );
     220
     221    // get barrier sense value
     222    sense = hal_remote_lw( XPTR( barrier_cxy , &barrier_ptr->sense ) );
     223
     224        // compute expected value
     225    if ( sense == 0 ) expected = 1;
     226    else              expected = 0;
     227
     228    // atomically increment current
     229    current = hal_remote_atomic_add( XPTR( barrier_cxy , &barrier_ptr->current ) , 1 );
     230
     231    // last thread reset current, toggle sense, and activate all waiting threads
     232    // other threads block, register in queue, and deschedule
     233
     234    if( current == (count-1) )                       // last thread
     235    {
     236        hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->current) , 0 ); 
     237        hal_remote_sw( XPTR( barrier_cxy , &barrier_ptr->sense  ) , expected ); 
     238
     239        // activate waiting threads if required
     240        if( xlist_is_empty( root_xp ) == false ) 
     241        {
     242            // disable interrupts
     243                hal_disable_irq( &irq_state );
     244 
     245            xptr_t  iter_xp;
     246            xptr_t  thread_xp;
     247            XLIST_FOREACH( root_xp , iter_xp )
     248            {
     249                // get extended pointer on waiting thread
     250                thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list );
     251       
     252                // remove waiting thread from queue
     253                remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) );
     254                xlist_unlink( XPTR( barrier_cxy , &barrier_ptr->list ) );
     255                remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) );
     256
     257                // unblock waiting thread
     258                thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC );
     259            }
     260
     261            // restore interrupts
     262            hal_restore_irq( irq_state );
     263        }
     264    }
     265    else                                             // not the last thread 
     266    {
     267        // disable interrupts
     268            hal_disable_irq( &irq_state );
     269 
     270        // register calling thread in barrier waiting queue
     271        xptr_t entry_xp = XPTR( thread_cxy , &thread_ptr->wait_list );
     272
     273        remote_spinlock_lock( XPTR( barrier_cxy , &barrier_ptr->lock ) );
     274        xlist_add_last( root_xp , entry_xp );
     275        remote_spinlock_unlock( XPTR( barrier_cxy , &barrier_ptr->lock ) );
     276
     277        // block & deschedule the calling thread   
     278        thread_block( thread_ptr , THREAD_BLOCKED_USERSYNC );
     279        sched_yield();
     280
     281        // restore interrupts
     282        hal_restore_irq( irq_state );
     283    }
     284}  // end remote_barrier_wait()
Note: See TracChangeset for help on using the changeset viewer.