1/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 2 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. 5 6 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 The GNU C Library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with the GNU C Library; if not, see 18 <http://www.gnu.org/licenses/>. */ 19 20#include <sysdep.h> 21#include <lowlevellock.h> 22#include <lowlevelcond.h> 23#include <bits/kernel-features.h> 24#include <pthread-pi-defines.h> 25#include <pthread-errnos.h> 26 27 28 .text 29 30 /* int pthread_cond_broadcast (pthread_cond_t *cond) */ 31 .globl __pthread_cond_broadcast 32 .type __pthread_cond_broadcast, @function 33 .protected __pthread_cond_broadcast 34 .align 16 35__pthread_cond_broadcast: 36 37 /* Get internal lock. */ 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 482: addq $cond_futex, %rdi 49 movq total_seq-cond_futex(%rdi), %r9 50 cmpq wakeup_seq-cond_futex(%rdi), %r9 51 jna 4f 52 53 /* Cause all currently waiting threads to recognize they are 54 woken up. */ 55 movq %r9, wakeup_seq-cond_futex(%rdi) 56 movq %r9, woken_seq-cond_futex(%rdi) 57 addq %r9, %r9 58 movl %r9d, (%rdi) 59 incl broadcast_seq-cond_futex(%rdi) 60 61 /* Get the address of the mutex used. */ 62 movq dep_mutex-cond_futex(%rdi), %r8 63 64 /* Unlock. */ 65 LOCK 66 decl cond_lock-cond_futex(%rdi) 67 jne 7f 68 698: cmpq $-1, %r8 70 je 9f 71 72 /* Do not use requeue for pshared condvars. */ 73 testl $PS_BIT, MUTEX_KIND(%r8) 74 jne 9f 75 76 /* Requeue to a PI mutex if the PI bit is set. */ 77 movl MUTEX_KIND(%r8), %eax 78 andl $(ROBUST_BIT|PI_BIT), %eax 79 cmpl $PI_BIT, %eax 80 je 81f 81 82 /* Wake up all threads. */ 83#ifdef __ASSUME_PRIVATE_FUTEX 84 movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi 85#else 86 movl %fs:PRIVATE_FUTEX, %esi 87 orl $FUTEX_CMP_REQUEUE, %esi 88#endif 89 movl $SYS_futex, %eax 90 movl $1, %edx 91 movl $0x7fffffff, %r10d 92 syscall 93 94 /* For any kind of error, which mainly is EAGAIN, we try again 95 with WAKE. The general test also covers running on old 96 kernels. */ 97 cmpq $-4095, %rax 98 jae 9f 99 10010: xorl %eax, %eax 101 retq 102 103 /* Wake up all threads. */ 10481: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi 105 movl $SYS_futex, %eax 106 movl $1, %edx 107 movl $0x7fffffff, %r10d 108 syscall 109 110 /* For any kind of error, which mainly is EAGAIN, we try again 111 with WAKE. The general test also covers running on old 112 kernels. */ 113 cmpq $-4095, %rax 114 jb 10b 115 jmp 9f 116 117 .align 16 118 /* Unlock. */ 1194: LOCK 120 decl cond_lock-cond_futex(%rdi) 121 jne 5f 122 1236: xorl %eax, %eax 124 retq 125 126 /* Initial locking failed. */ 1271: 128#if cond_lock != 0 129 addq $cond_lock, %rdi 130#endif 131 cmpq $-1, dep_mutex-cond_lock(%rdi) 132 movl $LLL_PRIVATE, %eax 133 movl $LLL_SHARED, %esi 134 cmovne %eax, %esi 135 callq __lll_lock_wait 136#if cond_lock != 0 137 subq $cond_lock, %rdi 138#endif 139 jmp 2b 140 141 /* Unlock in loop requires wakeup. */ 1425: addq $cond_lock-cond_futex, %rdi 143 cmpq $-1, dep_mutex-cond_lock(%rdi) 144 movl $LLL_PRIVATE, %eax 145 movl $LLL_SHARED, %esi 146 cmovne %eax, %esi 147 callq __lll_unlock_wake 148 jmp 6b 149 150 /* Unlock in loop requires wakeup. */ 1517: addq $cond_lock-cond_futex, %rdi 152 cmpq $-1, %r8 153 movl $LLL_PRIVATE, %eax 154 movl $LLL_SHARED, %esi 155 cmovne %eax, %esi 156 callq __lll_unlock_wake 157 subq $cond_lock-cond_futex, %rdi 158 jmp 8b 159 1609: /* The futex requeue functionality is not available. */ 161 cmpq $-1, %r8 162 movl $0x7fffffff, %edx 163#ifdef __ASSUME_PRIVATE_FUTEX 164 movl $FUTEX_WAKE, %eax 165 movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi 166 cmove %eax, %esi 167#else 168 movl $0, %eax 169 movl %fs:PRIVATE_FUTEX, %esi 170 cmove %eax, %esi 171 orl $FUTEX_WAKE, %esi 172#endif 173 movl $SYS_futex, %eax 174 syscall 175 jmp 10b 176 .size __pthread_cond_broadcast, .-__pthread_cond_broadcast 177weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) 178