bdfc506fe095ce7cd02cc17d4fe47264f119b4d0
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevellock.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
22         .text
23
24 #ifdef UP
25 # define LOCK
26 #else
27 # define LOCK lock
28 #endif
29
30 #define SYS_gettimeofday        __NR_gettimeofday
31 #define SYS_futex               240
32 #define FUTEX_WAIT              0
33 #define FUTEX_WAKE              1
34
35 #define ETIMEDOUT               110
36
37
38         .globl  __lll_lock_wait
39         .type   __lll_lock_wait,@function
40         .hidden __lll_lock_wait
41         .align  16
42 __lll_lock_wait:
43         pushl   %esi
44         pushl   %ebx
45         pushl   %edx
46
47         movl    %ecx, %ebx
48         xorl    %esi, %esi      /* No timeout.  */
49         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
50 1:
51         leal    -1(%eax), %edx  /* account for the preceeded xadd.  */
52         movl    $SYS_futex, %eax
53         ENTER_KERNEL
54
55         orl     $-1, %eax       /* Load -1.  */
56         LOCK
57         xaddl   %eax, (%ebx)
58         jne,pn  1b
59
60         movl    $-1, (%ebx)
61
62         popl    %edx
63         popl    %ebx
64         popl    %esi
65         ret
66         .size   __lll_lock_wait,.-__lll_lock_wait
67
68
69         .globl  lll_unlock_wake_cb
70         .type   lll_unlock_wake_cb,@function
71         .hidden lll_unlock_wake_cb
72         .align  16
73 lll_unlock_wake_cb:
74         pushl   %esi
75         pushl   %ebx
76         pushl   %ecx
77         pushl   %edx
78
79         movl    20(%esp), %ebx
80         LOCK
81         incl    (%ebx)
82         jng     1f
83
84         popl    %edx
85         popl    %ecx
86         popl    %ebx
87         popl    %esi
88         ret
89         .size   lll_unlock_wake_cb,.-lll_unlock_wake_cb
90
91
92         .globl  __lll_unlock_wake
93         .type   __lll_unlock_wake,@function
94         .hidden __lll_unlock_wake
95 __lll_unlock_wake:
96         pushl   %esi
97         pushl   %ebx
98         pushl   %ecx
99         pushl   %edx
100
101         movl    %eax, %ebx
102 1:      movl    $FUTEX_WAKE, %ecx
103         movl    $1, %edx        /* Wake one thread.  */
104         xorl    %esi, %esi
105         movl    %edx, (%ebx)    /* Stores '$1'.  */
106         movl    $SYS_futex, %eax
107         ENTER_KERNEL
108
109         popl    %edx
110         popl    %ecx
111         popl    %ebx
112         popl    %esi
113         ret
114         .size   __lll_unlock_wake,.-__lll_unlock_wake
115
116
117         .globl  __lll_timedwait_tid
118         .type   __lll_timedwait_tid,@function
119         .hidden __lll_timedwait_tid
120 __lll_timedwait_tid:
121         pushl   %edi
122         pushl   %esi
123         pushl   %ebx
124         pushl   %ebp
125
126         movl    %eax, %ebp
127         movl    %edx, %edi
128         subl    $8, %esp
129
130         /* Get current time.  */
131 2:      movl    %esp, %ebx
132         xorl    %ecx, %ecx
133         movl    $SYS_gettimeofday, %eax
134         ENTER_KERNEL
135
136         /* Compute relative timeout.  */
137         movl    4(%esp), %eax
138         movl    $1000, %edx
139         mul     %edx            /* Milli seconds to nano seconds.  */
140         movl    (%edi), %ecx
141         movl    4(%edi), %edx
142         subl    (%esp), %ecx
143         subl    %eax, %edx
144         jns     5f
145         addl    $1000000000, %edx
146         decl    %ecx
147 5:      testl   %ecx, %ecx
148         js      6f              /* Time is already up.  */
149
150         movl    %ecx, (%esp)    /* Store relative timeout.  */
151         movl    %edx, 4(%esp)
152
153         movl    (%ebp), %edx
154         testl   %edx, %edx
155         jz      4f
156
157         movl    %esp, %esi
158         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
159         movl    %ebp, %ebx
160         movl    $SYS_futex, %eax
161         ENTER_KERNEL
162
163         movl    %eax, %edx
164
165         cmpl    $0, (%ebx)
166         jne     1f
167 4:      xorl    %eax, %eax
168
169 3:      addl    $8, %esp
170         popl    %ebp
171         popl    %ebx
172         popl    %esi
173         popl    %edi
174         ret
175
176 1:      cmpl    $-ETIMEDOUT, %edx
177         jne     2b
178 6:      movl    $ETIMEDOUT, %eax
179         jmp     3b
180         .size   __lll_timedwait_tid,.-__lll_timedwait_tid