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