Updated to fedora-glibc-20080612T1619
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / pthread_rwlock_wrlock.S
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.
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 <lowlevellock.h>
22 #include <lowlevelrwlock.h>
23 #include <pthread-errnos.h>
24 #include <kernel-features.h>
25
26
27         .text
28
29         .globl  __pthread_rwlock_wrlock
30         .type   __pthread_rwlock_wrlock,@function
31         .align  16
32 __pthread_rwlock_wrlock:
33         cfi_startproc
34         pushl   %esi
35         cfi_adjust_cfa_offset(4)
36         pushl   %ebx
37         cfi_adjust_cfa_offset(4)
38         cfi_offset(%esi, -8)
39         cfi_offset(%ebx, -12)
40
41         xorl    %esi, %esi
42         movl    12(%esp), %ebx
43
44         /* Get the lock.  */
45         movl    $1, %edx
46         xorl    %eax, %eax
47         LOCK
48 #if MUTEX == 0
49         cmpxchgl %edx, (%ebx)
50 #else
51         cmpxchgl %edx, MUTEX(%ebx)
52 #endif
53         jnz     1f
54
55 2:      movl    WRITER(%ebx), %eax
56         testl   %eax, %eax
57         jne     14f
58         cmpl    $0, NR_READERS(%ebx)
59         je      5f
60
61 3:      addl    $1, WRITERS_QUEUED(%ebx)
62         je      4f
63
64         movl    WRITERS_WAKEUP(%ebx), %edx
65
66         LOCK
67 #if MUTEX == 0
68         subl    $1, (%ebx)
69 #else
70         subl    $1, MUTEX(%ebx)
71 #endif
72         jne     10f
73
74 11:
75 #ifdef __ASSUME_PRIVATE_FUTEX
76         movzbl  PSHARED(%ebx), %ecx
77         xorl    $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx
78 #else
79         movzbl  PSHARED(%ebx), %ecx
80 # if FUTEX_WAIT != 0
81         orl     $FUTEX_WAIT, %ecx
82 # endif
83         xorl    %gs:PRIVATE_FUTEX, %ecx
84 #endif
85         addl    $WRITERS_WAKEUP, %ebx
86         movl    $SYS_futex, %eax
87         ENTER_KERNEL
88
89         subl    $WRITERS_WAKEUP, %ebx
90
91         /* Reget the lock.  */
92         movl    $1, %edx
93         xorl    %eax, %eax
94         LOCK
95 #if MUTEX == 0
96         cmpxchgl %edx, (%ebx)
97 #else
98         cmpxchgl %edx, MUTEX(%ebx)
99 #endif
100         jnz     12f
101
102 13:     subl    $1, WRITERS_QUEUED(%ebx)
103         jmp     2b
104
105 5:      xorl    %edx, %edx
106         movl    %gs:TID, %eax
107         movl    %eax, WRITER(%ebx)
108 9:      LOCK
109 #if MUTEX == 0
110         subl    $1, (%ebx)
111 #else
112         subl    $1, MUTEX(%ebx)
113 #endif
114         jne     6f
115 7:
116
117         movl    %edx, %eax
118         popl    %ebx
119         cfi_adjust_cfa_offset(-4)
120         cfi_restore(%ebx)
121         popl    %esi
122         cfi_adjust_cfa_offset(-4)
123         cfi_restore(%esi)
124         ret
125
126         cfi_adjust_cfa_offset(8)
127         cfi_offset(%esi, -8)
128         cfi_offset(%ebx, -12)
129 1:
130 #if MUTEX == 0
131         movl    %ebx, %edx
132 #else
133         leal    MUTEX(%ebx), %edx
134 #endif
135         movzbl  PSHARED(%ebx), %ecx
136         call    __lll_lock_wait
137         jmp     2b
138
139 14:     cmpl    %gs:TID , %eax
140         jne     3b
141         movl    $EDEADLK, %edx
142         jmp     9b
143
144 6:
145 #if MUTEX == 0
146         movl    %ebx, %eax
147 #else
148         leal    MUTEX(%ebx), %eax
149 #endif
150         movzbl  PSHARED(%ebx), %ecx
151         call    __lll_unlock_wake
152         jmp     7b
153
154 4:      subl    $1, WRITERS_QUEUED(%ebx)
155         movl    $EAGAIN, %edx
156         jmp     9b
157
158 10:
159 #if MUTEX == 0
160         movl    %ebx, %eax
161 #else
162         leal    MUTEX(%ebx), %eax
163 #endif
164         movzbl  PSHARED(%ebx), %ecx
165         call    __lll_unlock_wake
166         jmp     11b
167
168 12:
169 #if MUTEX == 0
170         movl    %ebx, %edx
171 #else
172         leal    MUTEX(%ebx), %edx
173 #endif
174         movzbl  PSHARED(%ebx), %ecx
175         call    __lll_lock_wait
176         jmp     13b
177         cfi_endproc
178         .size   __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
179
180         .globl  pthread_rwlock_wrlock
181 pthread_rwlock_wrlock = __pthread_rwlock_wrlock
182
183         .globl  __pthread_rwlock_wrlock_internal
184 __pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock