1 /* Set current priority ceiling of pthread_mutex_t.
2 Copyright (C) 2006-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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, see
17 <https://www.gnu.org/licenses/>. */
23 #include <futex-internal.h>
24 #include <shlib-compat.h>
27 __pthread_mutex_setprioceiling (pthread_mutex_t
*mutex
, int prioceiling
,
30 /* See concurrency notes regarding __kind in struct __pthread_mutex_s
31 in sysdeps/nptl/bits/thread-shared-types.h. */
32 if ((atomic_load_relaxed (&(mutex
->__data
.__kind
))
33 & PTHREAD_MUTEX_PRIO_PROTECT_NP
) == 0)
36 /* See __init_sched_fifo_prio. */
37 if (atomic_load_relaxed (&__sched_fifo_min_prio
) == -1
38 || atomic_load_relaxed (&__sched_fifo_max_prio
) == -1)
39 __init_sched_fifo_prio ();
41 if (__glibc_unlikely (prioceiling
42 < atomic_load_relaxed (&__sched_fifo_min_prio
))
43 || __glibc_unlikely (prioceiling
44 > atomic_load_relaxed (&__sched_fifo_max_prio
))
45 || __glibc_unlikely ((prioceiling
46 & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK
47 >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT
))
51 /* Check whether we already hold the mutex. */
53 int kind
= PTHREAD_MUTEX_TYPE (mutex
);
54 if (mutex
->__data
.__owner
== THREAD_GETMEM (THREAD_SELF
, tid
))
56 if (kind
== PTHREAD_MUTEX_PP_ERRORCHECK_NP
)
59 if (kind
== PTHREAD_MUTEX_PP_RECURSIVE_NP
)
63 int oldval
= mutex
->__data
.__lock
;
67 /* Need to lock the mutex, but without obeying the priority
69 int ceilval
= (oldval
& PTHREAD_MUTEX_PRIO_CEILING_MASK
);
71 oldval
= atomic_compare_and_exchange_val_acq (&mutex
->__data
.__lock
,
72 ceilval
| 1, ceilval
);
73 if (oldval
== ceilval
)
79 = atomic_compare_and_exchange_val_acq (&mutex
->__data
.__lock
,
83 if ((oldval
& PTHREAD_MUTEX_PRIO_CEILING_MASK
) != ceilval
)
86 if (oldval
!= ceilval
)
87 futex_wait ((unsigned int *) &mutex
->__data
.__lock
, ceilval
| 2,
88 PTHREAD_MUTEX_PSHARED (mutex
));
90 while (atomic_compare_and_exchange_val_acq (&mutex
->__data
.__lock
,
94 if ((oldval
& PTHREAD_MUTEX_PRIO_CEILING_MASK
) != ceilval
)
99 int oldprio
= (oldval
& PTHREAD_MUTEX_PRIO_CEILING_MASK
)
100 >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT
;
103 int ret
= __pthread_tpp_change_priority (oldprio
, prioceiling
);
108 if (old_ceiling
!= NULL
)
109 *old_ceiling
= oldprio
;
113 newlock
= (mutex
->__data
.__lock
& ~PTHREAD_MUTEX_PRIO_CEILING_MASK
);
114 mutex
->__data
.__lock
= newlock
115 | (prioceiling
<< PTHREAD_MUTEX_PRIO_CEILING_SHIFT
);
116 atomic_full_barrier ();
118 futex_wake ((unsigned int *)&mutex
->__data
.__lock
, INT_MAX
,
119 PTHREAD_MUTEX_PSHARED (mutex
));
123 versioned_symbol (libc
, __pthread_mutex_setprioceiling
,
124 pthread_mutex_setprioceiling
, GLIBC_2_34
);
126 #if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_4, GLIBC_2_34)
127 compat_symbol (libpthread
, __pthread_mutex_setprioceiling
,
128 pthread_mutex_setprioceiling
, GLIBC_2_4
);