a77b7d5965e4972598018dafd891983d69343c83
[platform/upstream/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_signal.S
1 /* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc.
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
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdep.h>
20 #include <shlib-compat.h>
21 #include <lowlevellock.h>
22 #include <lowlevelcond.h>
23 #include <pthread-pi-defines.h>
24 #include <kernel-features.h>
25 #include <pthread-errnos.h>
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.  */
37         movq    %rdi, %r8
38         movl    $1, %esi
39         xorl    %eax, %eax
40         LOCK
41 #if cond_lock == 0
42         cmpxchgl %esi, (%rdi)
43 #else
44         cmpxchgl %esi, cond_lock(%rdi)
45 #endif
46         jnz     1f
47
48 2:      addq    $cond_futex, %rdi
49         movq    total_seq(%r8), %rcx
50         cmpq    wakeup_seq(%r8), %rcx
51         jbe     4f
52
53         /* Bump the wakeup number.  */
54         addq    $1, wakeup_seq(%r8)
55         addl    $1, (%rdi)
56
57         /* Wake up one thread.  */
58         LP_OP(cmp) $-1, dep_mutex(%r8)
59         movl    $FUTEX_WAKE_OP, %esi
60         movl    $1, %edx
61         movl    $SYS_futex, %eax
62         je      8f
63
64         /* Get the address of the mutex used.  */
65         mov     dep_mutex(%r8), %RCX_LP
66         movl    MUTEX_KIND(%rcx), %r11d
67         andl    $(ROBUST_BIT|PI_BIT), %r11d
68         cmpl    $PI_BIT, %r11d
69         je      9f
70
71 #ifdef __ASSUME_PRIVATE_FUTEX
72         movl    $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi
73 #else
74         orl     %fs:PRIVATE_FUTEX, %esi
75 #endif
76
77 8:      movl    $1, %r10d
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
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
115         movl    $SYS_futex, %eax
116         /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
117         movl    $1, %edx  */
118         syscall
119
120         /* Unlock.  */
121 4:      LOCK
122 #if cond_lock == 0
123         decl    (%r8)
124 #else
125         decl    cond_lock(%r8)
126 #endif
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
137         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
138         movl    $LLL_PRIVATE, %eax
139         movl    $LLL_SHARED, %esi
140         cmovne  %eax, %esi
141         callq   __lll_lock_wait
142 #if cond_lock != 0
143         subq    $cond_lock, %rdi
144 #endif
145         jmp     2b
146
147         /* Unlock in loop requires wakeup.  */
148 5:
149         movq    %r8, %rdi
150 #if cond_lock != 0
151         addq    $cond_lock, %rdi
152 #endif
153         LP_OP(cmp) $-1, dep_mutex-cond_lock(%rdi)
154         movl    $LLL_PRIVATE, %eax
155         movl    $LLL_SHARED, %esi
156         cmovne  %eax, %esi
157         callq   __lll_unlock_wake
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)