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

Last change on this file since 457 was 457, checked in by alain, 8 years ago

This version modifies the exec syscall and fixes a large number of small bugs.
The version number has been updated (0.1)

File size: 7.4 KB
Line 
1/*
2 * remote_rwlock.c - kernel remote rwlock implementation.
3 *
4 * Authors Alain Greiner (2016,2017,2018)
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_kernel_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 DEBUG_REMOTE_RWLOCKS
44hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
45xlist_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 DEBUG_REMOTE_RWLOCKS
89xlist_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 DEBUG_REMOTE_RWLOCKS
129xlist_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 DEBUG_REMOTE_RWLOCKS
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 ) );
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
212hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
213xlist_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.