* sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_rdlock.S
blobc61c69798526d245ea2c7cf68fcdee1d4f991a50
1 /* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
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.  */
20 #include <sysdep.h>
21 #include <lowlevelrwlock.h>
22 #include <pthread-errnos.h>
25 #define SYS_futex               240
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
29 #ifndef UP
30 # define LOCK lock
31 #else
32 # define LOCK
33 #endif
36         .text
38         .globl  __pthread_rwlock_rdlock
39         .type   __pthread_rwlock_rdlock,@function
40         .align  16
41 __pthread_rwlock_rdlock:
42         pushl   %esi
43         pushl   %ebx
45         xorl    %esi, %esi
46         movl    12(%esp), %ebx
48         /* Get the lock.  */
49         movl    $1, %edx
50         xorl    %eax, %eax
51         LOCK
52 #if MUTEX == 0
53         cmpxchgl %edx, (%ebx)
54 #else
55         cmpxchgl %edx, MUTEX(%ebx)
56 #endif
57         jnz     1f
59 2:      movl    WRITER(%ebx), %eax
60         testl   %eax, %eax
61         jne     14f
62         cmpl    $0, WRITERS_QUEUED(%ebx)
63         je      5f
64         cmpb    $0, FLAGS(%ebx)
65         je      5f
67 3:      addl    $1, READERS_QUEUED(%ebx)
68         je      4f
70         movl    READERS_WAKEUP(%ebx), %edx
72         LOCK
73 #if MUTEX == 0
74         subl    $1, (%ebx)
75 #else
76         subl    $1, MUTEX(%ebx)
77 #endif
78         jne     10f
80 11:
81 #if __ASSUME_PRIVATE_FUTEX
82         movzbl  PSHARED(%ebx), %ecx
83         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
84 #else
85         movzbl  PSHARED(%ebx), %ecx
86 # if FUTEX_WAIT != 0
87         orl     $FUTEX_WAIT, %ecx
88 # endif
89         xorl    %gs:PRIVATE_FUTEX, %ecx
90 #endif
91         addl    $READERS_WAKEUP, %ebx
92         movl    $SYS_futex, %eax
93         ENTER_KERNEL
95         subl    $READERS_WAKEUP, %ebx
97         /* Reget the lock.  */
98         movl    $1, %edx
99         xorl    %eax, %eax
100         LOCK
101 #if MUTEX == 0
102         cmpxchgl %edx, (%ebx)
103 #else
104         cmpxchgl %edx, MUTEX(%ebx)
105 #endif
106         jnz     12f
108 13:     subl    $1, READERS_QUEUED(%ebx)
109         jmp     2b
111 5:      xorl    %ecx, %ecx
112         addl    $1, NR_READERS(%ebx)
113         je      8f
114 9:      LOCK
115 #if MUTEX == 0
116         subl    $1, (%ebx)
117 #else
118         subl    $1, MUTEX(%ebx)
119 #endif
120         jne     6f
123         movl    %ecx, %eax
124         popl    %ebx
125         popl    %esi
126         ret
129 #if MUTEX == 0
130         movl    %ebx, %ecx
131 #else
132         leal    MUTEX(%ebx), %ecx
133 #endif
134         call    __lll_mutex_lock_wait
135         jmp     2b
137 14:     cmpl    %gs:TID, %eax
138         jne     3b
139         /* Deadlock detected.  */
140         movl    $EDEADLK, %ecx
141         jmp     9b
144 #if MUTEX == 0
145         movl    %ebx, %eax
146 #else
147         leal    MUTEX(%ebx), %eax
148 #endif
149         call    __lll_mutex_unlock_wake
150         jmp     7b
152         /* Overflow.  */
153 8:      subl    $1, NR_READERS(%ebx)
154         movl    $EAGAIN, %ecx
155         jmp     9b
157         /* Overflow.  */
158 4:      subl    $1, READERS_QUEUED(%ebx)
159         movl    $EAGAIN, %ecx
160         jmp     9b
163 #if MUTEX == 0
164         movl    %ebx, %eax
165 #else
166         leal    MUTEX(%ebx), %eax
167 #endif
168         call    __lll_mutex_unlock_wake
169         jmp     11b
172 #if MUTEX == 0
173         movl    %ebx, %ecx
174 #else
175         leal    MUTEX(%ebx), %ecx
176 #endif
177         call    __lll_mutex_lock_wait
178         jmp     13b
179         .size   __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
181         .globl  pthread_rwlock_rdlock
182 pthread_rwlock_rdlock = __pthread_rwlock_rdlock
184         .globl  __pthread_rwlock_rdlock_internal
185 __pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock