Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_rwlock_unlock.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
23
24 #define SYS_futex               202
25 #define FUTEX_WAIT              0
26 #define FUTEX_WAKE              1
27
28 #ifndef UP
29 # define LOCK lock
30 #else
31 # define LOCK
32 #endif
33
34
35         .text
36
37         .globl  __pthread_rwlock_unlock
38         .type   __pthread_rwlock_unlock,@function
39         .align  16
40 __pthread_rwlock_unlock:
41         /* Get the lock.  */
42         movl    $1, %esi
43         xorl    %eax, %eax
44         LOCK
45 #if MUTEX == 0
46         cmpxchgl %esi, (%rdi)
47 #else
48         cmpxchgl %esi, MUTEX(%rdi)
49 #endif
50         jnz     1f
51
52 2:      cmpl    $0, WRITER(%rdi)
53         jne     5f
54         decl    NR_READERS(%rdi)
55         jnz     6f
56
57 5:      movl    $0, WRITER(%rdi)
58
59         movq    $1, %rsi
60         leaq    WRITERS_WAKEUP(%rdi), %r10
61         movq    %rsi, %rdx
62         cmpl    $0, WRITERS_QUEUED(%rdi)
63         jne     0f
64
65         /* If also no readers waiting nothing to do.  */
66         cmpl    $0, READERS_QUEUED(%rdi)
67         je      6f
68
69         movl    $0x7fffffff, %edx
70         leaq    READERS_WAKEUP(%rdi), %r10
71
72 0:      incl    (%r10)
73         LOCK
74 #if MUTEX == 0
75         decl    (%rdi)
76 #else
77         decl    MUTEX(%rdi)
78 #endif
79         jne     7f
80
81 8:      movq    $SYS_futex, %rax
82         movq    %r10, %rdi
83         syscall
84
85         xorq    %rax, %rax
86         retq
87
88         .align  16
89 6:      LOCK
90 #if MUTEX == 0
91         decl    (%rdi)
92 #else
93         decl    MUTEX(%rdi)
94 #endif
95         jne     3f
96
97 4:      xorq    %rax, %rax
98         retq
99
100 1:
101 #if MUTEX != 0
102         addq    $MUTEX, %rdi
103 #endif
104         callq   __lll_mutex_lock_wait
105 #if MUTEX != 0
106         subq    $MUTEX, %rdi
107 #endif
108         jmp     2b
109
110 3:
111 #if MUTEX != 0
112         addq    $MUTEX, %rdi
113 #endif
114         callq   __lll_mutex_unlock_wake
115         jmp     4b
116
117 7:
118 #if MUTEX != 0
119         addq    $MUTEX, %rdi
120 #endif
121         callq   __lll_mutex_unlock_wake
122         jmp     8b
123
124         .size   __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
125
126         .globl  pthread_rwlock_unlock
127 pthread_rwlock_unlock = __pthread_rwlock_unlock
128
129         .globl  __pthread_rwlock_unlock_internal
130 __pthread_rwlock_unlock_internal = __pthread_rwlock_unlock