Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_rdlock.S
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
23
24
25 #define SYS_futex               202
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
28
29 #ifndef UP
30 # define LOCK lock
31 #else
32 # define LOCK
33 #endif
34
35
36         .text
37
38         .globl  __pthread_rwlock_rdlock
39         .type   __pthread_rwlock_rdlock,@function
40         .align  16
41 __pthread_rwlock_rdlock:
42         xorq    %r10, %r10
43
44         /* Get the lock.  */
45         movl    $1, %esi
46         xorl    %eax, %eax
47         LOCK
48 #if MUTEX == 0
49         cmpxchgl %esi, (%rdi)
50 #else
51         cmpxchgl %esi, MUTEX(%rdi)
52 #endif
53         jnz     1f
54
55 2:      movl    WRITER(%rdi), %eax
56         testl   %eax, %eax
57         jne     14f
58         cmpl    $0, WRITERS_QUEUED(%rdi)
59         je      5f
60         cmpl    $0, FLAGS(%rdi)
61         je      5f
62
63 3:      incl    READERS_QUEUED(%rdi)
64         je      4f
65
66         movl    READERS_WAKEUP(%rdi), %edx
67
68         LOCK
69 #if MUTEX == 0
70         decl    (%rdi)
71 #else
72         decl    MUTEX(%rdi)
73 #endif
74         jne     10f
75
76 11:     addq    $READERS_WAKEUP, %rdi
77         movq    %r10, %rsi      /* movq $FUTEX_WAIT, %rsi */
78         movq    $SYS_futex, %rax
79         syscall
80
81         subq    $READERS_WAKEUP, %rdi
82
83         /* Reget the lock.  */
84         movl    $1, %esi
85         xorl    %eax, %eax
86         LOCK
87 #if MUTEX == 0
88         cmpxchgl %esi, (%rdi)
89 #else
90         cmpxchgl %esi, MUTEX(%rdi)
91 #endif
92         jnz     12f
93
94 13:     decl    READERS_QUEUED(%rdi)
95         jmp     2b
96
97 5:      xorq    %rdx, %rdx
98         incl    NR_READERS(%rdi)
99         je      8f
100 9:      LOCK
101 #if MUTEX == 0
102         decl    (%rdi)
103 #else
104         decl    MUTEX(%rdi)
105 #endif
106         jne     6f
107 7:
108
109         movq    %rdx, %rax
110         retq
111
112 1:
113 #if MUTEX != 0
114         addq    $MUTEX, %rdi
115 #endif
116         callq   __lll_mutex_lock_wait
117 #if MUTEX != 0
118         subq    $MUTEX, %rdi
119 #endif
120         jmp     2b
121
122 14:     cmpl    %fs:TID, %eax
123         jne     3b
124         /* Deadlock detected.  */
125         movq    $EDEADLK, %rdx
126         jmp     9b
127
128 6:
129 #if MUTEX != 0
130         addq    $MUTEX, %rdi
131 #endif
132         callq   __lll_mutex_unlock_wake
133 #if MUTEX != 0
134         subq    $MUTEX, %rdi
135 #endif
136         jmp     7b
137
138         /* Overflow.  */
139 8:      decl    NR_READERS(%rdi)
140         movq    $EAGAIN, %rdx
141         jmp     9b
142
143         /* Overflow.  */
144 4:      decl    READERS_QUEUED(%rdi)
145         movq    $EAGAIN, %rdx
146         jmp     9b
147
148 10:
149 #if MUTEX != 0
150         addq    $MUTEX, %rdi
151 #endif
152         callq   __lll_mutex_unlock_wake
153 #if MUTEX != 0
154         subq    $MUTEX, %rdi
155 #endif
156         jmp     11b
157
158 12:
159 #if MUTEX == 0
160         addq    $MUTEX, %rdi
161 #endif
162         callq   __lll_mutex_lock_wait
163 #if MUTEX != 0
164         subq    $MUTEX, %rdi
165 #endif
166         jmp     13b
167         .size   __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
168
169         .globl  pthread_rwlock_rdlock
170 pthread_rwlock_rdlock = __pthread_rwlock_rdlock
171
172         .globl  __pthread_rwlock_rdlock_internal
173 __pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock