sem_timedwait implementation for Linux/i486.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / sem_timedwait.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 <shlib-compat.h>
22
23 #ifndef UP
24 # define LOCK lock
25 #else
26 # define
27 #endif
28
29 #define SYS_gettimeofday        __NR_gettimeofday
30 #define SYS_futex               240
31 #define FUTEX_WAKE              1
32
33 #define EWOULDBLOCK             11
34 #define EINVAL                  22
35 #define ETIMEDOUT               110
36
37
38         .text
39
40         .globl  sem_timedwait
41         .type   sem_timedwait,@function
42         .align  16
43 sem_timedwait:
44         movl    4(%esp), %ecx
45
46         movl    (%ecx), %eax
47 2:      testl   %eax, %eax
48         je,pn   1f
49
50         leal    -1(%eax), %edx
51         LOCK
52         cmpxchgl %edx, (%ecx)
53         jne,pn  2b
54
55         xorl    %eax, %eax
56         ret
57
58         /* Check whether the timeout value is valid.  */
59 1:      pushl   %esi
60         pushl   %edi
61         pushl   %ebx
62         subl    $8, %esp
63
64         movl    %esp, %esi
65         movl    28(%esp), %edi
66
67         /* Check for invalid nanosecond field.  */
68         cmpl    $1000000000, 4(%edi)
69         movl    $EINVAL, %eax
70         jae     6f
71
72 7:      xorl    %ecx, %ecx
73         movl    %esp, %ebx
74         movl    %ecx, %edx
75         movl    $SYS_gettimeofday, %eax
76         ENTER_KERNEL
77
78         /* Compute relative timeout.  */
79         movl    4(%esp), %eax
80         movl    $1000, %edx
81         mul     %edx            /* Milli seconds to nano seconds.  */
82         movl    (%edi), %ecx
83         movl    4(%edi), %edx
84         subl    (%esp), %ecx
85         subl    %eax, %edx
86         jns     5f
87         addl    $1000000000, %edx
88         decl    %ecx
89 5:      testl   %ecx, %ecx
90         movl    $ETIMEDOUT, %eax
91         js      6f              /* Time is already up.  */
92
93         movl    %ecx, (%esp)    /* Store relative timeout.  */
94         movl    %edx, 4(%esp)
95         movl    24(%esp), %ebx
96         xorl    %ecx, %ecx
97         movl    $SYS_futex, %eax
98         xorl    %edx, %edx
99         ENTER_KERNEL
100
101         testl   %eax, %eax
102         je,pt   9f
103         cmpl    $-EWOULDBLOCK, %eax
104         jne     3f
105
106 9:      movl    (%ebx), %eax
107 8:      testl   %eax, %eax
108         je      7b
109
110         leal    -1(%eax), %ecx
111         LOCK
112         cmpxchgl %ecx, (%ebx)
113         jne,pn  8b
114
115         addl    $8, %esp
116         xorl    %eax, %eax
117         popl    %ebx
118         popl    %edi
119         popl    %esi
120         ret
121
122 3:      negl    %eax
123 6:
124 #ifdef PIC
125         call    __i686.get_pc_thunk.bx
126 #else
127         movl    $4f, %ebx
128 4:
129 #endif
130         addl    $_GLOBAL_OFFSET_TABLE_, %ebx
131 #if USE___THREAD
132         movl    %gs:0, %edx
133         subl    errno@gottpoff(%ebx), %edx
134         movl    %eax, (%edx)
135 #else
136         movl    %eax, %edx
137         call    __errno_location@plt
138         movl    %edx, (%eax)
139 #endif
140
141         addl    $8, %esp
142         orl     $-1, %eax
143         popl    %ebx
144         popl    %edi
145         popl    %esi
146         ret
147         .size   sem_timedwait,.-sem_timedwait