Update copyright notices with scripts/update-copyrights
[jlayton/glibc.git] / nptl / 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