2.9
[glibc/nacl-glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_signal.S
blob8f65f2cd69ad1956206d74dc22fb73a386ef6df6
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <shlib-compat.h>
22 #include <lowlevellock.h>
23 #include <lowlevelcond.h>
24 #include <kernel-features.h>
25 #include <pthread-errnos.h>
28         .text
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:
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
48 2:      addq    $cond_futex, %rdi
49         movq    total_seq(%r8), %rcx
50         cmpq    wakeup_seq(%r8), %rcx
51         jbe     4f
53         /* Bump the wakeup number.  */
54         addq    $1, wakeup_seq(%r8)
55         addl    $1, (%rdi)
57         /* Wake up one thread.  */
58         cmpq    $-1, dep_mutex(%r8)
59         movl    $1, %edx
60 #ifdef __ASSUME_PRIVATE_FUTEX
61         movl    $FUTEX_WAKE_OP, %eax
62         movl    $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi
63         cmove   %eax, %esi
64 #else
65         movl    $0, %eax
66         movl    %fs:PRIVATE_FUTEX, %esi
67         cmove   %eax, %esi
68         orl     $FUTEX_WAKE_OP, %esi
69 #endif
70         movl    $1, %r10d
71         movl    $SYS_futex, %eax
72 #if cond_lock != 0
73         addq    $cond_lock, %r8
74 #endif
75         movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
76         syscall
77 #if cond_lock != 0
78         subq    $cond_lock, %r8
79 #endif
80         /* For any kind of error, we try again with WAKE.
81            The general test also covers running on old kernels.  */
82         cmpq    $-4095, %rax
83         jae     7f
85         xorl    %eax, %eax
86         retq
88 7:      /* %esi should be either FUTEX_WAKE_OP or
89            FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall.  */
90         xorl    $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %esi
91         movl    $SYS_futex, %eax
92         /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
93         movl    $1, %edx  */
94         syscall
96         /* Unlock.  */
97 4:      LOCK
98 #if cond_lock == 0
99         decl    (%r8)
100 #else
101         decl    cond_lock(%r8)
102 #endif
103         jne     5f
105 6:      xorl    %eax, %eax
106         retq
108         /* Initial locking failed.  */
110 #if cond_lock != 0
111         addq    $cond_lock, %rdi
112 #endif
113         cmpq    $-1, dep_mutex-cond_lock(%rdi)
114         movl    $LLL_PRIVATE, %eax
115         movl    $LLL_SHARED, %esi
116         cmovne  %eax, %esi
117         callq   __lll_lock_wait
118 #if cond_lock != 0
119         subq    $cond_lock, %rdi
120 #endif
121         jmp     2b
123         /* Unlock in loop requires wakeup.  */
125         movq    %r8, %rdi
126 #if cond_lock != 0
127         addq    $cond_lock, %rdi
128 #endif
129         cmpq    $-1, dep_mutex-cond_lock(%rdi)
130         movl    $LLL_PRIVATE, %eax
131         movl    $LLL_SHARED, %esi
132         cmovne  %eax, %esi
133         callq   __lll_unlock_wake
134         jmp     6b
135         .size   __pthread_cond_signal, .-__pthread_cond_signal
136 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
137                   GLIBC_2_3_2)