Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kernel.h: move PTR_IF() and u64_to_user_ptr() to util_macros.h

While the natural choice of PTR_IF() is kconfig.h, the latter is too broad
to include C code and actually the macro was moved out from there in the
past. But kernel.h is neither a good choice for that. Move it to
util_macros.h. Do the same for u64_to_user_ptr().

While moving, add necessary documentation.

Link: https://lkml.kernel.org/r/20250324105228.775784-3-andriy.shevchenko@linux.intel.com
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Alexandru Ardelean <aardelean@baylibre.com>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Andy Shevchenko and committed by
Andrew Morton
029c896c 4ef5211e

+67 -9
+1 -9
include/linux/kernel.h
··· 33 33 #include <linux/sprintf.h> 34 34 #include <linux/static_call_types.h> 35 35 #include <linux/instruction_pointer.h> 36 + #include <linux/util_macros.h> 36 37 #include <linux/wordpart.h> 37 38 38 39 #include <asm/byteorder.h> ··· 41 40 #include <uapi/linux/kernel.h> 42 41 43 42 #define STACK_MAGIC 0xdeadbeef 44 - 45 - #define PTR_IF(cond, ptr) ((cond) ? (ptr) : NULL) 46 - 47 - #define u64_to_user_ptr(x) ( \ 48 - { \ 49 - typecheck(u64, (x)); \ 50 - (void __user *)(uintptr_t)(x); \ 51 - } \ 52 - ) 53 43 54 44 struct completion; 55 45 struct user;
+66
include/linux/util_macros.h
··· 80 80 }) 81 81 82 82 /** 83 + * PTR_IF - evaluate to @ptr if @cond is true, or to NULL otherwise. 84 + * @cond: A conditional, usually in a form of IS_ENABLED(CONFIG_FOO) 85 + * @ptr: A pointer to assign if @cond is true. 86 + * 87 + * PTR_IF(IS_ENABLED(CONFIG_FOO), ptr) evaluates to @ptr if CONFIG_FOO is set 88 + * to 'y' or 'm', or to NULL otherwise. The (ptr) argument must be a pointer. 89 + * 90 + * The macro can be very useful to help compiler dropping dead code. 91 + * 92 + * For instance, consider the following:: 93 + * 94 + * #ifdef CONFIG_FOO_SUSPEND 95 + * static int foo_suspend(struct device *dev) 96 + * { 97 + * ... 98 + * } 99 + * #endif 100 + * 101 + * static struct pm_ops foo_ops = { 102 + * #ifdef CONFIG_FOO_SUSPEND 103 + * .suspend = foo_suspend, 104 + * #endif 105 + * }; 106 + * 107 + * While this works, the foo_suspend() macro is compiled conditionally, 108 + * only when CONFIG_FOO_SUSPEND is set. This is problematic, as there could 109 + * be a build bug in this function, we wouldn't have a way to know unless 110 + * the configuration option is set. 111 + * 112 + * An alternative is to declare foo_suspend() always, but mark it 113 + * as __maybe_unused. This works, but the __maybe_unused attribute 114 + * is required to instruct the compiler that the function may not 115 + * be referenced anywhere, and is safe to remove without making 116 + * a fuss about it. This makes the programmer responsible for tagging 117 + * the functions that can be garbage-collected. 118 + * 119 + * With the macro it is possible to write the following: 120 + * 121 + * static int foo_suspend(struct device *dev) 122 + * { 123 + * ... 124 + * } 125 + * 126 + * static struct pm_ops foo_ops = { 127 + * .suspend = PTR_IF(IS_ENABLED(CONFIG_FOO_SUSPEND), foo_suspend), 128 + * }; 129 + * 130 + * The foo_suspend() function will now be automatically dropped by the 131 + * compiler, and it does not require any specific attribute. 132 + */ 133 + #define PTR_IF(cond, ptr) ((cond) ? (ptr) : NULL) 134 + 135 + /** 136 + * to_user_ptr - cast a pointer passed as u64 from user space to void __user * 137 + * @x: The u64 value from user space, usually via IOCTL 138 + * 139 + * to_user_ptr() simply casts a pointer passed as u64 from user space to void 140 + * __user * correctly. Using this lets us get rid of all the tiresome casts. 141 + */ 142 + #define u64_to_user_ptr(x) \ 143 + ({ \ 144 + typecheck(u64, (x)); \ 145 + (void __user *)(uintptr_t)(x); \ 146 + }) 147 + 148 + /** 83 149 * is_insidevar - check if the @ptr points inside the @var memory range. 84 150 * @ptr: the pointer to a memory address. 85 151 * @var: the variable which address and size identify the memory range.