f1795131f86bb064e6824fdb3a0fcd053256d821
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_rwlock_rdlock.S
1 /* Copyright (C) 2003, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <sysdep.h>
20 #include <lowlevelrwlock.h>
21 #include <pthread-errnos.h>
22 #include <tcb-offsets.h>
23 #include <kernel-features.h>
24 #include "lowlevel-atomic.h"
25
26 #define SYS_futex               240
27 #define FUTEX_WAIT              0
28 #define FUTEX_WAKE              1
29 #define FUTEX_PRIVATE_FLAG      128
30
31
32         .text
33
34         .globl  __pthread_rwlock_rdlock
35         .type   __pthread_rwlock_rdlock,@function
36         .align  5
37 __pthread_rwlock_rdlock:
38         mov.l   r12, @-r15
39         mov.l   r9, @-r15
40         mov.l   r8, @-r15
41         sts.l   pr, @-r15
42         mov     r4, r8
43
44         /* Get the lock.  */
45         mov     #0, r3
46         mov     #1, r4
47 #if MUTEX == 0
48         CMPXCHG (r3, @r8, r4, r2)
49 #else
50         CMPXCHG (r3, @(MUTEX,r8), r4, r2)
51 #endif
52         bf      1f
53 2:
54         mov.l   @(WRITER,r8), r0
55         tst     r0, r0
56         bf      14f
57         mov.l   @(WRITERS_QUEUED,r8), r0
58         tst     r0, r0
59         bt      5f
60         mov     #FLAGS, r0
61         mov.b   @(r0,r8), r0
62         tst     r0, r0
63         bt      5f
64 3:
65         mov.l   @(READERS_QUEUED,r8), r0
66         add     #1, r0
67         mov.l   r0, @(READERS_QUEUED,r8)
68         tst     r0, r0
69         bt      4f
70
71         mov.l   @(READERS_WAKEUP,r8), r9
72
73 #if MUTEX == 0
74         DEC (@r8, r2)
75 #else
76         DEC (@(MUTEX,r8), r2)
77 #endif
78         tst     r2, r2
79         bf      10f
80 11:
81 #if __ASSUME_PRIVATE_FUTEX
82         mov     #PSHARED, r0
83         mov.b   @(r0,r8), r5
84         mov     #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0
85         xor     r0, r5
86         extu.b  r5, r5
87 #else
88         mov     #PSHARED, r0
89         mov.b   @(r0,r8), r5
90         extu.b  r5, r5
91 # if FUTEX_WAIT != 0
92         mov     #FUTEX_WAIT, r0
93         or      r0, r5
94 # endif
95         stc     gbr, r1
96         mov.w   .Lpfoff, r2
97         add     r2, r1
98         mov.l   @r1, r0
99         xor     r0, r5
100 #endif
101         mov     r8, r4
102         add     #READERS_WAKEUP, r4
103         mov     r9, r6
104         mov     #0, r7
105         mov     #SYS_futex, r3
106         extu.b  r3, r3
107         trapa   #0x14
108         SYSCALL_INST_PAD
109
110         /* Reget the lock.  */
111         mov     #0, r3
112         mov     #1, r4
113 #if MUTEX == 0
114         CMPXCHG (r3, @r8, r4, r2)
115 #else
116         CMPXCHG (r3, @(MUTEX,r8), r4, r2)
117 #endif
118         bf      12f
119 13:
120         mov.l   @(READERS_QUEUED,r8), r0
121         add     #-1, r0
122         bra     2b
123          mov.l  r0, @(READERS_QUEUED,r8)
124
125 5:
126         mov     #0, r3
127         mov.l   @(NR_READERS,r8), r0
128         add     #1, r0
129         mov.l   r0, @(NR_READERS,r8)
130         tst     r0, r0
131         bt      8f
132
133 9:
134 #if MUTEX == 0
135         DEC (@r8, r2)
136 #else
137         DEC (@(MUTEX,r8), r2)
138 #endif
139         tst     r2, r2
140         bf      6f
141 7:
142         lds.l   @r15+, pr
143         mov.l   @r15+, r8
144         mov.l   @r15+, r9
145         mov.l   @r15+, r12
146         rts
147          mov    r3, r0
148
149 #if !__ASSUME_PRIVATE_FUTEX
150 .Lpfoff:
151         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
152 #endif
153
154 1:
155         mov     r8, r5
156 #if MUTEX != 0
157         add     #MUTEX, r5
158 #endif
159         mov     r2, r4
160         mov.l   .Lwait0, r1
161         bsrf    r1
162          nop
163 .Lwait0b:
164         bra     2b
165          nop
166 14:
167         stc     gbr, r1
168         mov.w   .Ltidoff, r2
169         add     r2, r1
170         mov.l   @r1, r1
171         cmp/eq  r1, r0
172         bf      3b
173         /* Deadlock detected.  */
174         bra     9b
175          mov    #EDEADLK, r3
176
177 .Ltidoff:
178         .word   TID - TLS_PRE_TCB_SIZE
179         
180 6:
181         mov     r8, r4
182 #if MUTEX != 0
183         add     #MUTEX, r4
184 #endif
185         mov.l   .Lwake0, r1
186         bsrf    r1
187          nop
188 .Lwake0b:
189         bra     7b
190          mov    #0, r3
191
192 8:
193         /* Overflow.  */
194         mov.l   @(NR_READERS,r8), r1
195         add     #-1, r1
196         mov.l   r1, @(NR_READERS,r8)
197         bra     9b
198          mov    #EAGAIN, r3
199
200 4:
201         /* Overflow.  */
202         mov.l   @(READERS_QUEUED,r8), r1
203         add     #-1, r1
204         mov.l   r1, @(READERS_QUEUED,r8)
205         bra     9b
206          mov    #EAGAIN, r3
207
208 10:
209         mov     r8, r4
210 #if MUTEX != 0
211         add     #MUTEX, r4
212 #endif
213         mov.l   .Lwake1, r1
214         bsrf    r1
215          nop
216 .Lwake1b:
217         bra     11b
218          nop
219
220 12:
221         mov     r8, r5
222 #if MUTEX != 0
223         add     #MUTEX, r5
224 #endif
225         mov     r2, r4
226         mov.l   .Lwait1, r1
227         bsrf    r1
228          nop
229 .Lwait1b:
230         bra     13b
231          nop
232
233         .align  2
234 .Lwait0:
235         .long   __lll_mutex_lock_wait-.Lwait0b
236 .Lwake0:
237         .long   __lll_mutex_unlock_wake-.Lwake0b
238 .Lwait1:
239         .long   __lll_mutex_lock_wait-.Lwait1b
240 .Lwake1:
241         .long   __lll_mutex_unlock_wake-.Lwake1b
242         .size   __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
243
244         .globl  pthread_rwlock_rdlock
245 pthread_rwlock_rdlock = __pthread_rwlock_rdlock
246
247         .globl  __pthread_rwlock_rdlock_internal
248 __pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock