* sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / sem_timedwait.S
blobbf70e17fca6e96b79977644d0b572f15d13da258
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
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.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <pthread-errnos.h>
24 #ifndef UP
25 # define LOCK lock
26 #else
27 # define
28 #endif
30 #define SYS_gettimeofday        __NR_gettimeofday
31 #define SYS_futex               240
32 #define FUTEX_WAKE              1
35         .text
37         .globl  sem_timedwait
38         .type   sem_timedwait,@function
39         .align  16
40         cfi_startproc
41 sem_timedwait:
42         /* First check for cancellation.  */
43         movl    %gs:CANCELHANDLING, %eax
44         andl    $0xfffffff9, %eax
45         cmpl    $8, %eax
46         je      10f
48         movl    4(%esp), %ecx
50         movl    (%ecx), %eax
51 2:      testl   %eax, %eax
52         je      1f
54         leal    -1(%eax), %edx
55         LOCK
56         cmpxchgl %edx, (%ecx)
57         jne     2b
59         xorl    %eax, %eax
60         ret
62         /* Check whether the timeout value is valid.  */
63 1:      pushl   %esi
64         cfi_adjust_cfa_offset(4)
65         pushl   %edi
66         cfi_adjust_cfa_offset(4)
67         pushl   %ebx
68         cfi_adjust_cfa_offset(4)
69         subl    $12, %esp
70         cfi_adjust_cfa_offset(12)
72         movl    32(%esp), %edi
73         cfi_offset(7, -12)              /* %edi */
75         /* Check for invalid nanosecond field.  */
76         cmpl    $1000000000, 4(%edi)
77         movl    $EINVAL, %esi
78         cfi_offset(6, -8)               /* %esi */
79         jae     6f
81         cfi_offset(3, -16)              /* %ebx */
82 7:      xorl    %ecx, %ecx
83         movl    %esp, %ebx
84         movl    %ecx, %edx
85         movl    $SYS_gettimeofday, %eax
86         ENTER_KERNEL
88         /* Compute relative timeout.  */
89         movl    4(%esp), %eax
90         movl    $1000, %edx
91         mul     %edx            /* Milli seconds to nano seconds.  */
92         movl    (%edi), %ecx
93         movl    4(%edi), %edx
94         subl    (%esp), %ecx
95         subl    %eax, %edx
96         jns     5f
97         addl    $1000000000, %edx
98         subl    $1, %ecx
99 5:      testl   %ecx, %ecx
100         movl    $ETIMEDOUT, %esi
101         js      6f              /* Time is already up.  */
103         movl    %ecx, (%esp)    /* Store relative timeout.  */
104         movl    %edx, 4(%esp)
106         call    __pthread_enable_asynccancel
107         movl    %eax, 8(%esp)
109         movl    28(%esp), %ebx
110         xorl    %ecx, %ecx
111         movl    %esp, %esi
112         movl    $SYS_futex, %eax
113         xorl    %edx, %edx
114         ENTER_KERNEL
115         movl    %eax, %esi
117         movl    8(%esp), %eax
118         call    __pthread_disable_asynccancel
120         testl   %esi, %esi
121         je      9f
122         cmpl    $-EWOULDBLOCK, %esi
123         jne     3f
125 9:      movl    (%ebx), %eax
126 8:      testl   %eax, %eax
127         je      7b
129         leal    -1(%eax), %ecx
130         LOCK
131         cmpxchgl %ecx, (%ebx)
132         jne     8b
134         addl    $12, %esp
135         cfi_adjust_cfa_offset(-12)
136         xorl    %eax, %eax
137         popl    %ebx
138         cfi_adjust_cfa_offset(-4)
139         cfi_restore(3)
140         popl    %edi
141         cfi_adjust_cfa_offset(-4)
142         cfi_restore(7)
143         popl    %esi
144         cfi_adjust_cfa_offset(-4)
145         cfi_restore(6)
146         ret
148         cfi_adjust_cfa_offset(24)
149         cfi_offset(6, -8)               /* %esi */
150         cfi_offset(7, -12)              /* %edi */
151         cfi_offset(3, -16)              /* %ebx */
152 3:      negl    %esi
154 #ifdef PIC
155         call    __i686.get_pc_thunk.bx
156 #else
157         movl    $4f, %ebx
159 #endif
160         addl    $_GLOBAL_OFFSET_TABLE_, %ebx
161 #if USE___THREAD
162 # ifdef NO_TLS_DIRECT_SEG_REFS
163         movl    errno@gotntpoff(%ebx), %edx
164         addl    %gs:0, %edx
165         movl    %esi, (%edx)
166 # else
167         movl    errno@gotntpoff(%ebx), %edx
168         movl    %esi, %gs:(%edx)
169 # endif
170 #else
171         call    __errno_location@plt
172         movl    %esi, (%eax)
173 #endif
175         addl    $12, %esp
176         cfi_adjust_cfa_offset(-12)
177         orl     $-1, %eax
178         popl    %ebx
179         cfi_adjust_cfa_offset(-4)
180         cfi_restore(3)
181         popl    %edi
182         cfi_adjust_cfa_offset(-4)
183         cfi_restore(7)
184         popl    %esi
185         cfi_adjust_cfa_offset(-4)
186         cfi_restore(6)
187         ret
189 10:     /* Canceled.  */
190         movl    $0xffffffff, %gs:RESULT
191         LOCK
192         orl     $0x10, %gs:CANCELHANDLING
193         movl    %gs:CLEANUP_JMP_BUF, %eax
194         jmp     HIDDEN_JUMPTARGET (__pthread_unwind)
195         cfi_endproc
196         .size   sem_timedwait,.-sem_timedwait