source: trunk/kernel/libk/remote_rwlock.c @ 442

Last change on this file since 442 was 438, checked in by alain, 7 years ago

Fix a bug in scheduler related to RPC blocking.

File size: 7.4 KB
RevLine 
[1]1/*
2 * remote_rwlock.c - kernel remote rwlock implementation.
3 *
[436]4 * Authors    Alain   Greiner (2016,2017,2018)
[1]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 <hal_types.h>
25#include <hal_remote.h>
26#include <hal_irqmask.h>
27#include <thread.h>
[50]28#include <printk.h>
[1]29#include <cluster.h>
30#include <scheduler.h>
31#include <remote_rwlock.h>
32
33///////////////////////////////////////////
34void remote_rwlock_init( xptr_t lock_xp )
35{ 
[423]36    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[1]37    cxy_t             lock_cxy = GET_CXY( lock_xp );
38
39    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->ticket )  , 0 );
40    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->current ) , 0 );
41    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->count )   , 0 );
[409]42
[438]43#if DEBUG_REMOTE_RWLOCKS
[436]44hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner )   , XPTR_NULL );
45xlist_entry_init( XPTR( lock_cxy , &lock_ptr->list ) );
[409]46#endif
47
[1]48}
49
50//////////////////////////////////////////////
51void remote_rwlock_rd_lock( xptr_t lock_xp )
52{ 
[60]53        reg_t      mode;
[1]54    uint32_t   ticket;
55
56    // get cluster and local pointer on remote_rwlock
[423]57    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[1]58    cxy_t             lock_cxy = GET_CXY( lock_xp );
59
[409]60    // get local pointer on local thread
[1]61    thread_t          * thread_ptr = CURRENT_THREAD;
62
[318]63    // extended pointers on ticket, current, count
[1]64    xptr_t              ticket_xp  = XPTR( lock_cxy   , &lock_ptr->ticket );
65    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
66    xptr_t              count_xp   = XPTR( lock_cxy   , &lock_ptr->count );
67
68    // disable interrupts
69    hal_disable_irq( &mode );
70
71    // get next free ticket
[23]72    ticket = hal_remote_atomic_add( ticket_xp , 1 );
[1]73
[23]74    // busy waiting loop to take the lock
[1]75        while( ticket != hal_remote_lw( current_xp ) )
76        {
77        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
78        }
79
80    ////////// From here we have the lock  ////////////
81
[318]82    // increment count
[1]83    hal_remote_atomic_add( count_xp , 1 );
84
[318]85    // increment thread.remote_locks
86    thread_ptr->remote_locks++;
87
[438]88#if DEBUG_REMOTE_RWLOCKS
[436]89xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
90                 XPTR( lock_cxy ,  &lock_ptr->list ) );
[409]91#endif
92
[1]93    // sync
[124]94    hal_fence();
[1]95
96    // release lock to allow several simultaneous readers
97    hal_remote_atomic_add( current_xp , 1 );
98
99    // enable interrupts
100        hal_restore_irq( mode );
101
102}  // end remote_rwlock_rd_lock()
103
104////////////////////////////////////////////////
105void remote_rwlock_rd_unlock( xptr_t lock_xp )
106{
[60]107        reg_t               mode;
[1]108
109    // get cluster and local pointer on remote_rwlock
[423]110    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[1]111    cxy_t             lock_cxy = GET_CXY( lock_xp );
112
113    // get cluster and local pointer on local thread
114    thread_t          * thread_ptr = CURRENT_THREAD;
115
[318]116    // extended pointers on lock->count
[1]117    xptr_t              count_xp = XPTR( lock_cxy   , &lock_ptr->count );
118
119    // disable interrupts
120        hal_disable_irq( &mode );
121 
[318]122    // decrement count
[1]123    hal_remote_atomic_add( count_xp , -1 );
124
[318]125    // decrement thread.remote_locks
126        thread_ptr->remote_locks--;
127
[438]128#if DEBUG_REMOTE_RWLOCKS
[436]129xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
[409]130#endif
131
[1]132    // enable interrupts
133        hal_restore_irq( mode );
[337]134   
135    // deschedule if pending request
136    thread_check_sched();
[1]137
138}  // end remote_rwlock_rd_unlock()
139
140//////////////////////////////////////////////
141void remote_rwlock_wr_lock( xptr_t lock_xp )
142{ 
[60]143        reg_t      mode;
[1]144    uint32_t   ticket;
145
146    // get cluster and local pointer on remote_rwlock
[423]147    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[1]148    cxy_t             lock_cxy = GET_CXY( lock_xp );
149
[409]150    // get local pointer on local thread
[1]151    thread_t          * thread_ptr = CURRENT_THREAD;
152
[318]153    // compute extended pointers on lock->ticket, lock->owner
[1]154    xptr_t              ticket_xp  = XPTR( lock_cxy   , &lock_ptr->ticket );
155    xptr_t              count_xp   = XPTR( lock_cxy   , &lock_ptr->count );
156    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
157
158    // disable interrupts
159    hal_disable_irq( &mode );
160
161    // get next free ticket
[23]162    ticket = hal_remote_atomic_add( ticket_xp , 1 );
[1]163
164    // loop to take the lock
165        while( ticket != hal_remote_lw( current_xp ) )
166        {
167        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
168        }
169
170    ////////// From here we have the lock  ////////////
171
172    // wait completion of read accesses
173    while( hal_remote_lw( count_xp ) != 0 )
174    {
175        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
176    }
177
[438]178#if DEBUG_REMOTE_RWLOCKS
[436]179hal_remote_swd( XPTR( lock_cxy  , &lock_ptr->owner ) ,
180                XPTR( local_cxy , thread_ptr ) );
181xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
182                 XPTR( lock_cxy  , &lock_ptr->list ) );
[409]183#endif   
[1]184
[318]185    // increment thread.remote_locks
186    thread_ptr->remote_locks++;
187
[1]188    // enable interrupts
189        hal_restore_irq( mode );
190
191}  // end remote_rwlock_wr_lock()
192
193//////////////////////////////////////////////
194void remote_rwlock_wr_unlock( xptr_t lock_xp )
195{
[60]196        reg_t               mode;
[1]197
198    // get cluster and local pointer on remote_rwlock
[423]199    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[1]200    cxy_t             lock_cxy = GET_CXY( lock_xp );
201
202    // get cluster and local pointer on local thread
203    thread_t          * thread_ptr = CURRENT_THREAD;
204
[409]205    // compute extended pointer on lock->ticket
[50]206    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
[1]207
208    // disable interrupts
209        hal_disable_irq( &mode );
210 
[409]211#if CONFIG_LOCKS_OWNER
[436]212hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
213xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
[409]214#endif
215
216    // release lock
[1]217    hal_remote_atomic_add( current_xp , 1 );
218
[318]219    // decrement thread.remote_locks
220        thread_ptr->remote_locks--;
221
[1]222    // enable interrupts
223        hal_restore_irq( mode );
[337]224   
225    // deschedule if pending request
226    thread_check_sched();
[1]227
228}  // end remote_rwlock_wr_unlock()
229
[50]230///////////////////////////////////////////
231void remote_rwlock_print( xptr_t   lock_xp,
232                          char   * comment )
233{
234    uint32_t     ticket;                // first free ticket index
235    uint32_t     current;               // ticket index of current owner
236    uint32_t     count;                 // current number of reader threads
[1]237
[50]238    // get cluster and local pointer on remote_rwlock
[423]239    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
[50]240    cxy_t             lock_cxy = GET_CXY( lock_xp );
241
242    ticket  = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->ticket ) );
243    current = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->current ) );
244    count   = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->count ) );
245
[409]246    printk("\n*** rwlock <%l> %s : ticket = %d / current = %d / count = %d\n",
247           lock_xp , comment , ticket , current , count ); 
[50]248
249}  // end remote_rwlock_print()
250
Note: See TracBrowser for help on using the repository browser.