xf.li | bfc6e71 | 2025-02-07 01:54:34 -0800 | [diff] [blame^] | 1 | /* Copyright (C) 2003-2016 Free Software Foundation, Inc. |
| 2 | This file is part of the GNU C Library. |
| 3 | Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003. |
| 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 <endian.h> |
| 20 | #include <errno.h> |
| 21 | #include <sysdep.h> |
| 22 | #include <lowlevellock.h> |
| 23 | #include <pthread.h> |
| 24 | #include <pthreadP.h> |
| 25 | #include <stap-probe.h> |
| 26 | |
| 27 | #include <shlib-compat.h> |
| 28 | #include <kernel-features.h> |
| 29 | |
| 30 | |
| 31 | int |
| 32 | __pthread_cond_broadcast (pthread_cond_t *cond) |
| 33 | { |
| 34 | LIBC_PROBE (cond_broadcast, 1, cond); |
| 35 | |
| 36 | int pshared = (cond->__data.__mutex == (void *) ~0l) |
| 37 | ? LLL_SHARED : LLL_PRIVATE; |
| 38 | /* Make sure we are alone. */ |
| 39 | lll_lock (cond->__data.__lock, pshared); |
| 40 | |
| 41 | /* Are there any waiters to be woken? */ |
| 42 | if (cond->__data.__total_seq > cond->__data.__wakeup_seq) |
| 43 | { |
| 44 | /* Yes. Mark them all as woken. */ |
| 45 | cond->__data.__wakeup_seq = cond->__data.__total_seq; |
| 46 | cond->__data.__woken_seq = cond->__data.__total_seq; |
| 47 | cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; |
| 48 | int futex_val = cond->__data.__futex; |
| 49 | /* Signal that a broadcast happened. */ |
| 50 | ++cond->__data.__broadcast_seq; |
| 51 | |
| 52 | /* We are done. */ |
| 53 | lll_unlock (cond->__data.__lock, pshared); |
| 54 | |
| 55 | /* Wake everybody. */ |
| 56 | pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; |
| 57 | |
| 58 | /* Do not use requeue for pshared condvars. */ |
| 59 | if (mut == (void *) ~0l |
| 60 | || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT) |
| 61 | goto wake_all; |
| 62 | |
| 63 | #if (defined lll_futex_cmp_requeue_pi \ |
| 64 | && defined __ASSUME_REQUEUE_PI) |
| 65 | if (USE_REQUEUE_PI (mut)) |
| 66 | { |
| 67 | if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX, |
| 68 | &mut->__data.__lock, futex_val, |
| 69 | LLL_PRIVATE) == 0) |
| 70 | return 0; |
| 71 | } |
| 72 | else |
| 73 | #endif |
| 74 | /* lll_futex_requeue returns 0 for success and non-zero |
| 75 | for errors. */ |
| 76 | if (!__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, |
| 77 | INT_MAX, &mut->__data.__lock, |
| 78 | futex_val, LLL_PRIVATE), 0)) |
| 79 | return 0; |
| 80 | |
| 81 | wake_all: |
| 82 | lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared); |
| 83 | return 0; |
| 84 | } |
| 85 | |
| 86 | /* We are done. */ |
| 87 | lll_unlock (cond->__data.__lock, pshared); |
| 88 | |
| 89 | return 0; |
| 90 | } |
| 91 | |
| 92 | versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, |
| 93 | GLIBC_2_3_2); |