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