Ignore:
Timestamp:
Oct 4, 2018, 11:16:13 PM (3 years ago)
Author:
alain
Message:

Complete restructuration of kernel spinlocks.

File:
1 edited

Legend:

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

    r457 r563  
    11/*
    2  * remote_condvar.c - distributed kernel condvar implementaion
    3  * 
    4  * Author   Alain Greiner (2016)
     2 * remote_condvar.c - remote kernel condition variable implementation.
     3 *
     4 * Authors     Alain Greiner (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    2222 */
    2323
     24#include <kernel_config.h>
    2425#include <hal_kernel_types.h>
    25 #include <hal_remote.h>
    26 #include <hal_irqmask.h>
    2726#include <thread.h>
    28 #include <kmem.h>
    29 #include <printk.h>
    30 #include <process.h>
    31 #include <vmm.h>
     27#include <scheduler.h>
    3228#include <xlist.h>
    3329#include <remote_mutex.h>
     30#include <remote_busylock.h>
    3431#include <remote_condvar.h>
     32
    3533
    3634///////////////////////////////////////////////////
     
    4543    // get cluster and local pointer on reference process
    4644    cxy_t          ref_cxy = GET_CXY( ref_xp );
    47     process_t    * ref_ptr = (process_t *)GET_PTR( ref_xp );
    48 
    49     // get extended pointer on root of condvars list
     45    process_t    * ref_ptr = GET_PTR( ref_xp );
     46
     47    // get extended pointer on condvars list
    5048    xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->condvar_root );
    51    
    52     // scan reference process condvars list
     49    xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock );
     50
     51    // get lock protecting synchro lists
     52    remote_queuelock_acquire( lock_xp );
     53 
     54    // scan reference process condvar list
    5355    xptr_t             iter_xp;
    5456    xptr_t             condvar_xp;
    5557    cxy_t              condvar_cxy;
    56     struct remote_condvar_s * condvar_ptr;
     58    remote_condvar_t * condvar_ptr;
    5759    intptr_t           current;
    5860    bool_t             found = false;
     
    6264        condvar_xp  = XLIST_ELEMENT( iter_xp , remote_condvar_t , list );
    6365        condvar_cxy = GET_CXY( condvar_xp );
    64         condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
    65         current     = (intptr_t)hal_remote_lpt( XPTR( condvar_cxy , &condvar_ptr->ident ) );   
    66         if( ident == current )
     66        condvar_ptr = GET_PTR( condvar_xp );
     67        current = (intptr_t)hal_remote_lpt( XPTR( condvar_cxy , &condvar_ptr->ident ) );   
     68
     69        if( current == ident )
    6770        {
    6871            found = true;
     
    7174    }
    7275
     76    // relese lock protecting synchros lists
     77    remote_queuelock_release( lock_xp );
     78 
    7379    if( found == false )  return XPTR_NULL;
    7480    else                  return condvar_xp;
     
    7682}  // end remote_condvar_from_ident()
    7783
    78 ///////////////////////////////////////////////
    79 error_t remote_condvar_create( intptr_t ident )
    80 {
     84/////////////////////////////////////////////////
     85error_t remote_condvar_create( intptr_t   ident )
     86{
     87    remote_condvar_t * condvar_ptr;
    8188    xptr_t             condvar_xp;
    82     remote_condvar_t * condvar_ptr;
    8389
    8490    // get pointer on local process descriptor
     
    9298    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
    9399
    94     // allocate memory for condvar descriptor
    95     if( ref_cxy == local_cxy )                  // local cluster is the reference
     100    // allocate memory for new condvar in reference cluster
     101    if( ref_cxy == local_cxy )                              // local cluster is the reference
    96102    {
    97103        kmem_req_t req;   
    98         req.type      = KMEM_CONDVAR;
    99         req.flags     = AF_ZERO;
    100         condvar_ptr   = kmem_alloc( &req );
    101         condvar_xp    = XPTR( local_cxy , condvar_ptr );
    102     }
    103     else                                       // reference is remote
     104        req.type    = KMEM_CONDVAR;
     105        req.flags   = AF_ZERO;
     106        condvar_ptr = kmem_alloc( &req );
     107        condvar_xp  = XPTR( local_cxy , condvar_ptr );
     108    }
     109    else                                                   // reference cluster is remote
    104110    {
    105111        rpc_kcm_alloc_client( ref_cxy , KMEM_CONDVAR , &condvar_xp );
    106         condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
    107     }
    108 
    109     if( condvar_ptr == NULL ) return ENOMEM;
     112        condvar_ptr = GET_PTR( condvar_xp );
     113    }
     114
     115    if( condvar_xp == XPTR_NULL ) return 0xFFFFFFFF;
    110116
    111117    // initialise condvar
    112     hal_remote_spt( XPTR( ref_cxy , &condvar_ptr->ident      ) , (void*)ident );
    113     xlist_entry_init( XPTR( ref_cxy , &condvar_ptr->list ) );
    114     xlist_root_init( XPTR( ref_cxy , &condvar_ptr->root ) );
    115 
    116     // register  condvar in reference process xlist
     118        hal_remote_spt( XPTR( ref_cxy , &condvar_ptr->ident ) , (void *)ident );
     119        xlist_root_init( XPTR( ref_cxy , &condvar_ptr->root ) );
     120        xlist_entry_init( XPTR( ref_cxy , &condvar_ptr->list ) );
     121    remote_busylock_init( XPTR( ref_cxy , &condvar_ptr->lock ), LOCK_CONDVAR_STATE );
     122
     123    // register condvar in reference process xlist
    117124    xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->condvar_root );
    118     xptr_t xp_list = XPTR( ref_cxy , &condvar_ptr->list );
    119 
    120     remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    121     xlist_add_first( root_xp , xp_list );
    122     remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     125    xptr_t list_xp = XPTR( ref_cxy , &condvar_ptr->list );
     126
     127    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     128    xlist_add_first( root_xp , list_xp );
     129    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    123130
    124131    return 0;
     
    137144    // get reference process cluster and local pointer
    138145    cxy_t       ref_cxy = GET_CXY( ref_xp );
    139     process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
    140 
    141     // get condvar cluster and local pointer
    142     cxy_t              condvar_cxy = GET_CXY( condvar_xp );
    143     remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
     146    process_t * ref_ptr = GET_PTR( ref_xp );
     147
     148    // get condvar cluster and local pointer
     149    cxy_t              condvar_cxy = GET_CXY( condvar_xp );
     150    remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp );
     151
     152    // get remote pointer on waiting queue root
     153    xptr_t root_xp = XPTR( condvar_cxy , &condvar_ptr->root );
     154 
     155    if( !xlist_is_empty( root_xp ) )   // user error
     156    {
     157        printk("WARNING in %s for thread %x in process %x : "
     158               "destroy condvar, but  waiting threads queue not empty\n",
     159               __FUNCTION__ , CURRENT_THREAD->trdid , CURRENT_THREAD->process->pid );
     160    }
    144161
    145162    // remove condvar from reference process xlist
    146     remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     163    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    147164    xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) );
    148     remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    149 
    150     // release memory allocated for condvaraphore descriptor
     165    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     166
     167    // release memory allocated for condvar descriptor
    151168    if( condvar_cxy == local_cxy )                            // reference is local
    152169    {
    153170        kmem_req_t  req;
    154         req.type = KMEM_BARRIER;
     171        req.type = KMEM_SEM;
    155172        req.ptr  = condvar_ptr;
    156173        kmem_free( &req );
     
    158175    else                                                  // reference is remote
    159176    {
    160         rpc_kcm_free_client( condvar_cxy , condvar_ptr , KMEM_BARRIER );
    161     }
    162 
    163 }  // end remote_condvar_destroy()
     177        rpc_kcm_free_client( condvar_cxy , condvar_ptr , KMEM_CONDVAR );
     178    }
     179
     180}  // end remote_convar_destroy()
    164181
    165182////////////////////////////////////////////
     
    167184                          xptr_t mutex_xp )
    168185{
    169     // unlock the mutex
     186    thread_t * this = CURRENT_THREAD;
     187
     188// check calling thread can yield
     189assert( (this->busylocks == 0),
     190"cannot yield : busylocks = %d\n", this->busylocks );
     191
     192    // get condvar cluster and local pointer
     193    remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp );
     194    cxy_t              condvar_cxy = GET_CXY( condvar_xp );
     195
     196    // register the calling thread in condvar waiting queue
     197    xlist_add_last( XPTR( condvar_cxy , &condvar_ptr->root ),
     198                    XPTR( local_cxy   , &this->wait_xlist ) );
     199
     200    // block the calling thread
     201    thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_USERSYNC );
     202
     203    // release the mutex
    170204    remote_mutex_unlock( mutex_xp );
    171205
    172     thread_t * this = CURRENT_THREAD;
    173 
    174     // get condvar cluster an local pointer
    175     remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
    176     cxy_t              condvar_cxy = GET_CXY( condvar_xp );
    177 
    178     // get extended pointer on condvar waiting queue
    179     xptr_t root_xp  = XPTR( condvar_cxy , &condvar_ptr->root );
    180 
    181     // get extended pointer on calling thread xlist_entry
    182     xptr_t entry_xp = XPTR( local_cxy , &this->wait_list );
    183 
    184     // register the calling thread in the condvar waiting queue
    185     remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    186     xlist_add_last( root_xp , entry_xp );
    187     remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    188 
    189     // block the calling thread
    190     thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_USERSYNC );
     206    // deschedule
    191207    sched_yield("blocked on condvar");
    192208
    193     // lock the mutex before return
    194     remote_mutex_unlock( mutex_xp );
     209    // re-acquire the mutex
     210    remote_mutex_lock( mutex_xp );
    195211
    196212}  // end remote_condvar_wait()
     
    199215void remote_condvar_signal( xptr_t condvar_xp )
    200216{
    201     reg_t     irq_state;
    202 
    203     // get condvar cluster an local pointer
    204     remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
    205     cxy_t              condvar_cxy = GET_CXY( condvar_xp );
    206 
    207     // get extended pointer on condvar waiting queue
    208     xptr_t root_xp  = XPTR( condvar_cxy , &condvar_ptr->root );
    209 
    210     if( xlist_is_empty( root_xp ) ) return;
    211 
    212     // disable interrupts
    213         hal_disable_irq( &irq_state );
    214  
    215     // get extended pointer on the first waiting thread
    216     xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
    217 
    218     // remove the first waiting thread from queue
    219     remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    220     xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) );
    221     remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    222 
    223     // unblock first waiting thread
    224     thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC );
    225 
    226     // restore interrupts
    227         hal_restore_irq( irq_state );
     217    // get condvar cluster and local pointer
     218    remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp );
     219    cxy_t              condvar_cxy = GET_CXY( condvar_xp );
     220
     221    // does nothing if waiting queue empty
     222    if( xlist_is_empty( XPTR( condvar_cxy, &condvar_ptr->root ) ) == false )
     223    {
     224         // get first waiting thread
     225         xptr_t thread_xp = XLIST_FIRST( XPTR( condvar_cxy , &condvar_ptr->root ),
     226                                         thread_t , wait_xlist );
     227
     228         // remove this waiting thread from queue
     229         thread_t * thread_ptr = GET_PTR( thread_xp );
     230         cxy_t      thread_cxy = GET_CXY( thread_xp );
     231         xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
     232
     233         // unblock this waiting thread
     234         thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC );
     235    }
    228236
    229237}  // end remote_condvar_signal()
     
    232240void remote_condvar_broadcast( xptr_t condvar_xp )
    233241{
    234     reg_t    irq_state;
    235 
    236     // get condvar cluster an local pointer
    237     remote_condvar_t * condvar_ptr = (remote_condvar_t *)GET_PTR( condvar_xp );
    238     cxy_t              condvar_cxy = GET_CXY( condvar_xp );
    239 
    240     // get extended pointer on condvar waiting queue
    241     xptr_t root_xp  = XPTR( condvar_cxy , &condvar_ptr->root );
    242 
    243     if( xlist_is_empty( root_xp ) ) return;
    244 
    245     // disable interrupts
    246     hal_disable_irq( &irq_state );
    247  
    248     // loop on waiting threads
    249     xptr_t  iter_xp;
    250     xptr_t  thread_xp;
    251     XLIST_FOREACH( root_xp , iter_xp )
    252     {
    253         // get extended pointer on waiting thread
    254         thread_xp = XLIST_ELEMENT( iter_xp , thread_t , wait_list );
    255        
    256         // remove waiting thread from queue
    257         remote_spinlock_lock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    258         xlist_unlink( XPTR( condvar_cxy , &condvar_ptr->list ) );
    259         remote_spinlock_unlock( XPTR( condvar_cxy , &condvar_ptr->lock ) );
    260 
    261         // unblock waiting thread
    262         thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC );
    263     }
    264 
    265     // restore interrupts
    266     hal_restore_irq( irq_state );
    267 
     242    // get condvar cluster and local pointer
     243    remote_condvar_t * condvar_ptr = GET_PTR( condvar_xp );
     244    cxy_t              condvar_cxy = GET_CXY( condvar_xp );
     245
     246    // does nothing if waiting queue empty
     247    while( xlist_is_empty( XPTR( condvar_cxy , &condvar_ptr->root ) ) == false )
     248    {
     249         // get first waiting thread
     250         xptr_t thread_xp = XLIST_FIRST( XPTR( condvar_cxy , &condvar_ptr->root ),
     251                                         thread_t , wait_xlist );
     252
     253         // remove this waiting thread from queue
     254         thread_t * thread_ptr = GET_PTR( thread_xp );
     255         cxy_t      thread_cxy = GET_CXY( thread_xp );
     256         xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
     257
     258         // unblock this waiting thread
     259         thread_unblock( thread_xp , THREAD_BLOCKED_USERSYNC );
     260    }
    268261}  // end remote_condvar_broadcast()
     262
Note: See TracChangeset for help on using the changeset viewer.