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

Complete restructuration of kernel spinlocks.

File:
1 edited

Legend:

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

    r469 r563  
    11/*
    2  * remote_sem.c - Kernel function implementing the semaphore related syscalls.
     2 * remote_sem.c - POSIX unnamed semaphore implementation.
    33 *
    4  * Author   Alain Greiner  (2016)
     4 * Author   Alain Greiner  (2016,2017,2018)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    3333
    3434///////////////////////////////////////////////
    35 xptr_t remote_sem_from_vaddr( intptr_t  vaddr )
     35xptr_t remote_sem_from_ident( intptr_t  ident )
    3636{
    3737    // get pointer on local process_descriptor
     
    4545    process_t    * ref_ptr = GET_PTR( ref_xp );
    4646
    47     // get extended pointer on root of semaphores list
     47    // get extended pointer on semaphores list
    4848    xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root );
     49    xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock );
    4950   
     51    // get lock protecting synchro lists
     52    remote_queuelock_acquire( lock_xp );
     53 
    5054    // scan reference process semaphores list
    5155    xptr_t         iter_xp;
     
    5357    cxy_t          sem_cxy;
    5458    remote_sem_t * sem_ptr;
    55     intptr_t       ident;
     59    intptr_t       current;
    5660    bool_t         found = false;
    5761           
     
    6165        sem_cxy = GET_CXY( sem_xp );
    6266        sem_ptr = GET_PTR( sem_xp );
    63         ident  = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) );   
    64 
    65         if( ident == vaddr )
     67        current = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) );   
     68
     69        if( current == ident )
    6670        {
    6771            found = true;
     
    7074    }
    7175
     76    // relese lock protecting synchros lists
     77    remote_queuelock_release( lock_xp );
     78 
    7279    if( found == false )  return XPTR_NULL;
    7380    else                  return sem_xp;
    7481
    75 }  // end remote_sem_from_vaddr()
     82}  // end remote_sem_from_ident()
    7683
    7784///////////////////////////////////////////
    7885error_t remote_sem_create( intptr_t   vaddr,
    79                            uint32_t   value,
    80                            xptr_t     sem_xp_xp )
     86                           uint32_t   value )
    8187{
    8288    remote_sem_t * sem_ptr;
     
    108114    }
    109115
    110     if( sem_xp == XPTR_NULL ) return -1;
     116    if( sem_xp == XPTR_NULL ) return 0xFFFFFFFF;
    111117
    112118    // initialise semaphore
    113     hal_remote_sw ( XPTR( ref_cxy , &sem_ptr->count ) , value );
     119    hal_remote_s32 ( XPTR( ref_cxy , &sem_ptr->count ) , value );
    114120        hal_remote_spt( XPTR( ref_cxy , &sem_ptr->ident ) , (void *)vaddr );
    115     remote_spinlock_init( XPTR( ref_cxy , &sem_ptr->lock ) );
    116121        xlist_root_init( XPTR( ref_cxy , &sem_ptr->root ) );
    117122        xlist_entry_init( XPTR( ref_cxy , &sem_ptr->list ) );
    118 
    119     // register semaphore in reference process xlist
     123    remote_busylock_init( XPTR( ref_cxy , &sem_ptr->lock ), LOCK_SEM_STATE );
     124
    120125    xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root );
    121     xptr_t xp_list = XPTR( ref_cxy , &sem_ptr->list );
    122     remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    123     xlist_add_first( root_xp , xp_list );
    124     remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    125 
    126     // write extended pointer on semaphore in calling thread buffer
    127     hal_remote_swd( sem_xp_xp , sem_xp );
     126    xptr_t list_xp = XPTR( ref_cxy , &sem_ptr->list );
     127
     128    // get lock protecting user synchro lists
     129    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     130
     131    // register semaphore in reference process list of semaphores
     132    xlist_add_first( root_xp , list_xp );
     133
     134    // release lock protecting user synchro lists
     135    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     136
     137#if DEBUG_SEM
     138thread_t * this = CURRENT_THREAD;
     139if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
     140printk("\n[DBG] %s : thread %x in process %x INITIALIZE sem(%x,%x) / value %d\n",
     141__FUNCTION__, this->trdid, this->process->pid, local_cxy, sem_ptr, value );
     142#endif
    128143
    129144    return 0;
    130145
    131 }  // en remote_sem_create()
     146}  // end remote_sem_create()
    132147 
    133148////////////////////////////////////////
     
    146161    // get semaphore cluster and local pointer
    147162    cxy_t          sem_cxy = GET_CXY( sem_xp );
    148     remote_sem_t * sem_ptr = (remote_sem_t *)GET_PTR( sem_xp );
    149 
    150     // get lock protecting semaphore
    151     remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
    152  
     163    remote_sem_t * sem_ptr = GET_PTR( sem_xp );
     164
    153165    // get remote pointer on waiting queue root
    154166    xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root );
     
    161173    }
    162174
    163     // reset semaphore count
    164     hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , 0 );
    165 
    166175    // remove semaphore from reference process xlist
    167     remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     176    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    168177    xlist_unlink( XPTR( sem_cxy , &sem_ptr->list ) );
    169     remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    170 
    171     // release lock
    172     remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
     178    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
    173179
    174180    // release memory allocated for semaphore descriptor
     
    190196void remote_sem_wait( xptr_t sem_xp )
    191197{
     198    thread_t * this = CURRENT_THREAD;
     199
     200// check calling thread can yield
     201assert( (this->busylocks == 0),
     202"cannot yield : busylocks = %d\n", this->busylocks );
     203
     204
    192205    // get semaphore cluster and local pointer
    193206    cxy_t          sem_cxy = GET_CXY( sem_xp );
    194207    remote_sem_t * sem_ptr = GET_PTR( sem_xp );
    195208
    196     // get lock protecting semaphore     
    197         remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
     209    // get extended pointers on sem fields
     210    xptr_t           count_xp = XPTR( sem_cxy , &sem_ptr->count );
     211    xptr_t           root_xp  = XPTR( sem_cxy , &sem_ptr->root );
     212    xptr_t           lock_xp  = XPTR( sem_cxy , &sem_ptr->lock );
     213
     214    while( 1 )
     215    {
     216        // get busylock protecting semaphore     
     217            remote_busylock_acquire( lock_xp );
    198218 
    199     // get semaphore current value
    200     uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
    201 
    202         if( count > 0 )       // success
    203         {
    204         // decrement semaphore value
    205         hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count - 1 );
    206 
    207         // release lock
    208             remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
    209         }
    210         else                 // failure
    211         {
    212         thread_t * this = CURRENT_THREAD;
    213 
    214         // register thread in waiting queue
    215         xptr_t root_xp = XPTR( sem_cxy   , &sem_ptr->root );
    216         xptr_t list_xp = XPTR( local_cxy , &this->wait_list );
    217                 xlist_add_last( root_xp , list_xp );
    218 
    219         // release lock
    220             remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
    221 
    222         // block and deschedule
    223         thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_SEM ); 
    224         sched_yield("blocked on semaphore");
     219        // get semaphore current value
     220        uint32_t count = hal_remote_l32( count_xp );
     221
     222            if( count > 0 )                     // success
     223            {
     224            // decrement semaphore value
     225            hal_remote_s32( count_xp , count - 1 );
     226
     227#if DEBUG_SEM
     228if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
     229printk("\n[DBG] %s : thread %x in process %x DECREMENT sem(%x,%x) / value %d\n",
     230__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count-1 );
     231#endif
     232            // release busylock protecting semaphore
     233                remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
     234
     235            return;
     236        }
     237            else                               // failure
     238            {
     239            // get cluster and pointers on calling thread
     240            cxy_t            caller_cxy = local_cxy;
     241            thread_t       * caller_ptr = CURRENT_THREAD;
     242            xptr_t           caller_xp  = XPTR( caller_cxy , caller_ptr );
     243
     244            // block the calling thread
     245            thread_block( caller_xp , THREAD_BLOCKED_SEM ); 
     246
     247            // register calling thread in waiting queue
     248            xptr_t entry_xp = XPTR( caller_cxy , &caller_ptr->wait_xlist );
     249                    xlist_add_last( root_xp , entry_xp );
     250
     251#if DEBUG_SEM
     252if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
     253printk("\n[DBG] %s : thread %x in process %x BLOCK on sem(%x,%x) / value %d\n",
     254__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count );
     255#endif
     256            // release busylock protecting semaphore
     257                remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
     258
     259            // deschedule calling thread
     260            sched_yield("blocked on semaphore");
     261        }
    225262        }
    226263}  // end remote_sem_wait()
     
    229266void remote_sem_post( xptr_t sem_xp )
    230267{
     268    // memory barrier before sem release
     269    hal_fence();
     270
    231271    // get semaphore cluster and local pointer
    232272    cxy_t          sem_cxy = GET_CXY( sem_xp );
    233273    remote_sem_t * sem_ptr = GET_PTR( sem_xp );
    234274
    235     // get lock protecting semaphore
    236         remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
     275    // get extended pointers on sem fields
     276    xptr_t           count_xp = XPTR( sem_cxy , &sem_ptr->count );
     277    xptr_t           root_xp  = XPTR( sem_cxy , &sem_ptr->root );
     278    xptr_t           lock_xp  = XPTR( sem_cxy , &sem_ptr->lock );
     279
     280    // get busylock protecting semaphore
     281        remote_busylock_acquire( lock_xp );
    237282 
    238     // get semaphore current value
    239     uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
    240 
    241     // get remote pointer on waiting queue root
    242     xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root );
    243  
    244         if( xlist_is_empty( root_xp ) )   // no waiting thread
    245     {
    246         // increment semaphore value
    247         hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count + 1 );
    248     }
    249     else
     283    // increment semaphore value
     284    hal_remote_atomic_add( count_xp , 1 );
     285
     286#if DEBUG_SEM
     287uint32_t count = hal_remote_l32( count_xp );
     288thread_t * this = CURRENT_THREAD;
     289if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
     290printk("\n[DBG] %s : thread %x in process %x INCREMENT sem(%x,%x) / value %d\n",
     291__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count );
     292#endif
     293
     294    // scan waiting queue to unblock all waiting threads
     295        while( xlist_is_empty( root_xp ) == false )   // waiting queue non empty
    250296    {
    251297        // get first waiting thread from queue
    252         xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
    253 
    254         // get thread cluster and local poiner
     298        xptr_t     thread_xp  = XLIST_FIRST( root_xp , thread_t , wait_xlist );
    255299        cxy_t      thread_cxy = GET_CXY( thread_xp );
    256300        thread_t * thread_ptr = GET_PTR( thread_xp );
    257301
    258         // remove this thread from the waiting queue, and unblock it
    259         xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_list ) );
     302        // remove this thread from the waiting queue
     303        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
     304
     305        // unblock this waiting thread
    260306                thread_unblock( thread_xp , THREAD_BLOCKED_SEM );
    261     }
    262 
    263     // release lock
    264         remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
     307
     308#if DEBUG_SEM
     309if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
     310{
     311trdid_t     trdid   = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
     312process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) );
     313pid_t       pid     = hal_remote_l32( XPTR( thread_cxy , &process->pid ) );
     314printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %x / sem(%x,%x)\n",
     315__FUNCTION__, this->trdid, this->process->pid, trdid, pid, sem_cxy, sem_ptr );
     316}
     317#endif
     318
     319    }
     320
     321    // release busylock protecting the semaphore
     322        remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
    265323
    266324}  // end remote_sem_post()
     
    275333    remote_sem_t * sem_ptr = GET_PTR( sem_xp );
    276334
    277     *data = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
     335    *data = hal_remote_l32( XPTR( sem_cxy , &sem_ptr->count ) );
    278336
    279337}  // end remote_sem_get_value()
Note: See TracChangeset for help on using the changeset viewer.