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

Last change on this file since 337 was 337, checked in by alain, 9 years ago

Introduce the delayed context switch if current thread has a lock.

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 = (remote_rwlock_t *)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 hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
43}
44
45//////////////////////////////////////////////
46void remote_rwlock_rd_lock( xptr_t lock_xp )
47{
48 reg_t mode;
49 uint32_t ticket;
50
51 // get cluster and local pointer on remote_rwlock
52 remote_rwlock_t * lock_ptr = (remote_rwlock_t *)GET_PTR( lock_xp );
53 cxy_t lock_cxy = GET_CXY( lock_xp );
54
55 // get cluster and local pointer on local thread
56 thread_t * thread_ptr = CURRENT_THREAD;
57
58 // extended pointers on ticket, current, count
59 xptr_t ticket_xp = XPTR( lock_cxy , &lock_ptr->ticket );
60 xptr_t current_xp = XPTR( lock_cxy , &lock_ptr->current );
61 xptr_t count_xp = XPTR( lock_cxy , &lock_ptr->count );
62
63 // disable interrupts
64 hal_disable_irq( &mode );
65
66 // get next free ticket
67 ticket = hal_remote_atomic_add( ticket_xp , 1 );
68
69 // busy waiting loop to take the lock
70 while( ticket != hal_remote_lw( current_xp ) )
71 {
72 hal_fixed_delay( CONFIG_RWLOCK_DELAY );
73 }
74
75 ////////// From here we have the lock ////////////
76
77 // increment count
78 hal_remote_atomic_add( count_xp , 1 );
79
80 // increment thread.remote_locks
81 thread_ptr->remote_locks++;
82
83 // sync
84 hal_fence();
85
86 // release lock to allow several simultaneous readers
87 hal_remote_atomic_add( current_xp , 1 );
88
89 // enable interrupts
90 hal_restore_irq( mode );
91
92} // end remote_rwlock_rd_lock()
93
94////////////////////////////////////////////////
95void remote_rwlock_rd_unlock( xptr_t lock_xp )
96{
97 reg_t mode;
98
99 // get cluster and local pointer on remote_rwlock
100 remote_rwlock_t * lock_ptr = (remote_rwlock_t *)GET_PTR( lock_xp );
101 cxy_t lock_cxy = GET_CXY( lock_xp );
102
103 // get cluster and local pointer on local thread
104 thread_t * thread_ptr = CURRENT_THREAD;
105
106 // extended pointers on lock->count
107 xptr_t count_xp = XPTR( lock_cxy , &lock_ptr->count );
108
109 // disable interrupts
110 hal_disable_irq( &mode );
111
112 // decrement count
113 hal_remote_atomic_add( count_xp , -1 );
114
115 // decrement thread.remote_locks
116 thread_ptr->remote_locks--;
117
118 // enable interrupts
119 hal_restore_irq( mode );
120
121 // deschedule if pending request
122 thread_check_sched();
123
124} // end remote_rwlock_rd_unlock()
125
126//////////////////////////////////////////////
127void remote_rwlock_wr_lock( xptr_t lock_xp )
128{
129 reg_t mode;
130 uint32_t ticket;
131
132 // get cluster and local pointer on remote_rwlock
133 remote_rwlock_t * lock_ptr = (remote_rwlock_t *)GET_PTR( lock_xp );
134 cxy_t lock_cxy = GET_CXY( lock_xp );
135
136 // get cluster and local pointer on local thread
137 cxy_t thread_cxy = local_cxy;
138 thread_t * thread_ptr = CURRENT_THREAD;
139
140 // compute extended pointers on lock->ticket, lock->owner
141 xptr_t ticket_xp = XPTR( lock_cxy , &lock_ptr->ticket );
142 xptr_t count_xp = XPTR( lock_cxy , &lock_ptr->count );
143 xptr_t current_xp = XPTR( lock_cxy , &lock_ptr->current );
144 xptr_t owner_xp = XPTR( lock_cxy , &lock_ptr->owner );
145 xptr_t thread_xp = XPTR( thread_cxy , thread_ptr );
146
147 // disable interrupts
148 hal_disable_irq( &mode );
149
150 // get next free ticket
151 ticket = hal_remote_atomic_add( ticket_xp , 1 );
152
153 // loop to take the lock
154 while( ticket != hal_remote_lw( current_xp ) )
155 {
156 hal_fixed_delay( CONFIG_RWLOCK_DELAY );
157 }
158
159 ////////// From here we have the lock ////////////
160
161 // wait completion of read accesses
162 while( hal_remote_lw( count_xp ) != 0 )
163 {
164 hal_fixed_delay( CONFIG_RWLOCK_DELAY );
165 }
166
167 // register owner thread
168 hal_remote_swd( owner_xp , thread_xp );
169
170 // increment thread.remote_locks
171 thread_ptr->remote_locks++;
172
173 // enable interrupts
174 hal_restore_irq( mode );
175
176} // end remote_rwlock_wr_lock()
177
178//////////////////////////////////////////////
179void remote_rwlock_wr_unlock( xptr_t lock_xp )
180{
181 reg_t mode;
182
183 // get cluster and local pointer on remote_rwlock
184 remote_rwlock_t * lock_ptr = (remote_rwlock_t *)GET_PTR( lock_xp );
185 cxy_t lock_cxy = GET_CXY( lock_xp );
186
187 // get cluster and local pointer on local thread
188 thread_t * thread_ptr = CURRENT_THREAD;
189
190 // compute extended pointers on lock->ticket, lock->owner
191 xptr_t current_xp = XPTR( lock_cxy , &lock_ptr->current );
192 xptr_t owner_xp = XPTR( lock_cxy , &lock_ptr->owner );
193
194 // disable interrupts
195 hal_disable_irq( &mode );
196
197 // unregister owner thread, and release lock
198 hal_remote_swd( owner_xp , XPTR_NULL );
199 hal_remote_atomic_add( current_xp , 1 );
200
201 // decrement thread.remote_locks
202 thread_ptr->remote_locks--;
203
204 // enable interrupts
205 hal_restore_irq( mode );
206
207 // deschedule if pending request
208 thread_check_sched();
209
210} // end remote_rwlock_wr_unlock()
211
212///////////////////////////////////////////
213void remote_rwlock_print( xptr_t lock_xp,
214 char * comment )
215{
216 uint32_t ticket; // first free ticket index
217 uint32_t current; // ticket index of current owner
218 uint32_t count; // current number of reader threads
219 xptr_t owner; // extended pointer on writer thread
220
221 // get cluster and local pointer on remote_rwlock
222 remote_rwlock_t * lock_ptr = (remote_rwlock_t *)GET_PTR( lock_xp );
223 cxy_t lock_cxy = GET_CXY( lock_xp );
224
225 ticket = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->ticket ) );
226 current = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->current ) );
227 count = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->count ) );
228 owner = hal_remote_lwd( XPTR( lock_cxy , &lock_ptr->owner ) );
229
230 printk("\n*** rwlock <%l> %s : ticket = %d / current = %d / count = %d / owner = %l\n",
231 lock_xp , comment , ticket , current , count , owner );
232
233} // end remote_rwlock_print()
234
Note: See TracBrowser for help on using the repository browser.