]>
Commit | Line | Data |
---|---|---|
f7a9f785 | 1 | /* Copyright (C) 2002-2016 Free Software Foundation, Inc. |
d0aacb47 UD |
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 | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
d0aacb47 UD |
18 | |
19 | #include <sysdep.h> | |
20 | #include <shlib-compat.h> | |
e51deae7 | 21 | #include <lowlevellock.h> |
d0aacb47 | 22 | #include <lowlevelcond.h> |
42e69bcf | 23 | #include <pthread-pi-defines.h> |
69431c9a | 24 | #include <kernel-features.h> |
e51deae7 | 25 | #include <pthread-errnos.h> |
5acf7263 | 26 | #include <stap-probe.h> |
d0aacb47 UD |
27 | |
28 | ||
29 | .text | |
30 | ||
31 | /* int pthread_cond_signal (pthread_cond_t *cond) */ | |
32 | .globl __pthread_cond_signal | |
33 | .type __pthread_cond_signal, @function | |
34 | .align 16 | |
35 | __pthread_cond_signal: | |
36 | ||
5acf7263 RM |
37 | LIBC_PROBE (cond_signal, 1, %rdi) |
38 | ||
d0aacb47 | 39 | /* Get internal lock. */ |
7661d9f7 | 40 | movq %rdi, %r8 |
d0aacb47 | 41 | movl $1, %esi |
3a226d33 | 42 | xorl %eax, %eax |
d0aacb47 UD |
43 | LOCK |
44 | #if cond_lock == 0 | |
3a226d33 | 45 | cmpxchgl %esi, (%rdi) |
d0aacb47 | 46 | #else |
3a226d33 | 47 | cmpxchgl %esi, cond_lock(%rdi) |
d0aacb47 | 48 | #endif |
3a226d33 | 49 | jnz 1f |
d0aacb47 | 50 | |
75fccede | 51 | 2: addq $cond_futex, %rdi |
69431c9a | 52 | movq total_seq(%r8), %rcx |
75fccede | 53 | cmpq wakeup_seq(%r8), %rcx |
d0aacb47 UD |
54 | jbe 4f |
55 | ||
56 | /* Bump the wakeup number. */ | |
75fccede UD |
57 | addq $1, wakeup_seq(%r8) |
58 | addl $1, (%rdi) | |
d0aacb47 UD |
59 | |
60 | /* Wake up one thread. */ | |
d9754f55 | 61 | LP_OP(cmp) $-1, dep_mutex(%r8) |
42e69bcf | 62 | movl $FUTEX_WAKE_OP, %esi |
ee618985 | 63 | movl $1, %edx |
42e69bcf UD |
64 | movl $SYS_futex, %eax |
65 | je 8f | |
66 | ||
67 | /* Get the address of the mutex used. */ | |
d9754f55 | 68 | mov dep_mutex(%r8), %RCX_LP |
ec492239 AS |
69 | movl MUTEX_KIND(%rcx), %r11d |
70 | andl $(ROBUST_BIT|PI_BIT), %r11d | |
71 | cmpl $PI_BIT, %r11d | |
b0948ffd | 72 | je 9f |
42e69bcf | 73 | |
5bd8a249 | 74 | #ifdef __ASSUME_PRIVATE_FUTEX |
5bd8a249 | 75 | movl $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi |
5bd8a249 | 76 | #else |
42e69bcf | 77 | orl %fs:PRIVATE_FUTEX, %esi |
5bd8a249 | 78 | #endif |
42e69bcf UD |
79 | |
80 | 8: movl $1, %r10d | |
a3615024 UD |
81 | #if cond_lock != 0 |
82 | addq $cond_lock, %r8 | |
83 | #endif | |
84 | movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d | |
85 | syscall | |
86 | #if cond_lock != 0 | |
87 | subq $cond_lock, %r8 | |
88 | #endif | |
89 | /* For any kind of error, we try again with WAKE. | |
90 | The general test also covers running on old kernels. */ | |
91 | cmpq $-4095, %rax | |
92 | jae 7f | |
93 | ||
94 | xorl %eax, %eax | |
95 | retq | |
96 | ||
42e69bcf UD |
97 | /* Wake up one thread and requeue none in the PI Mutex case. */ |
98 | 9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi | |
99 | movq %rcx, %r8 | |
100 | xorq %r10, %r10 | |
101 | movl (%rdi), %r9d // XXX Can this be right? | |
102 | syscall | |
103 | ||
104 | leaq -cond_futex(%rdi), %r8 | |
105 | ||
106 | /* For any kind of error, we try again with WAKE. | |
107 | The general test also covers running on old kernels. */ | |
108 | cmpq $-4095, %rax | |
109 | jb 4f | |
110 | ||
111 | 7: | |
112 | #ifdef __ASSUME_PRIVATE_FUTEX | |
113 | andl $FUTEX_PRIVATE_FLAG, %esi | |
114 | #else | |
115 | andl %fs:PRIVATE_FUTEX, %esi | |
116 | #endif | |
117 | orl $FUTEX_WAKE, %esi | |
a3615024 UD |
118 | movl $SYS_futex, %eax |
119 | /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall. | |
120 | movl $1, %edx */ | |
d0aacb47 UD |
121 | syscall |
122 | ||
123 | /* Unlock. */ | |
124 | 4: LOCK | |
7661d9f7 UD |
125 | #if cond_lock == 0 |
126 | decl (%r8) | |
127 | #else | |
69431c9a | 128 | decl cond_lock(%r8) |
7661d9f7 | 129 | #endif |
d0aacb47 UD |
130 | jne 5f |
131 | ||
132 | 6: xorl %eax, %eax | |
133 | retq | |
134 | ||
135 | /* Initial locking failed. */ | |
136 | 1: | |
137 | #if cond_lock != 0 | |
138 | addq $cond_lock, %rdi | |
139 | #endif | |
d9754f55 | 140 | LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) |
5bd8a249 | 141 | movl $LLL_PRIVATE, %eax |
e51deae7 | 142 | movl $LLL_SHARED, %esi |
5bd8a249 | 143 | cmovne %eax, %esi |
e51deae7 | 144 | callq __lll_lock_wait |
d0aacb47 UD |
145 | #if cond_lock != 0 |
146 | subq $cond_lock, %rdi | |
147 | #endif | |
148 | jmp 2b | |
149 | ||
7661d9f7 | 150 | /* Unlock in loop requires wakeup. */ |
69431c9a | 151 | 5: |
69431c9a | 152 | movq %r8, %rdi |
5bd8a249 UD |
153 | #if cond_lock != 0 |
154 | addq $cond_lock, %rdi | |
155 | #endif | |
d9754f55 | 156 | LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi) |
5bd8a249 | 157 | movl $LLL_PRIVATE, %eax |
e51deae7 | 158 | movl $LLL_SHARED, %esi |
5bd8a249 | 159 | cmovne %eax, %esi |
e51deae7 | 160 | callq __lll_unlock_wake |
d0aacb47 UD |
161 | jmp 6b |
162 | .size __pthread_cond_signal, .-__pthread_cond_signal | |
163 | versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, | |
164 | GLIBC_2_3_2) |