]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S
1b2933dadc2938481d2219bf06f996f8b514c6be
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / i486 / lowlevelrobustlock.S
1 /* Copyright (C) 2002-2014 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, see
17 <http://www.gnu.org/licenses/>. */
18
19 #include <sysdep.h>
20 #include <pthread-errnos.h>
21 #include <lowlevellock.h>
22 #include <lowlevelrobustlock.h>
23 #include <kernel-features.h>
24
25 .text
26
27 #define FUTEX_WAITERS 0x80000000
28 #define FUTEX_OWNER_DIED 0x40000000
29
30 #ifdef __ASSUME_PRIVATE_FUTEX
31 # define LOAD_FUTEX_WAIT(reg) \
32 xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg
33 #else
34 # if FUTEX_WAIT == 0
35 # define LOAD_FUTEX_WAIT(reg) \
36 xorl $FUTEX_PRIVATE_FLAG, reg ; \
37 andl %gs:PRIVATE_FUTEX, reg
38 # else
39 # define LOAD_FUTEX_WAIT(reg) \
40 xorl $FUTEX_PRIVATE_FLAG, reg ; \
41 andl %gs:PRIVATE_FUTEX, reg ; \
42 orl $FUTEX_WAIT, reg
43 # endif
44 #endif
45
46 .globl __lll_robust_lock_wait
47 .type __lll_robust_lock_wait,@function
48 .hidden __lll_robust_lock_wait
49 .align 16
50 __lll_robust_lock_wait:
51 cfi_startproc
52 pushl %edx
53 cfi_adjust_cfa_offset(4)
54 pushl %ebx
55 cfi_adjust_cfa_offset(4)
56 pushl %esi
57 cfi_adjust_cfa_offset(4)
58 cfi_offset(%edx, -8)
59 cfi_offset(%ebx, -12)
60 cfi_offset(%esi, -16)
61
62 movl %edx, %ebx
63 xorl %esi, %esi /* No timeout. */
64 LOAD_FUTEX_WAIT (%ecx)
65
66 4: movl %eax, %edx
67 orl $FUTEX_WAITERS, %edx
68
69 testl $FUTEX_OWNER_DIED, %eax
70 jnz 3f
71
72 cmpl %edx, %eax /* NB: %edx == 2 */
73 je 1f
74
75 LOCK
76 cmpxchgl %edx, (%ebx)
77 jnz 2f
78
79 1: movl $SYS_futex, %eax
80 ENTER_KERNEL
81
82 movl (%ebx), %eax
83
84 2: test %eax, %eax
85 jne 4b
86
87 movl %gs:TID, %edx
88 orl $FUTEX_WAITERS, %edx
89 LOCK
90 cmpxchgl %edx, (%ebx)
91 jnz 4b
92 /* NB: %eax == 0 */
93
94 3: popl %esi
95 cfi_adjust_cfa_offset(-4)
96 cfi_restore(%esi)
97 popl %ebx
98 cfi_adjust_cfa_offset(-4)
99 cfi_restore(%ebx)
100 popl %edx
101 cfi_adjust_cfa_offset(-4)
102 cfi_restore(%edx)
103 ret
104 cfi_endproc
105 .size __lll_robust_lock_wait,.-__lll_robust_lock_wait
106
107
108 .globl __lll_robust_timedlock_wait
109 .type __lll_robust_timedlock_wait,@function
110 .hidden __lll_robust_timedlock_wait
111 .align 16
112 __lll_robust_timedlock_wait:
113 cfi_startproc
114 /* Check for a valid timeout value. */
115 cmpl $1000000000, 4(%edx)
116 jae 3f
117
118 pushl %edi
119 cfi_adjust_cfa_offset(4)
120 pushl %esi
121 cfi_adjust_cfa_offset(4)
122 pushl %ebx
123 cfi_adjust_cfa_offset(4)
124 pushl %ebp
125 cfi_adjust_cfa_offset(4)
126 cfi_offset(%edi, -8)
127 cfi_offset(%esi, -12)
128 cfi_offset(%ebx, -16)
129 cfi_offset(%ebp, -20)
130
131 /* Stack frame for the timespec and timeval structs. */
132 subl $12, %esp
133 cfi_adjust_cfa_offset(12)
134
135 movl %ecx, %ebp
136 movl %edx, %edi
137
138 1: movl %eax, 8(%esp)
139
140 /* Get current time. */
141 movl %esp, %ebx
142 xorl %ecx, %ecx
143 movl $__NR_gettimeofday, %eax
144 ENTER_KERNEL
145
146 /* Compute relative timeout. */
147 movl 4(%esp), %eax
148 movl $1000, %edx
149 mul %edx /* Milli seconds to nano seconds. */
150 movl (%edi), %ecx
151 movl 4(%edi), %edx
152 subl (%esp), %ecx
153 subl %eax, %edx
154 jns 4f
155 addl $1000000000, %edx
156 subl $1, %ecx
157 4: testl %ecx, %ecx
158 js 8f /* Time is already up. */
159
160 /* Store relative timeout. */
161 movl %ecx, (%esp)
162 movl %edx, 4(%esp)
163
164 movl %ebp, %ebx
165
166 movl 8(%esp), %edx
167 movl %edx, %eax
168 orl $FUTEX_WAITERS, %edx
169
170 testl $FUTEX_OWNER_DIED, %eax
171 jnz 6f
172
173 cmpl %eax, %edx
174 je 2f
175
176 LOCK
177 cmpxchgl %edx, (%ebx)
178 movl $0, %ecx /* Must use mov to avoid changing cc. */
179 jnz 5f
180
181 2:
182 /* Futex call. */
183 movl %esp, %esi
184 movl 20(%esp), %ecx
185 LOAD_FUTEX_WAIT (%ecx)
186 movl $SYS_futex, %eax
187 ENTER_KERNEL
188 movl %eax, %ecx
189
190 movl (%ebx), %eax
191
192 5: testl %eax, %eax
193 jne 7f
194
195 movl %gs:TID, %edx
196 orl $FUTEX_WAITERS, %edx
197 LOCK
198 cmpxchgl %edx, (%ebx)
199 jnz 7f
200
201 6: addl $12, %esp
202 cfi_adjust_cfa_offset(-12)
203 popl %ebp
204 cfi_adjust_cfa_offset(-4)
205 cfi_restore(%ebp)
206 popl %ebx
207 cfi_adjust_cfa_offset(-4)
208 cfi_restore(%ebx)
209 popl %esi
210 cfi_adjust_cfa_offset(-4)
211 cfi_restore(%esi)
212 popl %edi
213 cfi_adjust_cfa_offset(-4)
214 cfi_restore(%edi)
215 ret
216
217 3: movl $EINVAL, %eax
218 ret
219
220 cfi_adjust_cfa_offset(28)
221 cfi_offset(%edi, -8)
222 cfi_offset(%esi, -12)
223 cfi_offset(%ebx, -16)
224 cfi_offset(%ebp, -20)
225 /* Check whether the time expired. */
226 7: cmpl $-ETIMEDOUT, %ecx
227 jne 1b
228
229 8: movl $ETIMEDOUT, %eax
230 jmp 6b
231 cfi_endproc
232 .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait