Release internal lock before wake threads.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / 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               240
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         pushl   %ebx
42         pushl   %esi
43         pushl   %edi
44
45         movl    16(%esp), %edi
46
47         /* Get the lock.  */
48         movl    $1, %eax
49         LOCK
50 #if MUTEX == 0
51         xaddl   %eax, (%edi)
52 #else
53         xaddl   %eax, MUTEX(%edi)
54 #endif
55         testl   %eax, %eax
56         jne     1f
57
58 2:      cmpl    $0, WRITER(%edi)
59         jne     5f
60         decl    NR_READERS(%edi)
61         jnz     6f
62
63 5:      movl    $0, WRITER(%edi)
64
65         movl    $1, %ecx
66         leal    WRITERS_WAKEUP(%edi), %ebx
67         movl    %ecx, %edx
68         cmpl    $0, WRITERS_QUEUED(%edi)
69         jne     0f
70
71         /* If also no readers waiting nothing to do.  */
72         cmpl    $0, READERS_QUEUED(%edi)
73         je      6f
74
75         movl    $0x7fffffff, %edx
76         leal    READERS_WAKEUP(%edi), %ebx
77
78 0:      incl    (%ebx)
79         LOCK
80 #if MUTEX == 0
81         decl    (%edi)
82 #else
83         decl    MUTEX(%edi)
84 #endif
85         jne     7f
86
87 8:      xorl    %esi, %esi
88         movl    $SYS_futex, %eax
89         ENTER_KERNEL
90
91         xorl    %eax, %eax
92         popl    %edi
93         popl    %esi
94         popl    %ebx
95         ret
96
97         .align  16
98 6:      LOCK
99 #if MUTEX == 0
100         decl    (%edi)
101 #else
102         decl    MUTEX(%edi)
103 #endif
104         jne     3f
105
106 4:      xorl    %eax, %eax
107         popl    %edi
108         popl    %esi
109         popl    %ebx
110         ret
111
112 1:
113 #if MUTEX == 0
114         movl    %edi, %ecx
115 #else
116         leal    MUTEX(%edx), %ecx
117 #endif
118         call    __lll_mutex_lock_wait
119         jmp     2b
120
121 3:
122 #if MUTEX == 0
123         movl    %edi, %eax
124 #else
125         leal    MUTEX(%edx), %eax
126 #endif
127         call    __lll_mutex_unlock_wake
128         jmp     4b
129
130 7:
131 #if MUTEX == 0
132         movl    %edi, %eax
133 #else
134         leal    MUTEX(%edx), %eax
135 #endif
136         call    __lll_mutex_unlock_wake
137         jmp     8b
138
139         .size   __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
140
141         .globl  pthread_rwlock_unlock
142 pthread_rwlock_unlock = __pthread_rwlock_unlock
143
144         .globl  __pthread_rwlock_unlock_internal
145 __pthread_rwlock_unlock_internal = __pthread_rwlock_unlock