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