diff options
| -rw-r--r-- | meta/recipes-core/glibc/glibc/0026-PR25847-9.patch | 193 | ||||
| -rw-r--r-- | meta/recipes-core/glibc/glibc_2.35.bb | 1 |
2 files changed, 194 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/0026-PR25847-9.patch b/meta/recipes-core/glibc/glibc/0026-PR25847-9.patch new file mode 100644 index 0000000000..49815c6fb7 --- /dev/null +++ b/meta/recipes-core/glibc/glibc/0026-PR25847-9.patch | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | From c2677e68956bb9677d8de4ee6c5341b1a744d490 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Malte Skarupke <malteskarupke@fastmail.fm> | ||
| 3 | Date: Tue, 14 Oct 2025 06:40:57 -0700 | ||
| 4 | Subject: [PATCH] nptl: Use all of g1_start and g_signals | ||
| 5 | |||
| 6 | The LSB of g_signals was unused. The LSB of g1_start was used to indicate | ||
| 7 | which group is G2. This was used to always go to sleep in pthread_cond_wait | ||
| 8 | if a waiter is in G2. A comment earlier in the file says that this is not | ||
| 9 | correct to do: | ||
| 10 | |||
| 11 | "Waiters cannot determine whether they are currently in G2 or G1 -- but they | ||
| 12 | do not have to because all they are interested in is whether there are | ||
| 13 | available signals" | ||
| 14 | |||
| 15 | I either would have had to update the comment, or get rid of the check. I | ||
| 16 | chose to get rid of the check. In fact I don't quite know why it was there. | ||
| 17 | There will never be available signals for group G2, so we didn't need the | ||
| 18 | special case. Even if there were, this would just be a spurious wake. This | ||
| 19 | might have caught some cases where the count has wrapped around, but it | ||
| 20 | wouldn't reliably do that, (and even if it did, why would you want to force a | ||
| 21 | sleep in that case?) and we don't support that many concurrent waiters | ||
| 22 | anyway. Getting rid of it allows us to use one more bit, making us more | ||
| 23 | robust to wraparound. | ||
| 24 | |||
| 25 | The following commits have been cherry-picked from Glibc master branch: | ||
| 26 | Bug : https://sourceware.org/bugzilla/show_bug.cgi?id=25847 | ||
| 27 | commit: 91bb902f58264a2fd50fbce8f39a9a290dd23706 | ||
| 28 | |||
| 29 | Upstream-Status: Submitted | ||
| 30 | [https://sourceware.org/pipermail/libc-stable/2025-July/002283.html] | ||
| 31 | |||
| 32 | Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com> | ||
| 33 | --- | ||
| 34 | nptl/pthread_cond_broadcast.c | 4 ++-- | ||
| 35 | nptl/pthread_cond_common.c | 26 ++++++++++---------------- | ||
| 36 | nptl/pthread_cond_signal.c | 2 +- | ||
| 37 | nptl/pthread_cond_wait.c | 14 +++++--------- | ||
| 38 | 4 files changed, 18 insertions(+), 28 deletions(-) | ||
| 39 | |||
| 40 | diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c | ||
| 41 | index a0743558..ef0943cd 100644 | ||
| 42 | --- a/nptl/pthread_cond_broadcast.c | ||
| 43 | +++ b/nptl/pthread_cond_broadcast.c | ||
| 44 | @@ -57,7 +57,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond) | ||
| 45 | { | ||
| 46 | /* Add as many signals as the remaining size of the group. */ | ||
| 47 | atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, | ||
| 48 | - cond->__data.__g_size[g1] << 1); | ||
| 49 | + cond->__data.__g_size[g1]); | ||
| 50 | cond->__data.__g_size[g1] = 0; | ||
| 51 | |||
| 52 | /* We need to wake G1 waiters before we switch G1 below. */ | ||
| 53 | @@ -73,7 +73,7 @@ ___pthread_cond_broadcast (pthread_cond_t *cond) | ||
| 54 | { | ||
| 55 | /* Step (3): Send signals to all waiters in the old G2 / new G1. */ | ||
| 56 | atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, | ||
| 57 | - cond->__data.__g_size[g1] << 1); | ||
| 58 | + cond->__data.__g_size[g1]); | ||
| 59 | cond->__data.__g_size[g1] = 0; | ||
| 60 | /* TODO Only set it if there are indeed futex waiters. */ | ||
| 61 | do_futex_wake = true; | ||
| 62 | diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c | ||
| 63 | index 3baac4da..e48f9143 100644 | ||
| 64 | --- a/nptl/pthread_cond_common.c | ||
| 65 | +++ b/nptl/pthread_cond_common.c | ||
| 66 | @@ -208,9 +208,9 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq, | ||
| 67 | behavior. | ||
| 68 | Note that this works correctly for a zero-initialized condvar too. */ | ||
| 69 | unsigned int old_orig_size = __condvar_get_orig_size (cond); | ||
| 70 | - uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1; | ||
| 71 | - if (((unsigned) (wseq - old_g1_start - old_orig_size) | ||
| 72 | - + cond->__data.__g_size[g1 ^ 1]) == 0) | ||
| 73 | + uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond); | ||
| 74 | + uint64_t new_g1_start = old_g1_start + old_orig_size; | ||
| 75 | + if (((unsigned) (wseq - new_g1_start) + cond->__data.__g_size[g1 ^ 1]) == 0) | ||
| 76 | return false; | ||
| 77 | |||
| 78 | /* We have to consider the following kinds of waiters: | ||
| 79 | @@ -221,16 +221,10 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq, | ||
| 80 | are not affected. | ||
| 81 | * Waiters in G1 have already received a signal and been woken. */ | ||
| 82 | |||
| 83 | - /* Update __g1_start, which closes this group. The value we add will never | ||
| 84 | - be negative because old_orig_size can only be zero when we switch groups | ||
| 85 | - the first time after a condvar was initialized, in which case G1 will be | ||
| 86 | - at index 1 and we will add a value of 1. Relaxed MO is fine because the | ||
| 87 | - change comes with no additional constraints that others would have to | ||
| 88 | - observe. */ | ||
| 89 | - __condvar_add_g1_start_relaxed (cond, | ||
| 90 | - (old_orig_size << 1) + (g1 == 1 ? 1 : - 1)); | ||
| 91 | - | ||
| 92 | - unsigned int lowseq = ((old_g1_start + old_orig_size) << 1) & ~1U; | ||
| 93 | + /* Update __g1_start, which closes this group. Relaxed MO is fine because | ||
| 94 | + the change comes with no additional constraints that others would have | ||
| 95 | + to observe. */ | ||
| 96 | + __condvar_add_g1_start_relaxed (cond, old_orig_size); | ||
| 97 | |||
| 98 | /* At this point, the old G1 is now a valid new G2 (but not in use yet). | ||
| 99 | No old waiter can neither grab a signal nor acquire a reference without | ||
| 100 | @@ -242,13 +236,13 @@ __condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq, | ||
| 101 | g1 ^= 1; | ||
| 102 | *g1index ^= 1; | ||
| 103 | |||
| 104 | - /* Now advance the new G1 g_signals to the new lowseq, giving it | ||
| 105 | + /* Now advance the new G1 g_signals to the new g1_start, giving it | ||
| 106 | an effective signal count of 0 to start. */ | ||
| 107 | - atomic_store_release (cond->__data.__g_signals + g1, lowseq); | ||
| 108 | + atomic_store_release (cond->__data.__g_signals + g1, (unsigned)new_g1_start); | ||
| 109 | |||
| 110 | /* These values are just observed by signalers, and thus protected by the | ||
| 111 | lock. */ | ||
| 112 | - unsigned int orig_size = wseq - (old_g1_start + old_orig_size); | ||
| 113 | + unsigned int orig_size = wseq - new_g1_start; | ||
| 114 | __condvar_set_orig_size (cond, orig_size); | ||
| 115 | /* Use and addition to not loose track of cancellations in what was | ||
| 116 | previously G2. */ | ||
| 117 | diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c | ||
| 118 | index a9bc10dc..07427369 100644 | ||
| 119 | --- a/nptl/pthread_cond_signal.c | ||
| 120 | +++ b/nptl/pthread_cond_signal.c | ||
| 121 | @@ -80,7 +80,7 @@ ___pthread_cond_signal (pthread_cond_t *cond) | ||
| 122 | release-MO store when initializing a group in __condvar_switch_g1 | ||
| 123 | because we use an atomic read-modify-write and thus extend that | ||
| 124 | store's release sequence. */ | ||
| 125 | - atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2); | ||
| 126 | + atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 1); | ||
| 127 | cond->__data.__g_size[g1]--; | ||
| 128 | /* TODO Only set it if there are indeed futex waiters. */ | ||
| 129 | do_futex_wake = true; | ||
| 130 | diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c | ||
| 131 | index 40a74342..d7e073ab 100644 | ||
| 132 | --- a/nptl/pthread_cond_wait.c | ||
| 133 | +++ b/nptl/pthread_cond_wait.c | ||
| 134 | @@ -84,7 +84,7 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g, | ||
| 135 | not hold a reference on the group. */ | ||
| 136 | __condvar_acquire_lock (cond, private); | ||
| 137 | |||
| 138 | - uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1; | ||
| 139 | + uint64_t g1_start = __condvar_load_g1_start_relaxed (cond); | ||
| 140 | if (g1_start > seq) | ||
| 141 | { | ||
| 142 | /* Our group is closed, so someone provided enough signals for it. | ||
| 143 | @@ -259,7 +259,6 @@ __condvar_cleanup_waiting (void *arg) | ||
| 144 | * Waiters fetch-add while having acquire the mutex associated with the | ||
| 145 | condvar. Signalers load it and fetch-xor it concurrently. | ||
| 146 | __g1_start: Starting position of G1 (inclusive) | ||
| 147 | - * LSB is index of current G2. | ||
| 148 | * Modified by signalers while having acquired the condvar-internal lock | ||
| 149 | and observed concurrently by waiters. | ||
| 150 | __g1_orig_size: Initial size of G1 | ||
| 151 | @@ -280,11 +279,9 @@ __condvar_cleanup_waiting (void *arg) | ||
| 152 | * Reference count used by waiters concurrently with signalers that have | ||
| 153 | acquired the condvar-internal lock. | ||
| 154 | __g_signals: The number of signals that can still be consumed, relative to | ||
| 155 | - the current g1_start. (i.e. bits 31 to 1 of __g_signals are bits | ||
| 156 | - 31 to 1 of g1_start with the signal count added) | ||
| 157 | + the current g1_start. (i.e. g1_start with the signal count added) | ||
| 158 | * Used as a futex word by waiters. Used concurrently by waiters and | ||
| 159 | signalers. | ||
| 160 | - * LSB is currently reserved and 0. | ||
| 161 | __g_size: Waiters remaining in this group (i.e., which have not been | ||
| 162 | signaled yet. | ||
| 163 | * Accessed by signalers and waiters that cancel waiting (both do so only | ||
| 164 | @@ -391,9 +388,8 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, | ||
| 165 | too. */ | ||
| 166 | unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g); | ||
| 167 | uint64_t g1_start = __condvar_load_g1_start_relaxed (cond); | ||
| 168 | - unsigned int lowseq = (g1_start & 1) == g ? signals : g1_start & ~1U; | ||
| 169 | |||
| 170 | - if (seq < (g1_start >> 1)) | ||
| 171 | + if (seq < g1_start) | ||
| 172 | { | ||
| 173 | /* If the group is closed already, | ||
| 174 | then this waiter originally had enough extra signals to | ||
| 175 | @@ -406,13 +402,13 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, | ||
| 176 | by now, perhaps in the process of switching back to an older | ||
| 177 | G2, but in either case we're allowed to consume the available | ||
| 178 | signal and should not block anymore. */ | ||
| 179 | - if ((int)(signals - lowseq) >= 2) | ||
| 180 | + if ((int)(signals - (unsigned int)g1_start) > 0) | ||
| 181 | { | ||
| 182 | /* Try to grab a signal. See above for MO. (if we do another loop | ||
| 183 | iteration we need to see the correct value of g1_start) */ | ||
| 184 | if (atomic_compare_exchange_weak_acquire ( | ||
| 185 | cond->__data.__g_signals + g, | ||
| 186 | - &signals, signals - 2)) | ||
| 187 | + &signals, signals - 1)) | ||
| 188 | break; | ||
| 189 | else | ||
| 190 | continue; | ||
| 191 | -- | ||
| 192 | 2.49.0 | ||
| 193 | |||
diff --git a/meta/recipes-core/glibc/glibc_2.35.bb b/meta/recipes-core/glibc/glibc_2.35.bb index 265dcb9129..26e8d8c408 100644 --- a/meta/recipes-core/glibc/glibc_2.35.bb +++ b/meta/recipes-core/glibc/glibc_2.35.bb | |||
| @@ -70,6 +70,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ | |||
| 70 | file://0026-PR25847-6.patch \ | 70 | file://0026-PR25847-6.patch \ |
| 71 | file://0026-PR25847-7.patch \ | 71 | file://0026-PR25847-7.patch \ |
| 72 | file://0026-PR25847-8.patch \ | 72 | file://0026-PR25847-8.patch \ |
| 73 | file://0026-PR25847-9.patch \ | ||
| 73 | \ | 74 | \ |
| 74 | file://0001-Revert-Linux-Implement-a-useful-version-of-_startup_.patch \ | 75 | file://0001-Revert-Linux-Implement-a-useful-version-of-_startup_.patch \ |
| 75 | file://0002-get_nscd_addresses-Fix-subscript-typos-BZ-29605.patch \ | 76 | file://0002-get_nscd_addresses-Fix-subscript-typos-BZ-29605.patch \ |
