forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: Add one-byte emulation function
Architectures are required to provide four-byte cmpxchg() and 64-bit architectures are additionally required to provide eight-byte cmpxchg(). However, there are cases where one-byte cmpxchg() would be extremely useful. Therefore, provide cmpxchg_emu_u8() that emulates one-byte cmpxchg() in terms of four-byte cmpxchg(). Note that this emulations is fully ordered, and can (for example) cause one-byte cmpxchg_relaxed() to incur the overhead of full ordering. If this causes problems for a given architecture, that architecture is free to provide its own lighter-weight primitives. [ paulmck: Apply Marco Elver feedback. ] [ paulmck: Apply kernel test robot feedback. ] [ paulmck: Drop two-byte support per Arnd Bergmann feedback. ] Link: https://lore.kernel.org/all/0733eb10-5e7a-4450-9b8a-527b97c842ff@paulmck-laptop/ Signed-off-by: Paul E. McKenney <[email protected]> Acked-by: Marco Elver <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: "Peter Zijlstra (Intel)" <[email protected]> Cc: Douglas Anderson <[email protected]> Cc: Petr Mladek <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: <[email protected]>
- Loading branch information
1 parent
d428032
commit a88d970
Showing
4 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* SPDX-License-Identifier: GPL-2.0+ */ | ||
/* | ||
* Emulated 1-byte and 2-byte cmpxchg operations for architectures | ||
* lacking direct support for these sizes. These are implemented in terms | ||
* of 4-byte cmpxchg operations. | ||
* | ||
* Copyright (C) 2024 Paul E. McKenney. | ||
*/ | ||
|
||
#ifndef __LINUX_CMPXCHG_EMU_H | ||
#define __LINUX_CMPXCHG_EMU_H | ||
|
||
uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new); | ||
|
||
#endif /* __LINUX_CMPXCHG_EMU_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
/* | ||
* Emulated 1-byte cmpxchg operation for architectures lacking direct | ||
* support for this size. This is implemented in terms of 4-byte cmpxchg | ||
* operations. | ||
* | ||
* Copyright (C) 2024 Paul E. McKenney. | ||
*/ | ||
|
||
#include <linux/types.h> | ||
#include <linux/export.h> | ||
#include <linux/instrumented.h> | ||
#include <linux/atomic.h> | ||
#include <linux/panic.h> | ||
#include <linux/bug.h> | ||
#include <asm-generic/rwonce.h> | ||
#include <linux/cmpxchg-emu.h> | ||
|
||
union u8_32 { | ||
u8 b[4]; | ||
u32 w; | ||
}; | ||
|
||
/* Emulate one-byte cmpxchg() in terms of 4-byte cmpxchg. */ | ||
uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new) | ||
{ | ||
u32 *p32 = (u32 *)(((uintptr_t)p) & ~0x3); | ||
int i = ((uintptr_t)p) & 0x3; | ||
union u8_32 old32; | ||
union u8_32 new32; | ||
u32 ret; | ||
|
||
ret = READ_ONCE(*p32); | ||
do { | ||
old32.w = ret; | ||
if (old32.b[i] != old) | ||
return old32.b[i]; | ||
new32.w = old32.w; | ||
new32.b[i] = new; | ||
instrument_atomic_read_write(p, 1); | ||
ret = data_race(cmpxchg(p32, old32.w, new32.w)); // Overridden above. | ||
} while (ret != old32.w); | ||
return old; | ||
} | ||
EXPORT_SYMBOL_GPL(cmpxchg_emu_u8); |