2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / pthread_cond_signal.S
blob9cb73a233c41952f43699ae18a609d9efda3a751
1 /* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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.
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.
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.  */
19 #include <sysdep.h>
20 #include <shlib-compat.h>
21 #include <lowlevellock.h>
22 #include <lowlevelcond.h>
23 #include <kernel-features.h>
24 #include <pthread-errnos.h>
25 #include "lowlevel-atomic.h"
27         .text
29         /* int pthread_cond_signal (pthread_cond_t *cond) */
30         .globl  __pthread_cond_signal
31         .type   __pthread_cond_signal, @function
32         .align  5
33 __pthread_cond_signal:
34         mov.l   r8, @-r15
35         sts.l   pr, @-r15
36         mov     r4, r8
38         /* Get internal lock.  */
39         mov     #0, r3
40         mov     #1, r4
41 #if cond_lock != 0
42         CMPXCHG (r3, @(cond_lock,r8), r4, r2)
43 #else
44         CMPXCHG (r3, @r8, r4, r2)
45 #endif
46         bf      1f
48         mov.l   @(total_seq+4,r8),r0
49         mov.l   @(total_seq,r8),r1
50         mov.l   @(wakeup_seq+4,r8), r2
51         cmp/hi  r2, r0
52         bt      3f
53         cmp/hi  r0, r2
54         bt      4f
55         mov.l   @(wakeup_seq,r8), r2
56         cmp/hi  r2, r1
57         bf      4f
60         /* Bump the wakeup number.  */
61         mov     #1, r2
62         mov     #0, r3
63         clrt
64         mov.l   @(wakeup_seq,r8),r0
65         mov.l   @(wakeup_seq+4,r8),r1
66         addc    r2, r0
67         addc    r3, r1
68         mov.l   r0,@(wakeup_seq,r8)
69         mov.l   r1,@(wakeup_seq+4,r8)
70         mov.l   @(cond_futex,r8),r0
71         add     r2, r0
72         mov.l   r0,@(cond_futex,r8)
74         /* Wake up one thread.  */
75         mov     r8, r4
76         add     #cond_futex, r4
77         mov.l   @(dep_mutex,r8), r0
78         cmp/eq  #-1, r0
79         bt/s    99f
80          mov    #FUTEX_WAKE_OP, r5
81 #ifdef __ASSUME_PRIVATE_FUTEX
82         mov     #(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), r5
83         extu.b  r5, r5
84 #else
85         stc     gbr, r1
86         mov.w   .Lpfoff, r2
87         add     r2, r1
88         mov.l   @r1, r5
89         mov     #FUTEX_WAKE_OP, r0
90         or      r0, r5
91 #endif
92 99:
93         mov     #1, r6
94         mov     #0, r7
95         mov     r8, r0
96         add     #cond_lock, r0
97         mov.l   .Lfutexop, r1
98         mov     #SYS_futex, r3
99         extu.b  r3, r3
100         trapa   #0x14
101         SYSCALL_INST_PAD
103         /* For any kind of error, we try again with WAKE.
104            The general test also covers running on old kernels.  */
105         mov     r0, r1
106         mov     #-12, r2
107         shad    r2, r1
108         not     r1, r1
109         tst     r1, r1
110         bt      7f
113         mov     #0, r0
114         lds.l   @r15+, pr
115         rts
116          mov.l  @r15+, r8
118 #ifndef __ASSUME_PRIVATE_FUTEX
119 .Lpfoff:
120         .word   PRIVATE_FUTEX - TLS_PRE_TCB_SIZE
121 #endif
122         .align  2
123 .Lfutexop:
124         .long   FUTEX_OP_CLEAR_WAKE_IF_GT_ONE
127         /* r5 should be either FUTEX_WAKE_OP or
128            FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall.  */
129         mov     #(FUTEX_WAKE ^ FUTEX_WAKE_OP), r0
130         xor     r0, r5
131         trapa   #0x14
132         SYSCALL_INST_PAD
135         /* Unlock.  */
136 #if cond_lock != 0
137         DEC (@(cond_lock,r8), r2)
138 #else
139         DEC (@r8, r2)
140 #endif
141         tst     r2, r2
142         bt      6b
145         /* Unlock in loop requires wakeup.  */
146         mov     r8, r4
147 #if cond_lock != 0
148         add     #cond_lock, r4
149 #endif
150         mov.l   @(dep_mutex,r8), r0
151         cmp/eq  #-1, r0
152         bf/s    99f
153          mov    #LLL_PRIVATE, r5
154         mov     #LLL_SHARED, r5
155 99:     
156         mov.l   .Lwake4, r1
157         bsrf    r1
158          extu.b r5, r5
159 .Lwake4b:
160         bra     6b
161          nop
164         /* Initial locking failed.  */
165         mov     r8, r5
166 #if cond_lock != 0
167         add     #cond_lock, r5
168 #endif
169         mov.l   @(dep_mutex,r8), r0
170         cmp/eq  #-1, r0
171         bf/s    99f
172          mov    #LLL_PRIVATE, r6
173         mov     #LLL_SHARED, r6
174 99:     
175         extu.b  r6, r6
176         mov.l   .Lwait4, r1
177         bsrf    r1
178          mov    r2, r4
179 .Lwait4b:
180         bra     2b
181          nop
183         .align  2
184 .Lwait4:
185         .long   __lll_lock_wait-.Lwait4b
186 .Lwake4:
187         .long   __lll_unlock_wake-.Lwake4b
188         .size   __pthread_cond_signal, .-__pthread_cond_signal
189 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
190                   GLIBC_2_3_2)