Support requeueing for condvars using PI mutex. x86-64 only.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / pthread_cond_signal.S
blobf1050fea7c55a6cacde6c0b07b52c655c510c41c
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.
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 <pthread-pi-defines.h>
25 #include <kernel-features.h>
26 #include <pthread-errnos.h>
29         .text
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:
37         /* Get internal lock.  */
38         movq    %rdi, %r8
39         movl    $1, %esi
40         xorl    %eax, %eax
41         LOCK
42 #if cond_lock == 0
43         cmpxchgl %esi, (%rdi)
44 #else
45         cmpxchgl %esi, cond_lock(%rdi)
46 #endif
47         jnz     1f
49 2:      addq    $cond_futex, %rdi
50         movq    total_seq(%r8), %rcx
51         cmpq    wakeup_seq(%r8), %rcx
52         jbe     4f
54         /* Bump the wakeup number.  */
55         addq    $1, wakeup_seq(%r8)
56         addl    $1, (%rdi)
58         /* Wake up one thread.  */
59         cmpq    $-1, dep_mutex(%r8)
60         movl    $FUTEX_WAKE_OP, %esi
61         movl    $1, %edx
62         movl    $SYS_futex, %eax
63         je      8f
65         /* Get the address of the mutex used.  */
66         movq    dep_mutex(%r8), %rcx
67         testl   $PI_BIT, MUTEX_KIND(%rcx)
68         jne     9f
70 #ifdef __ASSUME_PRIVATE_FUTEX
71         movl    $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi
72 #else
73         orl     %fs:PRIVATE_FUTEX, %esi
74 #endif
76 8:      movl    $1, %r10d
77 #if cond_lock != 0
78         addq    $cond_lock, %r8
79 #endif
80         movl    $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d
81         syscall
82 #if cond_lock != 0
83         subq    $cond_lock, %r8
84 #endif
85         /* For any kind of error, we try again with WAKE.
86            The general test also covers running on old kernels.  */
87         cmpq    $-4095, %rax
88         jae     7f
90         xorl    %eax, %eax
91         retq
93         /* Wake up one thread and requeue none in the PI Mutex case.  */
94 9:      movl    $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi
95         movq    %rcx, %r8
96         xorq    %r10, %r10
97         movl    (%rdi), %r9d    // XXX Can this be right?
98         syscall
100         leaq    -cond_futex(%rdi), %r8
102         /* For any kind of error, we try again with WAKE.
103            The general test also covers running on old kernels.  */
104         cmpq    $-4095, %rax
105         jb      4f
108 #ifdef __ASSUME_PRIVATE_FUTEX
109         andl    $FUTEX_PRIVATE_FLAG, %esi
110 #else
111         andl    %fs:PRIVATE_FUTEX, %esi
112 #endif
113         orl     $FUTEX_WAKE, %esi
114         movl    $SYS_futex, %eax
115         /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall.
116         movl    $1, %edx  */
117         syscall
119         /* Unlock.  */
120 4:      LOCK
121 #if cond_lock == 0
122         decl    (%r8)
123 #else
124         decl    cond_lock(%r8)
125 #endif
126         jne     5f
128 6:      xorl    %eax, %eax
129         retq
131         /* Initial locking failed.  */
133 #if cond_lock != 0
134         addq    $cond_lock, %rdi
135 #endif
136         cmpq    $-1, dep_mutex-cond_lock(%rdi)
137         movl    $LLL_PRIVATE, %eax
138         movl    $LLL_SHARED, %esi
139         cmovne  %eax, %esi
140         callq   __lll_lock_wait
141 #if cond_lock != 0
142         subq    $cond_lock, %rdi
143 #endif
144         jmp     2b
146         /* Unlock in loop requires wakeup.  */
148         movq    %r8, %rdi
149 #if cond_lock != 0
150         addq    $cond_lock, %rdi
151 #endif
152         cmpq    $-1, dep_mutex-cond_lock(%rdi)
153         movl    $LLL_PRIVATE, %eax
154         movl    $LLL_SHARED, %esi
155         cmovne  %eax, %esi
156         callq   __lll_unlock_wake
157         jmp     6b
158         .size   __pthread_cond_signal, .-__pthread_cond_signal
159 versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
160                   GLIBC_2_3_2)