sem_timedwait implementation on Linux/SH.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_barrier_wait.S
1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <sysdep.h>
20 #include "lowlevel-atomic.h"
21
22 #define SYS_futex       240
23 #define FUTEX_WAIT      0
24 #define FUTEX_WAKE      1
25
26 #define CURR_EVENT      0
27 #define MUTEX           4
28 #define LEFT            8
29 #define INIT_COUNT      12
30
31
32         .text
33
34         .globl  pthread_barrier_wait
35         .type   pthread_barrier_wait,@function
36         .align  5
37 pthread_barrier_wait:
38         mov.l   r9, @-r15
39         mov.l   r8, @-r15
40         sts.l   pr, @-r15
41         mov     r4, r8
42
43         /* Get the mutex.  */
44         mov     #-1, r3
45         XADD (r3, @(MUTEX,r8), r2)
46         tst     r3, r3
47         bf      1f
48
49         /* One less waiter.  If this was the last one needed wake
50            everybody.  */
51 2:
52         mov.l   @(LEFT,r8), r0
53         add     #-1, r0
54         mov.l   r0, @(LEFT,r8)
55         tst     r0, r0
56         bt      3f
57
58         /* There are more threads to come.  */
59         mov.l   @(CURR_EVENT,r8), r6
60
61         /* Release the mutex.  */
62         INC (@(MUTEX,r8), r2)
63         cmp/pl  r2
64         bf      6f
65 7:
66         /* Wait for the remaining threads.  The call will return immediately
67            if the CURR_EVENT memory has meanwhile been changed.  */
68         mov     r8, r4
69 #if CURR_EVENT != 0
70         add     #CURR_EVENT, r4
71 #endif
72         mov     #FUTEX_WAIT, r5
73         mov     #0, r7
74 8:
75         mov     #SYS_futex, r3
76         extu.b  r3, r3
77         trapa   #0x14
78         SYSCALL_INST_PAD
79
80         /* Don't return on spurious wakeups.  The syscall does not change
81            any register except r0 so there is no need to reload any of
82            them.  */
83         mov.l   @(CURR_EVENT,r8), r0
84         cmp/eq  r0, r6
85         bt      8b
86
87         mov     #0, r0          /* != PTHREAD_BARRIER_SERIAL_THREAD */
88         lds.l   @r15+, pr
89         mov.l   @r15+, r8
90         rts
91          mov.l  @r15+, r9
92
93 3:      
94         /* The necessary number of threads arrived.  */
95         mov.l   @(INIT_COUNT,r8), r0
96         mov.l   r0, @(LEFT,r8)
97         mov.l   @(CURR_EVENT,r8), r1
98         add     #1, r1
99         mov.l   r1, @(CURR_EVENT,r8)
100
101         /* Wake up all waiters.  The count is a signed number in the kernel
102            so 0x7fffffff is the highest value.  */
103         mov.l   .Lall, r6
104         mov     r8, r4
105 #if CURR_EVENT != 0
106         add     #CURR_EVENT, r4
107 #endif
108         mov     #0, r7
109         mov     #FUTEX_WAKE, r5
110         mov     #SYS_futex, r3
111         extu.b  r3, r3
112         trapa   #0x14
113         SYSCALL_INST_PAD
114
115         /* Release the mutex.  */
116         INC (@(MUTEX,r8), r2)
117         cmp/pl  r2
118         bf      4f
119 5:
120         mov     #-1, r0         /* == PTHREAD_BARRIER_SERIAL_THREAD */
121         lds.l   @r15+, pr
122         mov.l   @r15+, r8
123         ret
124          mov.l  @r15+, r9
125
126 1:
127         mov     r2, r4
128         mov     r8, r5
129         mov.l   .Lwait0, r1
130         bsrf    r1
131          add    #MUTEX, r5
132 .Lwait0b:
133         bra     2b
134          nop
135
136 4:
137         mov     r8, r4
138         mov.l   .Lwake0, r1
139         bsrf    r1
140          add    #MUTEX, r4
141 .Lwake0b:
142         bra     5b
143          nop
144
145 6:
146         mov     r6, r9
147         mov     r8, r4
148         mov.l   .Lwake1, r1
149         bsrf    r1
150          add    #MUTEX, r4
151 .Lwake1b:
152         bra     7b
153          mov    r9, r6
154
155         .align  2
156 .Lall:
157         .long   0x7fffffff
158 .Lwait0:
159         .long   __lll_lock_wait-.Lwait0b
160 .Lwake0:
161         .long   __lll_unlock_wake-.Lwake0b
162 .Lwake1:
163         .long   __lll_unlock_wake-.Lwake1b      
164         .size   pthread_barrier_wait,.-pthread_barrier_wait