OSDN Git Service

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