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

Last change on this file since 434 was 433, checked in by alain, 7 years ago

blip

File size: 7.4 KB
Line 
1/*
2 * remote_rwlock.c - kernel remote rwlock implementation.
3 *
4 * Authors    Alain   Greiner (2016,2017)
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>
28#include <printk.h>
29#include <cluster.h>
30#include <scheduler.h>
31#include <remote_rwlock.h>
32
33///////////////////////////////////////////
34void remote_rwlock_init( xptr_t lock_xp )
35{ 
36    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
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 );
42
43#if CONFIG_DEBUG_LOCKS
44    hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner )   , XPTR_NULL );
45    xlist_entry_init( XPTR( lock_cxy , &lock_ptr->list ) );
46#endif
47
48}
49
50//////////////////////////////////////////////
51void remote_rwlock_rd_lock( xptr_t lock_xp )
52{ 
53        reg_t      mode;
54    uint32_t   ticket;
55
56    // get cluster and local pointer on remote_rwlock
57    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
58    cxy_t             lock_cxy = GET_CXY( lock_xp );
59
60    // get local pointer on local thread
61    thread_t          * thread_ptr = CURRENT_THREAD;
62
63    // extended pointers on ticket, current, count
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
72    ticket = hal_remote_atomic_add( ticket_xp , 1 );
73
74    // busy waiting loop to take the lock
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
82    // increment count
83    hal_remote_atomic_add( count_xp , 1 );
84
85    // increment thread.remote_locks
86    thread_ptr->remote_locks++;
87
88#if CONFIG_DEBUG_LOCKS
89    xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
90                     XPTR( lock_cxy ,  &lock_ptr->list ) );
91#endif
92
93    // sync
94    hal_fence();
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{
107        reg_t               mode;
108
109    // get cluster and local pointer on remote_rwlock
110    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
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
116    // extended pointers on lock->count
117    xptr_t              count_xp = XPTR( lock_cxy   , &lock_ptr->count );
118
119    // disable interrupts
120        hal_disable_irq( &mode );
121 
122    // decrement count
123    hal_remote_atomic_add( count_xp , -1 );
124
125    // decrement thread.remote_locks
126        thread_ptr->remote_locks--;
127
128#if CONFIG_DEBUG_LOCKS
129    xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
130#endif
131
132    // enable interrupts
133        hal_restore_irq( mode );
134   
135    // deschedule if pending request
136    thread_check_sched();
137
138}  // end remote_rwlock_rd_unlock()
139
140//////////////////////////////////////////////
141void remote_rwlock_wr_lock( xptr_t lock_xp )
142{ 
143        reg_t      mode;
144    uint32_t   ticket;
145
146    // get cluster and local pointer on remote_rwlock
147    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
148    cxy_t             lock_cxy = GET_CXY( lock_xp );
149
150    // get local pointer on local thread
151    thread_t          * thread_ptr = CURRENT_THREAD;
152
153    // compute extended pointers on lock->ticket, lock->owner
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
162    ticket = hal_remote_atomic_add( ticket_xp , 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
178#if CONFIG_DEBUG_LOCKS
179    hal_remote_swd( XPTR( lock_cxy  , &lock_ptr->owner ) ,
180                    XPTR( local_cxy , thread_ptr ) );
181    xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
182                     XPTR( lock_cxy  , &lock_ptr->list ) );
183#endif   
184
185    // increment thread.remote_locks
186    thread_ptr->remote_locks++;
187
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{
196        reg_t               mode;
197
198    // get cluster and local pointer on remote_rwlock
199    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
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
205    // compute extended pointer on lock->ticket
206    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
207
208    // disable interrupts
209        hal_disable_irq( &mode );
210 
211#if CONFIG_LOCKS_OWNER
212    hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
213    xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
214#endif
215
216    // release lock
217    hal_remote_atomic_add( current_xp , 1 );
218
219    // decrement thread.remote_locks
220        thread_ptr->remote_locks--;
221
222    // enable interrupts
223        hal_restore_irq( mode );
224   
225    // deschedule if pending request
226    thread_check_sched();
227
228}  // end remote_rwlock_wr_unlock()
229
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
237
238    // get cluster and local pointer on remote_rwlock
239    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
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
246    printk("\n*** rwlock <%l> %s : ticket = %d / current = %d / count = %d\n",
247           lock_xp , comment , ticket , current , count ); 
248
249}  // end remote_rwlock_print()
250
Note: See TracBrowser for help on using the repository browser.