From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
To fix this, the runtime checks are adjusted to silently ignore any lock that is not 4-byte aligned, effectively disabling the feature in such cases and avoiding the related warnings.
Thanks to Geert Uytterhoeven for bisecting!
Reported-by: Eero Tamminen oak@helsinkinet.fi Closes: https://lore.kernel.org/lkml/CAMuHMdW7Ab13DdGs2acMQcix5ObJK0O2dG_Fxzr8_g58Rc... Fixes: e711faaafbe5 ("hung_task: replace blocker_mutex with encoded blocker") Cc: stable@vger.kernel.org Reviewed-by: Masami Hiramatsu (Google) mhiramat@kernel.org Signed-off-by: Lance Yang lance.yang@linux.dev --- v1 -> v2: - Pick RB from Masami - thanks! - Update the changelog and comments - https://lore.kernel.org/lkml/20250823050036.7748-1-lance.yang@linux.dev/
include/linux/hung_task.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/linux/hung_task.h b/include/linux/hung_task.h index 34e615c76ca5..c4403eeb7144 100644 --- a/include/linux/hung_task.h +++ b/include/linux/hung_task.h @@ -20,6 +20,10 @@ * always zero. So we can use these bits to encode the specific blocking * type. * + * Note that on architectures where this is not guaranteed, or for any + * unaligned lock, this tracking mechanism is silently skipped for that + * lock. + * * Type encoding: * 00 - Blocked on mutex (BLOCKER_TYPE_MUTEX) * 01 - Blocked on semaphore (BLOCKER_TYPE_SEM) @@ -45,7 +49,7 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type) * If the lock pointer matches the BLOCKER_TYPE_MASK, return * without writing anything. */ - if (WARN_ON_ONCE(lock_ptr & BLOCKER_TYPE_MASK)) + if (lock_ptr & BLOCKER_TYPE_MASK) return;
WRITE_ONCE(current->blocker, lock_ptr | type); @@ -53,8 +57,6 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type)
static inline void hung_task_clear_blocker(void) { - WARN_ON_ONCE(!READ_ONCE(current->blocker)); - WRITE_ONCE(current->blocker, 0UL); }
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
To fix this, the runtime checks are adjusted to silently ignore any lock that is not 4-byte aligned, effectively disabling the feature in such cases and avoiding the related warnings.
Thanks to Geert Uytterhoeven for bisecting!
Reported-by: Eero Tamminen oak@helsinkinet.fi Closes: https://lore.kernel.org/lkml/CAMuHMdW7Ab13DdGs2acMQcix5ObJK0O2dG_Fxzr8_g58Rc... Fixes: e711faaafbe5 ("hung_task: replace blocker_mutex with encoded blocker") Cc: stable@vger.kernel.org Reviewed-by: Masami Hiramatsu (Google) mhiramat@kernel.org Signed-off-by: Lance Yang lance.yang@linux.dev
v1 -> v2:
- Pick RB from Masami - thanks!
- Update the changelog and comments
- https://lore.kernel.org/lkml/20250823050036.7748-1-lance.yang@linux.dev/
include/linux/hung_task.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/linux/hung_task.h b/include/linux/hung_task.h index 34e615c76ca5..c4403eeb7144 100644 --- a/include/linux/hung_task.h +++ b/include/linux/hung_task.h @@ -20,6 +20,10 @@
- always zero. So we can use these bits to encode the specific blocking
- type.
- Note that on architectures where this is not guaranteed, or for any
- unaligned lock, this tracking mechanism is silently skipped for that
- lock.
- Type encoding:
- 00 - Blocked on mutex (BLOCKER_TYPE_MUTEX)
- 01 - Blocked on semaphore (BLOCKER_TYPE_SEM)
@@ -45,7 +49,7 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type) * If the lock pointer matches the BLOCKER_TYPE_MASK, return * without writing anything. */
- if (WARN_ON_ONCE(lock_ptr & BLOCKER_TYPE_MASK))
- if (lock_ptr & BLOCKER_TYPE_MASK) return;
WRITE_ONCE(current->blocker, lock_ptr | type); @@ -53,8 +57,6 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type) static inline void hung_task_clear_blocker(void) {
- WARN_ON_ONCE(!READ_ONCE(current->blocker));
- WRITE_ONCE(current->blocker, 0UL);
} -- 2.49.0
On Tue, 2025-09-09 at 12:46 -0400, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
Yes, and it does this on Linux only. I have been trying to change it upstream though as the official SysV ELF ABI for m68k requires a 4-byte natural alignment [1].
Adrian
[1] https://people.debian.org/~glaubitz/m68k-sysv-abi.pdf (p. 29)
On Tue, Sep 09, 2025 at 06:55:42PM +0200, John Paul Adrian Glaubitz wrote:
On Tue, 2025-09-09 at 12:46 -0400, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
Yes, and it does this on Linux only. I have been trying to change it upstream though as the official SysV ELF ABI for m68k requires a 4-byte natural alignment [1].
Better to make it an explicit ifdef on the architecture, then...
On Tue, 9 Sep 2025, John Paul Adrian Glaubitz wrote:
I have been trying to change it upstream though
That ship sailed decades ago.
as the official SysV ELF ABI for m68k requires a 4-byte natural alignment [1] ...
[1] https://people.debian.org/~glaubitz/m68k-sysv-abi.pdf (p. 29)
GNU/Linux is not AT&T Unix and was never intended to be that. Hence, your old System V (trademark) binaries are not going to work, unfortunately.
On Tue, 9 Sept 2025 at 18:55, John Paul Adrian Glaubitz glaubitz@physik.fu-berlin.de wrote:
On Tue, 2025-09-09 at 12:46 -0400, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
Yes, and it does this on Linux only. I have been trying to change it upstream though as the official SysV ELF ABI for m68k requires a 4-byte natural alignment [1].
M68k does this on various OSes and ABIs that predate or are not explicitly compatible with the SysV ELF ABI.
Other architectures like CRIS (1-byte alignment!) are no longer supported by Linux.
FWIW, doubles (and doublewords) are not naturally aligned in the SysV ELF ABI for i386, while doubles (no mention of doublewords) are naturally aligned in the SysV ELF ABI for m68k.
Gr{oetje,eeting}s,
Geert
On Wed, 2025-09-10 at 09:34 +0200, Geert Uytterhoeven wrote:
Isn't m68k the only architecture that's weird like this?
Yes, and it does this on Linux only. I have been trying to change it upstream though as the official SysV ELF ABI for m68k requires a 4-byte natural alignment [1].
M68k does this on various OSes and ABIs that predate or are not explicitly compatible with the SysV ELF ABI.
I know. I was talking in the context of SysV ELF systems.
Other architectures like CRIS (1-byte alignment!) are no longer supported by Linux.
Yes, that's why we should take care of the alignment ;-).
FWIW, doubles (and doublewords) are not naturally aligned in the SysV ELF ABI for i386, while doubles (no mention of doublewords) are naturally aligned in the SysV ELF ABI for m68k.
I wouldn't consider i386 a role model for us ;-).
Adrian
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
No. Historically, Linux/CRIS did not naturally align integer types either. AFAIK, there's no standard that demands natural alignment of integer types. Linux ABIs differ significantly.
For example, Linux/i386 does not naturally align long longs. Therefore, x86 may be expected to become the next m68k (or CRIS) unless such assumptions are avoided and alignment requirements are made explicit.
The real problem here is the algorithm. Some under-resourced distros choose to blame the ABI instead of the algorithm, because in doing so, they are freed from having to work to improve upstream code bases.
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland) but that sort of workaround would not address the root cause (i.e. algorithms with bad assumptions).
[1] https://lore.kernel.org/lkml/CAMuHMdW7Ab13DdGs2acMQcix5ObJK0O2dG_Fxzr8_g58Rc...
On Wed, Sep 10, 2025 at 10:07:04AM +1000, Finn Thain wrote:
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
No. Historically, Linux/CRIS did not naturally align integer types either. AFAIK, there's no standard that demands natural alignment of integer types. Linux ABIs differ significantly.
For example, Linux/i386 does not naturally align long longs. Therefore, x86 may be expected to become the next m68k (or CRIS) unless such assumptions are avoided and alignment requirements are made explicit.
That doesn't really apply; i386's long long is ugly but it's not as much of an issue in practice, because it's greater than a machine word.
The real problem here is the algorithm. Some under-resourced distros choose to blame the ABI instead of the algorithm, because in doing so, they are freed from having to work to improve upstream code bases.
Hang on, let's avoid playing the blame game. It's perfectly reasonable to view standards not as holy religious texts that must be adhered to; these things were written down when specifications were much looser.
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
That kind of thinking really dates from before multithreaded and even lockless algorithms became absolutely pervasive, especially in the kernel.
These days, READ_ONCE() and WRITE_ONCE() are pervasive, and since C lacks any notion of atomics in the type system (the place this primarily comes up), it would go a long ways towards improving portability and eliminating nasty land mines.
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Wed, Sep 10, 2025 at 10:07:04AM +1000, Finn Thain wrote:
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
No. Historically, Linux/CRIS did not naturally align integer types either. AFAIK, there's no standard that demands natural alignment of integer types. Linux ABIs differ significantly.
For example, Linux/i386 does not naturally align long longs. Therefore, x86 may be expected to become the next m68k (or CRIS) unless such assumptions are avoided and alignment requirements are made explicit.
That doesn't really apply; i386's long long is ugly but it's not as much of an issue in practice, because it's greater than a machine word.
Similarly, on m68k, there is no issue with __alignof(long) == 2 because these platforms don't trap on misaligned access. But that seems a bit irrelevant to the real issue, which is not specific architectural quirks, but the algorithms and their ongoing development.
...
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
That kind of thinking really dates from before multithreaded and even lockless algorithms became absolutely pervasive, especially in the kernel.
What I meant was, "assumptions hinder portability etc." not "good C hinders portability etc." (my bad).
These days, READ_ONCE() and WRITE_ONCE() are pervasive, and since C lacks any notion of atomics in the type system (the place this primarily comes up), it would go a long ways towards improving portability and eliminating nasty land mines.
Natural alignment would seem to be desirable for new ABIs, until you realize that it implies wasted RAM on embedded systems and reduced data locality (that is, cooler caches if you did this on i386).
On Wed, Sep 10, 2025 at 11:35:56AM +1000, Finn Thain wrote:
Similarly, on m68k, there is no issue with __alignof(long) == 2 because these platforms don't trap on misaligned access. But that seems a bit irrelevant to the real issue, which is not specific architectural quirks, but the algorithms and their ongoing development.
Err, I believe the topic was just alignment and the breaking of commonly held expectations :)
...
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
That kind of thinking really dates from before multithreaded and even lockless algorithms became absolutely pervasive, especially in the kernel.
What I meant was, "assumptions hinder portability etc." not "good C hinders portability etc." (my bad).
Of course, but given the lack of a true atomic type in C there's no good alternative way to avoid this landmine.
Also, grep for READ_ONCE/WRITE_ONCE in the kernel tree if you want to see how big the issue is - ad then remember that only captures a fraction of it :)
These days, READ_ONCE() and WRITE_ONCE() are pervasive, and since C lacks any notion of atomics in the type system (the place this primarily comes up), it would go a long ways towards improving portability and eliminating nasty land mines.
Natural alignment would seem to be desirable for new ABIs, until you realize that it implies wasted RAM on embedded systems and reduced data locality (that is, cooler caches if you did this on i386).
For the data structures where it matters we tend to organize things by natural alignment already.
If anyone wanted to gather precise numbers, there's memory allocation profiling + pahole :)
On Tue, 9 Sep 2025, Kent Overstreet wrote:
Err, I believe the topic was just alignment and the breaking of commonly held expectations :)
...
Also, grep for READ_ONCE/WRITE_ONCE in the kernel tree if you want to see how big the issue is
I'm already aware of the comment in include/asm-generic/rwonce.h about load tearing and 64-bit loads on 32-bit architectures. That's partly why I mentioned long long alignment on i386. Perhaps, for being so common, i386 has generally lowered expectations?
On Sep 10 2025, Finn Thain wrote:
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland)
No, you can't. It would change the layout of basic user-level structures, breaking the syscall ABI.
On Wed, 2025-09-10 at 08:52 +0200, Andreas Schwab wrote:
On Sep 10 2025, Finn Thain wrote:
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland)
No, you can't. It would change the layout of basic user-level structures, breaking the syscall ABI.
Not if you rebuild the whole userspace as well.
FWIW, the Gentoo people already created a chroot with 32-bit alignmment:
https://dev.gentoo.org/~dilfridge/m68k/
It works with qemu-user. I haven't tried it on qemu-system with a 32-bit- aligned kernel yet.
Adrian
Hi Adrian,
On Wed, 10 Sept 2025 at 09:39, John Paul Adrian Glaubitz glaubitz@physik.fu-berlin.de wrote:
On Wed, 2025-09-10 at 08:52 +0200, Andreas Schwab wrote:
On Sep 10 2025, Finn Thain wrote:
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland)
No, you can't. It would change the layout of basic user-level structures, breaking the syscall ABI.
Not if you rebuild the whole userspace as well.
Linux does not break the userspace ABI.
FWIW, the Gentoo people already created a chroot with 32-bit alignmment:
That would be a different Linux architecture (m68k-32?).
Gr{oetje,eeting}s,
Geert
On Wed, 10 Sep 2025, Andreas Schwab wrote:
On Sep 10 2025, Finn Thain wrote:
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland)
No, you can't. It would change the layout of basic user-level structures, breaking the syscall ABI.
So you'd have to patch the uapi headers at the same time. I think that's "feasible", no?
On Sep 10 2025, Finn Thain wrote:
So you'd have to patch the uapi headers at the same time. I think that's "feasible", no?
I would surely be a big task.
On Wed, 10 Sept 2025 at 02:07, Finn Thain fthain@linux-m68k.org wrote:
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
No. Historically, Linux/CRIS did not naturally align integer types either. AFAIK, there's no standard that demands natural alignment of integer types. Linux ABIs differ significantly.
For example, Linux/i386 does not naturally align long longs. Therefore, x86 may be expected to become the next m68k (or CRIS) unless such assumptions are avoided and alignment requirements are made explicit.
The real problem here is the algorithm. Some under-resourced distros choose to blame the ABI instead of the algorithm, because in doing so, they are freed from having to work to improve upstream code bases.
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland) but that sort of workaround would not address the root cause (i.e. algorithms with bad assumptions).
The first step to preserve compatibility with userland would be to properly annotate the few uapi definitions that would change with -malign-int otherwise. I am still waiting for these patches...
Gr{oetje,eeting}s,
Geert
On Wed, Sep 10, 2025 at 09:36:34AM +0200, Geert Uytterhoeven wrote:
On Wed, 10 Sept 2025 at 02:07, Finn Thain fthain@linux-m68k.org wrote:
On Tue, 9 Sep 2025, Kent Overstreet wrote:
On Tue, Sep 09, 2025 at 10:52:43PM +0800, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
The blocker tracking mechanism assumes that lock pointers are at least 4-byte aligned to use their lower bits for type encoding.
However, as reported by Eero Tamminen, some architectures like m68k only guarantee 2-byte alignment of 32-bit values. This breaks the assumption and causes two related WARN_ON_ONCE checks to trigger.
Isn't m68k the only architecture that's weird like this?
No. Historically, Linux/CRIS did not naturally align integer types either. AFAIK, there's no standard that demands natural alignment of integer types. Linux ABIs differ significantly.
For example, Linux/i386 does not naturally align long longs. Therefore, x86 may be expected to become the next m68k (or CRIS) unless such assumptions are avoided and alignment requirements are made explicit.
The real problem here is the algorithm. Some under-resourced distros choose to blame the ABI instead of the algorithm, because in doing so, they are freed from having to work to improve upstream code bases.
IMHO, good C doesn't make alignment assumptions, because that hinders source code portability and reuse, as well as algorithm extensibility. We've seen it before. The issue here [1] is no different from the pointer abuse which we fixed in Cpython [2].
Linux is probably the only non-trivial program that could be feasibly rebuilt with -malign-int without ill effect (i.e. without breaking userland) but that sort of workaround would not address the root cause (i.e. algorithms with bad assumptions).
The first step to preserve compatibility with userland would be to properly annotate the few uapi definitions that would change with -malign-int otherwise. I am still waiting for these patches...
I think it'd need a new gcc attribute to do it sanely...
linux-stable-mirror@lists.linaro.org