(pthread_barrier_wait): Don't save, load, and restore %esi for last thread.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / libc-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 #include <tls.h>
22
23         .text
24
25 #define SYS_gettimeofday        __NR_gettimeofday
26 #define SYS_futex               240
27 #define FUTEX_WAIT              0
28 #define FUTEX_WAKE              1
29
30 #define ETIMEDOUT               110
31
32
33         .globl  __lll_lock_wait
34         .type   __lll_lock_wait,@function
35         .hidden __lll_lock_wait
36         .align  16
37 __lll_lock_wait:
38         pushl   %esi
39         pushl   %ebx
40         pushl   %edx
41
42         movl    %ecx, %ebx
43         xorl    %esi, %esi      /* No timeout.  */
44         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
45 1:
46         leal    -1(%eax), %edx  /* account for the preceeded xadd.  */
47         movl    $SYS_futex, %eax
48         ENTER_KERNEL
49
50         orl     $-1, %eax       /* Load -1.  */
51 #ifndef UP
52         cmpl    $0, %gs:MULTIPLE_THREADS_OFFSET
53         je,pt   0f
54         lock
55 0:
56 #endif
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
70         .type   __lll_unlock_wake,@function
71         .hidden __lll_unlock_wake
72 __lll_unlock_wake:
73         pushl   %esi
74         pushl   %ebx
75         pushl   %ecx
76         pushl   %edx
77
78         movl    %eax, %ebx
79 1:      movl    $FUTEX_WAKE, %ecx
80         movl    $1, %edx        /* Wake one thread.  */
81         xorl    %esi, %esi
82         movl    %edx, (%ebx)    /* Stores '$1'.  */
83         movl    $SYS_futex, %eax
84         ENTER_KERNEL
85
86         popl    %edx
87         popl    %ecx
88         popl    %ebx
89         popl    %esi
90         ret
91         .size   __lll_unlock_wake,.-__lll_unlock_wake
92
93
94         .globl  __lll_timedwait_tid
95         .type   __lll_timedwait_tid,@function
96         .hidden __lll_timedwait_tid
97 __lll_timedwait_tid:
98         pushl   %edi
99         pushl   %esi
100         pushl   %ebx
101         pushl   %ebp
102
103         movl    %eax, %ebp
104         movl    %edx, %edi
105         subl    $8, %esp
106
107         /* Get current time.  */
108 2:      movl    %esp, %ebx
109         xorl    %ecx, %ecx
110         movl    $SYS_gettimeofday, %eax
111         ENTER_KERNEL
112
113         /* Compute relative timeout.  */
114         movl    4(%esp), %eax
115         movl    $1000, %edx
116         mul     %edx            /* Milli seconds to nano seconds.  */
117         movl    (%edi), %ecx
118         movl    4(%edi), %edx
119         subl    (%esp), %ecx
120         subl    %eax, %edx
121         jns     5f
122         addl    $1000000000, %edx
123         decl    %ecx
124 5:      testl   %ecx, %ecx
125         js      6f              /* Time is already up.  */
126
127         movl    %ecx, (%esp)    /* Store relative timeout.  */
128         movl    %edx, 4(%esp)
129
130         movl    (%ebp), %edx
131         testl   %edx, %edx
132         jz      4f
133
134         movl    %esp, %esi
135         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
136         movl    %ebp, %ebx
137         movl    $SYS_futex, %eax
138         ENTER_KERNEL
139
140         movl    %eax, %edx
141
142         cmpl    $0, (%ebx)
143         jne     1f
144 4:      xorl    %eax, %eax
145
146 3:      addl    $8, %esp
147         popl    %ebp
148         popl    %ebx
149         popl    %esi
150         popl    %edi
151         ret
152
153 1:      cmpl    $-ETIMEDOUT, %edx
154         jne     2b
155 6:      movl    $ETIMEDOUT, %eax
156         jmp     3b
157         .size   __lll_timedwait_tid,.-__lll_timedwait_tid