Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_wrlock.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_wrlock
39         .type   __pthread_rwlock_wrlock,@function
40         .align  16
41 __pthread_rwlock_wrlock:
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, NR_READERS(%rdi)
59         je      5f
60
61 3:      incl    WRITERS_QUEUED(%rdi)
62         je      4f
63
64         movl    WRITERS_WAKEUP(%rdi), %edx
65
66         LOCK
67 #if MUTEX == 0
68         decl    (%rdi)
69 #else
70         decl    MUTEX(%rdi)
71 #endif
72         jne     10f
73
74 11:     addq    $WRITERS_WAKEUP, %rdi
75         movq    %r10, %rsi      /* movq $FUTEX_WAIT, %rsi */
76         movq    $SYS_futex, %rax
77         syscall
78
79         subq    $WRITERS_WAKEUP, %rdi
80
81         /* Reget the lock.  */
82         movl    $1, %esi
83         xorl    %eax, %eax
84         LOCK
85 #if MUTEX == 0
86         cmpxchgl %esi, (%rdi)
87 #else
88         cmpxchgl %esi, MUTEX(%rdi)
89 #endif
90         jnz     12f
91
92 13:     decl    WRITERS_QUEUED(%rdi)
93         jmp     2b
94
95 5:      xorq    %rdx, %rdx
96         movl    %fs:TID, %eax
97         movl    %eax, WRITER(%rdi)
98 9:      LOCK
99 #if MUTEX == 0
100         decl    (%rdi)
101 #else
102         decl    MUTEX(%rdi)
103 #endif
104         jne     6f
105 7:
106
107         movq    %rdx, %rax
108         retq
109
110 1:
111 #if MUTEX != 0
112         addq    $MUTEX, %rdi
113 #endif
114         callq   __lll_mutex_lock_wait
115 #if MUTEX != 0
116         subq    $MUTEX, %rdi
117 #endif
118         jmp     2b
119
120 14:     cmpl    %fs:TID, %eax
121         jne     3b
122         movq    $EDEADLK, %rdx
123         jmp     9b
124
125 6:
126 #if MUTEX != 0
127         addq    $MUTEX, %rdi
128 #endif
129         callq   __lll_mutex_unlock_wake
130         jmp     7b
131
132 4:      decl    WRITERS_QUEUED(%rdi)
133         movl    $EAGAIN, %edx
134         jmp     9b
135
136 10:
137 #if MUTEX != 0
138         addq    $MUTEX, %rdi
139 #endif
140         callq   __lll_mutex_unlock_wake
141 #if MUTEX != 0
142         subq    $MUTEX, %rdi
143 #endif
144         jmp     11b
145
146 12:
147 #if MUTEX != 0
148         addq    $MUTEX, %rdi
149 #endif
150         callq   __lll_mutex_lock_wait
151 #if MUTEX != 0
152         subq    $MUTEX, %rdi
153 #endif
154         jmp     13b
155         .size   __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
156
157         .globl  pthread_rwlock_wrlock
158 pthread_rwlock_wrlock = __pthread_rwlock_wrlock
159
160         .globl  __pthread_rwlock_wrlock_internal
161 __pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock