Here are a series of patches to start converting the kernel to C++. It
requires g++ v8.
What rocks:
(1) Inline template functions, which makes implementation of things like
cmpxchg() and get_user() much cleaner.
(2) Inline overloaded functions, which makes implementation of things like
static_branch_likely() cleaner.
(3) Class inheritance. For instance, all those inode wrappers that require
the base inode struct to be included and that has to be accessed with
something like:
inode->vfs_inode.i_mtime
when you could instead do:
inode->i_mtime
What I would disallow:
(1) new and delete. There's no way to pass GFP_* flags in.
(2) Constructors and destructors. Nests of implicit code makes the code less
obvious, and the replacement of static initialisation with constructor
calls would make the code size larger.
(3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
exception handling is limited without it, and since destructors are not
allowed, you still have to manually clean up after an error.
(4) Operator overloading (except in special cases).
(5) Function overloading (except in special inline cases).
(6) STL (though some type trait bits are needed to replace __builtins that
don't exist in g++).
(7) 'class', 'private', 'namespace'.
(8) 'virtual'. Don't want virtual base classes, though virtual function
tables might make operations tables more efficient.
Issues:
(1) Need spaces inserting between strings and symbols.
(2) Direct assignment of pointers to/from void* isn't allowed by C++, though
g++ grudgingly permits it with -fpermissive. I would imagine that a
compiler option could easily be added to hide the error entirely.
(3) Need gcc v8+ to statically initialise an object of any struct that's not
really simple (e.g. if it's got an embedded union).
(4) Symbol length. Really need to extern "C" everything to reduce the size
of the symbols stored in the kernel image. This shouldn't be a problem
if out-of-line function overloading isn't permitted.
So far, it gets as far as compiling init/main.c to a .o file.
Seriously, though...
Apart from the cleaner inline functions allowed by templating, I'm not sure
there's a lot of the C++ language that we would want to use in the kernel
unless we want to go for more advanced classes implementing interesting types.
We could, for example, wrap things like userspace pointers, __be numbers,
ioport addresses and control access to them that way, but I don't know that it
gains a whole load that sparse doesn't give us.
And finally, doing this did find a few minor things that can be fixed.
David
---
David Howells (45):
Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID
Fix exception_enter() return value
Fix loop var in be32_to_cpu_array() and cpu_to_be32_array()
Fix use of ACPI_COMPANION_SET()
C++: Set compilation as C++ for .c files
C++: Do some basic C++ type definition
C++: Define a header with some C++ type traits for type checking
C++: Implement abs() as an inline template function
C++: x86: Fix the x86 syscall table production for C++
C++: x86: Turn xchg(), xadd() & co. into inline template functions
C++: x86: Turn cmpxchg() & co. into inline template functions
C++: x86: Turn cmpxchg_double() & co. into inline template functions
C++: x86: Turn cmpxchg64() & co. into inline template functions
C++: x86: Turn put_user(), get_user() & co. into inline template functions
C++: Need space between string and symbol
C++: Disable VERIFY_OCTAL_PERMISSIONS() for the moment
C++: Turn READ_ONCE(), WRITE_ONCE() & co. into inline template functions
C++: Turn RCU accessors into inline template functions
C++: Turn ktime_add/sub_ns() into inline template functions
C++: init/main: Constify pointers
C++: Set the type of atomic64_t to s64
C++: Define apic_intr_mode after the enum definition, not before
C++: Don't do "extern asmlinkage"
C++: Fix BUILD_BUG_ON_ZERO()
C++: Fix void variables
C++: Can't have variable/member names the same as typedef names
C++: Disable __same_type() for the moment
C++: Move ctx_state enum out of struct context_tracking
C++: Move the print_line_t enum before first use
C++: Include linux/hrtimer.h from linux/timer.h
C++: Avoid using 'compl' and 'and' as names
C++: __to_fd() needs to reduce the size of v for struct fd::flags
C++: Move irqchip_irq_state enum
C++: Fix up use of LIST_POISON*
C++: Fix static_branch_likely/unlikely()
C++: Fix kernfs_type() int->enum
C++: Fix page_zonenum() int->enum
C++: mutex_trylock_recursive_enum() int->enum
C++: Fix spinlock initialisation
C++: Fix sema_init()
C++: Cast in bitops
C++: Hide C++ keywords
C++: Don't need to declare struct pgd_t after typedef
C++: Can't declare unsized-array in struct cgroup
C++: Move initcall_level_names[] to __initdata section
Makefile | 13 -
arch/x86/Makefile | 2
arch/x86/entry/syscalls/Makefile | 8
arch/x86/entry/syscalls/syscallhdr.pl | 73 ++++
arch/x86/entry/syscalls/syscalltbl.pl | 95 +++++
arch/x86/include/asm/alternative.h | 10 -
arch/x86/include/asm/apic.h | 2
arch/x86/include/asm/arch_hweight.h | 4
arch/x86/include/asm/atomic.h | 2
arch/x86/include/asm/atomic64_64.h | 12 -
arch/x86/include/asm/cmpxchg.h | 430 +++++++++++-----------
arch/x86/include/asm/cmpxchg_64.h | 28 +
arch/x86/include/asm/hw_irq.h | 38 +-
arch/x86/include/asm/percpu.h | 94 ++---
arch/x86/include/asm/perf_event.h | 2
arch/x86/include/asm/processor.h | 2
arch/x86/include/asm/special_insns.h | 2
arch/x86/include/asm/tlbflush.h | 1
arch/x86/include/asm/uaccess.h | 630 +++++++++++++++++---------------
arch/x86/include/asm/uaccess_64.h | 66 +--
arch/x86/kernel/asm-offsets_32.c | 1
arch/x86/kernel/asm-offsets_64.c | 1
arch/x86/purgatory/Makefile | 2
include/asm-generic/bitops/le.h | 32 +-
include/asm-generic/sections.h | 2
include/linux/acpi.h | 2
include/linux/backing-dev-defs.h | 4
include/linux/blkdev.h | 86 ++--
include/linux/build_bug.h | 5
include/linux/byteorder/generic.h | 4
include/linux/cgroup-defs.h | 2
include/linux/compat.h | 2
include/linux/compiler-c++.h | 54 +++
include/linux/compiler-gcc.h | 5
include/linux/compiler.h | 93 +----
include/linux/compiler_types.h | 2
include/linux/context_tracking.h | 4
include/linux/context_tracking_state.h | 14 -
include/linux/cpumask.h | 4
include/linux/crypto.h | 4
include/linux/elevator.h | 82 ++--
include/linux/file.h | 2
include/linux/interrupt.h | 10 -
include/linux/irq.h | 1
include/linux/irqflags.h | 10 +
include/linux/jump_label.h | 41 +-
include/linux/kernel.h | 35 --
include/linux/kernfs.h | 2
include/linux/ktime.h | 12 +
include/linux/list.h | 8
include/linux/list_bl.h | 4
include/linux/list_nulls.h | 2
include/linux/lockdep.h | 2
include/linux/mm.h | 2
include/linux/mutex.h | 5
include/linux/page-flags.h | 3
include/linux/poison.h | 6
include/linux/printk.h | 4
include/linux/projid.h | 2
include/linux/rculist.h | 4
include/linux/rculist_bl.h | 2
include/linux/rcupdate.h | 124 ++++--
include/linux/sched/task.h | 2
include/linux/semaphore.h | 5
include/linux/spinlock.h | 2
include/linux/spinlock_types.h | 4
include/linux/start_kernel.h | 2
include/linux/stddef.h | 12 -
include/linux/sysctl.h | 6
include/linux/timer.h | 1
include/linux/trace_events.h | 16 -
include/linux/types.h | 16 +
include/linux/uidgid.h | 4
init/main.c | 4
scripts/checksyscalls.sh | 2
tools/power/cpupower/Makefile | 1
tools/virtio/Makefile | 2
77 files changed, 1269 insertions(+), 1010 deletions(-)
create mode 100644 arch/x86/entry/syscalls/syscallhdr.pl
create mode 100644 arch/x86/entry/syscalls/syscalltbl.pl
create mode 100644 include/linux/compiler-c++.h
Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID as the
parameter is an unsigned integer.
Signed-off-by: David Howells <[email protected]>
---
include/linux/projid.h | 2 +-
include/linux/uidgid.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/projid.h b/include/linux/projid.h
index 613730622a1a..7c60a79424c9 100644
--- a/include/linux/projid.h
+++ b/include/linux/projid.h
@@ -30,7 +30,7 @@ static inline projid_t __kprojid_val(kprojid_t projid)
#define KPROJIDT_INIT(value) (kprojid_t){ value }
-#define INVALID_PROJID KPROJIDT_INIT(-1)
+#define INVALID_PROJID KPROJIDT_INIT(UINT_MAX)
#define OVERFLOW_PROJID 65534
static inline bool projid_eq(kprojid_t left, kprojid_t right)
diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h
index b0542cd11aeb..75f602075b63 100644
--- a/include/linux/uidgid.h
+++ b/include/linux/uidgid.h
@@ -55,8 +55,8 @@ static inline gid_t __kgid_val(kgid_t gid)
#define GLOBAL_ROOT_UID KUIDT_INIT(0)
#define GLOBAL_ROOT_GID KGIDT_INIT(0)
-#define INVALID_UID KUIDT_INIT(-1)
-#define INVALID_GID KGIDT_INIT(-1)
+#define INVALID_UID KUIDT_INIT(UINT_MAX)
+#define INVALID_GID KGIDT_INIT(UINT_MAX)
static inline bool uid_eq(kuid_t left, kuid_t right)
{
ACPI_COMPANION_SET() takes a bool as the third argument, not a pointer, so
pass false in, not NULL.
Signed-off-by: David Howells <[email protected]>
---
include/linux/acpi.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 968173ec2726..9e59bad1d301 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -101,7 +101,7 @@ static inline bool has_acpi_companion(struct device *dev)
static inline void acpi_preset_companion(struct device *dev,
struct acpi_device *parent, u64 addr)
{
- ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, NULL));
+ ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, false));
}
static inline const char *acpi_dev_name(struct acpi_device *adev)
Fix the loop variable in be32_to_cpu_array() and cpu_to_be32_array() to be
a size_t like the variable it's limited by to avoid signed-unsigned
comparison warnings.
Signed-off-by: David Howells <[email protected]>
---
include/linux/byteorder/generic.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
index 451aaa0786ae..4e297a6376d3 100644
--- a/include/linux/byteorder/generic.h
+++ b/include/linux/byteorder/generic.h
@@ -173,7 +173,7 @@ static inline void be64_add_cpu(__be64 *var, u64 val)
static inline void cpu_to_be32_array(__be32 *dst, const u32 *src, size_t len)
{
- int i;
+ size_t i;
for (i = 0; i < len; i++)
dst[i] = cpu_to_be32(src[i]);
@@ -181,7 +181,7 @@ static inline void cpu_to_be32_array(__be32 *dst, const u32 *src, size_t len)
static inline void be32_to_cpu_array(u32 *dst, const __be32 *src, size_t len)
{
- int i;
+ size_t i;
for (i = 0; i < len; i++)
dst[i] = be32_to_cpu(src[i]);
---
Makefile | 13 ++++---------
arch/x86/Makefile | 2 +-
arch/x86/purgatory/Makefile | 2 +-
include/linux/types.h | 4 ++++
scripts/checksyscalls.sh | 2 +-
tools/power/cpupower/Makefile | 1 -
tools/virtio/Makefile | 2 +-
7 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/Makefile b/Makefile
index e02d092bc2d6..76e2ca8bf0fe 100644
--- a/Makefile
+++ b/Makefile
@@ -370,7 +370,7 @@ HOST_LOADLIBES := $(HOST_LFS_LIBS)
# Make variables (CC, etc...)
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
-CC = $(CROSS_COMPILE)gcc
+CC = $(CROSS_COMPILE)g++
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
@@ -415,11 +415,12 @@ LINUXINCLUDE := \
$(USERINCLUDE)
KBUILD_AFLAGS := -D__ASSEMBLY__
-KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+KBUILD_CFLAGS := -Wall -Wundef -Wno-trigraphs \
-fno-strict-aliasing -fno-common -fshort-wchar \
-Werror-implicit-function-declaration \
-Wno-format-security \
- -std=gnu89
+ -std=gnu89 -Wno-pointer-arith \
+ -fno-rtti -fno-exceptions -fpermissive
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
@@ -817,12 +818,6 @@ endif
NOSTDINC_FLAGS += -nostdinc -isystem $(call shell-cached,$(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
-# warn about C99 declaration after statement
-KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
-
-# disable pointer signed / unsigned warnings in gcc 4.0
-KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign)
-
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 498c1b812300..9933a5f2e628 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -33,7 +33,7 @@ M16_CFLAGS := $(call cc-option, -m16, $(CODE16GCC_CFLAGS))
REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -D__KERNEL__ \
-DDISABLE_BRANCH_PROFILING \
- -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
+ -Wall -march=i386 -mregparm=3 \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
-mno-mmx -mno-sse
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 2f15a2ac4209..3911b8b1b140 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -16,7 +16,7 @@ KCOV_INSTRUMENT := n
# in turn leaves some undefined symbols like __fentry__ in purgatory and not
# sure how to relocate those. Like kexec-tools, use custom flags.
-KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
+KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large -x c++ -Wno-pointer-arith
KBUILD_CFLAGS += -m$(BITS)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
diff --git a/include/linux/types.h b/include/linux/types.h
index c94d59ef96cc..31e8258ac048 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -2,6 +2,10 @@
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
+#ifndef __cplusplus
+#error not c++
+#endif
+
#define __EXPORTED_HEADERS__
#include <uapi/linux/types.h>
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index ee3dfb5be6cd..2f9aa09602e7 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -212,4 +212,4 @@ syscall_list() {
}
(ignore_list && syscall_list $(dirname $0)/../arch/x86/entry/syscalls/syscall_32.tbl) | \
-$* -E -x c - > /dev/null
+$* -E -x c++ - > /dev/null
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 1dd5f4fcffd5..68d2e199b402 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -125,7 +125,6 @@ cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2
OPTIMIZATION := $(call cc-supports,-Os,-O2)
WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare
-WARNINGS += $(call cc-supports,-Wno-pointer-sign)
WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
WARNINGS += -Wshadow
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
index 8e2a908115c2..fde1fccb019d 100644
--- a/tools/virtio/Makefile
+++ b/tools/virtio/Makefile
@@ -4,7 +4,7 @@ test: virtio_test vringh_test
virtio_test: virtio_ring.o virtio_test.o
vringh_test: vringh_test.o vringh.o virtio_ring.o
-CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
+CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
vpath %.c ../../drivers/virtio ../../drivers/vhost
mod:
${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
NULL should be defined as nullptr rather than (void *)0 as nullptr is a
special compiler type.
Don't define bool, true and false as these are defined by the compiler.
Signed-off-by: David Howells <[email protected]>
---
include/linux/stddef.h | 12 ++++++------
include/linux/types.h | 2 --
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 998a4ba28eba..470cf32e9119 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -4,13 +4,13 @@
#include <uapi/linux/stddef.h>
-#undef NULL
-#define NULL ((void *)0)
+/*
+ * The type of the NULL pointer. This is a special C++ pointer type.
+ */
+typedef decltype(nullptr) nullptr_t;
-enum {
- false = 0,
- true = 1
-};
+#undef NULL
+#define NULL nullptr
#undef offsetof
#ifdef __compiler_offsetof
diff --git a/include/linux/types.h b/include/linux/types.h
index 31e8258ac048..68323cb03910 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -31,8 +31,6 @@ typedef __kernel_timer_t timer_t;
typedef __kernel_clockid_t clockid_t;
typedef __kernel_mqd_t mqd_t;
-typedef _Bool bool;
-
typedef __kernel_uid32_t uid_t;
typedef __kernel_gid32_t gid_t;
typedef __kernel_uid16_t uid16_t;
Implement abs() as an C++ inline template function as that greatly
simplifies the source.
Signed-off-by: David Howells <[email protected]>
---
include/linux/kernel.h | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e779a7487c34..59089f76c7d8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -246,20 +246,11 @@ extern int _cond_resched(void);
*
* Return: an absolute value of x.
*/
-#define abs(x) __abs_choose_expr(x, long long, \
- __abs_choose_expr(x, long, \
- __abs_choose_expr(x, int, \
- __abs_choose_expr(x, short, \
- __abs_choose_expr(x, char, \
- __builtin_choose_expr( \
- __builtin_types_compatible_p(typeof(x), char), \
- (char)({ signed char __x = (x); __x<0?-__x:__x; }), \
- ((void)0)))))))
-
-#define __abs_choose_expr(x, type, other) __builtin_choose_expr( \
- __builtin_types_compatible_p(typeof(x), signed type) || \
- __builtin_types_compatible_p(typeof(x), unsigned type), \
- ({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
+template<typename T>
+static inline T abs(T v)
+{
+ return v < 0 ? -v : v;
+}
/**
* reciprocal_scale - "scale" a value into range [0, ep_ro)
Add a header that provides the following facilities:
(1) A construction to determine whether two types are the same.
(2) A construction to determine whether a pointer can be determined to be
NULL at compile time.
(3) A construction to determine whether a type is an array as compile
time.
Note that these are implemented as C++ type traits, for example:
char *p;
if (__is_array(p))
this_is_not_executed();
else
this_is_executed();
See http://en.cppreference.com/w/cpp/types
Signed-off-by: David Howells <[email protected]>
---
include/linux/compiler-c++.h | 54 ++++++++++++++++++++++++++++++++++++++++++
include/linux/compiler-gcc.h | 5 ++--
include/linux/kernel.h | 3 ++
3 files changed, 59 insertions(+), 3 deletions(-)
create mode 100644 include/linux/compiler-c++.h
diff --git a/include/linux/compiler-c++.h b/include/linux/compiler-c++.h
new file mode 100644
index 000000000000..84f7607d6ccc
--- /dev/null
+++ b/include/linux/compiler-c++.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 -*- c++ -*- */
+/*
+ * C++ type traits. See http://en.cppreference.com/w/cpp/types
+ */
+#ifndef _LINUX_TYPE_TRAITS_H
+#define _LINUX_TYPE_TRAITS_H
+
+template<typename T, T v>
+struct integral_constant {
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant type; // using injected-typename-name
+ constexpr operator value_type() const noexcept { return value; }
+ constexpr value_type operator()() const noexcept { return value; } //since c++14
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+/*
+ * Determine if two types are the same.
+ */
+template<typename T, typename U> struct is_same : false_type {};
+template<typename T> struct is_same<T, T> : true_type {};
+
+/*
+ * Strip const and volatile from type.
+ */
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<const T> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<volatile T> { typedef T type; };
+template<typename T> struct remove_cv {
+ typedef typename remove_volatile<typename remove_const<T>::type>::type type;
+};
+
+template<typename T> using remove_cv_t = typename remove_cv<T>::type;
+template<typename T> using remove_const_t = typename remove_const<T>::type;
+template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
+
+/*
+ * Determine if a type is the NULL pointer type.
+ */
+template<typename T> struct is_null_pointer : is_same<nullptr_t, remove_cv_t<T>> {};
+
+/*
+ * Determine if a type is an array type.
+ */
+template<typename T> struct is_array : false_type {};
+template<typename T> struct is_array<T[]> : true_type {};
+template<typename T, size_t N> struct is_array<T[N]> : true_type {};
+#define __is_array(T) is_array<typeof(T)>::value
+
+#endif /* _LINUX_TYPE_TRAITS_H */
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index e2c7f4369eff..6ab6431a65a6 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -58,11 +58,12 @@
#define OPTIMIZER_HIDE_VAR(var) \
__asm__ ("" : "=r" (var) : "0" (var))
-#ifdef __CHECKER__
+#if defined(__CHECKER__) // || defined(__cplusplus)
#define __must_be_array(a) 0
#else
/* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+//#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__is_array(a))
#endif
/*
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3fd291503576..e779a7487c34 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 -*- c++ -*- */
#ifndef _LINUX_KERNEL_H
#define _LINUX_KERNEL_H
@@ -8,6 +8,7 @@
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/compiler.h>
+#include <linux/compiler-c++.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/typecheck.h>
Fix the x86 syscall table production for C++ to not miss out any slots in
the syscall table as this would otherwise cause errors from the compiler.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/entry/syscalls/Makefile | 8 +--
arch/x86/entry/syscalls/syscallhdr.pl | 73 +++++++++++++++++++++++++
arch/x86/entry/syscalls/syscalltbl.pl | 95 +++++++++++++++++++++++++++++++++
arch/x86/kernel/asm-offsets_32.c | 1
arch/x86/kernel/asm-offsets_64.c | 1
5 files changed, 174 insertions(+), 4 deletions(-)
create mode 100644 arch/x86/entry/syscalls/syscallhdr.pl
create mode 100644 arch/x86/entry/syscalls/syscalltbl.pl
diff --git a/arch/x86/entry/syscalls/Makefile b/arch/x86/entry/syscalls/Makefile
index 6fb9b57ed5ba..18d87b98e3e3 100644
--- a/arch/x86/entry/syscalls/Makefile
+++ b/arch/x86/entry/syscalls/Makefile
@@ -9,16 +9,16 @@ _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') \
syscall32 := $(srctree)/$(src)/syscall_32.tbl
syscall64 := $(srctree)/$(src)/syscall_64.tbl
-syshdr := $(srctree)/$(src)/syscallhdr.sh
-systbl := $(srctree)/$(src)/syscalltbl.sh
+syshdr := $(srctree)/$(src)/syscallhdr.pl
+systbl := $(srctree)/$(src)/syscalltbl.pl
quiet_cmd_syshdr = SYSHDR $@
- cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
+ cmd_syshdr = perl '$(syshdr)' '$<' '$@' \
'$(syshdr_abi_$(basetarget))' \
'$(syshdr_pfx_$(basetarget))' \
'$(syshdr_offset_$(basetarget))'
quiet_cmd_systbl = SYSTBL $@
- cmd_systbl = $(CONFIG_SHELL) '$(systbl)' $< $@
+ cmd_systbl = perl '$(systbl)' $< $@
quiet_cmd_hypercalls = HYPERCALLS $@
cmd_hypercalls = $(CONFIG_SHELL) '$<' $@ $(filter-out $<,$^)
diff --git a/arch/x86/entry/syscalls/syscallhdr.pl b/arch/x86/entry/syscalls/syscallhdr.pl
new file mode 100644
index 000000000000..2e16a1c9c48a
--- /dev/null
+++ b/arch/x86/entry/syscalls/syscallhdr.pl
@@ -0,0 +1,73 @@
+#!/usr/bin/perl -w
+# SPDX-License-Identifier: GPL-2.0
+use strict;
+
+my ($in, $out, $abi_list, $prefix, $offset) = @ARGV;
+
+$offset = ""
+ if ($#ARGV < 4);
+
+#
+# Parse the table file
+#
+my %syscalls = ();
+my $highest_nr = 0;
+open TBL, "<$in" || die $in;
+while (my $line = <TBL>) {
+ if ($line =~ m/^[0-9A-Fa-fXx]+[[:space:]]/) {
+ my @bits = split(" ", $line);
+ my $nr = int($bits[0]);
+ $syscalls{$nr} = {
+ nr => $nr,
+ abi => $bits[1],
+ name => $bits[2],
+ sys => $bits[3],
+ sys32 => $bits[4],
+ };
+ $highest_nr = $nr
+ if ($nr > $highest_nr);
+ }
+}
+close TBL || die $in;
+
+#
+# Determine which ABIs we are interested in
+#
+my %my_abis = ();
+foreach (split(",", $abi_list)) {
+ $my_abis{$_} = 1;
+}
+
+#
+# Generate the output
+#
+my $fileguard = $out;
+$fileguard =~ s!.*/!!;
+$fileguard = "_ASM_X86_" . $fileguard;
+$fileguard =~ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/;
+$fileguard =~ s/[^A-Z0-9_]/_/g;
+$fileguard =~ s/__/_/g;
+
+open OUT, ">$out" || die $out;
+print OUT "#ifndef ${fileguard}\n";
+print OUT "#define ${fileguard} 1\n";
+print OUT "\n";
+
+for (my $i = 0; $i <= $highest_nr; $i++) {
+ next unless exists($syscalls{$i});
+
+ my $c = $syscalls{$i};
+ next unless exists($my_abis{$c->{abi}});
+
+ if ($offset eq "") {
+ print OUT "#define __NR_" . $prefix . $c->{name} . " " . $c->{nr} . "\n";
+ } else {
+ print OUT "#define __NR_" . $prefix . $c->{name} . " (" . $offset . "+" . $c->{nr} . ")\n";
+ }
+}
+
+print OUT "\n";
+print OUT "#endif /* ${fileguard} */\n";
+close OUT || die $out;
+
+exit 0;
diff --git a/arch/x86/entry/syscalls/syscalltbl.pl b/arch/x86/entry/syscalls/syscalltbl.pl
new file mode 100644
index 000000000000..71664f3aa78d
--- /dev/null
+++ b/arch/x86/entry/syscalls/syscalltbl.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+# SPDX-License-Identifier: GPL-2.0
+use strict;
+
+my ($in, $out) = @ARGV;
+
+#
+# Parse the table file
+#
+my %syscalls = ();
+my $highest_nr = 0;
+open TBL, "<$in" || die $in;
+while (my $line = <TBL>) {
+ if ($line =~ m/^[0-9A-Fa-fXx]+[[:space:]]/) {
+ my @bits = split(" ", $line);
+ push @bits, "" if ($#bits == 2);
+ push @bits, "" if ($#bits == 3);
+ my $nr = int($bits[0]);
+ $syscalls{$nr} = {
+ nr => $nr,
+ abi => $bits[1],
+ name => $bits[2],
+ entry => $bits[3],
+ compat => $bits[4],
+ };
+ $highest_nr = $nr
+ if ($nr > $highest_nr);
+ }
+}
+close TBL || die $in;
+
+#
+# Generate the output
+#
+sub syscall_macro($$$) {
+ my ($abi, $nr, $entry) = @_;
+
+ # Entry can be either just a function name or "function/qualifier"
+ my @pieces = split("/", $entry);
+ my ($func, $qualifier) = @pieces;
+ $qualifier = "" unless ($#pieces == 1);
+
+ return "__SYSCALL_" . $abi . "(" . $nr . ", " . $func . ", " . $qualifier . ")";
+}
+
+sub emit($$$$) {
+ my ($abi, $nr, $entry, $compat) = @_;
+
+ die "a compat entry for a 64-bit syscall makes no sense"
+ if ($abi eq "64" && $compat);
+
+ if ($compat eq "") {
+ if ($entry) {
+ print OUT syscall_macro($abi, $nr, $entry), "\n"
+ } else {
+ print OUT "__NO_SYSCALL_(" . $nr . ")\n";
+ }
+ } else {
+ print OUT "#ifdef CONFIG_X86_32\n";
+ print OUT syscall_macro($abi, $nr, $entry), "\n"
+ if ($entry);
+ print OUT "#else\n";
+ print OUT syscall_macro($abi, $nr, $compat), "\n";
+ print OUT "#endif\n";
+ }
+}
+
+open OUT, ">$out" || die $out;
+for (my $i = 0; $i <= $highest_nr; $i++) {
+ if (!exists($syscalls{$i})) {
+ print OUT "__NO_SYSCALL_(" . $i . ")\n";
+ next;
+ }
+
+ my $c = $syscalls{$i};
+ my $abi = uc($c->{abi});
+ if ($abi eq "COMMON" || $abi eq "64") {
+ # COMMON is the same as 64, except that we don't expect X32
+ # programs to use it. Our expectation has nothing to do with
+ # any generated code, so treat them the same.
+ emit(64, $c->{nr}, $c->{entry}, $c->{compat});
+ } elsif ($abi eq "X32") {
+ # X32 is equivalent to 64 on an X32-compatible kernel.
+ print OUT "#ifdef CONFIG_X86_X32_ABI\n";
+ emit(64, $c->{nr}, $c->{entry}, $c->{compat});
+ print OUT "#endif\n";
+ } elsif ($abi eq "I386") {
+ emit($abi, $c->{nr}, $c->{entry}, $c->{compat});
+ } else {
+ die "Unknown abi $abi";
+ }
+}
+close OUT || die $out;
+
+exit 0;
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index f91ba53e06c8..d83af227d373 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -6,6 +6,7 @@
#include <asm/ucontext.h>
#define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
+#define __NO_SYSCALL(nr, sym, qual) [nr] = 0,
static char syscalls[] = {
#include <asm/syscalls_32.h>
};
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index bf51e51d808d..8f507236fec5 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -5,6 +5,7 @@
#include <asm/ia32.h>
+#define __NO_SYSCALL_(nr) [nr] = 0,
#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
static char syscalls_64[] = {
#include <asm/syscalls_64.h>
Turn xchg(), xadd() and similar functions into inline C++ template
functions. This produces more robust source as the all the casting the C
macros require is then unnecessary.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/cmpxchg.h | 109 ++++++++++++++++++++++++----------------
1 file changed, 65 insertions(+), 44 deletions(-)
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index 56bd436ed01b..5e896c17476d 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 -*- c++ -*- */
#ifndef ASM_X86_CMPXCHG_H
#define ASM_X86_CMPXCHG_H
@@ -39,43 +39,73 @@ extern void __add_wrong_size(void)
* An exchange-type operation, which takes a value and a pointer, and
* returns the old value.
*/
-#define __xchg_op(ptr, arg, op, lock) \
- ({ \
- __typeof__ (*(ptr)) __ret = (arg); \
- switch (sizeof(*(ptr))) { \
- case __X86_CASE_B: \
- asm volatile (lock #op "b %b0, %1\n" \
- : "+q" (__ret), "+m" (*(ptr)) \
- : : "memory", "cc"); \
- break; \
- case __X86_CASE_W: \
- asm volatile (lock #op "w %w0, %1\n" \
- : "+r" (__ret), "+m" (*(ptr)) \
- : : "memory", "cc"); \
- break; \
- case __X86_CASE_L: \
- asm volatile (lock #op "l %0, %1\n" \
- : "+r" (__ret), "+m" (*(ptr)) \
- : : "memory", "cc"); \
- break; \
- case __X86_CASE_Q: \
- asm volatile (lock #op "q %q0, %1\n" \
- : "+r" (__ret), "+m" (*(ptr)) \
- : : "memory", "cc"); \
- break; \
- default: \
- __ ## op ## _wrong_size(); \
- } \
- __ret; \
- })
+template <typename P, typename N>
+static inline P xchg(P *ptr, N rep)
+{
+ P v = rep;
+
+ if (sizeof(P) > sizeof(unsigned long))
+ __xchg_wrong_size();
+
+ /* Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
+ * Since this is generally used to protect other memory information, we
+ * use "asm volatile" and "memory" clobbers to prevent gcc from moving
+ * information around.
+ */
+ asm volatile("xchg %[v], %[ptr]"
+ : [ptr] "+m" (*ptr),
+ [v] "+a" (v)
+ :
+ : "memory");
+
+ return v;
+}
/*
- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
- * Since this is generally used to protect other memory information, we
- * use "asm volatile" and "memory" clobbers to prevent gcc from moving
- * information around.
+ * __xadd() adds "inc" to "*ptr" and atomically returns the previous
+ * value of "*ptr".
+ *
+ * __xadd() is always locked.
*/
-#define xchg(ptr, v) __xchg_op((ptr), (v), xchg, "")
+template <typename P, typename N>
+static inline P __xadd(P *ptr, N inc)
+{
+ P v = inc;
+
+ if (sizeof(P) > sizeof(unsigned long))
+ __xadd_wrong_size();
+
+ asm volatile("lock; xadd %[v], %[ptr]"
+ : [ptr] "+m" (*ptr),
+ [v] "+a" (v)
+ :
+ : "memory");
+
+ return v;
+}
+
+/*
+ * xadd() adds "inc" to "*ptr" and atomically returns the previous
+ * value of "*ptr".
+ *
+ * xadd() is locked when multiple CPUs are online
+ */
+template <typename P, typename N>
+static inline P xadd(P *ptr, N inc)
+{
+ P v = inc;
+
+ if (sizeof(P) > sizeof(unsigned long))
+ __xadd_wrong_size();
+
+ asm volatile(LOCK_PREFIX "xadd %[v], %[ptr]"
+ : [ptr] "+m" (*ptr),
+ [v] "+a" (v)
+ :
+ : "memory");
+
+ return v;
+}
/*
* Atomic compare and exchange. Compare OLD with MEM, if identical,
@@ -224,15 +254,6 @@ extern void __add_wrong_size(void)
#define try_cmpxchg(ptr, pold, new) \
__try_cmpxchg((ptr), (pold), (new), sizeof(*(ptr)))
-/*
- * xadd() adds "inc" to "*ptr" and atomically returns the previous
- * value of "*ptr".
- *
- * xadd() is locked when multiple CPUs are online
- */
-#define __xadd(ptr, inc, lock) __xchg_op((ptr), (inc), xadd, lock)
-#define xadd(ptr, inc) __xadd((ptr), (inc), LOCK_PREFIX)
-
#define __cmpxchg_double(pfx, p1, p2, o1, o2, n1, n2) \
({ \
bool __ret; \
Turn cmpxchg64() and similar functions into inline C++ template functions.
This produces more robust source as the all the casting the C macros
require is then unnecessary.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/cmpxchg_64.h | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 03cad196a301..55beb7fc036d 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 -*- c++ -*- */
#ifndef _ASM_X86_CMPXCHG_64_H
#define _ASM_X86_CMPXCHG_64_H
@@ -7,17 +7,23 @@ static inline void set_64bit(volatile u64 *ptr, u64 val)
*ptr = val;
}
-#define cmpxchg64(ptr, o, n) \
-({ \
- BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
- cmpxchg((ptr), (o), (n)); \
-})
+template <typename P, typename N>
+static inline P cmpxchg64(P *ptr, P old, N rep)
+{
+ P ret = old;
+ if (sizeof(P) != 8)
+ __cmpxchg_wrong_size();
+ return cmpxchg(ptr, ret, rep);
+}
-#define cmpxchg64_local(ptr, o, n) \
-({ \
- BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
- cmpxchg_local((ptr), (o), (n)); \
-})
+template <typename P, typename N>
+static inline P cmpxchg64_local(P *ptr, P old, N rep)
+{
+ P ret = old;
+ if (sizeof(P) != 8)
+ __cmpxchg_wrong_size();
+ return cmpxchg_local(ptr, ret, rep);
+}
#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX16)
Turn cmpxchg_double() and similar functions into inline C++ template
functions. This produces more robust source as the all the casting the C
macros require is then unnecessary.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/cmpxchg.h | 93 +++++++++++++++++++++++++++++++---------
1 file changed, 71 insertions(+), 22 deletions(-)
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index 4bbf947c88a2..2ffe1c621eb1 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -180,27 +180,76 @@ static inline P sync_cmpxchg(P *ptr, P old, N rep)
# include <asm/cmpxchg_64.h>
#endif
-#define __cmpxchg_double(pfx, p1, p2, o1, o2, n1, n2) \
-({ \
- bool __ret; \
- __typeof__(*(p1)) __old1 = (o1), __new1 = (n1); \
- __typeof__(*(p2)) __old2 = (o2), __new2 = (n2); \
- BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \
- BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \
- VM_BUG_ON((unsigned long)(p1) % (2 * sizeof(long))); \
- VM_BUG_ON((unsigned long)((p1) + 1) != (unsigned long)(p2)); \
- asm volatile(pfx "cmpxchg%c4b %2; sete %0" \
- : "=a" (__ret), "+d" (__old2), \
- "+m" (*(p1)), "+m" (*(p2)) \
- : "i" (2 * sizeof(long)), "a" (__old1), \
- "b" (__new1), "c" (__new2)); \
- __ret; \
-})
-
-#define cmpxchg_double(p1, p2, o1, o2, n1, n2) \
- __cmpxchg_double(LOCK_PREFIX, p1, p2, o1, o2, n1, n2)
-
-#define cmpxchg_double_local(p1, p2, o1, o2, n1, n2) \
- __cmpxchg_double(, p1, p2, o1, o2, n1, n2)
+template <typename P1, typename P2, typename N1, typename N2>
+static inline bool __cmpxchg_double(P1 *p1, P2 *p2,
+ P1 old1, P2 old2,
+ N1 rep1, N2 rep2,
+ enum cmpxchg_lock lock = __lock_always)
+{
+ bool ret;
+
+ if (sizeof(P1) != sizeof(long)) __cmpxchg_wrong_size();
+ if (sizeof(P2) != sizeof(long)) __cmpxchg_wrong_size();
+
+ //VM_BUG_ON((unsigned long)(p1) % (2 * sizeof(long)));
+ //VM_BUG_ON((unsigned long)((p1) + 1) != (unsigned long)(p2));
+
+ switch (lock) {
+ case __lock_local:
+ asm volatile("cmpxchg%c4b %[ptr1]"
+ CC_SET(z)
+ : CC_OUT(z) (ret),
+ [old2]"+d" (old2),
+ [ptr1] "+m" (*p1),
+ [ptr2] "+m" (*p2)
+ : "i" (2 * sizeof(long)),
+ [old1] "a" (old1),
+ [rep1] "b" (rep1),
+ [rep2] "c" (rep2));
+ break;
+ case __lock_smp:
+ asm volatile(LOCK_PREFIX "cmpxchg%c4b %[ptr1]"
+ CC_SET(z)
+ : CC_OUT(z) (ret),
+ [old2]"+d" (old2),
+ [ptr1] "+m" (*p1),
+ [ptr2] "+m" (*p2)
+ : "i" (2 * sizeof(long)),
+ [old1] "a" (old1),
+ [rep1] "b" (rep1),
+ [rep2] "c" (rep2));
+ break;
+ case __lock_always:
+ asm volatile("lock; cmpxchg%c4b %[ptr1]"
+ CC_SET(z)
+ : CC_OUT(z) (ret),
+ [old2]"+d" (old2),
+ [ptr1] "+m" (*p1),
+ [ptr2] "+m" (*p2)
+ : "i" (2 * sizeof(long)),
+ [old1] "a" (old1),
+ [rep1] "b" (rep1),
+ [rep2] "c" (rep2));
+ break;
+ }
+
+ return ret;
+}
+
+template <typename P1, typename P2, typename N1, typename N2>
+static inline bool cmpxchg_double(P1 *p1, P2 *p2,
+ P1 old1, P2 old2,
+ N1 rep1, N2 rep2)
+{
+ return __cmpxchg_double(p1, p2, old1, old2, rep1, rep2, __lock_always);
+}
+
+template <typename P1, typename P2, typename N1, typename N2>
+static inline bool cmpxchg_double_local(P1 *p1, P2 *p2,
+ P1 old1, P2 old2,
+ N1 rep1, N2 rep2)
+{
+ return __cmpxchg_double(p1, p2, old1, old2, rep1, rep2, __lock_local);
+}
#endif /* ASM_X86_CMPXCHG_H */
Don't do "extern asmlinkage" as asmlinkage is defined to include extern
"C".
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/hw_irq.h | 38 +++++++++++++++++-----------------
arch/x86/include/asm/processor.h | 2 +-
arch/x86/include/asm/special_insns.h | 2 +-
include/linux/compat.h | 2 +-
include/linux/lockdep.h | 2 +-
include/linux/printk.h | 4 ++--
include/linux/sched/task.h | 2 +-
include/linux/start_kernel.h | 2 +-
8 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 2851077b6051..21cb1299170a 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -29,25 +29,25 @@
#include <asm/sections.h>
/* Interrupt handlers registered during init_IRQ */
-extern asmlinkage void apic_timer_interrupt(void);
-extern asmlinkage void x86_platform_ipi(void);
-extern asmlinkage void kvm_posted_intr_ipi(void);
-extern asmlinkage void kvm_posted_intr_wakeup_ipi(void);
-extern asmlinkage void kvm_posted_intr_nested_ipi(void);
-extern asmlinkage void error_interrupt(void);
-extern asmlinkage void irq_work_interrupt(void);
-
-extern asmlinkage void spurious_interrupt(void);
-extern asmlinkage void thermal_interrupt(void);
-extern asmlinkage void reschedule_interrupt(void);
-
-extern asmlinkage void irq_move_cleanup_interrupt(void);
-extern asmlinkage void reboot_interrupt(void);
-extern asmlinkage void threshold_interrupt(void);
-extern asmlinkage void deferred_error_interrupt(void);
-
-extern asmlinkage void call_function_interrupt(void);
-extern asmlinkage void call_function_single_interrupt(void);
+asmlinkage void apic_timer_interrupt(void);
+asmlinkage void x86_platform_ipi(void);
+asmlinkage void kvm_posted_intr_ipi(void);
+asmlinkage void kvm_posted_intr_wakeup_ipi(void);
+asmlinkage void kvm_posted_intr_nested_ipi(void);
+asmlinkage void error_interrupt(void);
+asmlinkage void irq_work_interrupt(void);
+
+asmlinkage void spurious_interrupt(void);
+asmlinkage void thermal_interrupt(void);
+asmlinkage void reschedule_interrupt(void);
+
+asmlinkage void irq_move_cleanup_interrupt(void);
+asmlinkage void reboot_interrupt(void);
+asmlinkage void threshold_interrupt(void);
+asmlinkage void deferred_error_interrupt(void);
+
+asmlinkage void call_function_interrupt(void);
+asmlinkage void call_function_single_interrupt(void);
#ifdef CONFIG_X86_LOCAL_APIC
struct irq_data;
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index b0ccd4847a58..606dbae01d5b 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -409,7 +409,7 @@ DECLARE_INIT_PER_CPU(irq_stack_union);
DECLARE_PER_CPU(char *, irq_stack_ptr);
DECLARE_PER_CPU(unsigned int, irq_count);
-extern asmlinkage void ignore_sysret(void);
+asmlinkage void ignore_sysret(void);
#else /* X86_64 */
#ifdef CONFIG_CC_STACKPROTECTOR
/*
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 317fc59b512c..6eb481e1bb27 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -134,7 +134,7 @@ static inline void native_wbinvd(void)
asm volatile("wbinvd": : :"memory");
}
-extern asmlinkage void native_load_gs_index(unsigned);
+asmlinkage void native_load_gs_index(unsigned);
static inline unsigned long __read_cr4(void)
{
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 16c3027074a2..218a993abdb1 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -305,7 +305,7 @@ extern int put_compat_rusage(const struct rusage *,
struct compat_siginfo;
-extern asmlinkage long compat_sys_waitid(int, compat_pid_t,
+asmlinkage long compat_sys_waitid(int, compat_pid_t,
struct compat_siginfo __user *, int,
struct compat_rusage __user *);
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 6fc77d4dbdcd..0b0c244b4cdc 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -270,7 +270,7 @@ extern void lockdep_info(void);
extern void lockdep_reset(void);
extern void lockdep_reset_lock(struct lockdep_map *lock);
extern void lockdep_free_key_range(void *start, unsigned long size);
-extern asmlinkage void lockdep_sys_exit(void);
+asmlinkage void lockdep_sys_exit(void);
extern void lockdep_off(void);
extern void lockdep_on(void);
diff --git a/include/linux/printk.h b/include/linux/printk.h
index e9b603ee9953..5b87db57e367 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -138,7 +138,7 @@ struct va_format {
})
#ifdef CONFIG_EARLY_PRINTK
-extern asmlinkage __printf(1, 2)
+asmlinkage __printf(1, 2)
void early_printk(const char *fmt, ...);
#else
static inline __printf(1, 2) __cold
@@ -279,7 +279,7 @@ static inline void printk_safe_flush_on_panic(void)
extern int kptr_restrict;
-extern asmlinkage void dump_stack(void) __cold;
+asmlinkage void dump_stack(void) __cold;
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 5be31eb7b266..26131c2aa8ce 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -29,7 +29,7 @@ extern struct task_struct init_task;
extern int lockdep_tasklist_lock_is_held(void);
#endif /* #ifdef CONFIG_PROVE_RCU */
-extern asmlinkage void schedule_tail(struct task_struct *prev);
+asmlinkage void schedule_tail(struct task_struct *prev);
extern void init_idle(struct task_struct *idle, int cpu);
extern int sched_fork(unsigned long clone_flags, struct task_struct *p);
diff --git a/include/linux/start_kernel.h b/include/linux/start_kernel.h
index 4b268d86a784..d752fb744822 100644
--- a/include/linux/start_kernel.h
+++ b/include/linux/start_kernel.h
@@ -8,6 +8,6 @@
/* Define the prototype for start_kernel here, rather than cluttering
up something else. */
-extern asmlinkage void __init start_kernel(void);
+asmlinkage void __init start_kernel(void);
#endif /* _LINUX_START_KERNEL_H */
Always declare the type of atomic64_t to be s64 rather than conditionally
defining it as long in generic code.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/atomic64_64.h | 12 ++++++------
include/linux/types.h | 4 +---
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 738495caf05f..895292a50c77 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -172,20 +172,20 @@ static inline long atomic64_fetch_sub(long i, atomic64_t *v)
#define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
#define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
-static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
+static inline long atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new_val)
{
- return cmpxchg(&v->counter, old, new);
+ return cmpxchg(&v->counter, old, new_val);
}
#define atomic64_try_cmpxchg atomic64_try_cmpxchg
-static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, s64 *old, long new)
+static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new_val)
{
- return try_cmpxchg(&v->counter, old, new);
+ return try_cmpxchg(&v->counter, *old, new_val);
}
-static inline long atomic64_xchg(atomic64_t *v, long new)
+static inline long atomic64_xchg(atomic64_t *v, long new_val)
{
- return xchg(&v->counter, new);
+ return xchg(&v->counter, new_val);
}
/**
diff --git a/include/linux/types.h b/include/linux/types.h
index 68323cb03910..d233b12c7ebe 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -179,11 +179,9 @@ typedef struct {
int counter;
} atomic_t;
-#ifdef CONFIG_64BIT
typedef struct {
- long counter;
+ s64 counter;
} atomic64_t;
-#endif
struct list_head {
struct list_head *next, *prev;
ramdisk_execute_command and initcall_level_names should be const char *
pointers.
Signed-off-by: David Howells <[email protected]>
---
init/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/init/main.c b/init/main.c
index 969eaf140ef0..642e917387db 100644
--- a/init/main.c
+++ b/init/main.c
@@ -135,7 +135,7 @@ static char *static_command_line;
static char *initcall_command_line;
static char *execute_command;
-static char *ramdisk_execute_command;
+static const char *ramdisk_execute_command;
/*
* Used to generate warnings if static_key manipulation functions are used
@@ -873,7 +873,7 @@ static initcall_t *initcall_levels[] __initdata = {
};
/* Keep these in sync with initcalls in include/linux/init.h */
-static char *initcall_level_names[] __initdata = {
+static const char *initcall_level_names[] __initconst = {
"early",
"core",
"postcore",
Simplify the RCU accessor functions by turning them into inline template
functions. There's then no need for the use of casts built around typeof.
Signed-off-by: David Howells <[email protected]>
---
include/linux/rcupdate.h | 124 +++++++++++++++++++++++++++++-----------------
1 file changed, 78 insertions(+), 46 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 043d04784675..328b312f09f0 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* Read-Copy Update mechanism for mutual exclusion
*
* This program is free software; you can redistribute it and/or modify
@@ -337,32 +337,50 @@ static inline void rcu_preempt_sleep_check(void) { }
#define rcu_dereference_sparse(p, space)
#endif /* #else #ifdef __CHECKER__ */
-#define __rcu_access_pointer(p, space) \
-({ \
- typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(_________p1)); \
-})
-#define __rcu_dereference_check(p, c, space) \
-({ \
- /* Dependency order vs. p above. */ \
- typeof(*p) *________p1 = (typeof(*p) *__force)READ_ONCE(p); \
- RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(________p1)); \
-})
-#define __rcu_dereference_protected(p, c, space) \
-({ \
- RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \
- rcu_dereference_sparse(p, space); \
- ((typeof(*p) __force __kernel *)(p)); \
-})
-#define rcu_dereference_raw(p) \
-({ \
- /* Dependency order vs. p above. */ \
- typeof(p) ________p1 = READ_ONCE(p); \
- ((typeof(*p) __force __kernel *)(________p1)); \
-})
+template <typename T>
+T *__rcu_access_pointer(T *&p)
+{
+ /* Dependency order vs. p above. */
+ T *p1 = (T *__force)READ_ONCE(p);
+ rcu_dereference_sparse(p, __rcu);
+ return (T __force __kernel *)p1;
+}
+
+template <typename T>
+T *__rcu_dereference_check(T *&p, bool c)
+{
+ /* Dependency order vs. p above. */
+ T *p1 = (T *__force)READ_ONCE(p);
+ RCU_LOCKDEP_WARN(!c, "suspicious rcu_dereference_check() usage");
+ rcu_dereference_sparse(p, __rcu);
+ return (T __force __kernel *)p1;
+}
+
+template <typename T>
+T *__rcu_dereference_check(T *const &p, bool c)
+{
+ /* Dependency order vs. p above. */
+ T *p1 = (T *__force)READ_ONCE(p);
+ RCU_LOCKDEP_WARN(!c, "suspicious rcu_dereference_check() usage");
+ rcu_dereference_sparse(p, __rcu);
+ return (T __force __kernel *)p1;
+}
+
+template <typename T>
+T *__rcu_dereference_protected(T *&p, bool c)
+{
+ RCU_LOCKDEP_WARN(!c, "suspicious rcu_dereference_protected() usage");
+ rcu_dereference_sparse(p, __rcu);
+ return (T __force __kernel *)p;
+}
+
+template <typename T>
+T *rcu_dereference_raw(T *&p)
+{
+ /* Dependency order vs. p above. */
+ T *p1 = READ_ONCE(p);
+ return (T __force __kernel *)p1;
+}
/**
* RCU_INITIALIZER() - statically initialize an RCU-protected global variable
@@ -401,16 +419,14 @@ static inline void rcu_preempt_sleep_check(void) { }
* please be careful when making changes to rcu_assign_pointer() and the
* other macros that it invokes.
*/
-#define rcu_assign_pointer(p, v) \
-({ \
- uintptr_t _r_a_p__v = (uintptr_t)(v); \
- \
- if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
- WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
- else \
- smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \
- _r_a_p__v; \
-})
+template <typename T>
+static inline void rcu_assign_pointer(T *&p, T *v)
+{
+ if (__builtin_constant_p(v) && !v)
+ WRITE_ONCE((p), v);
+ else
+ smp_store_release(&p, (T __force __rcu *)v);
+}
/**
* rcu_swap_protected() - swap an RCU and a regular pointer
@@ -482,8 +498,17 @@ static inline void rcu_preempt_sleep_check(void) { }
* which pointers are protected by RCU and checks that the pointer is
* annotated as __rcu.
*/
-#define rcu_dereference_check(p, c) \
- __rcu_dereference_check((p), (c) || rcu_read_lock_held(), __rcu)
+template <typename T>
+T *rcu_dereference_check(T *&p, bool c)
+{
+ return __rcu_dereference_check(p, c || rcu_read_lock_held());
+}
+
+template <typename T>
+T *rcu_dereference_check(T *const &p, bool c)
+{
+ return __rcu_dereference_check(p, c || rcu_read_lock_held());
+}
/**
* rcu_dereference_bh_check() - rcu_dereference_bh with debug checking
@@ -493,7 +518,7 @@ static inline void rcu_preempt_sleep_check(void) { }
* This is the RCU-bh counterpart to rcu_dereference_check().
*/
#define rcu_dereference_bh_check(p, c) \
- __rcu_dereference_check((p), (c) || rcu_read_lock_bh_held(), __rcu)
+ __rcu_dereference_check((p), (c) || rcu_read_lock_bh_held())
/**
* rcu_dereference_sched_check() - rcu_dereference_sched with debug checking
@@ -532,7 +557,7 @@ static inline void rcu_preempt_sleep_check(void) { }
* but very ugly failures.
*/
#define rcu_dereference_protected(p, c) \
- __rcu_dereference_protected((p), (c), __rcu)
+ __rcu_dereference_protected((p), (c))
/**
@@ -814,11 +839,18 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
* Note that unlike rcu_assign_pointer(), RCU_INIT_POINTER() provides no
* ordering guarantees for either the CPU or the compiler.
*/
-#define RCU_INIT_POINTER(p, v) \
- do { \
- rcu_dereference_sparse(p, __rcu); \
- WRITE_ONCE(p, RCU_INITIALIZER(v)); \
- } while (0)
+template <typename T>
+static inline void RCU_INIT_POINTER(T *&p, T *v)
+{
+ rcu_dereference_sparse(p, __rcu);
+ WRITE_ONCE(p, (T __force __rcu *)v);
+}
+
+template <typename T>
+static inline void RCU_INIT_POINTER(T *&p, nullptr_t v)
+{
+ WRITE_ONCE(p, (T __force __rcu *)v);
+}
/**
* RCU_POINTER_INITIALIZER() - statically initialize an RCU protected pointer
Fix BUILD_BUG_ON_ZERO() to work in C++. The construction format:
(struct { ... })
is something C++ doesn't like.
Signed-off-by: David Howells <[email protected]>
---
include/linux/build_bug.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h
index 43d1fd50d433..7445385cd26f 100644
--- a/include/linux/build_bug.h
+++ b/include/linux/build_bug.h
@@ -20,13 +20,16 @@
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
+extern int __build_bug_on_zero(void)
+ __compiletime_error("Build bug on zero");
+
/*
* Force a compilation error if condition is true, but also produce a
* result (of value 0 and type size_t), so the expression can be used
* e.g. in a structure initializer (or where-ever else comma expressions
* aren't permitted).
*/
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
+#define BUILD_BUG_ON_ZERO(e) ((e) ? 0 : __build_bug_on_zero())
/*
* BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the
Signed-off-by: David Howells <[email protected]>
---
include/linux/compiler_types.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 6b79a9bba9a7..7858c827c100 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -263,7 +263,7 @@ struct ftrace_likely_data {
/* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type
-# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+# define __same_type(a, b) true // not in C++ __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
/* Is this type a native word size -- useful for atomic operations */
Turn void-type variables into char-type as C++ doesn't allow the former.
Signed-off-by: David Howells <[email protected]>
---
include/asm-generic/sections.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 849cd8eb5ca0..f3efd6cc9ba0 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -53,7 +53,7 @@ extern char __ctors_start[], __ctors_end[];
/* Start and end of .opd section - used for function descriptors. */
extern char __start_opd[], __end_opd[];
-extern __visible const void __nosave_begin, __nosave_end;
+extern __visible const char __nosave_begin[], __nosave_end[];
/* Function descriptor handling (if any). Override in asm/sections.h */
#ifndef dereference_function_descriptor
Move the print_line_t enum definition to before its first use.
Signed-off-by: David Howells <[email protected]>
---
include/linux/trace_events.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 8a1442c4e513..38a7667827ca 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -104,6 +104,14 @@ struct trace_iterator {
/* All new field here will be zeroed out in pipe_read */
};
+/* Return values for print_line callback */
+enum print_line_t {
+ TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
+ TRACE_TYPE_HANDLED = 1,
+ TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
+ TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
+};
+
enum trace_iter_flags {
TRACE_FILE_LAT_FMT = 1,
TRACE_FILE_ANNOTATE = 2,
@@ -131,14 +139,6 @@ struct trace_event {
extern int register_trace_event(struct trace_event *event);
extern int unregister_trace_event(struct trace_event *event);
-/* Return values for print_line callback */
-enum print_line_t {
- TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
- TRACE_TYPE_HANDLED = 1,
- TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
- TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
-};
-
enum print_line_t trace_handle_return(struct trace_seq *s);
void tracing_generic_entry_update(struct trace_entry *entry,
linux/timer.h needs stuff from linux/hrtimer.h so include the latter from
the former.
Signed-off-by: David Howells <[email protected]>
---
include/linux/timer.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 2448f9cc48a3..f99724c1288e 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -7,6 +7,7 @@
#include <linux/stddef.h>
#include <linux/debugobjects.h>
#include <linux/stringify.h>
+#include <linux/hrtimer.h>
struct tvec_base;
Turn cmpxchg() and similar functions into inline C++ template functions.
This produces more robust source as the all the casting the C macros
require is then unnecessary.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/atomic.h | 2
arch/x86/include/asm/cmpxchg.h | 222 +++++++++++++---------------------------
2 files changed, 75 insertions(+), 149 deletions(-)
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 72759f131cc5..20f225cd47e8 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -190,7 +190,7 @@ static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
#define atomic_try_cmpxchg atomic_try_cmpxchg
static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
{
- return try_cmpxchg(&v->counter, old, new);
+ return try_cmpxchg(&v->counter, *old, new);
}
static inline int atomic_xchg(atomic_t *v, int new)
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index 5e896c17476d..4bbf947c88a2 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -6,6 +6,12 @@
#include <asm/cpufeatures.h>
#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+enum cmpxchg_lock {
+ __lock_local,
+ __lock_smp,
+ __lock_always
+};
+
/*
* Non-existant functions to indicate usage errors at link time
* (or compile-time if the compiler implements __compiletime_error().
@@ -20,22 +26,6 @@ extern void __add_wrong_size(void)
__compiletime_error("Bad argument size for add");
/*
- * Constants for operation sizes. On 32-bit, the 64-bit size it set to
- * -1 because sizeof will never return -1, thereby making those switch
- * case statements guaranteeed dead code which the compiler will
- * eliminate, and allowing the "missing symbol in the default case" to
- * indicate a usage error.
- */
-#define __X86_CASE_B 1
-#define __X86_CASE_W 2
-#define __X86_CASE_L 4
-#ifdef CONFIG_64BIT
-#define __X86_CASE_Q 8
-#else
-#define __X86_CASE_Q -1 /* sizeof will never return -1 */
-#endif
-
-/*
* An exchange-type operation, which takes a value and a pointer, and
* returns the old value.
*/
@@ -107,67 +97,82 @@ static inline P xadd(P *ptr, N inc)
return v;
}
+/*
+ * Atomic compare and exchange.
+ */
+template <typename P, typename N>
+static inline bool try_cmpxchg(P *ptr, P &old, N _rep,
+ enum cmpxchg_lock lock = __lock_smp)
+{
+ bool success;
+ P rep = _rep;
+
+ if (sizeof(P) > sizeof(unsigned long))
+ __cmpxchg_wrong_size();
+
+ switch (lock) {
+ case __lock_local:
+ asm volatile("cmpxchg %[rep], %[ptr]"
+ CC_SET(z)
+ : CC_OUT(z) (success),
+ [ptr] "+m" (*ptr),
+ [old] "+a" (old)
+ : [rep] "q" (rep)
+ : "memory");
+ break;
+ case __lock_smp:
+ asm volatile(LOCK_PREFIX "cmpxchg %[rep], %[ptr]"
+ CC_SET(z)
+ : CC_OUT(z) (success),
+ [ptr] "+m" (*ptr),
+ [old] "+a" (old)
+ : [rep] "q" (rep)
+ : "memory");
+ break;
+ case __lock_always:
+ asm volatile("lock; cmpxchg %[rep], %[ptr]"
+ CC_SET(z)
+ : CC_OUT(z) (success),
+ [ptr] "+m" (*ptr),
+ [old] "+a" (old)
+ : [rep] "q" (rep)
+ : "memory");
+ break;
+ }
+
+ return likely(success);
+}
+
+
/*
* Atomic compare and exchange. Compare OLD with MEM, if identical,
* store NEW in MEM. Return the initial value in MEM. Success is
* indicated by comparing RETURN with OLD.
*/
-#define __raw_cmpxchg(ptr, old, new, size, lock) \
-({ \
- __typeof__(*(ptr)) __ret; \
- __typeof__(*(ptr)) __old = (old); \
- __typeof__(*(ptr)) __new = (new); \
- switch (size) { \
- case __X86_CASE_B: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(ptr); \
- asm volatile(lock "cmpxchgb %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "q" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_W: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(ptr); \
- asm volatile(lock "cmpxchgw %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_L: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(ptr); \
- asm volatile(lock "cmpxchgl %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_Q: \
- { \
- volatile u64 *__ptr = (volatile u64 *)(ptr); \
- asm volatile(lock "cmpxchgq %2,%1" \
- : "=a" (__ret), "+m" (*__ptr) \
- : "r" (__new), "0" (__old) \
- : "memory"); \
- break; \
- } \
- default: \
- __cmpxchg_wrong_size(); \
- } \
- __ret; \
-})
-#define __cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+template <typename P, typename N>
+static inline P cmpxchg_local(P *ptr, P old, N rep)
+{
+ P ret = old;
+ try_cmpxchg(ptr, ret, rep, __lock_local);
+ return ret;
+}
-#define __sync_cmpxchg(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
+template <typename P, typename N>
+static inline P cmpxchg(P *ptr, P old, N rep)
+{
+ P ret = old;
+ try_cmpxchg(ptr, ret, rep, __lock_smp);
+ return ret;
+}
-#define __cmpxchg_local(ptr, old, new, size) \
- __raw_cmpxchg((ptr), (old), (new), (size), "")
+template <typename P, typename N>
+static inline P sync_cmpxchg(P *ptr, P old, N rep)
+{
+ P ret = old;
+ try_cmpxchg(ptr, ret, rep, __lock_always);
+ return ret;
+}
#ifdef CONFIG_X86_32
# include <asm/cmpxchg_32.h>
@@ -175,85 +180,6 @@ static inline P xadd(P *ptr, N inc)
# include <asm/cmpxchg_64.h>
#endif
-#define cmpxchg(ptr, old, new) \
- __cmpxchg(ptr, old, new, sizeof(*(ptr)))
-
-#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
-
-#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
-
-
-#define __raw_try_cmpxchg(_ptr, _pold, _new, size, lock) \
-({ \
- bool success; \
- __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
- __typeof__(*(_ptr)) __old = *_old; \
- __typeof__(*(_ptr)) __new = (_new); \
- switch (size) { \
- case __X86_CASE_B: \
- { \
- volatile u8 *__ptr = (volatile u8 *)(_ptr); \
- asm volatile(lock "cmpxchgb %[new], %[ptr]" \
- CC_SET(z) \
- : CC_OUT(z) (success), \
- [ptr] "+m" (*__ptr), \
- [old] "+a" (__old) \
- : [new] "q" (__new) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_W: \
- { \
- volatile u16 *__ptr = (volatile u16 *)(_ptr); \
- asm volatile(lock "cmpxchgw %[new], %[ptr]" \
- CC_SET(z) \
- : CC_OUT(z) (success), \
- [ptr] "+m" (*__ptr), \
- [old] "+a" (__old) \
- : [new] "r" (__new) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_L: \
- { \
- volatile u32 *__ptr = (volatile u32 *)(_ptr); \
- asm volatile(lock "cmpxchgl %[new], %[ptr]" \
- CC_SET(z) \
- : CC_OUT(z) (success), \
- [ptr] "+m" (*__ptr), \
- [old] "+a" (__old) \
- : [new] "r" (__new) \
- : "memory"); \
- break; \
- } \
- case __X86_CASE_Q: \
- { \
- volatile u64 *__ptr = (volatile u64 *)(_ptr); \
- asm volatile(lock "cmpxchgq %[new], %[ptr]" \
- CC_SET(z) \
- : CC_OUT(z) (success), \
- [ptr] "+m" (*__ptr), \
- [old] "+a" (__old) \
- : [new] "r" (__new) \
- : "memory"); \
- break; \
- } \
- default: \
- __cmpxchg_wrong_size(); \
- } \
- if (unlikely(!success)) \
- *_old = __old; \
- likely(success); \
-})
-
-#define __try_cmpxchg(ptr, pold, new, size) \
- __raw_try_cmpxchg((ptr), (pold), (new), (size), LOCK_PREFIX)
-
-#define try_cmpxchg(ptr, pold, new) \
- __try_cmpxchg((ptr), (pold), (new), sizeof(*(ptr)))
-
#define __cmpxchg_double(pfx, p1, p2, o1, o2, n1, n2) \
({ \
bool __ret; \
'compl' and 'and' are synonyms for operators, so avoid them.
Signed-off-by: David Howells <[email protected]>
---
include/linux/cpumask.h | 4 ++--
include/linux/crypto.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index bf53d893ad02..73bee9ff6cb3 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -273,9 +273,9 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
*
* After the loop, cpu is >= nr_cpu_ids.
*/
-#define for_each_cpu_and(cpu, mask, and) \
+#define for_each_cpu_and(cpu, mask, and_with) \
for ((cpu) = -1; \
- (cpu) = cpumask_next_and((cpu), (mask), (and)), \
+ (cpu) = cpumask_next_and((cpu), (mask), (and_with)), \
(cpu) < nr_cpu_ids;)
#endif /* SMP */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 7e6e84cf6383..f8f95615ba69 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -1034,9 +1034,9 @@ static inline void ablkcipher_request_free(struct ablkcipher_request *req)
*/
static inline void ablkcipher_request_set_callback(
struct ablkcipher_request *req,
- u32 flags, crypto_completion_t compl, void *data)
+ u32 flags, crypto_completion_t c, void *data)
{
- req->base.complete = compl;
+ req->base.complete = c;
req->base.data = data;
req->base.flags = flags;
}
C++ requires a space between a string and a following symbol. For example,
the following is not permitted:
asm volatile("btl "__percpu_arg(2)",%1"
but this is:
asm volatile("btl " __percpu_arg(2) ",%1"
The former produces warnings like the following:
arch/x86/include/asm/alternative.h:95:42: warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix]
This ought to be possible to script conversion for.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/alternative.h | 10 ++--
arch/x86/include/asm/arch_hweight.h | 4 +
arch/x86/include/asm/percpu.h | 94 ++++++++++++++++++-----------------
arch/x86/include/asm/perf_event.h | 2 -
include/linux/spinlock.h | 2 -
5 files changed, 56 insertions(+), 56 deletions(-)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index cf5961ca8677..cc200eb8288e 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -85,14 +85,14 @@ static inline int alternatives_text_reserved(void *start, void *end)
}
#endif /* CONFIG_SMP */
-#define b_replacement(num) "664"#num
-#define e_replacement(num) "665"#num
+#define b_replacement(num) "664" #num
+#define e_replacement(num) "665" #num
#define alt_end_marker "663"
#define alt_slen "662b-661b"
-#define alt_pad_len alt_end_marker"b-662b"
-#define alt_total_slen alt_end_marker"b-661b"
-#define alt_rlen(num) e_replacement(num)"f-"b_replacement(num)"f"
+#define alt_pad_len alt_end_marker "b-662b"
+#define alt_total_slen alt_end_marker "b-661b"
+#define alt_rlen(num) e_replacement(num) "f-" b_replacement(num) "f"
#define __OLDINSTR(oldinstr, num) \
"661:\n\t" oldinstr "\n662:\n" \
diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h
index 34a10b2d5b73..75c4038ea63a 100644
--- a/arch/x86/include/asm/arch_hweight.h
+++ b/arch/x86/include/asm/arch_hweight.h
@@ -25,7 +25,7 @@ static __always_inline unsigned int __arch_hweight32(unsigned int w)
unsigned int res;
asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
- : "="REG_OUT (res)
+ : "=" REG_OUT (res)
: REG_IN (w));
return res;
@@ -53,7 +53,7 @@ static __always_inline unsigned long __arch_hweight64(__u64 w)
unsigned long res;
asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
- : "="REG_OUT (res)
+ : "=" REG_OUT (res)
: REG_IN (w));
return res;
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index a06b07399d17..10b63180fb27 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -46,7 +46,7 @@
#include <linux/stringify.h>
#ifdef CONFIG_SMP
-#define __percpu_prefix "%%"__stringify(__percpu_seg)":"
+#define __percpu_prefix "%%" __stringify(__percpu_seg) ":"
#define __my_cpu_offset this_cpu_read(this_cpu_off)
/*
@@ -97,22 +97,22 @@ do { \
} \
switch (sizeof(var)) { \
case 1: \
- asm(op "b %1,"__percpu_arg(0) \
+ asm(op "b %1," __percpu_arg(0) \
: "+m" (var) \
: "qi" ((pto_T__)(val))); \
break; \
case 2: \
- asm(op "w %1,"__percpu_arg(0) \
+ asm(op "w %1," __percpu_arg(0) \
: "+m" (var) \
: "ri" ((pto_T__)(val))); \
break; \
case 4: \
- asm(op "l %1,"__percpu_arg(0) \
+ asm(op "l %1," __percpu_arg(0) \
: "+m" (var) \
: "ri" ((pto_T__)(val))); \
break; \
case 8: \
- asm(op "q %1,"__percpu_arg(0) \
+ asm(op "q %1," __percpu_arg(0) \
: "+m" (var) \
: "re" ((pto_T__)(val))); \
break; \
@@ -138,41 +138,41 @@ do { \
switch (sizeof(var)) { \
case 1: \
if (pao_ID__ == 1) \
- asm("incb "__percpu_arg(0) : "+m" (var)); \
+ asm("incb " __percpu_arg(0) : "+m" (var)); \
else if (pao_ID__ == -1) \
- asm("decb "__percpu_arg(0) : "+m" (var)); \
+ asm("decb " __percpu_arg(0) : "+m" (var)); \
else \
- asm("addb %1, "__percpu_arg(0) \
+ asm("addb %1, " __percpu_arg(0) \
: "+m" (var) \
: "qi" ((pao_T__)(val))); \
break; \
case 2: \
if (pao_ID__ == 1) \
- asm("incw "__percpu_arg(0) : "+m" (var)); \
+ asm("incw " __percpu_arg(0) : "+m" (var)); \
else if (pao_ID__ == -1) \
- asm("decw "__percpu_arg(0) : "+m" (var)); \
+ asm("decw " __percpu_arg(0) : "+m" (var)); \
else \
- asm("addw %1, "__percpu_arg(0) \
+ asm("addw %1, " __percpu_arg(0) \
: "+m" (var) \
: "ri" ((pao_T__)(val))); \
break; \
case 4: \
if (pao_ID__ == 1) \
- asm("incl "__percpu_arg(0) : "+m" (var)); \
+ asm("incl " __percpu_arg(0) : "+m" (var)); \
else if (pao_ID__ == -1) \
- asm("decl "__percpu_arg(0) : "+m" (var)); \
+ asm("decl " __percpu_arg(0) : "+m" (var)); \
else \
- asm("addl %1, "__percpu_arg(0) \
+ asm("addl %1, " __percpu_arg(0) \
: "+m" (var) \
: "ri" ((pao_T__)(val))); \
break; \
case 8: \
if (pao_ID__ == 1) \
- asm("incq "__percpu_arg(0) : "+m" (var)); \
+ asm("incq " __percpu_arg(0) : "+m" (var)); \
else if (pao_ID__ == -1) \
- asm("decq "__percpu_arg(0) : "+m" (var)); \
+ asm("decq " __percpu_arg(0) : "+m" (var)); \
else \
- asm("addq %1, "__percpu_arg(0) \
+ asm("addq %1, " __percpu_arg(0) \
: "+m" (var) \
: "re" ((pao_T__)(val))); \
break; \
@@ -185,22 +185,22 @@ do { \
typeof(var) pfo_ret__; \
switch (sizeof(var)) { \
case 1: \
- asm(op "b "__percpu_arg(1)",%0" \
+ asm(op "b " __percpu_arg(1)",%0" \
: "=q" (pfo_ret__) \
: "m" (var)); \
break; \
case 2: \
- asm(op "w "__percpu_arg(1)",%0" \
+ asm(op "w " __percpu_arg(1)",%0" \
: "=r" (pfo_ret__) \
: "m" (var)); \
break; \
case 4: \
- asm(op "l "__percpu_arg(1)",%0" \
+ asm(op "l " __percpu_arg(1)",%0" \
: "=r" (pfo_ret__) \
: "m" (var)); \
break; \
case 8: \
- asm(op "q "__percpu_arg(1)",%0" \
+ asm(op "q " __percpu_arg(1)",%0" \
: "=r" (pfo_ret__) \
: "m" (var)); \
break; \
@@ -214,22 +214,22 @@ do { \
typeof(var) pfo_ret__; \
switch (sizeof(var)) { \
case 1: \
- asm(op "b "__percpu_arg(P1)",%0" \
+ asm(op "b " __percpu_arg(P1)",%0" \
: "=q" (pfo_ret__) \
: "p" (&(var))); \
break; \
case 2: \
- asm(op "w "__percpu_arg(P1)",%0" \
+ asm(op "w " __percpu_arg(P1)",%0" \
: "=r" (pfo_ret__) \
: "p" (&(var))); \
break; \
case 4: \
- asm(op "l "__percpu_arg(P1)",%0" \
+ asm(op "l " __percpu_arg(P1)",%0" \
: "=r" (pfo_ret__) \
: "p" (&(var))); \
break; \
case 8: \
- asm(op "q "__percpu_arg(P1)",%0" \
+ asm(op "q " __percpu_arg(P1)",%0" \
: "=r" (pfo_ret__) \
: "p" (&(var))); \
break; \
@@ -242,19 +242,19 @@ do { \
({ \
switch (sizeof(var)) { \
case 1: \
- asm(op "b "__percpu_arg(0) \
+ asm(op "b " __percpu_arg(0) \
: "+m" (var)); \
break; \
case 2: \
- asm(op "w "__percpu_arg(0) \
+ asm(op "w " __percpu_arg(0) \
: "+m" (var)); \
break; \
case 4: \
- asm(op "l "__percpu_arg(0) \
+ asm(op "l " __percpu_arg(0) \
: "+m" (var)); \
break; \
case 8: \
- asm(op "q "__percpu_arg(0) \
+ asm(op "q " __percpu_arg(0) \
: "+m" (var)); \
break; \
default: __bad_percpu_size(); \
@@ -269,22 +269,22 @@ do { \
typeof(var) paro_ret__ = val; \
switch (sizeof(var)) { \
case 1: \
- asm("xaddb %0, "__percpu_arg(1) \
+ asm("xaddb %0, " __percpu_arg(1) \
: "+q" (paro_ret__), "+m" (var) \
: : "memory"); \
break; \
case 2: \
- asm("xaddw %0, "__percpu_arg(1) \
+ asm("xaddw %0, " __percpu_arg(1) \
: "+r" (paro_ret__), "+m" (var) \
: : "memory"); \
break; \
case 4: \
- asm("xaddl %0, "__percpu_arg(1) \
+ asm("xaddl %0, " __percpu_arg(1) \
: "+r" (paro_ret__), "+m" (var) \
: : "memory"); \
break; \
case 8: \
- asm("xaddq %0, "__percpu_arg(1) \
+ asm("xaddq %0, " __percpu_arg(1) \
: "+re" (paro_ret__), "+m" (var) \
: : "memory"); \
break; \
@@ -305,32 +305,32 @@ do { \
typeof(var) pxo_new__ = (nval); \
switch (sizeof(var)) { \
case 1: \
- asm("\n\tmov "__percpu_arg(1)",%%al" \
- "\n1:\tcmpxchgb %2, "__percpu_arg(1) \
+ asm("\n\tmov " __percpu_arg(1)",%%al" \
+ "\n1:\tcmpxchgb %2, " __percpu_arg(1) \
"\n\tjnz 1b" \
: "=&a" (pxo_ret__), "+m" (var) \
: "q" (pxo_new__) \
: "memory"); \
break; \
case 2: \
- asm("\n\tmov "__percpu_arg(1)",%%ax" \
- "\n1:\tcmpxchgw %2, "__percpu_arg(1) \
+ asm("\n\tmov " __percpu_arg(1)",%%ax" \
+ "\n1:\tcmpxchgw %2, " __percpu_arg(1) \
"\n\tjnz 1b" \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
: "memory"); \
break; \
case 4: \
- asm("\n\tmov "__percpu_arg(1)",%%eax" \
- "\n1:\tcmpxchgl %2, "__percpu_arg(1) \
+ asm("\n\tmov " __percpu_arg(1)",%%eax" \
+ "\n1:\tcmpxchgl %2, " __percpu_arg(1) \
"\n\tjnz 1b" \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
: "memory"); \
break; \
case 8: \
- asm("\n\tmov "__percpu_arg(1)",%%rax" \
- "\n1:\tcmpxchgq %2, "__percpu_arg(1) \
+ asm("\n\tmov " __percpu_arg(1)",%%rax" \
+ "\n1:\tcmpxchgq %2, " __percpu_arg(1) \
"\n\tjnz 1b" \
: "=&a" (pxo_ret__), "+m" (var) \
: "r" (pxo_new__) \
@@ -352,25 +352,25 @@ do { \
typeof(var) pco_new__ = (nval); \
switch (sizeof(var)) { \
case 1: \
- asm("cmpxchgb %2, "__percpu_arg(1) \
+ asm("cmpxchgb %2, " __percpu_arg(1) \
: "=a" (pco_ret__), "+m" (var) \
: "q" (pco_new__), "0" (pco_old__) \
: "memory"); \
break; \
case 2: \
- asm("cmpxchgw %2, "__percpu_arg(1) \
+ asm("cmpxchgw %2, " __percpu_arg(1) \
: "=a" (pco_ret__), "+m" (var) \
: "r" (pco_new__), "0" (pco_old__) \
: "memory"); \
break; \
case 4: \
- asm("cmpxchgl %2, "__percpu_arg(1) \
+ asm("cmpxchgl %2, " __percpu_arg(1) \
: "=a" (pco_ret__), "+m" (var) \
: "r" (pco_new__), "0" (pco_old__) \
: "memory"); \
break; \
case 8: \
- asm("cmpxchgq %2, "__percpu_arg(1) \
+ asm("cmpxchgq %2, " __percpu_arg(1) \
: "=a" (pco_ret__), "+m" (var) \
: "r" (pco_new__), "0" (pco_old__) \
: "memory"); \
@@ -450,7 +450,7 @@ do { \
bool __ret; \
typeof(pcp1) __o1 = (o1), __n1 = (n1); \
typeof(pcp2) __o2 = (o2), __n2 = (n2); \
- asm volatile("cmpxchg8b "__percpu_arg(1)"\n\tsetz %0\n\t" \
+ asm volatile("cmpxchg8b " __percpu_arg(1)"\n\tsetz %0\n\t" \
: "=a" (__ret), "+m" (pcp1), "+m" (pcp2), "+d" (__o2) \
: "b" (__n1), "c" (__n2), "a" (__o1)); \
__ret; \
@@ -526,7 +526,7 @@ static inline bool x86_this_cpu_variable_test_bit(int nr,
{
bool oldbit;
- asm volatile("btl "__percpu_arg(2)",%1"
+ asm volatile("btl " __percpu_arg(2) ",%1"
CC_SET(c)
: CC_OUT(c) (oldbit)
: "m" (*(unsigned long __percpu *)addr), "Ir" (nr));
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 12f54082f4c8..7c8c8797932e 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -256,7 +256,7 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
(regs)->cs = __KERNEL_CS; \
regs->flags = 0; \
asm volatile( \
- _ASM_MOV "%%"_ASM_SP ", %0\n" \
+ _ASM_MOV "%%" _ASM_SP ", %0\n" \
: "=m" ((regs)->sp) \
:: "memory" \
); \
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 4894d322d258..84b77941ee11 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -62,7 +62,7 @@
/*
* Must define these before including other files, inline functions need them
*/
-#define LOCK_SECTION_NAME ".text..lock."KBUILD_BASENAME
+#define LOCK_SECTION_NAME ".text..lock." KBUILD_BASENAME
#define LOCK_SECTION_START(extra) \
".subsection 1\n\t" \
Turn put_user(), get_user() and similar functions into C++ inline template
functions as the source for this is simpler and more obvious and not
heavily macroised.
Note that it is unnecessary to stick an extension on the load or store
instruction that does the protected access to memory as the assembler can
work that out from the size of the source/destination register.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/uaccess.h | 630 ++++++++++++++++++++-----------------
arch/x86/include/asm/uaccess_64.h | 66 +---
2 files changed, 361 insertions(+), 335 deletions(-)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index aae77eb8491c..64bd782c87c6 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -12,6 +12,10 @@
#include <asm/smap.h>
#include <asm/extable.h>
+/* FIXME: this hack is definitely wrong -AK */
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct __user *)(x))
+
/*
* The fs value determines whether argument validity checking should be
* performed or not. If get_fs() == USER_DS, checking is performed, with
@@ -101,6 +105,12 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
likely(!__range_not_ok(addr, size, user_addr_max())); \
})
+extern void __put_user_bad(void);
+extern void __get_user_unsupported_size(void)
+ __compiletime_error("Bad argument size for get_user");
+extern void __put_user_unsupported_size(void)
+ __compiletime_error("Bad argument size for put_user");
+
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
@@ -130,13 +140,6 @@ extern int __get_user_bad(void);
barrier_nospec(); \
})
-/*
- * This is a type: either unsigned long, if the argument fits into
- * that type, or otherwise unsigned long long.
- */
-#define __inttype(x) \
-__typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
-
/**
* get_user: - Get a simple variable from user space.
* @x: Variable to store result.
@@ -168,62 +171,21 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
* Clang/LLVM cares about the size of the register, but still wants
* the base register for something that ends up being a pair.
*/
-#define get_user(x, ptr) \
-({ \
- int __ret_gu; \
- register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \
- __chk_user_ptr(ptr); \
- might_fault(); \
- asm volatile("call __get_user_%P4" \
- : "=a" (__ret_gu), "=r" (__val_gu), \
- ASM_CALL_CONSTRAINT \
- : "0" (ptr), "i" (sizeof(*(ptr)))); \
- (x) = (__force __typeof__(*(ptr))) __val_gu; \
- __builtin_expect(__ret_gu, 0); \
-})
-
-#define __put_user_x(size, x, ptr, __ret_pu) \
- asm volatile("call __put_user_" #size : "=a" (__ret_pu) \
- : "0" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
-
-
-
-#ifdef CONFIG_X86_32
-#define __put_user_asm_u64(x, addr, err, errret) \
- asm volatile("\n" \
- "1: movl %%eax,0(%2)\n" \
- "2: movl %%edx,4(%2)\n" \
- "3:" \
- ".section .fixup,\"ax\"\n" \
- "4: movl %3,%0\n" \
- " jmp 3b\n" \
- ".previous\n" \
- _ASM_EXTABLE(1b, 4b) \
- _ASM_EXTABLE(2b, 4b) \
- : "=r" (err) \
- : "A" (x), "r" (addr), "i" (errret), "0" (err))
-
-#define __put_user_asm_ex_u64(x, addr) \
- asm volatile("\n" \
- "1: movl %%eax,0(%1)\n" \
- "2: movl %%edx,4(%1)\n" \
- "3:" \
- _ASM_EXTABLE_EX(1b, 2b) \
- _ASM_EXTABLE_EX(2b, 3b) \
- : : "A" (x), "r" (addr))
-
-#define __put_user_x8(x, ptr, __ret_pu) \
- asm volatile("call __put_user_8" : "=a" (__ret_pu) \
- : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
-#else
-#define __put_user_asm_u64(x, ptr, retval, errret) \
- __put_user_asm(x, ptr, retval, "q", "", "er", errret)
-#define __put_user_asm_ex_u64(x, addr) \
- __put_user_asm_ex(x, addr, "q", "", "er")
-#define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
-#endif
-
-extern void __put_user_bad(void);
+template <typename VAL, typename TYPE>
+static inline int get_user(VAL &x, TYPE *ptr)
+{
+ register TYPE val asm("%" _ASM_DX);
+ int ret;
+
+ __chk_user_ptr(ptr);
+ might_fault();
+ asm volatile("call __get_user_%P4"
+ : "=a" (ret), "=r" (val),
+ ASM_CALL_CONSTRAINT
+ : "0" (ptr), "i" (sizeof(*(ptr))));
+ x = val;
+ return __builtin_expect(ret, 0);
+}
/*
* Strange magic calling convention: pointer in %ecx,
@@ -251,157 +213,47 @@ extern void __put_user_8(void);
*
* Returns zero on success, or -EFAULT on error.
*/
-#define put_user(x, ptr) \
-({ \
- int __ret_pu; \
- __typeof__(*(ptr)) __pu_val; \
- __chk_user_ptr(ptr); \
- might_fault(); \
- __pu_val = x; \
- switch (sizeof(*(ptr))) { \
- case 1: \
- __put_user_x(1, __pu_val, ptr, __ret_pu); \
- break; \
- case 2: \
- __put_user_x(2, __pu_val, ptr, __ret_pu); \
- break; \
- case 4: \
- __put_user_x(4, __pu_val, ptr, __ret_pu); \
- break; \
- case 8: \
- __put_user_x8(__pu_val, ptr, __ret_pu); \
- break; \
- default: \
- __put_user_x(X, __pu_val, ptr, __ret_pu); \
- break; \
- } \
- __builtin_expect(__ret_pu, 0); \
-})
-
-#define __put_user_size(x, ptr, size, retval, errret) \
-do { \
- retval = 0; \
- __chk_user_ptr(ptr); \
- switch (size) { \
- case 1: \
- __put_user_asm(x, ptr, retval, "b", "b", "iq", errret); \
- break; \
- case 2: \
- __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \
- break; \
- case 4: \
- __put_user_asm(x, ptr, retval, "l", "k", "ir", errret); \
- break; \
- case 8: \
- __put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval, \
- errret); \
- break; \
- default: \
- __put_user_bad(); \
- } \
-} while (0)
-
-/*
- * This doesn't do __uaccess_begin/end - the exception handling
- * around it must do that.
- */
-#define __put_user_size_ex(x, ptr, size) \
-do { \
- __chk_user_ptr(ptr); \
- switch (size) { \
- case 1: \
- __put_user_asm_ex(x, ptr, "b", "b", "iq"); \
- break; \
- case 2: \
- __put_user_asm_ex(x, ptr, "w", "w", "ir"); \
- break; \
- case 4: \
- __put_user_asm_ex(x, ptr, "l", "k", "ir"); \
- break; \
- case 8: \
- __put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr); \
- break; \
- default: \
- __put_user_bad(); \
- } \
-} while (0)
+template <typename VAL, typename TYPE>
+static inline int put_user(VAL x, TYPE *ptr)
+{
+ register TYPE val asm("%" _ASM_DX);
+ int ret;
+ __chk_user_ptr(ptr);
+ might_fault();
+ switch (sizeof(*(ptr))) {
+ case 8:
#ifdef CONFIG_X86_32
-#define __get_user_asm_u64(x, ptr, retval, errret) \
-({ \
- __typeof__(ptr) __ptr = (ptr); \
- asm volatile("\n" \
- "1: movl %2,%%eax\n" \
- "2: movl %3,%%edx\n" \
- "3:\n" \
- ".section .fixup,\"ax\"\n" \
- "4: mov %4,%0\n" \
- " xorl %%eax,%%eax\n" \
- " xorl %%edx,%%edx\n" \
- " jmp 3b\n" \
- ".previous\n" \
- _ASM_EXTABLE(1b, 4b) \
- _ASM_EXTABLE(2b, 4b) \
- : "=r" (retval), "=&A"(x) \
- : "m" (__m(__ptr)), "m" __m(((u32 __user *)(__ptr)) + 1), \
- "i" (errret), "0" (retval)); \
-})
+ asm volatile("call __put_user_%8"
+ : "=a" (ret), "=r" (val),
+ ASM_CALL_CONSTRAINT
+ : "A" (val), "c" (ptr)
+ : "ebx");
+ break;
+#endif
+ /* Fall through */
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("call __put_user_%P4"
+ : "=a" (ret), "=r" (val),
+ ASM_CALL_CONSTRAINT
+ : "0" (val), "c" (ptr)
+ : "ebx");
+ break;
+ default:
+ __put_user_unsupported_size();
+ }
+ return __builtin_expect(ret, 0);
+}
+#ifdef CONFIG_X86_32
#define __get_user_asm_ex_u64(x, ptr) (x) = __get_user_bad()
#else
-#define __get_user_asm_u64(x, ptr, retval, errret) \
- __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
#define __get_user_asm_ex_u64(x, ptr) \
__get_user_asm_ex(x, ptr, "q", "", "=r")
#endif
-#define __get_user_size(x, ptr, size, retval, errret) \
-do { \
- retval = 0; \
- __chk_user_ptr(ptr); \
- switch (size) { \
- case 1: \
- __get_user_asm(x, ptr, retval, "b", "b", "=q", errret); \
- break; \
- case 2: \
- __get_user_asm(x, ptr, retval, "w", "w", "=r", errret); \
- break; \
- case 4: \
- __get_user_asm(x, ptr, retval, "l", "k", "=r", errret); \
- break; \
- case 8: \
- __get_user_asm_u64(x, ptr, retval, errret); \
- break; \
- default: \
- (x) = __get_user_bad(); \
- } \
-} while (0)
-
-#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
- asm volatile("\n" \
- "1: mov"itype" %2,%"rtype"1\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: mov %3,%0\n" \
- " xor"itype" %"rtype"1,%"rtype"1\n" \
- " jmp 2b\n" \
- ".previous\n" \
- _ASM_EXTABLE(1b, 3b) \
- : "=r" (err), ltype(x) \
- : "m" (__m(addr)), "i" (errret), "0" (err))
-
-#define __get_user_asm_nozero(x, addr, err, itype, rtype, ltype, errret) \
- asm volatile("\n" \
- "1: mov"itype" %2,%"rtype"1\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: mov %3,%0\n" \
- " jmp 2b\n" \
- ".previous\n" \
- _ASM_EXTABLE(1b, 3b) \
- : "=r" (err), ltype(x) \
- : "m" (__m(addr)), "i" (errret), "0" (err))
-
/*
* This doesn't do __uaccess_begin/end - the exception handling
* around it must do that.
@@ -437,53 +289,6 @@ do { \
_ASM_EXTABLE_EX(1b, 3b) \
: ltype(x) : "m" (__m(addr)))
-#define __put_user_nocheck(x, ptr, size) \
-({ \
- int __pu_err; \
- __uaccess_begin(); \
- __put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \
- __uaccess_end(); \
- __builtin_expect(__pu_err, 0); \
-})
-
-#define __get_user_nocheck(x, ptr, size) \
-({ \
- int __gu_err; \
- __inttype(*(ptr)) __gu_val; \
- __uaccess_begin_nospec(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
- __uaccess_end(); \
- (x) = (__force __typeof__(*(ptr)))__gu_val; \
- __builtin_expect(__gu_err, 0); \
-})
-
-/* FIXME: this hack is definitely wrong -AK */
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct __user *)(x))
-
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
- asm volatile("\n" \
- "1: mov"itype" %"rtype"1,%2\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: mov %3,%0\n" \
- " jmp 2b\n" \
- ".previous\n" \
- _ASM_EXTABLE(1b, 3b) \
- : "=r"(err) \
- : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
-
-#define __put_user_asm_ex(x, addr, itype, rtype, ltype) \
- asm volatile("1: mov"itype" %"rtype"0,%1\n" \
- "2:\n" \
- _ASM_EXTABLE_EX(1b, 2b) \
- : : ltype(x), "m" (__m(addr)))
-
/*
* uaccess_try and catch
*/
@@ -501,6 +306,111 @@ struct __large_struct { unsigned long buf[100]; };
(err) |= (current->thread.uaccess_err ? -EFAULT : 0); \
} while (0)
+/**
+ * __get_user_unsafe_nozero - Read a value from userspace with no uaccess check
+ */
+template <typename VAL, typename TYPE>
+static inline int __get_user_unsafe_nozero(VAL &x, const TYPE *ptr, int err=-EFAULT)
+{
+ TYPE val;
+ int ret = 0;
+
+ __chk_user_ptr(ptr);
+ switch (sizeof(TYPE)) {
+ case 8:
+#if __LONG_WIDTH__ == 32
+ asm volatile("\n"
+ "1: mov %2,%%eax\n"
+ "2: mov %3,%%edx\n"
+ "3:\n"
+ ".section .fixup,\"ax\"\n"
+ "4: mov %4,%0\n"
+ " jmp 3b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 4b)
+ _ASM_EXTABLE(2b, 4b)
+ : "=r" (ret), "=&A"(val)
+ : "m" (__m(ptr)),
+ "m" (__m((const char *)ptr + 4)),
+ "i" (err), "0" (ret));
+ break;
+#endif
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("\n"
+ "1: mov %2,%1\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3: mov %3,%0\n"
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+ : "=r" (ret), "=r"(val)
+ : "m" (__m(ptr)), "i" (err), "0" (ret));
+ break;
+ default:
+ __get_user_unsupported_size();
+ }
+
+ x = val;
+ return __builtin_expect(ret, 0);
+}
+
+/**
+ * __get_user_unsafe - Read a value from userspace with no uaccess check
+ */
+template <typename VAL, typename TYPE>
+static inline int __get_user_unsafe(VAL &x, const TYPE *ptr, int err=-EFAULT)
+{
+ TYPE val;
+ int ret = 0;
+
+ __chk_user_ptr(ptr);
+ switch (sizeof(TYPE)) {
+ case 8:
+#if __LONG_WIDTH__ == 32
+ asm volatile("\n"
+ "1: mov %2,%%eax\n"
+ "2: mov %3,%%edx\n"
+ "3:\n"
+ ".section .fixup,\"ax\"\n"
+ "4: mov %4,%0\n"
+ " xor %%eax,%%eax\n"
+ " xor %%edx,%%edx\n"
+ " jmp 3b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 4b)
+ _ASM_EXTABLE(2b, 4b)
+ : "=r" (ret), "=&A"(val)
+ : "m" (__m(ptr)),
+ "m" (__m((const char *)ptr + 4)),
+ "i" (err), "0" (ret));
+ break;
+#endif
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("\n"
+ "1: mov %2,%1\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3: mov %3,%0\n"
+ " xor %1,%1\n"
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+ : "=r" (ret), "=r"(val)
+ : "m" (__m(ptr)), "i" (err), "0" (ret));
+ break;
+ default:
+ __get_user_unsupported_size();
+ }
+
+ x = val;
+ return __builtin_expect(ret, 0);
+}
+
/**
* __get_user: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
@@ -509,9 +419,9 @@ struct __large_struct { unsigned long buf[100]; };
* Context: User context only. This function may sleep if pagefaults are
* enabled.
*
- * This macro copies a single simple variable from user space to kernel
- * space. It supports simple types like char and int, but not larger
- * data types like structures or arrays.
+ * This function copies a single simple variable from user space to kernel
+ * space. It supports simple types like char and int, but not larger data
+ * types like structures or arrays.
*
* @ptr must have pointer-to-simple-variable type, and the result of
* dereferencing @ptr must be assignable to @x without a cast.
@@ -522,9 +432,68 @@ struct __large_struct { unsigned long buf[100]; };
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
+template <typename VAL, typename TYPE>
+static inline int __get_user(VAL &x, const TYPE *ptr)
+{
+ int ret;
-#define __get_user(x, ptr) \
- __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+ __uaccess_begin_nospec();
+ ret = __get_user_unsafe(x, ptr);
+ __uaccess_end();
+ return ret;
+}
+
+/**
+ * __put_user_unsafe - Copy a value to userspace with no uaccess check
+ */
+template <typename VAL, typename TYPE>
+static inline int __put_user_unsafe(VAL x, TYPE *ptr, int err=-EFAULT)
+{
+ TYPE val;
+ int ret = 0;
+
+ __chk_user_ptr(ptr);
+ switch (sizeof(TYPE)) {
+ case 8:
+#if __LONG_WIDTH__ == 32
+ asm volatile("\n"
+ "1: mov %%eax,%2\n"
+ "2: mov %%edx,%3\n"
+ "3:\n"
+ ".section .fixup,\"ax\"\n"
+ "4: mov %4,%0\n"
+ " jmp 3b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 4b)
+ _ASM_EXTABLE(2b, 4b)
+ : "=r" (ret)
+ : "A"(val),
+ "m" (__m(ptr)),
+ "m" (__m((const char *)ptr + 4)),
+ "i" (err), "0" (ret));
+ break;
+#endif
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("\n"
+ "1: mov %1,%2\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3: mov %3,%0\n"
+ " jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+ : "=r" (ret), "=r"(val)
+ : "m" (__m(ptr)), "i" (err), "0" (ret));
+ break;
+ default:
+ __put_user_unsupported_size();
+ }
+
+ x = val;
+ return __builtin_expect(ret, 0);
+}
/**
* __put_user: - Write a simple value into user space, with less checking.
@@ -546,32 +515,117 @@ struct __large_struct { unsigned long buf[100]; };
*
* Returns zero on success, or -EFAULT on error.
*/
+template <typename VAL, typename TYPE>
+static inline int __put_user(VAL x, TYPE *ptr, int err=-EFAULT)
+{
+ int ret;
-#define __put_user(x, ptr) \
- __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+ __uaccess_begin();
+ ret = __put_user_unsafe(x, ptr, err);
+ __uaccess_end();
+ return ret;
+}
-/*
- * {get|put}_user_try and catch
+/**
+ * get_user_ex - Read a value from userspace with indirect error
*
- * get_user_try {
- * get_user_ex(...);
- * } get_user_catch(err)
+ * Use as:
+ * get_user_try {
+ * get_user_ex(...);
+ * } get_user_catch(err)
*/
+template <typename VAL, typename TYPE>
+static inline void get_user_ex(VAL &x, const TYPE *ptr)
+{
+ TYPE val;
+
+ __chk_user_ptr(ptr);
+ switch (sizeof(TYPE)) {
+ case 8:
+#if __LONG_WIDTH__ == 32
+ asm volatile("\n"
+ "1: mov %1,%%eax\n"
+ "2: mov %2,%%edx\n"
+ "3:\n"
+ _ASM_EXTABLE(1b, 3b)
+ _ASM_EXTABLE(2b, 3b)
+ : "=&A"(val)
+ : "m" (__m(ptr)),
+ "m" (__m((const char *)ptr + 4)));
+ break;
+#endif
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("\n"
+ "1: mov %1,%0\n"
+ "2:\n"
+ _ASM_EXTABLE(1b, 2b)
+ : "=r"(val)
+ : "m" (__m(ptr)));
+ break;
+ default:
+ __get_user_unsupported_size();
+ }
+
+ x = val;
+}
#define get_user_try uaccess_try_nospec
#define get_user_catch(err) uaccess_catch(err)
-#define get_user_ex(x, ptr) do { \
- unsigned long __gue_val; \
- __get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr)))); \
- (x) = (__force __typeof__(*(ptr)))__gue_val; \
-} while (0)
+/**
+ * put_user_ex - Copy a value to userspace with indirect error
+ *
+ * Use as:
+ * put_user_try {
+ * put_user_ex(...);
+ * } put_user_catch(err)
+ */
+template <typename VAL, typename TYPE>
+static inline void put_user_ex(VAL x, TYPE *ptr)
+{
+ TYPE val;
+
+
+ /* We tell gcc that we're reading from memory instead of writing: this
+ * is because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ */
+ __chk_user_ptr(ptr);
+ switch (sizeof(TYPE)) {
+ case 8:
+#if __LONG_WIDTH__ == 32
+ asm volatile("\n"
+ "1: mov %%eax,%1\n"
+ "2: mov %%edx,%2\n"
+ "3:\n"
+ _ASM_EXTABLE(1b, 3b)
+ _ASM_EXTABLE(2b, 3b)
+ :
+ : "A"(val),
+ "m" (__m(ptr)),
+ "m" (__m((const char *)ptr + 4)));
+ break;
+#endif
+ case 1:
+ case 2:
+ case 4:
+ asm volatile("\n"
+ "1: mov %0,%1\n"
+ "2:\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 2b)
+ :
+ : "=r"(val), "m" (__m(ptr)));
+ break;
+ default:
+ __put_user_unsupported_size();
+ }
+}
#define put_user_try uaccess_try
#define put_user_catch(err) uaccess_catch(err)
-#define put_user_ex(x, ptr) \
- __put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
-
extern unsigned long
copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
extern __must_check long
@@ -711,22 +765,20 @@ extern struct movsl_mask {
#define user_access_begin() __uaccess_begin()
#define user_access_end() __uaccess_end()
-#define unsafe_put_user(x, ptr, err_label) \
-do { \
- int __pu_err; \
- __typeof__(*(ptr)) __pu_val = (x); \
- __put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \
- if (unlikely(__pu_err)) goto err_label; \
-} while (0)
-
-#define unsafe_get_user(x, ptr, err_label) \
-do { \
- int __gu_err; \
- __inttype(*(ptr)) __gu_val; \
- __get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT); \
- (x) = (__force __typeof__(*(ptr)))__gu_val; \
- if (unlikely(__gu_err)) goto err_label; \
-} while (0)
+#define unsafe_put_user(x, ptr, err_label) \
+ do { \
+ int __pu_err; \
+ __pu_err = __put_user_unsafe(x, ptr); \
+ if (unlikely(__gu_err)) \
+ goto err_label; \
+ } while (0)
+
+#define unsafe_get_user(x, ptr, err_label) \
+ do { \
+ int __gu_err; \
+ __gu_err = __get_user_unsafe(x, ptr); \
+ if (unlikely(__gu_err)) \
+ goto err_label; \
+ } while (0)
#endif /* _ASM_X86_UACCESS_H */
-
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 62546b3a398e..24bf7d0a21b6 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -56,46 +56,40 @@ raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
switch (size) {
case 1:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u8 *)dst, (u8 __user *)src,
- ret, "b", "b", "=q", 1);
+ ret = __get_user_unsafe_nozero(*(u8 *)dst, (u8 __user *)src, 1);
__uaccess_end();
return ret;
case 2:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u16 *)dst, (u16 __user *)src,
- ret, "w", "w", "=r", 2);
+ ret = __get_user_unsafe_nozero(*(u16 *)dst, (u16 __user *)src, 2);
__uaccess_end();
return ret;
case 4:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u32 *)dst, (u32 __user *)src,
- ret, "l", "k", "=r", 4);
+ ret = __get_user_unsafe_nozero(*(u32 *)dst, (u32 __user *)src, 4);
__uaccess_end();
return ret;
case 8:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 8);
+ ret = __get_user_unsafe_nozero(*(u64 *)dst, (u64 __user *)src, 8);
__uaccess_end();
return ret;
case 10:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 10);
+ ret = __get_user_unsafe_nozero(*(u64 *)dst, (u64 __user *)src, 10);
if (likely(!ret))
- __get_user_asm_nozero(*(u16 *)(8 + (char *)dst),
- (u16 __user *)(8 + (char __user *)src),
- ret, "w", "w", "=r", 2);
+ ret = __get_user_unsafe_nozero(
+ *(u16 *)(8 + (char *)dst),
+ (u16 __user *)(8 + (char __user *)src), 2);
__uaccess_end();
return ret;
case 16:
__uaccess_begin_nospec();
- __get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 16);
+ ret = __get_user_unsafe_nozero(*(u64 *)dst, (u64 __user *)src, 16);
if (likely(!ret))
- __get_user_asm_nozero(*(u64 *)(8 + (char *)dst),
- (u64 __user *)(8 + (char __user *)src),
- ret, "q", "", "=r", 8);
+ ret = __get_user_unsafe_nozero(
+ *(u64 *)(8 + (char *)dst),
+ (u64 __user *)(8 + (char __user *)src), 8);
__uaccess_end();
return ret;
default:
@@ -112,48 +106,28 @@ raw_copy_to_user(void __user *dst, const void *src, unsigned long size)
return copy_user_generic((__force void *)dst, src, size);
switch (size) {
case 1:
- __uaccess_begin();
- __put_user_asm(*(u8 *)src, (u8 __user *)dst,
- ret, "b", "b", "iq", 1);
- __uaccess_end();
- return ret;
+ return __put_user(*(u8 *)src, (u8 __user *)dst, 1);
case 2:
- __uaccess_begin();
- __put_user_asm(*(u16 *)src, (u16 __user *)dst,
- ret, "w", "w", "ir", 2);
- __uaccess_end();
- return ret;
+ return __put_user(*(u16 *)src, (u16 __user *)dst, 2);
case 4:
- __uaccess_begin();
- __put_user_asm(*(u32 *)src, (u32 __user *)dst,
- ret, "l", "k", "ir", 4);
- __uaccess_end();
- return ret;
+ return __put_user(*(u32 *)src, (u32 __user *)dst, 4);
case 8:
- __uaccess_begin();
- __put_user_asm(*(u64 *)src, (u64 __user *)dst,
- ret, "q", "", "er", 8);
- __uaccess_end();
- return ret;
+ return __put_user(*(u64 *)src, (u64 __user *)dst, 8);
case 10:
__uaccess_begin();
- __put_user_asm(*(u64 *)src, (u64 __user *)dst,
- ret, "q", "", "er", 10);
+ ret = __put_user_unsafe(*(u64 *)src, (u64 __user *)dst, 10);
if (likely(!ret)) {
asm("":::"memory");
- __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
- ret, "w", "w", "ir", 2);
+ ret = __put_user_unsafe(4[(u16 *)src], 4 + (u16 __user *)dst, 2);
}
__uaccess_end();
return ret;
case 16:
__uaccess_begin();
- __put_user_asm(*(u64 *)src, (u64 __user *)dst,
- ret, "q", "", "er", 16);
+ ret =__put_user_unsafe(*(u64 *)src, (u64 __user *)dst, 16);
if (likely(!ret)) {
asm("":::"memory");
- __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
- ret, "q", "", "er", 8);
+ ret = __put_user_unsafe(1[(u64 *)src], 1 + (u64 __user *)dst, 8);
}
__uaccess_end();
return ret;
__to_fd() needs to reduce the size of v before it assigns the computed
value to fd::flags or suffer a warning about reduction of size of integer.
Signed-off-by: David Howells <[email protected]>
---
include/linux/file.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/file.h b/include/linux/file.h
index 279720db984a..9807271c850a 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -49,7 +49,7 @@ extern void __f_unlock_pos(struct file *);
static inline struct fd __to_fd(unsigned long v)
{
- return (struct fd){(struct file *)(v & ~3),v & 3};
+ return (struct fd){(struct file *)(v & ~3), (unsigned int)v & 3};
}
static inline struct fd fdget(unsigned int fd)
Fix static_branch_likely/unlikely() to use C++ function overloading to
simplify the source.
Signed-off-by: David Howells <[email protected]>
---
include/linux/jump_label.h | 41 +++++++++++++++++++----------------------
1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 2168cc6b8b30..25683b1764bf 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -387,29 +387,26 @@ extern bool ____wrong_branch_error(void);
* See jump_label_type() / jump_label_init_type().
*/
-#define static_branch_likely(x) \
-({ \
- bool branch; \
- if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
- branch = !arch_static_branch(&(x)->key, true); \
- else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
- branch = !arch_static_branch_jump(&(x)->key, true); \
- else \
- branch = ____wrong_branch_error(); \
- likely(branch); \
-})
-#define static_branch_unlikely(x) \
-({ \
- bool branch; \
- if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
- branch = arch_static_branch_jump(&(x)->key, false); \
- else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
- branch = arch_static_branch(&(x)->key, false); \
- else \
- branch = ____wrong_branch_error(); \
- unlikely(branch); \
-})
+static inline bool static_branch_likely(struct static_key_true *x)
+{
+ return likely(!arch_static_branch(&(x)->key, true));
+}
+
+static inline bool static_branch_likely(struct static_key_false *x)
+{
+ return likely(!arch_static_branch_jump(&(x)->key, true));
+}
+
+static inline bool static_branch_unlikely(struct static_key_true *x)
+{
+ return unlikely(!arch_static_branch_jump(&(x)->key, true));
+}
+
+static inline bool static_branch_unlikely(struct static_key_false *x)
+{
+ return unlikely(!arch_static_branch(&(x)->key, true));
+}
#else /* !HAVE_JUMP_LABEL */
Define apic_intr_mode after the enum definition, not before, otherwise an
error results.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/apic.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 98722773391d..c8eef5e6c46c 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -53,7 +53,6 @@ extern int local_apic_timer_c2_ok;
extern int disable_apic;
extern unsigned int lapic_timer_frequency;
-extern enum apic_intr_mode_id apic_intr_mode;
enum apic_intr_mode_id {
APIC_PIC,
APIC_VIRTUAL_WIRE,
@@ -61,6 +60,7 @@ enum apic_intr_mode_id {
APIC_SYMMETRIC_IO,
APIC_SYMMETRIC_IO_NO_ROUTING
};
+extern enum apic_intr_mode_id apic_intr_mode;
#ifdef CONFIG_SMP
extern void __inquire_remote_apic(int apicid);
Turn ktime ns arithmetic functions into template functions to handle the
nanosecond value type conversion correctly.
Signed-off-by: David Howells <[email protected]>
---
include/linux/ktime.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 5b9fddbaac41..d46a16f23ffc 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -58,13 +58,21 @@ static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs)
* Add a ktime_t variable and a scalar nanosecond value.
* res = kt + nsval:
*/
-#define ktime_add_ns(kt, nsval) ((kt) + (nsval))
+template <typename NSVAL>
+static inline ktime_t ktime_add_ns(ktime_t kt, NSVAL nsval)
+{
+ return kt + nsval;
+}
/*
* Subtract a scalar nanosecod from a ktime_t variable
* res = kt - nsval:
*/
-#define ktime_sub_ns(kt, nsval) ((kt) - (nsval))
+template <typename NSVAL>
+static inline ktime_t ktime_sub_ns(ktime_t kt, NSVAL nsval)
+{
+ return kt - nsval;
+}
/* convert a timespec to ktime_t format: */
static inline ktime_t timespec_to_ktime(struct timespec ts)
Make page_zonenum() cast the int it derives to the enum return type.
Signed-off-by: David Howells <[email protected]>
---
include/linux/mm.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ad06d42adb1a..f91087e1ece6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -797,7 +797,7 @@ int finish_mkwrite_fault(struct vm_fault *vmf);
static inline enum zone_type page_zonenum(const struct page *page)
{
- return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
+ return (enum zone_type)((page->flags >> ZONES_PGSHIFT) & ZONES_MASK);
}
#ifdef CONFIG_ZONE_DEVICE
Fix a couple of bits of spinlock initialisation:
(1) owner_cpu is unsigned: set to UINT_MAX rather than -1.
(2) Don't need to cast the result of __SPIN_LOCK_INITIALIZER().
Signed-off-by: David Howells <[email protected]>
---
include/linux/spinlock_types.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
index 24b4e6f2c1a2..d1ab81ee85fd 100644
--- a/include/linux/spinlock_types.h
+++ b/include/linux/spinlock_types.h
@@ -41,7 +41,7 @@ typedef struct raw_spinlock {
#ifdef CONFIG_DEBUG_SPINLOCK
# define SPIN_DEBUG_INIT(lockname) \
.magic = SPINLOCK_MAGIC, \
- .owner_cpu = -1, \
+ .owner_cpu = UINT_MAX, \
.owner = SPINLOCK_OWNER_INIT,
#else
# define SPIN_DEBUG_INIT(lockname)
@@ -76,7 +76,7 @@ typedef struct spinlock {
{ { .rlock = __RAW_SPIN_LOCK_INITIALIZER(lockname) } }
#define __SPIN_LOCK_UNLOCKED(lockname) \
- (spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)
+ __SPIN_LOCK_INITIALIZER(lockname)
#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
In the generic bitops functions, cast the void* bits pointer to unsigned
long* before using it to avoid things like:
include/asm-generic/bitops/le.h:15:28: error: invalid conversion from 'const void*' to 'const long unsigned int*' [-fpermissive]
Signed-off-by: David Howells <[email protected]>
---
include/asm-generic/bitops/le.h | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h
index 188d3eba3ace..8b0fb40da390 100644
--- a/include/asm-generic/bitops/le.h
+++ b/include/asm-generic/bitops/le.h
@@ -12,19 +12,19 @@
static inline unsigned long find_next_zero_bit_le(const void *addr,
unsigned long size, unsigned long offset)
{
- return find_next_zero_bit(addr, size, offset);
+ return find_next_zero_bit(static_cast<const unsigned long *>(addr), size, offset);
}
static inline unsigned long find_next_bit_le(const void *addr,
unsigned long size, unsigned long offset)
{
- return find_next_bit(addr, size, offset);
+ return find_next_bit(static_cast<const unsigned long *>(addr), size, offset);
}
static inline unsigned long find_first_zero_bit_le(const void *addr,
unsigned long size)
{
- return find_first_zero_bit(addr, size);
+ return find_first_zero_bit(static_cast<const unsigned long *>(addr), size);
}
#elif defined(__BIG_ENDIAN)
@@ -52,47 +52,55 @@ extern unsigned long find_next_bit_le(const void *addr,
static inline int test_bit_le(int nr, const void *addr)
{
- return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ return test_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<const unsigned long *>(addr));
}
static inline void set_bit_le(int nr, void *addr)
{
- set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ set_bit(nr ^ BITOP_LE_SWIZZLE, static_cast<unsigned long *>(addr));
}
static inline void clear_bit_le(int nr, void *addr)
{
- clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ clear_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline void __set_bit_le(int nr, void *addr)
{
- __set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ __set_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline void __clear_bit_le(int nr, void *addr)
{
- __clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ __clear_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline int test_and_set_bit_le(int nr, void *addr)
{
- return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline int test_and_clear_bit_le(int nr, void *addr)
{
- return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline int __test_and_set_bit_le(int nr, void *addr)
{
- return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
static inline int __test_and_clear_bit_le(int nr, void *addr)
{
- return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+ return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE,
+ static_cast<unsigned long *>(addr));
}
#endif /* _ASM_GENERIC_BITOPS_LE_H_ */
Fix sema_init() to manually initialise the semaphore rather than using
__SEMAPHORE_INITIALIZER() as that doesn't seem to work on C++.
Signed-off-by: David Howells <[email protected]>
---
include/linux/semaphore.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h
index 11c86fbfeb98..364fb4721db5 100644
--- a/include/linux/semaphore.h
+++ b/include/linux/semaphore.h
@@ -32,7 +32,10 @@ struct semaphore {
static inline void sema_init(struct semaphore *sem, int val)
{
static struct lock_class_key __key;
- *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+
+ sem->count = val;
+ INIT_LIST_HEAD(&sem->wait_list);
+ raw_spin_lock_init(&sem->lock);
lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
}
struct pgd_t is typedef'd to pgd_t so predeclaration isn't required in
asm/tlbflush.h.
Signed-off-by: David Howells <[email protected]>
---
arch/x86/include/asm/tlbflush.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 84137c22fdfa..c0c13d4f6c41 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -117,7 +117,6 @@ static inline u16 user_pcid(u16 asid)
return ret;
}
-struct pgd_t;
static inline unsigned long build_cr3(pgd_t *pgd, u16 asid)
{
if (static_cpu_has(X86_FEATURE_PCID)) {
Move the irqchip_irq_state enum to linux/irqflags.h so that it is defined
before its first use.
Signed-off-by: David Howells <[email protected]>
---
include/linux/interrupt.h | 10 ----------
include/linux/irq.h | 1 -
include/linux/irqflags.h | 10 ++++++++++
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 69c238210325..6975377bda00 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -413,16 +413,6 @@ static inline int disable_irq_wake(unsigned int irq)
return irq_set_irq_wake(irq, 0);
}
-/*
- * irq_get_irqchip_state/irq_set_irqchip_state specific flags
- */
-enum irqchip_irq_state {
- IRQCHIP_STATE_PENDING, /* Is interrupt pending? */
- IRQCHIP_STATE_ACTIVE, /* Is interrupt in progress? */
- IRQCHIP_STATE_MASKED, /* Is interrupt masked? */
- IRQCHIP_STATE_LINE_LEVEL, /* Is IRQ line high? */
-};
-
extern int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
bool *state);
extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
diff --git a/include/linux/irq.h b/include/linux/irq.h
index a0231e96a578..34c1338215ae 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -32,7 +32,6 @@
struct seq_file;
struct module;
struct msi_msg;
-enum irqchip_irq_state;
/*
* IRQ line status.
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 9700f00bbc04..59854eafbedf 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -159,4 +159,14 @@ do { \
#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
+/*
+ * irq_get_irqchip_state/irq_set_irqchip_state specific flags
+ */
+enum irqchip_irq_state {
+ IRQCHIP_STATE_PENDING, /* Is interrupt pending? */
+ IRQCHIP_STATE_ACTIVE, /* Is interrupt in progress? */
+ IRQCHIP_STATE_MASKED, /* Is interrupt masked? */
+ IRQCHIP_STATE_LINE_LEVEL, /* Is IRQ line high? */
+};
+
#endif
Move initcall_level_names[] to __initdata section for the moment as g++
doesn't want to put it in __initconst:
init/main.c:876:20: error: 'initcall_level_names' causes a section type conflict with '__setup_str_set_debug_rodata'
Signed-off-by: David Howells <[email protected]>
---
init/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/init/main.c b/init/main.c
index 642e917387db..6d404fc07007 100644
--- a/init/main.c
+++ b/init/main.c
@@ -873,7 +873,7 @@ static initcall_t *initcall_levels[] __initdata = {
};
/* Keep these in sync with initcalls in include/linux/init.h */
-static const char *initcall_level_names[] __initconst = {
+static const char *initcall_level_names[] __initdata = {
"early",
"core",
"postcore",
Hide C++ keywords like new, delete, class and private.
Signed-off-by: David Howells <[email protected]>
---
include/linux/page-flags.h | 3 +++
include/linux/types.h | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 50c2b8786831..6705394b8f69 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -131,6 +131,9 @@ enum pageflags {
/* non-lru isolated movable page */
PG_isolated = PG_reclaim,
+
+ /* C++-ism */
+ PG__Private = PG_private,
};
#ifndef __GENERATING_BOUNDS_H
diff --git a/include/linux/types.h b/include/linux/types.h
index d233b12c7ebe..1554319a3ff2 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -11,6 +11,12 @@
#ifndef __ASSEMBLY__
+#define class _Class
+#define new _New
+#define delete _Delete
+#define namespace _Namespace
+#define private _Private
+
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
struct cgroup can't be defined with an unsized array in it (ancestors_ids)
as the struct is embedded in another struct. Fix it to have a 0 in there.
Signed-off-by: David Howells <[email protected]>
---
include/linux/cgroup-defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 9f242b876fde..86fe9c6c6466 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -428,7 +428,7 @@ struct cgroup {
struct cgroup_bpf bpf;
/* ids of the ancestors at each level including self */
- int ancestor_ids[];
+ int ancestor_ids[0];
};
/*
Make mutex_trylock_recursive_enum() cast the int it derives to the enum
return type.
Signed-off-by: David Howells <[email protected]>
---
include/linux/mutex.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index cb3bbed4e633..2bacc5065980 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -224,13 +224,14 @@ enum mutex_trylock_recursive_enum {
* - MUTEX_TRYLOCK_SUCCESS - lock acquired,
* - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock.
*/
-static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
+static inline /* __deprecated */ __must_check
+enum mutex_trylock_recursive_enum
mutex_trylock_recursive(struct mutex *lock)
{
if (unlikely(__mutex_owner(lock) == current))
return MUTEX_TRYLOCK_RECURSIVE;
- return mutex_trylock(lock);
+ return (enum mutex_trylock_recursive_enum)mutex_trylock(lock);
}
#endif /* __LINUX_MUTEX_H */
Fix kernfs_type() to cast the integer derived from kn->flags to the return
type enum.
Signed-off-by: David Howells <[email protected]>
---
include/linux/kernfs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index ab25c8b6d9e3..1f06e9ddc930 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -271,7 +271,7 @@ struct kernfs_ops {
static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn)
{
- return kn->flags & KERNFS_TYPE_MASK;
+ return (enum kernfs_node_type)(kn->flags & KERNFS_TYPE_MASK);
}
/**
Implicitly casting void* to a non-void pointer is frowned upon in C++,
though -fpermissive causes it to be accepted. Fix up LIST_POISON1/2
somewhat to handle this a bit better.
Signed-off-by: David Howells <[email protected]>
---
include/linux/list.h | 8 ++++----
include/linux/list_bl.h | 4 ++--
include/linux/list_nulls.h | 2 +-
include/linux/poison.h | 6 ++++--
include/linux/rculist.h | 4 ++--
include/linux/rculist_bl.h | 2 +-
6 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/include/linux/list.h b/include/linux/list.h
index 4b129df4d46b..6aa933e4b109 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -123,8 +123,8 @@ static inline void __list_del_entry(struct list_head *entry)
static inline void list_del(struct list_head *entry)
{
__list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
+ entry->next = static_cast<struct list_head *>(LIST_POISON1);
+ entry->prev = static_cast<struct list_head *>(LIST_POISON2);
}
/**
@@ -654,8 +654,8 @@ static inline void __hlist_del(struct hlist_node *n)
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
- n->next = LIST_POISON1;
- n->pprev = LIST_POISON2;
+ n->next = HLIST_POISON1;
+ n->pprev = HLIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h
index 3fc2cc57ba1b..474c87c2e72e 100644
--- a/include/linux/list_bl.h
+++ b/include/linux/list_bl.h
@@ -105,8 +105,8 @@ static inline void __hlist_bl_del(struct hlist_bl_node *n)
static inline void hlist_bl_del(struct hlist_bl_node *n)
{
__hlist_bl_del(n);
- n->next = LIST_POISON1;
- n->pprev = LIST_POISON2;
+ n->next = ((struct hlist_bl_node *) (0x100 + POISON_POINTER_DELTA));
+ n->pprev = ((struct hlist_bl_node **) (0x200 + POISON_POINTER_DELTA));
}
static inline void hlist_bl_del_init(struct hlist_bl_node *n)
diff --git a/include/linux/list_nulls.h b/include/linux/list_nulls.h
index 3ef96743db8d..6c471fd62c9c 100644
--- a/include/linux/list_nulls.h
+++ b/include/linux/list_nulls.h
@@ -91,7 +91,7 @@ static inline void __hlist_nulls_del(struct hlist_nulls_node *n)
static inline void hlist_nulls_del(struct hlist_nulls_node *n)
{
__hlist_nulls_del(n);
- n->pprev = LIST_POISON2;
+ n->pprev = (struct hlist_nulls_node **)LIST_POISON2;
}
/**
diff --git a/include/linux/poison.h b/include/linux/poison.h
index 15927ebc22f2..21544c2bf1a7 100644
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -20,8 +20,10 @@
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
-#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
-#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
+#define LIST_POISON1 ((struct list_head *) (0x100 + POISON_POINTER_DELTA))
+#define LIST_POISON2 ((struct list_head *) (0x200 + POISON_POINTER_DELTA))
+#define HLIST_POISON1 ((struct hlist_node *) (0x100 + POISON_POINTER_DELTA))
+#define HLIST_POISON2 ((struct hlist_node **) (0x200 + POISON_POINTER_DELTA))
/********** include/linux/timer.h **********/
/*
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 127f534fec94..d7b6a0a697c8 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -425,7 +425,7 @@ static inline void list_splice_tail_init_rcu(struct list_head *list,
static inline void hlist_del_rcu(struct hlist_node *n)
{
__hlist_del(n);
- n->pprev = LIST_POISON2;
+ n->pprev = HLIST_POISON2;
}
/**
@@ -445,7 +445,7 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
rcu_assign_pointer(*(struct hlist_node __rcu **)new->pprev, new);
if (next)
new->next->pprev = &new->next;
- old->pprev = LIST_POISON2;
+ old->pprev = HLIST_POISON2;
}
/*
diff --git a/include/linux/rculist_bl.h b/include/linux/rculist_bl.h
index 66e73ec1aa99..e5a2c59deb6d 100644
--- a/include/linux/rculist_bl.h
+++ b/include/linux/rculist_bl.h
@@ -74,7 +74,7 @@ static inline void hlist_bl_del_init_rcu(struct hlist_bl_node *n)
static inline void hlist_bl_del_rcu(struct hlist_bl_node *n)
{
__hlist_bl_del(n);
- n->pprev = LIST_POISON2;
+ n->pprev = ((struct hlist_bl_node **) (0x200 + POISON_POINTER_DELTA));
}
/**
Move ctx_state enum out of struct context_tracking so that it isn't limited
in scope.
Signed-off-by: David Howells <[email protected]>
---
include/linux/context_tracking_state.h | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/include/linux/context_tracking_state.h b/include/linux/context_tracking_state.h
index f128dc3be0df..02a9efe0827e 100644
--- a/include/linux/context_tracking_state.h
+++ b/include/linux/context_tracking_state.h
@@ -5,6 +5,13 @@
#include <linux/percpu.h>
#include <linux/static_key.h>
+enum ctx_state {
+ CONTEXT_DISABLED = -1, /* returned by ct_state() if unknown */
+ CONTEXT_KERNEL = 0,
+ CONTEXT_USER,
+ CONTEXT_GUEST,
+};
+
struct context_tracking {
/*
* When active is false, probes are unset in order
@@ -14,12 +21,7 @@ struct context_tracking {
*/
bool active;
int recursion;
- enum ctx_state {
- CONTEXT_DISABLED = -1, /* returned by ct_state() if unknown */
- CONTEXT_KERNEL = 0,
- CONTEXT_USER,
- CONTEXT_GUEST,
- } state;
+ enum ctx_state state;
};
#ifdef CONFIG_CONTEXT_TRACKING
Type names in C++ share a namespace with variable names and member names,
so struct member names can't have the same name as their type. Suffix
types with _t.
Signed-off-by: David Howells <[email protected]>
---
include/linux/backing-dev-defs.h | 4 +-
include/linux/blkdev.h | 86 +++++++++++++++++++-------------------
include/linux/elevator.h | 82 ++++++++++++++++++------------------
include/linux/sysctl.h | 6 +--
4 files changed, 89 insertions(+), 89 deletions(-)
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index bfe86b54f6c1..f412919a4c9a 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -33,7 +33,7 @@ enum wb_congested_state {
WB_sync_congested, /* The sync queue is getting full */
};
-typedef int (congested_fn)(void *, int);
+typedef int (congested_fn_t)(void *, int);
enum wb_stat_item {
WB_RECLAIMABLE,
@@ -168,7 +168,7 @@ struct backing_dev_info {
struct list_head bdi_list;
unsigned long ra_pages; /* max readahead in PAGE_SIZE units */
unsigned long io_pages; /* max allowed IO size */
- congested_fn *congested_fn; /* Function pointer if device is md/dm */
+ congested_fn_t *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
const char *name;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ed63f3b69c12..e0486f768473 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -58,7 +58,7 @@ struct blk_stat_callback;
*/
#define BLKCG_MAX_POLS 3
-typedef void (rq_end_io_fn)(struct request *, blk_status_t);
+typedef void (rq_end_io_fn_t)(struct request *, blk_status_t);
#define BLK_RL_SYNCFULL (1U << 0)
#define BLK_RL_ASYNCFULL (1U << 1)
@@ -199,7 +199,7 @@ struct request {
struct {
unsigned int seq;
struct list_head list;
- rq_end_io_fn *saved_end_io;
+ rq_end_io_fn_t *saved_end_io;
} flush;
};
@@ -259,7 +259,7 @@ struct request {
/*
* completion callback.
*/
- rq_end_io_fn *end_io;
+ rq_end_io_fn_t *end_io;
void *end_io_data;
/* for bidi */
@@ -313,19 +313,19 @@ static inline unsigned short req_get_ioprio(struct request *req)
struct blk_queue_ctx;
-typedef void (request_fn_proc) (struct request_queue *q);
-typedef blk_qc_t (make_request_fn) (struct request_queue *q, struct bio *bio);
-typedef bool (poll_q_fn) (struct request_queue *q, blk_qc_t);
-typedef int (prep_rq_fn) (struct request_queue *, struct request *);
-typedef void (unprep_rq_fn) (struct request_queue *, struct request *);
+typedef void (request_fn_proc_t) (struct request_queue *q);
+typedef blk_qc_t (make_request_fn_t) (struct request_queue *q, struct bio *bio);
+typedef bool (poll_q_fn_t) (struct request_queue *q, blk_qc_t);
+typedef int (prep_rq_fn_t) (struct request_queue *, struct request *);
+typedef void (unprep_rq_fn_t) (struct request_queue *, struct request *);
struct bio_vec;
-typedef void (softirq_done_fn)(struct request *);
-typedef int (dma_drain_needed_fn)(struct request *);
-typedef int (lld_busy_fn) (struct request_queue *q);
-typedef int (bsg_job_fn) (struct bsg_job *);
-typedef int (init_rq_fn)(struct request_queue *, struct request *, gfp_t);
-typedef void (exit_rq_fn)(struct request_queue *, struct request *);
+typedef void (softirq_done_fn_t)(struct request *);
+typedef int (dma_drain_needed_fn_t)(struct request *);
+typedef int (lld_busy_fn_t) (struct request_queue *q);
+typedef int (bsg_job_fn_t) (struct bsg_job *);
+typedef int (init_rq_fn_t)(struct request_queue *, struct request *, gfp_t);
+typedef void (exit_rq_fn_t)(struct request_queue *, struct request *);
enum blk_eh_timer_return {
BLK_EH_NOT_HANDLED,
@@ -333,7 +333,7 @@ enum blk_eh_timer_return {
BLK_EH_RESET_TIMER,
};
-typedef enum blk_eh_timer_return (rq_timed_out_fn)(struct request *);
+typedef enum blk_eh_timer_return (rq_timed_out_fn_t)(struct request *);
enum blk_queue_state {
Queue_down,
@@ -456,19 +456,19 @@ struct request_queue {
*/
struct request_list root_rl;
- request_fn_proc *request_fn;
- make_request_fn *make_request_fn;
- poll_q_fn *poll_fn;
- prep_rq_fn *prep_rq_fn;
- unprep_rq_fn *unprep_rq_fn;
- softirq_done_fn *softirq_done_fn;
- rq_timed_out_fn *rq_timed_out_fn;
- dma_drain_needed_fn *dma_drain_needed;
- lld_busy_fn *lld_busy_fn;
+ request_fn_proc_t *request_fn;
+ make_request_fn_t *make_request_fn;
+ poll_q_fn_t *poll_fn;
+ prep_rq_fn_t *prep_rq_fn;
+ unprep_rq_fn_t *unprep_rq_fn;
+ softirq_done_fn_t *softirq_done_fn;
+ rq_timed_out_fn_t *rq_timed_out_fn;
+ dma_drain_needed_fn_t *dma_drain_needed;
+ lld_busy_fn_t *lld_busy_fn;
/* Called just after a request is allocated */
- init_rq_fn *init_rq_fn;
+ init_rq_fn_t *init_rq_fn;
/* Called just before a request is freed */
- exit_rq_fn *exit_rq_fn;
+ exit_rq_fn_t *exit_rq_fn;
/* Called from inside blk_get_request() */
void (*initialize_rq_fn)(struct request *rq);
@@ -635,7 +635,7 @@ struct request_queue {
atomic_t mq_freeze_depth;
#if defined(CONFIG_BLK_DEV_BSG)
- bsg_job_fn *bsg_job_fn;
+ bsg_job_fn_t *bsg_job_fn;
struct bsg_class_device bsg_dev;
#endif
@@ -1067,7 +1067,7 @@ extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
extern void blk_execute_rq(struct request_queue *, struct gendisk *,
struct request *, int);
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
- struct request *, int, rq_end_io_fn *);
+ struct request *, int, rq_end_io_fn_t *);
int blk_status_to_errno(blk_status_t status);
blk_status_t errno_to_blk_status(int errno);
@@ -1235,12 +1235,12 @@ extern void blk_unprep_request(struct request *);
/*
* Access functions for manipulating queue properties
*/
-extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn,
+extern struct request_queue *blk_init_queue_node(request_fn_proc_t *rfn,
spinlock_t *lock, int node_id);
-extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *);
+extern struct request_queue *blk_init_queue(request_fn_proc_t *, spinlock_t *);
extern int blk_init_allocated_queue(struct request_queue *);
extern void blk_cleanup_queue(struct request_queue *);
-extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
+extern void blk_queue_make_request(struct request_queue *, make_request_fn_t *);
extern void blk_queue_bounce_limit(struct request_queue *, u64);
extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
extern void blk_queue_chunk_sectors(struct request_queue *, unsigned int);
@@ -1275,17 +1275,17 @@ extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue
extern void blk_queue_dma_pad(struct request_queue *, unsigned int);
extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int);
extern int blk_queue_dma_drain(struct request_queue *q,
- dma_drain_needed_fn *dma_drain_needed,
+ dma_drain_needed_fn_t *dma_drain_needed,
void *buf, unsigned int size);
-extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn);
+extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn_t *fn);
extern void blk_queue_segment_boundary(struct request_queue *, unsigned long);
extern void blk_queue_virt_boundary(struct request_queue *, unsigned long);
-extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn);
-extern void blk_queue_unprep_rq(struct request_queue *, unprep_rq_fn *ufn);
+extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn_t *pfn);
+extern void blk_queue_unprep_rq(struct request_queue *, unprep_rq_fn_t *ufn);
extern void blk_queue_dma_alignment(struct request_queue *, int);
extern void blk_queue_update_dma_alignment(struct request_queue *, int);
-extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
-extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *);
+extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn_t *);
+extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn_t *);
extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua);
@@ -1369,13 +1369,13 @@ struct blk_plug {
#define BLK_PLUG_FLUSH_SIZE (128 * 1024)
struct blk_plug_cb;
-typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *, bool);
+typedef void (*blk_plug_cb_fn_t)(struct blk_plug_cb *, bool);
struct blk_plug_cb {
struct list_head list;
- blk_plug_cb_fn callback;
+ blk_plug_cb_fn_t callback;
void *data;
};
-extern struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug,
+extern struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn_t unplug,
void *data, int size);
extern void blk_start_plug(struct blk_plug *);
extern void blk_finish_plug(struct blk_plug *);
@@ -1884,11 +1884,11 @@ struct blk_integrity_iter {
const char *disk_name;
};
-typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *);
+typedef blk_status_t (integrity_processing_fn_t) (struct blk_integrity_iter *);
struct blk_integrity_profile {
- integrity_processing_fn *generate_fn;
- integrity_processing_fn *verify_fn;
+ integrity_processing_fn_t *generate_fn;
+ integrity_processing_fn_t *verify_fn;
const char *name;
};
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 6d9e230dffd2..87702b83acb6 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -23,72 +23,72 @@ enum elv_merge {
ELEVATOR_DISCARD_MERGE = 3,
};
-typedef enum elv_merge (elevator_merge_fn) (struct request_queue *, struct request **,
+typedef enum elv_merge (elevator_merge_fn_t) (struct request_queue *, struct request **,
struct bio *);
-typedef void (elevator_merge_req_fn) (struct request_queue *, struct request *, struct request *);
+typedef void (elevator_merge_req_fn_t) (struct request_queue *, struct request *, struct request *);
-typedef void (elevator_merged_fn) (struct request_queue *, struct request *, enum elv_merge);
+typedef void (elevator_merged_fn_t) (struct request_queue *, struct request *, enum elv_merge);
-typedef int (elevator_allow_bio_merge_fn) (struct request_queue *,
+typedef int (elevator_allow_bio_merge_fn_t) (struct request_queue *,
struct request *, struct bio *);
-typedef int (elevator_allow_rq_merge_fn) (struct request_queue *,
+typedef int (elevator_allow_rq_merge_fn_t) (struct request_queue *,
struct request *, struct request *);
-typedef void (elevator_bio_merged_fn) (struct request_queue *,
+typedef void (elevator_bio_merged_fn_t) (struct request_queue *,
struct request *, struct bio *);
-typedef int (elevator_dispatch_fn) (struct request_queue *, int);
+typedef int (elevator_dispatch_fn_t) (struct request_queue *, int);
-typedef void (elevator_add_req_fn) (struct request_queue *, struct request *);
-typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *);
-typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
-typedef int (elevator_may_queue_fn) (struct request_queue *, unsigned int);
+typedef void (elevator_add_req_fn_t) (struct request_queue *, struct request *);
+typedef struct request *(elevator_request_list_fn_t) (struct request_queue *, struct request *);
+typedef void (elevator_completed_req_fn_t) (struct request_queue *, struct request *);
+typedef int (elevator_may_queue_fn_t) (struct request_queue *, unsigned int);
-typedef void (elevator_init_icq_fn) (struct io_cq *);
-typedef void (elevator_exit_icq_fn) (struct io_cq *);
-typedef int (elevator_set_req_fn) (struct request_queue *, struct request *,
+typedef void (elevator_init_icq_fn_t) (struct io_cq *);
+typedef void (elevator_exit_icq_fn_t) (struct io_cq *);
+typedef int (elevator_set_req_fn_t) (struct request_queue *, struct request *,
struct bio *, gfp_t);
-typedef void (elevator_put_req_fn) (struct request *);
-typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *);
-typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *);
+typedef void (elevator_put_req_fn_t) (struct request *);
+typedef void (elevator_activate_req_fn_t) (struct request_queue *, struct request *);
+typedef void (elevator_deactivate_req_fn_t) (struct request_queue *, struct request *);
-typedef int (elevator_init_fn) (struct request_queue *,
+typedef int (elevator_init_fn_t) (struct request_queue *,
struct elevator_type *e);
-typedef void (elevator_exit_fn) (struct elevator_queue *);
-typedef void (elevator_registered_fn) (struct request_queue *);
+typedef void (elevator_exit_fn_t) (struct elevator_queue *);
+typedef void (elevator_registered_fn_t) (struct request_queue *);
struct elevator_ops
{
- elevator_merge_fn *elevator_merge_fn;
- elevator_merged_fn *elevator_merged_fn;
- elevator_merge_req_fn *elevator_merge_req_fn;
- elevator_allow_bio_merge_fn *elevator_allow_bio_merge_fn;
- elevator_allow_rq_merge_fn *elevator_allow_rq_merge_fn;
- elevator_bio_merged_fn *elevator_bio_merged_fn;
+ elevator_merge_fn_t *elevator_merge_fn;
+ elevator_merged_fn_t *elevator_merged_fn;
+ elevator_merge_req_fn_t *elevator_merge_req_fn;
+ elevator_allow_bio_merge_fn_t *elevator_allow_bio_merge_fn;
+ elevator_allow_rq_merge_fn_t *elevator_allow_rq_merge_fn;
+ elevator_bio_merged_fn_t *elevator_bio_merged_fn;
- elevator_dispatch_fn *elevator_dispatch_fn;
- elevator_add_req_fn *elevator_add_req_fn;
- elevator_activate_req_fn *elevator_activate_req_fn;
- elevator_deactivate_req_fn *elevator_deactivate_req_fn;
+ elevator_dispatch_fn_t *elevator_dispatch_fn;
+ elevator_add_req_fn_t *elevator_add_req_fn;
+ elevator_activate_req_fn_t *elevator_activate_req_fn;
+ elevator_deactivate_req_fn_t *elevator_deactivate_req_fn;
- elevator_completed_req_fn *elevator_completed_req_fn;
+ elevator_completed_req_fn_t *elevator_completed_req_fn;
- elevator_request_list_fn *elevator_former_req_fn;
- elevator_request_list_fn *elevator_latter_req_fn;
+ elevator_request_list_fn_t *elevator_former_req_fn;
+ elevator_request_list_fn_t *elevator_latter_req_fn;
- elevator_init_icq_fn *elevator_init_icq_fn; /* see iocontext.h */
- elevator_exit_icq_fn *elevator_exit_icq_fn; /* ditto */
+ elevator_init_icq_fn_t *elevator_init_icq_fn; /* see iocontext.h */
+ elevator_exit_icq_fn_t *elevator_exit_icq_fn; /* ditto */
- elevator_set_req_fn *elevator_set_req_fn;
- elevator_put_req_fn *elevator_put_req_fn;
+ elevator_set_req_fn_t *elevator_set_req_fn;
+ elevator_put_req_fn_t *elevator_put_req_fn;
- elevator_may_queue_fn *elevator_may_queue_fn;
+ elevator_may_queue_fn_t *elevator_may_queue_fn;
- elevator_init_fn *elevator_init_fn;
- elevator_exit_fn *elevator_exit_fn;
- elevator_registered_fn *elevator_registered_fn;
+ elevator_init_fn_t *elevator_init_fn;
+ elevator_exit_fn_t *elevator_exit_fn;
+ elevator_registered_fn_t *elevator_registered_fn;
};
struct blk_mq_alloc_data;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index b769ecfcc3bd..3c551fda1853 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -37,8 +37,8 @@ struct ctl_table_root;
struct ctl_table_header;
struct ctl_dir;
-typedef int proc_handler (struct ctl_table *ctl, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos);
+typedef int (*proc_handler_t)(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
extern int proc_dostring(struct ctl_table *, int,
void __user *, size_t *, loff_t *);
@@ -117,7 +117,7 @@ struct ctl_table
int maxlen;
umode_t mode;
struct ctl_table *child; /* Deprecated */
- proc_handler *proc_handler; /* Callback for text formatting */
+ proc_handler_t proc_handler; /* Callback for text formatting */
struct ctl_table_poll *poll;
void *extra1;
void *extra2;
Disable VERIFY_OCTAL_PERMISSIONS() for the moment as it's unclear as to why
g++ doesn't like it.
Signed-off-by: David Howells <[email protected]>
---
include/linux/kernel.h | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 59089f76c7d8..06b7e3a79c7a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -931,15 +931,6 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
#endif
/* Permissions on a sysfs file: you didn't miss the 0 prefix did you? */
-#define VERIFY_OCTAL_PERMISSIONS(perms) \
- (BUILD_BUG_ON_ZERO((perms) < 0) + \
- BUILD_BUG_ON_ZERO((perms) > 0777) + \
- /* USER_READABLE >= GROUP_READABLE >= OTHER_READABLE */ \
- BUILD_BUG_ON_ZERO((((perms) >> 6) & 4) < (((perms) >> 3) & 4)) + \
- BUILD_BUG_ON_ZERO((((perms) >> 3) & 4) < ((perms) & 4)) + \
- /* USER_WRITABLE >= GROUP_WRITABLE */ \
- BUILD_BUG_ON_ZERO((((perms) >> 6) & 2) < (((perms) >> 3) & 2)) + \
- /* OTHER_WRITABLE? Generally considered a bad idea. */ \
- BUILD_BUG_ON_ZERO((perms) & 2) + \
- (perms))
+#define VERIFY_OCTAL_PERMISSIONS(perms) \
+ (perms)
#endif
Turn READ_ONCE(), WRITE_ONCE() and similar into inline template functions.
This allows the source to be simplified since there doesn't need to be
magic casting and switch-statements inside macroisation.
Signed-off-by: David Howells <[email protected]>
---
include/linux/compiler.h | 93 ++++++++++++++--------------------------------
1 file changed, 29 insertions(+), 64 deletions(-)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index ab4711c63601..f9be82b93e20 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -3,6 +3,8 @@
#define __LINUX_COMPILER_H
#include <linux/compiler_types.h>
+#include <linux/kasan-checks.h>
+#include <asm/barrier.h>
#ifndef __ASSEMBLY__
@@ -168,26 +170,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#include <uapi/linux/types.h>
-#define __READ_ONCE_SIZE \
-({ \
- switch (size) { \
- case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \
- case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \
- case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \
- case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \
- default: \
- barrier(); \
- __builtin_memcpy((void *)res, (const void *)p, size); \
- barrier(); \
- } \
-})
-
-static __always_inline
-void __read_once_size(const volatile void *p, void *res, int size)
-{
- __READ_ONCE_SIZE;
-}
-
#ifdef CONFIG_KASAN
/*
* We can't declare function 'inline' because __no_sanitize_address confilcts
@@ -200,26 +182,6 @@ void __read_once_size(const volatile void *p, void *res, int size)
# define __no_kasan_or_inline __always_inline
#endif
-static __no_kasan_or_inline
-void __read_once_size_nocheck(const volatile void *p, void *res, int size)
-{
- __READ_ONCE_SIZE;
-}
-
-static __always_inline void __write_once_size(volatile void *p, void *res, int size)
-{
- switch (size) {
- case 1: *(volatile __u8 *)p = *(__u8 *)res; break;
- case 2: *(volatile __u16 *)p = *(__u16 *)res; break;
- case 4: *(volatile __u32 *)p = *(__u32 *)res; break;
- case 8: *(volatile __u64 *)p = *(__u64 *)res; break;
- default:
- barrier();
- __builtin_memcpy((void *)p, (const void *)res, size);
- barrier();
- }
-}
-
/*
* Prevent the compiler from merging or refetching reads or writes. The
* compiler is also forbidden from reordering successive instances of
@@ -242,27 +204,30 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
* with an explicit memory barrier or atomic instruction that provides the
* required ordering.
*/
-#include <asm/barrier.h>
-#include <linux/kasan-checks.h>
+template <typename P>
+static inline P READ_ONCE(P &ptr)
+{
+ barrier();
+ P val = *(volatile P *)&ptr;
+ smp_read_barrier_depends(); /* Enforce dependency ordering from x */
+ return val;
+}
-#define __READ_ONCE(x, check) \
-({ \
- union { typeof(x) __val; char __c[1]; } __u; \
- if (check) \
- __read_once_size(&(x), __u.__c, sizeof(x)); \
- else \
- __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
- smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \
- __u.__val; \
-})
-#define READ_ONCE(x) __READ_ONCE(x, 1)
+template <typename P>
+static __no_kasan_or_inline P READ_ONCE_NOCHECK(P &ptr)
+{
+ barrier();
+ P val = *(volatile P *)&ptr;
+ smp_read_barrier_depends(); /* Enforce dependency ordering from x */
+ return val;
+}
/*
- * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
- * to hide memory access from KASAN.
+ * This function is not 'inline' because __no_sanitize_address confilcts
+ * with inlining. Attempt to inline it may cause a build failure.
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
*/
-#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
-
static __no_kasan_or_inline
unsigned long read_word_at_a_time(const void *addr)
{
@@ -270,13 +235,13 @@ unsigned long read_word_at_a_time(const void *addr)
return *(unsigned long *)addr;
}
-#define WRITE_ONCE(x, val) \
-({ \
- union { typeof(x) __val; char __c[1]; } __u = \
- { .__val = (__force typeof(x)) (val) }; \
- __write_once_size(&(x), __u.__c, sizeof(x)); \
- __u.__val; \
-})
+template <typename P, typename T>
+static inline void WRITE_ONCE(P &ptr, T val)
+{
+ barrier();
+ *(volatile P *)&ptr = val;
+ barrier();
+}
#endif /* __KERNEL__ */
Fix the return value of exception_enter() to return CONTEXT_KERNEL rather
than 0 when the facility is disabled as the function returns an ctx_state
enum rather than a plain integer.
Signed-off-by: David Howells <[email protected]>
---
include/linux/context_tracking.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h
index d05609ad329d..b4e9f9d80745 100644
--- a/include/linux/context_tracking.h
+++ b/include/linux/context_tracking.h
@@ -50,7 +50,7 @@ static inline enum ctx_state exception_enter(void)
enum ctx_state prev_ctx;
if (!context_tracking_is_enabled())
- return 0;
+ return CONTEXT_KERNEL;
prev_ctx = this_cpu_read(context_tracking.state);
if (prev_ctx != CONTEXT_KERNEL)
@@ -85,7 +85,7 @@ static inline void user_enter(void) { }
static inline void user_exit(void) { }
static inline void user_enter_irqoff(void) { }
static inline void user_exit_irqoff(void) { }
-static inline enum ctx_state exception_enter(void) { return 0; }
+static inline enum ctx_state exception_enter(void) { return CONTEXT_KERNEL; }
static inline void exception_exit(enum ctx_state prev_ctx) { }
static inline enum ctx_state ct_state(void) { return CONTEXT_DISABLED; }
#endif /* !CONFIG_CONTEXT_TRACKING */
> - entry->next = LIST_POISON1;
> - entry->prev = LIST_POISON2;
> + entry->next = static_cast<struct list_head *>(LIST_POISON1);
> + entry->prev = static_cast<struct list_head *>(LIST_POISON2);
There is a better way ;-)
--- a/include/linux/poison.h
+++ b/include/linux/poison.h
@@ -2,6 +2,22 @@
#ifndef _LINUX_POISON_H
#define _LINUX_POISON_H
+class POISON {
+ unsigned long p;
+
+public:
+ explicit POISON(unsigned long val)
+ : p{val}
+ {
+ }
+
+ template<typename T>
+ operator T*() const
+ {
+ return p;
+ }
+};
+
/********** include/linux/list.h **********/
/*
@@ -20,15 +36,15 @@
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
-#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
-#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
+#define LIST_POISON1 POISON{0x100UL + POISON_POINTER_DELTA}
+#define LIST_POISON2 POISON{0x200UL + POISON_POINTER_DELTA}
/********** include/linux/timer.h **********/
/*
* Magic number "tsta" to indicate a static timer initializer
* for the object debugging code.
*/
-#define TIMER_ENTRY_STATIC ((void *) 0x300 + POISON_POINTER_DELTA)
+#define TIMER_ENTRY_STATIC POISON{0x300UL + POISON_POINTER_DELTA}
/********** mm/debug-pagealloc.c **********/
#ifdef CONFIG_PAGE_POISONING_ZERO
@@ -39,7 +55,7 @@
/********** mm/page_alloc.c ************/
-#define TAIL_MAPPING ((void *) 0x400 + POISON_POINTER_DELTA)
+#define TAIL_MAPPING POISON{0x400UL + POISON_POINTER_DELTA}
/********** mm/slab.c **********/
/*
@@ -81,7 +97,7 @@
/********** kernel/mutexes **********/
#define MUTEX_DEBUG_INIT 0x11
#define MUTEX_DEBUG_FREE 0x22
-#define MUTEX_POISON_WW_CTX ((void *) 0x500 + POISON_POINTER_DELTA)
+#define MUTEX_POISON_WW_CTX POISON{0x500UL + POISON_POINTER_DELTA}
/********** lib/flex_array.c **********/
#define FLEX_ARRAY_FREE 0x6c /* for use-after-free poisoning */
> We could, for example, wrap things like userspace pointers, __be numbers,
> ioport addresses and control access to them that way, but I don't know that it
> gains a whole load that sparse doesn't give us.
The problem with sparse is that it is not mandatory part of a build
process. And it spams lot ATM.
On 04/01/2018 01:40 PM, David Howells wrote:
>
> Here are a series of patches to start converting the kernel to C++. It
> requires g++ v8.
>
...
>
> What I would disallow:
>
> (1) new and delete. There's no way to pass GFP_* flags in.
>
> (2) Constructors and destructors. Nests of implicit code makes the code less
> obvious, and the replacement of static initialisation with constructor
> calls would make the code size larger.
>
> (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
> exception handling is limited without it, and since destructors are not
> allowed, you still have to manually clean up after an error.
>
> (4) Operator overloading (except in special cases).
>
> (5) Function overloading (except in special inline cases).
>
> (6) STL (though some type trait bits are needed to replace __builtins that
> don't exist in g++).
>
> (7) 'class', 'private', 'namespace'.
Please fix https://bugzilla.kernel.org/show_bug.cgi?id=191051
while you are at it. :)
> (8) 'virtual'. Don't want virtual base classes, though virtual function
> tables might make operations tables more efficient.
ta.
--
~Randy
On 04/01/2018 01:40 PM, David Howells wrote:
> Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID as the
> parameter is an unsigned integer.
>
> Signed-off-by: David Howells <[email protected]>
> ---
>
> include/linux/projid.h | 2 +-
> include/linux/uidgid.h | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/projid.h b/include/linux/projid.h
> index 613730622a1a..7c60a79424c9 100644
> --- a/include/linux/projid.h
> +++ b/include/linux/projid.h
> @@ -30,7 +30,7 @@ static inline projid_t __kprojid_val(kprojid_t projid)
+#include <linux/kernel.h>
> #define KPROJIDT_INIT(value) (kprojid_t){ value }
>
> -#define INVALID_PROJID KPROJIDT_INIT(-1)
> +#define INVALID_PROJID KPROJIDT_INIT(UINT_MAX)
> #define OVERFLOW_PROJID 65534
>
> static inline bool projid_eq(kprojid_t left, kprojid_t right)
> diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h
> index b0542cd11aeb..75f602075b63 100644
> --- a/include/linux/uidgid.h
> +++ b/include/linux/uidgid.h
> @@ -55,8 +55,8 @@ static inline gid_t __kgid_val(kgid_t gid)
+#include <linux/kernel.h>
> #define GLOBAL_ROOT_UID KUIDT_INIT(0)
> #define GLOBAL_ROOT_GID KGIDT_INIT(0)
>
> -#define INVALID_UID KUIDT_INIT(-1)
> -#define INVALID_GID KGIDT_INIT(-1)
> +#define INVALID_UID KUIDT_INIT(UINT_MAX)
> +#define INVALID_GID KGIDT_INIT(UINT_MAX)
>
> static inline bool uid_eq(kuid_t left, kuid_t right)
> {
>
--
~Randy
On 04/01/2018 01:44 PM, David Howells wrote:
> Make mutex_trylock_recursive_enum() cast the int it derives to the enum
> return type.
>
> Signed-off-by: David Howells <[email protected]>
> ---
>
> include/linux/mutex.h | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mutex.h b/include/linux/mutex.h
> index cb3bbed4e633..2bacc5065980 100644
> --- a/include/linux/mutex.h
> +++ b/include/linux/mutex.h
> @@ -224,13 +224,14 @@ enum mutex_trylock_recursive_enum {
> * - MUTEX_TRYLOCK_SUCCESS - lock acquired,
> * - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock.
> */
> -static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
> +static inline /* __deprecated */ __must_check
> +enum mutex_trylock_recursive_enum
nak that change from 1 to 2 lines. It's only 79 characters.
> mutex_trylock_recursive(struct mutex *lock)
> {
> if (unlikely(__mutex_owner(lock) == current))
> return MUTEX_TRYLOCK_RECURSIVE;
>
> - return mutex_trylock(lock);
> + return (enum mutex_trylock_recursive_enum)mutex_trylock(lock);
> }
>
> #endif /* __LINUX_MUTEX_H */
>
--
~Randy
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-x002-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
include/linux/types.h:188:1: warning: empty declaration
struct list_head {
^~~~~~
include/linux/types.h:192:1: warning: empty declaration
struct hlist_head {
^~~~~~
include/linux/types.h:196:1: warning: empty declaration
struct hlist_node {
^~~~~~
include/linux/types.h:201:2: error: expected specifier-qualifier-list before '__kernel_daddr_t'
__kernel_daddr_t f_tfree;
^~~~~~~~~~~~~~~~
include/linux/types.h:200:1: warning: empty declaration
struct ustat {
^~~~~~
include/linux/types.h:226:1: warning: empty declaration
struct callback_head {
^~~~~~
include/linux/types.h:232:16: error: storage class specified for parameter 'rcu_callback_t'
typedef void (*rcu_callback_t)(struct rcu_head *head);
^~~~~~~~~~~~~~
include/linux/types.h:233:56: error: expected declaration specifiers or '...' before 'rcu_callback_t'
typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
^~~~~~~~~~~~~~
In file included from include/asm-generic/bug.h:5:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/compiler.h:187:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/compiler.h:205:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/compiler.h:210:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from arch/x86/include/asm/barrier.h:5:0,
from include/linux/compiler.h:245,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/alternative.h:48:1: warning: empty declaration
struct alt_instr {
^~~~~~
arch/x86/include/asm/alternative.h:61:12: error: storage class specified for parameter 'alternatives_patched'
extern int alternatives_patched;
^~~~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:63:13: error: storage class specified for parameter 'alternative_instructions'
extern void alternative_instructions(void);
^~~~~~~~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:64:13: error: storage class specified for parameter 'apply_alternatives'
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
^~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:66:1: warning: empty declaration
struct module;
^~~~~~
arch/x86/include/asm/alternative.h:79:41: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
void *text, void *text_end) {}
^
arch/x86/include/asm/alternative.h:80:68: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
static inline void alternatives_smp_module_del(struct module *mod) {}
^
arch/x86/include/asm/alternative.h:81:50: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
static inline void alternatives_enable_smp(void) {}
^
arch/x86/include/asm/alternative.h:83:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from arch/x86/include/asm/barrier.h:6:0,
from include/linux/compiler.h:245,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/nops.h:143:37: error: storage class specified for parameter 'ideal_nops'
extern const unsigned char * const *ideal_nops;
^~~~~~~~~~
arch/x86/include/asm/nops.h:144:13: error: storage class specified for parameter 'arch_init_ideal_nops'
extern void arch_init_ideal_nops(void);
^~~~~~~~~~~~~~~~~~~~
In file included from include/linux/compiler.h:245:0,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/barrier.h:38:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from include/linux/compiler.h:246:0,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
>> include/linux/kasan-checks.h:10:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{ }
^
include/linux/kasan-checks.h:12:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{ }
^
In file included from include/asm-generic/bug.h:5:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/compiler.h:268:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from include/linux/kernel.h:6:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
/usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h:40:27: error: storage class specified for parameter '__gnuc_va_list'
typedef __builtin_va_list __gnuc_va_list;
^~~~~~~~~~~~~~
In file included from include/linux/kernel.h:6:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
/usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h:99:24: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'va_list'
typedef __gnuc_va_list va_list;
^~~~~~~
In file included from include/linux/linkage.h:7:0,
from include/linux/kernel.h:7,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/export.h:27:1: warning: empty declaration
struct kernel_symbol
^~~~~~
In file included from include/linux/kernel.h:11:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/bitops.h:29:21: error: storage class specified for parameter '__sw_hweight8'
extern unsigned int __sw_hweight8(unsigned int w);
^~~~~~~~~~~~~
include/linux/bitops.h:30:21: error: storage class specified for parameter '__sw_hweight16'
extern unsigned int __sw_hweight16(unsigned int w);
^~~~~~~~~~~~~~
include/linux/bitops.h:31:21: error: storage class specified for parameter '__sw_hweight32'
extern unsigned int __sw_hweight32(unsigned int w);
^~~~~~~~~~~~~~
include/linux/bitops.h:32:22: error: storage class specified for parameter '__sw_hweight64'
extern unsigned long __sw_hweight64(__u64 w);
^~~~~~~~~~~~~~
In file included from include/linux/bitops.h:38:0,
from include/linux/kernel.h:11,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/bitops.h:74:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:96:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:112:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:133:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:139:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:143:24: error: unknown type name 'bool'
static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
^~~~
arch/x86/include/asm/bitops.h:144:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:169:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:184:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:198:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:218:24: error: unknown type name 'bool'
static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr)
^~~~
arch/x86/include/asm/bitops.h:219:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
vim +10 include/linux/kasan-checks.h
64f8ebaf Andrey Ryabinin 2016-05-20 4
64f8ebaf Andrey Ryabinin 2016-05-20 5 #ifdef CONFIG_KASAN
f06e8c58 Dmitry Vyukov 2017-06-22 6 void kasan_check_read(const volatile void *p, unsigned int size);
f06e8c58 Dmitry Vyukov 2017-06-22 7 void kasan_check_write(const volatile void *p, unsigned int size);
64f8ebaf Andrey Ryabinin 2016-05-20 8 #else
f06e8c58 Dmitry Vyukov 2017-06-22 9 static inline void kasan_check_read(const volatile void *p, unsigned int size)
f06e8c58 Dmitry Vyukov 2017-06-22 @10 { }
f06e8c58 Dmitry Vyukov 2017-06-22 11 static inline void kasan_check_write(const volatile void *p, unsigned int size)
f06e8c58 Dmitry Vyukov 2017-06-22 12 { }
64f8ebaf Andrey Ryabinin 2016-05-20 13 #endif
64f8ebaf Andrey Ryabinin 2016-05-20 14
:::::: The code at line 10 was first introduced by commit
:::::: f06e8c584fa0d05312c11ea66194f3d2efb93c21 kasan: Allow kasan_check_read/write() to accept pointers to volatiles
:::::: TO: Dmitry Vyukov <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-x006-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
^~~~~~~~
include/linux/types.h:115:17: error: storage class specified for parameter 'u_int64_t'
typedef __u64 u_int64_t;
^~~~~~~~~
include/linux/types.h:116:17: error: storage class specified for parameter 'int64_t'
typedef __s64 int64_t;
^~~~~~~
include/linux/types.h:136:23: error: storage class specified for parameter 'sector_t'
typedef unsigned long sector_t;
^~~~~~~~
include/linux/types.h:137:23: error: storage class specified for parameter 'blkcnt_t'
typedef unsigned long blkcnt_t;
^~~~~~~~
include/linux/types.h:155:13: error: storage class specified for parameter 'dma_addr_t'
typedef u64 dma_addr_t;
^~~~~~~~~~
include/linux/types.h:160:28: error: storage class specified for parameter 'gfp_t'
typedef unsigned __bitwise gfp_t;
^~~~~
include/linux/types.h:161:28: error: storage class specified for parameter 'slab_flags_t'
typedef unsigned __bitwise slab_flags_t;
^~~~~~~~~~~~
include/linux/types.h:162:28: error: storage class specified for parameter 'fmode_t'
typedef unsigned __bitwise fmode_t;
^~~~~~~
include/linux/types.h:165:13: error: storage class specified for parameter 'phys_addr_t'
typedef u64 phys_addr_t;
^~~~~~~~~~~
include/linux/types.h:170:21: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'resource_size_t'
typedef phys_addr_t resource_size_t;
^~~~~~~~~~~~~~~
include/linux/types.h:176:23: error: storage class specified for parameter 'irq_hw_number_t'
typedef unsigned long irq_hw_number_t;
^~~~~~~~~~~~~~~
include/linux/types.h:180:3: error: storage class specified for parameter 'atomic_t'
} atomic_t;
^~~~~~~~
include/linux/types.h:185:3: error: storage class specified for parameter 'atomic64_t'
} atomic64_t;
^~~~~~~~~~
include/linux/types.h:188:1: warning: empty declaration
struct list_head {
^~~~~~
include/linux/types.h:192:1: warning: empty declaration
struct hlist_head {
^~~~~~
include/linux/types.h:196:1: warning: empty declaration
struct hlist_node {
^~~~~~
include/linux/types.h:201:2: error: expected specifier-qualifier-list before '__kernel_daddr_t'
__kernel_daddr_t f_tfree;
^~~~~~~~~~~~~~~~
include/linux/types.h:200:1: warning: empty declaration
struct ustat {
^~~~~~
include/linux/types.h:226:1: warning: empty declaration
struct callback_head {
^~~~~~
include/linux/types.h:232:16: error: storage class specified for parameter 'rcu_callback_t'
typedef void (*rcu_callback_t)(struct rcu_head *head);
^~~~~~~~~~~~~~
include/linux/types.h:233:56: error: expected declaration specifiers or '...' before 'rcu_callback_t'
typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
^~~~~~~~~~~~~~
In file included from include/asm-generic/bug.h:5:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/compiler.h:187:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/compiler.h:205:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/compiler.h:210:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from arch/x86/include/asm/barrier.h:5:0,
from include/linux/compiler.h:245,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/alternative.h:48:1: warning: empty declaration
struct alt_instr {
^~~~~~
arch/x86/include/asm/alternative.h:61:12: error: storage class specified for parameter 'alternatives_patched'
extern int alternatives_patched;
^~~~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:63:13: error: storage class specified for parameter 'alternative_instructions'
extern void alternative_instructions(void);
^~~~~~~~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:64:13: error: storage class specified for parameter 'apply_alternatives'
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
^~~~~~~~~~~~~~~~~~
arch/x86/include/asm/alternative.h:66:1: warning: empty declaration
struct module;
^~~~~~
>> arch/x86/include/asm/alternative.h:69:13: error: storage class specified for parameter 'alternatives_smp_module_add'
extern void alternatives_smp_module_add(struct module *mod, char *name,
^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/x86/include/asm/alternative.h:72:13: error: storage class specified for parameter 'alternatives_smp_module_del'
extern void alternatives_smp_module_del(struct module *mod);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/x86/include/asm/alternative.h:73:13: error: storage class specified for parameter 'alternatives_enable_smp'
extern void alternatives_enable_smp(void);
^~~~~~~~~~~~~~~~~~~~~~~
>> arch/x86/include/asm/alternative.h:74:12: error: storage class specified for parameter 'alternatives_text_reserved'
extern int alternatives_text_reserved(void *start, void *end);
^~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/x86/include/asm/alternative.h:75:8: error: unknown type name 'bool'
extern bool skip_smp_alternatives;
^~~~
>> arch/x86/include/asm/alternative.h:75:13: error: storage class specified for parameter 'skip_smp_alternatives'
extern bool skip_smp_alternatives;
^~~~~~~~~~~~~~~~~~~~~
In file included from arch/x86/include/asm/barrier.h:6:0,
from include/linux/compiler.h:245,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/nops.h:143:37: error: storage class specified for parameter 'ideal_nops'
extern const unsigned char * const *ideal_nops;
^~~~~~~~~~
arch/x86/include/asm/nops.h:144:13: error: storage class specified for parameter 'arch_init_ideal_nops'
extern void arch_init_ideal_nops(void);
^~~~~~~~~~~~~~~~~~~~
In file included from include/linux/compiler.h:245:0,
from include/asm-generic/bug.h:5,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/barrier.h:38:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from include/asm-generic/bug.h:5:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/compiler.h:268:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
In file included from include/linux/kernel.h:6:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
/usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h:40:27: error: storage class specified for parameter '__gnuc_va_list'
typedef __builtin_va_list __gnuc_va_list;
^~~~~~~~~~~~~~
In file included from include/linux/kernel.h:6:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
/usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h:99:24: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'va_list'
typedef __gnuc_va_list va_list;
^~~~~~~
In file included from include/linux/linkage.h:7:0,
from include/linux/kernel.h:7,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/export.h:27:1: warning: empty declaration
struct kernel_symbol
^~~~~~
In file included from include/linux/kernel.h:11:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/bitops.h:29:21: error: storage class specified for parameter '__sw_hweight8'
extern unsigned int __sw_hweight8(unsigned int w);
^~~~~~~~~~~~~
include/linux/bitops.h:30:21: error: storage class specified for parameter '__sw_hweight16'
extern unsigned int __sw_hweight16(unsigned int w);
^~~~~~~~~~~~~~
include/linux/bitops.h:31:21: error: storage class specified for parameter '__sw_hweight32'
extern unsigned int __sw_hweight32(unsigned int w);
^~~~~~~~~~~~~~
include/linux/bitops.h:32:22: error: storage class specified for parameter '__sw_hweight64'
extern unsigned long __sw_hweight64(__u64 w);
^~~~~~~~~~~~~~
In file included from include/linux/bitops.h:38:0,
from include/linux/kernel.h:11,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
arch/x86/include/asm/bitops.h:74:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:96:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:112:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:133:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
arch/x86/include/asm/bitops.h:139:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
--
^~~~~~~~~~~~~~~~~
include/linux/printk.h:189:12: error: storage class specified for parameter 'dmesg_restrict'
extern int dmesg_restrict;
^~~~~~~~~~~~~~
include/linux/printk.h:193:6: error: expected declaration specifiers or '...' before 'size_t'
size_t *lenp, loff_t *ppos);
^~~~~~
include/linux/printk.h:193:20: error: unknown type name 'loff_t'; did you mean 'pgoff_t'?
size_t *lenp, loff_t *ppos);
^~~~~~
pgoff_t
include/linux/printk.h:195:13: error: storage class specified for parameter 'wake_up_klogd'
extern void wake_up_klogd(void);
^~~~~~~~~~~~~
include/linux/printk.h:200:13: error: section attribute not allowed for 'setup_log_buf'
void __init setup_log_buf(int early);
^~~~~~~~~~~~~
include/linux/printk.h:200:1: warning: '__cold__' attribute ignored [-Wattributes]
void __init setup_log_buf(int early);
^~~~
In file included from include/linux/compiler_types.h:58:0,
from include/linux/kconfig.h:74,
from <command-line>:0:
include/linux/compiler-gcc.h:129:25: error: expected declaration specifiers before '__attribute__'
#define __printf(a, b) __attribute__((format(printf, a, b)))
^
include/linux/printk.h:201:1: note: in expansion of macro '__printf'
__printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...);
^~~~~~~~
In file included from include/linux/kernel.h:14:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/printk.h:204:13: error: storage class specified for parameter 'printk_safe_init'
extern void printk_safe_init(void);
^~~~~~~~~~~~~~~~
include/linux/printk.h:205:13: error: storage class specified for parameter 'printk_safe_flush'
extern void printk_safe_flush(void);
^~~~~~~~~~~~~~~~~
include/linux/printk.h:206:13: error: storage class specified for parameter 'printk_safe_flush_on_panic'
extern void printk_safe_flush_on_panic(void);
^~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:280:12: error: storage class specified for parameter 'kptr_restrict'
extern int kptr_restrict;
^~~~~~~~~~~~~
include/linux/printk.h:282:24: error: storage class specified for parameter 'dump_stack'
extern asmlinkage void dump_stack(void) __cold;
^~~~~~~~~~
include/linux/printk.h:282:1: warning: '__cold__' attribute ignored [-Wattributes]
extern asmlinkage void dump_stack(void) __cold;
^~~~~~
include/linux/printk.h:474:37: error: storage class specified for parameter 'kmsg_fops'
extern const struct file_operations kmsg_fops;
^~~~~~~~~
include/linux/printk.h:476:1: warning: empty declaration
enum {
^~~~
include/linux/printk.h:481:48: error: expected declaration specifiers or '...' before 'size_t'
extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
^~~~~~
include/linux/printk.h:482:40: error: expected declaration specifiers or '...' before 'size_t'
int groupsize, char *linebuf, size_t linebuflen,
^~~~~~
include/linux/printk.h:483:10: error: unknown type name 'bool'; did you mean '_Bool'?
bool ascii);
^~~~
_Bool
include/linux/printk.h:487:24: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len, bool ascii);
^~~~~~
include/linux/printk.h:487:36: error: unknown type name 'bool'; did you mean '_Bool'?
const void *buf, size_t len, bool ascii);
^~~~
_Bool
include/linux/printk.h:493:23: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len);
^~~~~~
include/linux/printk.h:521:23: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len, bool ascii)
^~~~~~
include/linux/printk.h:521:35: error: unknown type name 'bool'; did you mean '_Bool'?
const void *buf, size_t len, bool ascii)
^~~~
_Bool
In file included from include/asm-generic/bug.h:18:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/kernel.h:202:1: warning: empty declaration
struct completion;
^~~~~~
include/linux/kernel.h:203:1: warning: empty declaration
struct pt_regs;
^~~~~~
include/linux/kernel.h:204:1: warning: empty declaration
struct user;
^~~~~~
>> include/linux/kernel.h:207:12: error: storage class specified for parameter '_cond_resched'
extern int _cond_resched(void);
^~~~~~~~~~~~~
include/linux/kernel.h:278:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:290:36: error: storage class specified for parameter 'panic_notifier_list'
extern struct atomic_notifier_head panic_notifier_list;
^~~~~~~~~~~~~~~~~~~
include/linux/kernel.h:291:15: error: storage class specified for parameter 'panic_blink'
extern long (*panic_blink)(int state);
^~~~~~~~~~~
In file included from include/linux/compiler_types.h:58:0,
from include/linux/kconfig.h:74,
from <command-line>:0:
include/linux/compiler-gcc.h:129:25: error: expected declaration specifiers before '__attribute__'
#define __printf(a, b) __attribute__((format(printf, a, b)))
^
include/linux/kernel.h:292:1: note: in expansion of macro '__printf'
__printf(1, 2)
^~~~~~~~
In file included from include/asm-generic/bug.h:18:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/kernel.h:295:13: error: storage class specified for parameter 'oops_enter'
extern void oops_enter(void);
^~~~~~~~~~
include/linux/kernel.h:296:13: error: storage class specified for parameter 'oops_exit'
extern void oops_exit(void);
^~~~~~~~~
include/linux/kernel.h:298:12: error: storage class specified for parameter 'oops_may_print'
extern int oops_may_print(void);
^~~~~~~~~~~~~~
include/linux/kernel.h:333:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:362:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:378:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:383:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:388:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:393:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:401:44: error: unknown type name 'bool'; did you mean '_Bool'?
int __must_check kstrtobool(const char *s, bool *res);
^~~~
_Bool
include/linux/kernel.h:403:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res);
^~~~~~
include/linux/kernel.h:404:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res);
^~~~~~
include/linux/kernel.h:405:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoul_from_user(const char __user *s, size_t count, unsigned int base, unsigned long *res);
^~~~~~
include/linux/kernel.h:406:58: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtol_from_user(const char __user *s, size_t count, unsigned int base, long *res);
^~~~~~
include/linux/kernel.h:407:61: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, unsigned int *res);
^~~~~~
include/linux/kernel.h:408:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, int *res);
^~~~~~
include/linux/kernel.h:409:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtou16_from_user(const char __user *s, size_t count, unsigned int base, u16 *res);
^~~~~~
include/linux/kernel.h:410:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res);
^~~~~~
include/linux/kernel.h:411:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res);
^~~~~~
include/linux/kernel.h:412:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtos8_from_user(const char __user *s, size_t count, unsigned int base, s8 *res);
^~~~~~
include/linux/kernel.h:413:61: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtobool_from_user(const char __user *s, size_t count, bool *res);
^~~~~~
include/linux/kernel.h:413:75: error: unknown type name 'bool'; did you mean '_Bool'?
int __must_check kstrtobool_from_user(const char __user *s, size_t count, bool *res);
^~~~
_Bool
include/linux/kernel.h:415:74: error: expected declaration specifiers or '...' before 'size_t'
static inline int __must_check kstrtou64_from_user(const char __user *s, size_t count, unsigned int base, u64 *res)
^~~~~~
include/linux/kernel.h:420:74: error: expected declaration specifiers or '...' before 'size_t'
static inline int __must_check kstrtos64_from_user(const char __user *s, size_t count, unsigned int base, s64 *res)
^~~~~~
include/linux/kernel.h:425:74: error: expected declaration specifiers or '...' before 'size_t'
..
vim +/alternatives_smp_module_add +69 arch/x86/include/asm/alternative.h
5e907bb0 arch/x86/include/asm/alternative.h Ingo Molnar 2015-04-30 62
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 @63 extern void alternative_instructions(void);
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 @64 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 65
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 @66 struct module;
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 67
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 68 #ifdef CONFIG_SMP
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 @69 extern void alternatives_smp_module_add(struct module *mod, char *name,
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 70 void *locks, void *locks_end,
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 71 void *text, void *text_end);
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 @72 extern void alternatives_smp_module_del(struct module *mod);
816afe4f arch/x86/include/asm/alternative.h Rusty Russell 2012-08-06 @73 extern void alternatives_enable_smp(void);
2cfa1978 arch/x86/include/asm/alternative.h Masami Hiramatsu 2010-02-02 @74 extern int alternatives_text_reserved(void *start, void *end);
3fb82d56 arch/x86/include/asm/alternative.h Suresh Siddha 2010-11-23 @75 extern bool skip_smp_alternatives;
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 76 #else
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 77 static inline void alternatives_smp_module_add(struct module *mod, char *name,
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 78 void *locks, void *locks_end,
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 79 void *text, void *text_end) {}
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 80 static inline void alternatives_smp_module_del(struct module *mod) {}
816afe4f arch/x86/include/asm/alternative.h Rusty Russell 2012-08-06 81 static inline void alternatives_enable_smp(void) {}
2cfa1978 arch/x86/include/asm/alternative.h Masami Hiramatsu 2010-02-02 82 static inline int alternatives_text_reserved(void *start, void *end)
2cfa1978 arch/x86/include/asm/alternative.h Masami Hiramatsu 2010-02-02 83 {
2cfa1978 arch/x86/include/asm/alternative.h Masami Hiramatsu 2010-02-02 84 return 0;
2cfa1978 arch/x86/include/asm/alternative.h Masami Hiramatsu 2010-02-02 85 }
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 86 #endif /* CONFIG_SMP */
6b592570 include/asm-x86/alternative.h H. Peter Anvin 2008-01-30 87
:::::: The code at line 69 was first introduced by commit
:::::: 6b59257082e136fbbce1aa017575a451c0df0592 x86: actually merge <asm/alternative.h>
:::::: TO: H. Peter Anvin <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-x016-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All error/warnings (new ones prefixed by >>):
include/linux/printk.h:183:12: error: storage class specified for parameter '__printk_ratelimit'
extern int __printk_ratelimit(const char *func);
^~~~~~~~~~~~~~~~~~
include/linux/printk.h:185:8: error: unknown type name 'bool'
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
^~~~
include/linux/printk.h:185:13: error: storage class specified for parameter 'printk_timed_ratelimit'
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
^~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:188:12: error: storage class specified for parameter 'printk_delay_msec'
extern int printk_delay_msec;
^~~~~~~~~~~~~~~~~
include/linux/printk.h:189:12: error: storage class specified for parameter 'dmesg_restrict'
extern int dmesg_restrict;
^~~~~~~~~~~~~~
include/linux/printk.h:193:6: error: expected declaration specifiers or '...' before 'size_t'
size_t *lenp, loff_t *ppos);
^~~~~~
include/linux/printk.h:193:20: error: unknown type name 'loff_t'; did you mean 'pgoff_t'?
size_t *lenp, loff_t *ppos);
^~~~~~
pgoff_t
include/linux/printk.h:195:13: error: storage class specified for parameter 'wake_up_klogd'
extern void wake_up_klogd(void);
^~~~~~~~~~~~~
include/linux/printk.h:200:13: error: section attribute not allowed for 'setup_log_buf'
void __init setup_log_buf(int early);
^~~~~~~~~~~~~
include/linux/printk.h:200:1: warning: '__cold__' attribute ignored [-Wattributes]
void __init setup_log_buf(int early);
^~~~
In file included from include/linux/compiler_types.h:58:0,
from include/linux/kconfig.h:74,
from <command-line>:0:
include/linux/compiler-gcc.h:130:25: error: expected declaration specifiers before '__attribute__'
#define __printf(a, b) __attribute__((format(printf, a, b)))
^
include/linux/printk.h:201:1: note: in expansion of macro '__printf'
__printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...);
^~~~~~~~
In file included from include/linux/kernel.h:15:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/printk.h:204:13: error: storage class specified for parameter 'printk_safe_init'
extern void printk_safe_init(void);
^~~~~~~~~~~~~~~~
include/linux/printk.h:205:13: error: storage class specified for parameter 'printk_safe_flush'
extern void printk_safe_flush(void);
^~~~~~~~~~~~~~~~~
include/linux/printk.h:206:13: error: storage class specified for parameter 'printk_safe_flush_on_panic'
extern void printk_safe_flush_on_panic(void);
^~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:280:12: error: storage class specified for parameter 'kptr_restrict'
extern int kptr_restrict;
^~~~~~~~~~~~~
include/linux/printk.h:282:1: warning: '__cold__' attribute ignored [-Wattributes]
asmlinkage void dump_stack(void) __cold;
^~~~~~~~~~
include/linux/printk.h:474:37: error: storage class specified for parameter 'kmsg_fops'
extern const struct file_operations kmsg_fops;
^~~~~~~~~
include/linux/printk.h:476:1: warning: empty declaration
enum {
^~~~
include/linux/printk.h:481:48: error: expected declaration specifiers or '...' before 'size_t'
extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
^~~~~~
include/linux/printk.h:482:40: error: expected declaration specifiers or '...' before 'size_t'
int groupsize, char *linebuf, size_t linebuflen,
^~~~~~
include/linux/printk.h:483:10: error: unknown type name 'bool'; did you mean '_Bool'?
bool ascii);
^~~~
_Bool
include/linux/printk.h:487:24: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len, bool ascii);
^~~~~~
include/linux/printk.h:487:36: error: unknown type name 'bool'; did you mean '_Bool'?
const void *buf, size_t len, bool ascii);
^~~~
_Bool
include/linux/printk.h:493:23: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len);
^~~~~~
include/linux/printk.h:521:23: error: expected declaration specifiers or '...' before 'size_t'
const void *buf, size_t len, bool ascii)
^~~~~~
include/linux/printk.h:521:35: error: unknown type name 'bool'; did you mean '_Bool'?
const void *buf, size_t len, bool ascii)
^~~~
_Bool
In file included from include/linux/kernel.h:16:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
>> include/linux/build_bug.h:23:12: error: storage class specified for parameter '__build_bug_on_zero'
extern int __build_bug_on_zero(void)
^~~~~~~~~~~~~~~~~~~
>> include/linux/build_bug.h:24:2: warning: 'error' attribute ignored [-Wattributes]
__compiletime_error("Build bug on zero");
^~~~~~~~~~~~~~~~~~~
In file included from include/asm-generic/bug.h:18:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/kernel.h:203:1: warning: empty declaration
struct completion;
^~~~~~
include/linux/kernel.h:204:1: warning: empty declaration
struct pt_regs;
^~~~~~
include/linux/kernel.h:205:1: warning: empty declaration
struct user;
^~~~~~
include/linux/kernel.h:249:1: error: expected declaration specifiers before 'template'
template<typename T>
^~~~~~~~
include/linux/kernel.h:270:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:282:36: error: storage class specified for parameter 'panic_notifier_list'
extern struct atomic_notifier_head panic_notifier_list;
^~~~~~~~~~~~~~~~~~~
include/linux/kernel.h:283:15: error: storage class specified for parameter 'panic_blink'
extern long (*panic_blink)(int state);
^~~~~~~~~~~
In file included from include/linux/compiler_types.h:58:0,
from include/linux/kconfig.h:74,
from <command-line>:0:
include/linux/compiler-gcc.h:130:25: error: expected declaration specifiers before '__attribute__'
#define __printf(a, b) __attribute__((format(printf, a, b)))
^
include/linux/kernel.h:284:1: note: in expansion of macro '__printf'
__printf(1, 2)
^~~~~~~~
In file included from include/asm-generic/bug.h:18:0,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/kernel.h:287:13: error: storage class specified for parameter 'oops_enter'
extern void oops_enter(void);
^~~~~~~~~~
include/linux/kernel.h:288:13: error: storage class specified for parameter 'oops_exit'
extern void oops_exit(void);
^~~~~~~~~
include/linux/kernel.h:290:12: error: storage class specified for parameter 'oops_may_print'
extern int oops_may_print(void);
^~~~~~~~~~~~~~
include/linux/kernel.h:325:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:354:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:370:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:375:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:380:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:385:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{
^
include/linux/kernel.h:393:44: error: unknown type name 'bool'; did you mean '_Bool'?
int __must_check kstrtobool(const char *s, bool *res);
^~~~
_Bool
include/linux/kernel.h:395:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res);
^~~~~~
include/linux/kernel.h:396:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res);
^~~~~~
include/linux/kernel.h:397:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoul_from_user(const char __user *s, size_t count, unsigned int base, unsigned long *res);
^~~~~~
include/linux/kernel.h:398:58: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtol_from_user(const char __user *s, size_t count, unsigned int base, long *res);
^~~~~~
include/linux/kernel.h:399:61: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, unsigned int *res);
^~~~~~
include/linux/kernel.h:400:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, int *res);
^~~~~~
include/linux/kernel.h:401:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtou16_from_user(const char __user *s, size_t count, unsigned int base, u16 *res);
^~~~~~
include/linux/kernel.h:402:60: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res);
^~~~~~
include/linux/kernel.h:403:59: error: expected declaration specifiers or '...' before 'size_t'
int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res);
^~~~~~
--
include/linux/kernel.h:460:12: error: declaration for parameter 'get_option' but no such parameter
extern int get_option(char **str, int *pint);
^~~~~~~~~~
include/linux/kernel.h:456:5: error: declaration for parameter 'sscanf' but no such parameter
int sscanf(const char *, const char *, ...);
^~~~~~
include/linux/kernel.h:438:27: error: declaration for parameter 'sprintf' but no such parameter
extern __printf(2, 3) int sprintf(char *buf, const char * fmt, ...);
^~~~~~~
include/linux/kernel.h:434:12: error: declaration for parameter 'num_to_str' but no such parameter
extern int num_to_str(char *buf, int size, unsigned long long num);
^~~~~~~~~~
include/linux/kernel.h:432:18: error: declaration for parameter 'simple_strtoll' but no such parameter
extern long long simple_strtoll(const char *,char **,unsigned int);
^~~~~~~~~~~~~~
include/linux/kernel.h:431:27: error: declaration for parameter 'simple_strtoull' but no such parameter
extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
^~~~~~~~~~~~~~~
include/linux/kernel.h:430:13: error: declaration for parameter 'simple_strtol' but no such parameter
extern long simple_strtol(const char *,char **,unsigned int);
^~~~~~~~~~~~~
include/linux/kernel.h:429:22: error: declaration for parameter 'simple_strtoul' but no such parameter
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
^~~~~~~~~~~~~~
include/linux/kernel.h:392:18: error: declaration for parameter 'kstrtos8' but no such parameter
int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
^~~~~~~~
include/linux/kernel.h:391:18: error: declaration for parameter 'kstrtou8' but no such parameter
int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
^~~~~~~~
include/linux/kernel.h:390:18: error: declaration for parameter 'kstrtos16' but no such parameter
int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
^~~~~~~~~
include/linux/kernel.h:389:18: error: declaration for parameter 'kstrtou16' but no such parameter
int __must_check kstrtou16(const char *s, unsigned int base, u16 *res);
^~~~~~~~~
include/linux/kernel.h:367:18: error: declaration for parameter 'kstrtoint' but no such parameter
int __must_check kstrtoint(const char *s, unsigned int base, int *res);
^~~~~~~~~
include/linux/kernel.h:366:18: error: declaration for parameter 'kstrtouint' but no such parameter
int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res);
^~~~~~~~~~
include/linux/kernel.h:306:18: error: declaration for parameter 'kstrtoll' but no such parameter
int __must_check kstrtoll(const char *s, unsigned int base, long long *res);
^~~~~~~~
include/linux/kernel.h:305:18: error: declaration for parameter 'kstrtoull' but no such parameter
int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res);
^~~~~~~~~
include/linux/kernel.h:303:18: error: declaration for parameter '_kstrtol' but no such parameter
int __must_check _kstrtol(const char *s, unsigned int base, long *res);
^~~~~~~~
include/linux/kernel.h:302:18: error: declaration for parameter '_kstrtoul' but no such parameter
int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res);
^~~~~~~~~
include/linux/kernel.h:295:6: error: declaration for parameter 'refcount_error_report' but no such parameter
void refcount_error_report(struct pt_regs *regs, const char *err);
^~~~~~~~~~~~~~~~~~~~~
include/linux/kernel.h:292:6: error: declaration for parameter 'complete_and_exit' but no such parameter
void complete_and_exit(struct completion *, long) __noreturn;
^~~~~~~~~~~~~~~~~
include/linux/kernel.h:291:6: error: declaration for parameter 'do_exit' but no such parameter
void do_exit(long error_code) __noreturn;
^~~~~~~
include/linux/kernel.h:290:12: error: declaration for parameter 'oops_may_print' but no such parameter
extern int oops_may_print(void);
^~~~~~~~~~~~~~
include/linux/kernel.h:289:6: error: declaration for parameter 'print_oops_end_marker' but no such parameter
void print_oops_end_marker(void);
^~~~~~~~~~~~~~~~~~~~~
include/linux/kernel.h:288:13: error: declaration for parameter 'oops_exit' but no such parameter
extern void oops_exit(void);
^~~~~~~~~
include/linux/kernel.h:287:13: error: declaration for parameter 'oops_enter' but no such parameter
extern void oops_enter(void);
^~~~~~~~~~
include/linux/kernel.h:286:6: error: declaration for parameter 'nmi_panic' but no such parameter
void nmi_panic(struct pt_regs *regs, const char *msg);
^~~~~~~~~
include/linux/kernel.h:283:15: error: declaration for parameter 'panic_blink' but no such parameter
extern long (*panic_blink)(int state);
^~~~~~~~~~~
include/linux/kernel.h:282:36: error: parameter 'panic_notifier_list' has incomplete type
extern struct atomic_notifier_head panic_notifier_list;
^~~~~~~~~~~~~~~~~~~
include/linux/kernel.h:282:36: error: declaration for parameter 'panic_notifier_list' but no such parameter
include/linux/kernel.h:277:6: error: declaration for parameter '__might_fault' but no such parameter
void __might_fault(const char *file, int line);
^~~~~~~~~~~~~
include/linux/kernel.h:216:8: error: declaration for parameter '__might_sleep' but no such parameter
void __might_sleep(const char *file, int line, int preempt_offset);
^~~~~~~~~~~~~
include/linux/kernel.h:215:8: error: declaration for parameter '___might_sleep' but no such parameter
void ___might_sleep(const char *file, int line, int preempt_offset);
^~~~~~~~~~~~~~
In file included from include/linux/kernel.h:16:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
>> include/linux/build_bug.h:23:12: error: declaration for parameter '__build_bug_on_zero' but no such parameter
extern int __build_bug_on_zero(void)
^~~~~~~~~~~~~~~~~~~
In file included from include/linux/kernel.h:15:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/printk.h:474:37: error: parameter 'kmsg_fops' has incomplete type
extern const struct file_operations kmsg_fops;
^~~~~~~~~
include/linux/printk.h:474:37: error: declaration for parameter 'kmsg_fops' but no such parameter
include/linux/printk.h:282:17: error: declaration for parameter 'dump_stack' but no such parameter
asmlinkage void dump_stack(void) __cold;
^~~~~~~~~~
include/linux/printk.h:280:12: error: declaration for parameter 'kptr_restrict' but no such parameter
extern int kptr_restrict;
^~~~~~~~~~~~~
include/linux/printk.h:206:13: error: declaration for parameter 'printk_safe_flush_on_panic' but no such parameter
extern void printk_safe_flush_on_panic(void);
^~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:205:13: error: declaration for parameter 'printk_safe_flush' but no such parameter
extern void printk_safe_flush(void);
^~~~~~~~~~~~~~~~~
include/linux/printk.h:204:13: error: declaration for parameter 'printk_safe_init' but no such parameter
extern void printk_safe_init(void);
^~~~~~~~~~~~~~~~
include/linux/printk.h:203:6: error: declaration for parameter 'show_regs_print_info' but no such parameter
void show_regs_print_info(const char *log_lvl);
^~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:202:6: error: declaration for parameter 'dump_stack_print_info' but no such parameter
void dump_stack_print_info(const char *log_lvl);
^~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:200:13: error: declaration for parameter 'setup_log_buf' but no such parameter
void __init setup_log_buf(int early);
^~~~~~~~~~~~~
include/linux/printk.h:199:6: error: declaration for parameter 'log_buf_vmcoreinfo_setup' but no such parameter
void log_buf_vmcoreinfo_setup(void);
^~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:198:5: error: declaration for parameter 'log_buf_len_get' but no such parameter
u32 log_buf_len_get(void);
^~~~~~~~~~~~~~~
include/linux/printk.h:197:7: error: declaration for parameter 'log_buf_addr_get' but no such parameter
char *log_buf_addr_get(void);
^~~~~~~~~~~~~~~~
include/linux/printk.h:195:13: error: declaration for parameter 'wake_up_klogd' but no such parameter
extern void wake_up_klogd(void);
^~~~~~~~~~~~~
include/linux/printk.h:189:12: error: declaration for parameter 'dmesg_restrict' but no such parameter
extern int dmesg_restrict;
^~~~~~~~~~~~~~
include/linux/printk.h:188:12: error: declaration for parameter 'printk_delay_msec' but no such parameter
extern int printk_delay_msec;
^~~~~~~~~~~~~~~~~
include/linux/printk.h:185:13: error: declaration for parameter 'printk_timed_ratelimit' but no such parameter
extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
^~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:183:12: error: declaration for parameter '__printk_ratelimit' but no such parameter
extern int __printk_ratelimit(const char *func);
^~~~~~~~~~~~~~~~~~
include/linux/printk.h:150:13: error: declaration for parameter 'printk_nmi_exit' but no such parameter
extern void printk_nmi_exit(void);
^~~~~~~~~~~~~~~
include/linux/printk.h:149:13: error: declaration for parameter 'printk_nmi_enter' but no such parameter
extern void printk_nmi_enter(void);
^~~~~~~~~~~~~~~~
include/linux/printk.h:83:13: error: declaration for parameter 'devkmsg_log_str' but no such parameter
extern char devkmsg_log_str[];
^~~~~~~~~~~~~~~
include/linux/printk.h:63:12: error: declaration for parameter 'console_printk' but no such parameter
extern int console_printk[];
^~~~~~~~~~~~~~
include/linux/printk.h:12:19: error: declaration for parameter 'linux_proc_banner' but no such parameter
extern const char linux_proc_banner[];
^~~~~~~~~~~~~~~~~
include/linux/printk.h:11:19: error: declaration for parameter 'linux_banner' but no such parameter
extern const char linux_banner[];
^~~~~~~~~~~~
In file included from include/linux/printk.h:6:0,
from include/linux/kernel.h:15,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from include/linux/page-flags.h:10,
from kernel/bounds.c:10:
include/linux/init.h:269:13: error: declaration for parameter 'parse_early_options' but no such parameter
void __init parse_early_options(char *cmdline);
^~~~~~~~~~~~~~~~~~~
include/linux/init.h:268:13: error: declaration for parameter 'parse_early_param' but no such parameter
void __init parse_early_param(void);
^~~~~~~~~~~~~~~~~
include/linux/init.h:146:13: error: declaration for parameter 'initcall_debug' but no such parameter
extern bool initcall_debug;
^~~~~~~~~~~~~~
include/linux/init.h:144:15: error: declaration for parameter 'late_time_init' but no such parameter
extern void (*late_time_init)(void);
^~~~~~~~~~~~~~
include/linux/init.h:141:6: error: declaration for parameter 'mark_rodata_ro' but no such parameter
void mark_rodata_ro(void);
^~~~~~~~~~~~~~
vim +/__build_bug_on_zero +23 include/linux/build_bug.h
bc6245e5 Ian Abbott 2017-07-10 16
bc6245e5 Ian Abbott 2017-07-10 17 /* Force a compilation error if a constant expression is not a power of 2 */
bc6245e5 Ian Abbott 2017-07-10 18 #define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \
bc6245e5 Ian Abbott 2017-07-10 19 BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
bc6245e5 Ian Abbott 2017-07-10 20 #define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
bc6245e5 Ian Abbott 2017-07-10 21 BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
bc6245e5 Ian Abbott 2017-07-10 22
73492728 David Howells 2018-04-01 @23 extern int __build_bug_on_zero(void)
73492728 David Howells 2018-04-01 @24 __compiletime_error("Build bug on zero");
73492728 David Howells 2018-04-01 25
:::::: The code at line 23 was first introduced by commit
:::::: 73492728261d8868947821e21053d51d2a2c1d3f C++: Fix BUILD_BUG_ON_ZERO()
:::::: TO: David Howells <[email protected]>
:::::: CC: 0day robot <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: i386-randconfig-x073-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
CONFIG_CC_STACKPROTECTOR_AUTO: Compiler does not support any known stack-protector
>> cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
>> cc1: warning: command line option '-fpermissive' is valid for C++/ObjC++ but not for C
>> cc1: error: CPU you selected does not support x86-64 instruction set
make[2]: *** [kernel/bounds.s] Error 1
make[2]: Target '__build' not remade because of errors.
make[1]: *** [prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-x014-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
scripts/Makefile.kasan:17: Cannot use CONFIG_KASAN: -fsanitize=kernel-address is not supported by compiler
cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
cc1: warning: command line option '-fpermissive' is valid for C++/ObjC++ but not for C
In file included from include/linux/page-flags.h:9:0,
from kernel/bounds.c:10:
>> include/linux/types.h:6:2: error: #error not c++
#error not c++
^~~~~
make[2]: *** [kernel/bounds.s] Error 1
make[2]: Target '__build' not remade because of errors.
make[1]: *** [prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
vim +6 include/linux/types.h
4
5 #ifndef __cplusplus
> 6 #error not c++
7 #endif
8
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-x016-201813 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
Note: the linux-review/David-Howells/C-Convert-the-kernel-to-C/20180402-120344 HEAD 6389202e6d769ba42860793ff4bb839d768ced5a builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
include/asm-generic/bitops/le.h: In function 'int test_and_clear_bit_le(int, void*)':
include/asm-generic/bitops/le.h:85:55: error: invalid conversion from 'void*' to 'volatile long unsigned int*' [-fpermissive]
return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
^
In file included from include/linux/bitops.h:38:0,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
arch/x86/include/asm/bitops.h:265:29: note: initializing argument 2 of 'bool test_and_clear_bit(long int, volatile long unsigned int*)'
static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr)
^~~~~~~~~~~~~~~~~~
In file included from arch/x86/include/asm/bitops.h:521:0,
from include/linux/bitops.h:38,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
include/asm-generic/bitops/le.h: In function 'int __test_and_set_bit_le(int, void*)':
include/asm-generic/bitops/le.h:90:55: error: invalid conversion from 'void*' to 'volatile long unsigned int*' [-fpermissive]
return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
^
In file included from include/linux/bitops.h:38:0,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
arch/x86/include/asm/bitops.h:246:29: note: initializing argument 2 of 'bool __test_and_set_bit(long int, volatile long unsigned int*)'
static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *addr)
^~~~~~~~~~~~~~~~~~
In file included from arch/x86/include/asm/bitops.h:521:0,
from include/linux/bitops.h:38,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
include/asm-generic/bitops/le.h: In function 'int __test_and_clear_bit_le(int, void*)':
include/asm-generic/bitops/le.h:95:57: error: invalid conversion from 'void*' to 'volatile long unsigned int*' [-fpermissive]
return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
^
In file included from include/linux/bitops.h:38:0,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
arch/x86/include/asm/bitops.h:287:29: note: initializing argument 2 of 'bool __test_and_clear_bit(long int, volatile long unsigned int*)'
static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned long *addr)
^~~~~~~~~~~~~~~~~~~~
In file included from include/linux/kernel.h:7:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
include/linux/printk.h: At global scope:
include/linux/linkage.h:16:31: error: expected unqualified-id before string constant
#define CPP_ASMLINKAGE extern "C"
^
include/linux/linkage.h:22:20: note: in expansion of macro 'CPP_ASMLINKAGE'
#define asmlinkage CPP_ASMLINKAGE
^~~~~~~~~~~~~~
include/linux/printk.h:141:8: note: in expansion of macro 'asmlinkage'
extern asmlinkage __printf(1, 2)
^~~~~~~~~~
include/linux/linkage.h:16:31: error: expected unqualified-id before string constant
#define CPP_ASMLINKAGE extern "C"
^
include/linux/linkage.h:22:20: note: in expansion of macro 'CPP_ASMLINKAGE'
#define asmlinkage CPP_ASMLINKAGE
^~~~~~~~~~~~~~
include/linux/printk.h:282:8: note: in expansion of macro 'asmlinkage'
extern asmlinkage void dump_stack(void) __cold;
^~~~~~~~~~
In file included from include/linux/kernel.h:16:0,
from include/asm-generic/bug.h:18,
from arch/x86/include/asm/bug.h:83,
from include/linux/bug.h:5,
from arch/x86/purgatory/purgatory.c:13:
arch/x86/purgatory/purgatory.c: In function 'int verify_sha256_digest()':
include/linux/build_bug.h:29:45: error: types may not be defined in 'sizeof' expressions
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
^
include/linux/compiler-gcc.h:66:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__is_array(a))
^~~~~~~~~~~~~~~~~
include/linux/kernel.h:72:59: note: in expansion of macro '__must_be_array'
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
^~~~~~~~~~~~~~~
arch/x86/purgatory/purgatory.c:48:32: note: in expansion of macro 'ARRAY_SIZE'
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
^~~~~~~~~~
>> include/linux/build_bug.h:29:58: error: negative width in bit-field 'verify_sha256_digest()::<unnamed struct>::<anonymous>'
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
^
include/linux/compiler-gcc.h:66:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__is_array(a))
^~~~~~~~~~~~~~~~~
include/linux/kernel.h:72:59: note: in expansion of macro '__must_be_array'
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
^~~~~~~~~~~~~~~
arch/x86/purgatory/purgatory.c:48:32: note: in expansion of macro 'ARRAY_SIZE'
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
^~~~~~~~~~
make[2]: *** [arch/x86/purgatory/purgatory.o] Error 1
make[2]: *** [arch/x86/purgatory/sha256.o] Error 1
make[2]: Target 'arch/x86/purgatory/kexec-purgatory.c' not remade because of errors.
make[1]: *** [archprepare] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
vim +29 include/linux/build_bug.h
bc6245e5 Ian Abbott 2017-07-10 16
bc6245e5 Ian Abbott 2017-07-10 17 /* Force a compilation error if a constant expression is not a power of 2 */
bc6245e5 Ian Abbott 2017-07-10 18 #define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \
bc6245e5 Ian Abbott 2017-07-10 19 BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
bc6245e5 Ian Abbott 2017-07-10 20 #define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
bc6245e5 Ian Abbott 2017-07-10 21 BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
bc6245e5 Ian Abbott 2017-07-10 22
bc6245e5 Ian Abbott 2017-07-10 23 /*
bc6245e5 Ian Abbott 2017-07-10 24 * Force a compilation error if condition is true, but also produce a
bc6245e5 Ian Abbott 2017-07-10 25 * result (of value 0 and type size_t), so the expression can be used
bc6245e5 Ian Abbott 2017-07-10 26 * e.g. in a structure initializer (or where-ever else comma expressions
bc6245e5 Ian Abbott 2017-07-10 27 * aren't permitted).
bc6245e5 Ian Abbott 2017-07-10 28 */
bc6245e5 Ian Abbott 2017-07-10 @29 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
bc6245e5 Ian Abbott 2017-07-10 30
:::::: The code at line 29 was first introduced by commit
:::::: bc6245e5efd70c41eaf9334b1b5e646745cb0fb3 bug: split BUILD_BUG stuff out into <linux/build_bug.h>
:::::: TO: Ian Abbott <[email protected]>
:::::: CC: Linus Torvalds <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: x86_64-randconfig-a0-04021307 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:230:41: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline void atomic64_and(long i, atomic64_t *v)
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:238:47: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long atomic64_fetch_and(long i, atomic64_t *v)
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:247:40: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline void atomic64_or(long i, atomic64_t *v)
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:255:46: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long atomic64_fetch_or(long i, atomic64_t *v)
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:264:41: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline void atomic64_xor(long i, atomic64_t *v)
^~~~~~~~~~
arch/x86/include/asm/atomic64_64.h:272:47: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long atomic64_fetch_xor(long i, atomic64_t *v)
^~~~~~~~~~
In file included from include/linux/debug_locks.h:6:0,
from include/linux/lockdep.h:28,
from include/linux/spinlock_types.h:18,
from kernel/bounds.c:14:
include/linux/atomic.h:531:37: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_add_unless(atomic_t *v, int a, int u)
^~~~~~~~
include/linux/atomic.h:548:41: error: expected declaration specifiers or '...' before 'atomic_t'
static inline void atomic_andnot(int i, atomic_t *v)
^~~~~~~~
include/linux/atomic.h:553:46: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_fetch_andnot(int i, atomic_t *v)
^~~~~~~~
include/linux/atomic.h:558:54: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_fetch_andnot_relaxed(int i, atomic_t *v)
^~~~~~~~
include/linux/atomic.h:563:54: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_fetch_andnot_acquire(int i, atomic_t *v)
^~~~~~~~
include/linux/atomic.h:568:54: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_fetch_andnot_release(int i, atomic_t *v)
^~~~~~~~
include/linux/atomic.h:587:44: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
^~~~~~~~
include/linux/atomic.h:607:46: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_inc_unless_negative(atomic_t *p)
^~~~~~~~
include/linux/atomic.h:620:46: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_dec_unless_positive(atomic_t *p)
^~~~~~~~
include/linux/atomic.h:640:42: error: expected declaration specifiers or '...' before 'atomic_t'
static inline int atomic_dec_if_positive(atomic_t *v)
^~~~~~~~
include/linux/atomic.h:1052:49: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline void atomic64_andnot(long long i, atomic64_t *v)
^~~~~~~~~~
include/linux/atomic.h:1057:60: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long long atomic64_fetch_andnot(long long i, atomic64_t *v)
^~~~~~~~~~
include/linux/atomic.h:1062:68: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long long atomic64_fetch_andnot_relaxed(long long i, atomic64_t *v)
^~~~~~~~~~
include/linux/atomic.h:1067:68: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long long atomic64_fetch_andnot_acquire(long long i, atomic64_t *v)
^~~~~~~~~~
include/linux/atomic.h:1072:68: error: expected declaration specifiers or '...' before 'atomic64_t'
static inline long long atomic64_fetch_andnot_release(long long i, atomic64_t *v)
^~~~~~~~~~
In file included from include/linux/atomic.h:1080:0,
from include/linux/debug_locks.h:6,
from include/linux/lockdep.h:28,
from include/linux/spinlock_types.h:18,
from kernel/bounds.c:14:
include/asm-generic/atomic-long.h:24:20: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'atomic_long_t'
typedef atomic64_t atomic_long_t;
^~~~~~~~~~~~~
include/asm-generic/atomic-long.h:39:47: error: unknown type name 'atomic_long_t'
static inline long atomic_long_read##mo(const atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:45:1: note: in expansion of macro 'ATOMIC_LONG_READ_OP'
ATOMIC_LONG_READ_OP()
^~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:40:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{ \
^
include/asm-generic/atomic-long.h:45:1: note: in expansion of macro 'ATOMIC_LONG_READ_OP'
ATOMIC_LONG_READ_OP()
^~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:39:47: error: unknown type name 'atomic_long_t'
static inline long atomic_long_read##mo(const atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:46:1: note: in expansion of macro 'ATOMIC_LONG_READ_OP'
ATOMIC_LONG_READ_OP(_acquire)
^~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:40:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
{ \
^
include/asm-generic/atomic-long.h:46:1: note: in expansion of macro 'ATOMIC_LONG_READ_OP'
ATOMIC_LONG_READ_OP(_acquire)
^~~~~~~~~~~~~~~~~~~
>> include/asm-generic/atomic-long.h:51:40: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
static inline void atomic_long_set##mo(atomic_long_t *l, long i) \
^
include/asm-generic/atomic-long.h:57:1: note: in expansion of macro 'ATOMIC_LONG_SET_OP'
ATOMIC_LONG_SET_OP()
^~~~~~~~~~~~~~~~~~
>> include/asm-generic/atomic-long.h:51:40: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
static inline void atomic_long_set##mo(atomic_long_t *l, long i) \
^
include/asm-generic/atomic-long.h:58:1: note: in expansion of macro 'ATOMIC_LONG_SET_OP'
ATOMIC_LONG_SET_OP(_release)
^~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:70:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(add,)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:71:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(add, _relaxed)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:72:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(add, _acquire)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:73:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(add, _release)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:74:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(sub,)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:75:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(sub, _relaxed)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:76:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(sub, _acquire)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:64:39: error: unknown type name 'atomic_long_t'; did you mean 'atomic_fetch_inc'?
atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:77:1: note: in expansion of macro 'ATOMIC_LONG_ADD_SUB_OP'
ATOMIC_LONG_ADD_SUB_OP(sub, _release)
^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:102:45: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
static __always_inline void atomic_long_inc(atomic_long_t *l)
^~~~~~~~~~~~~
atomic_long_xchg
include/asm-generic/atomic-long.h:109:45: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
static __always_inline void atomic_long_dec(atomic_long_t *l)
^~~~~~~~~~~~~
atomic_long_xchg
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:125:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(add, )
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:126:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(add, _relaxed)
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:127:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(add, _acquire)
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:128:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(add, _release)
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:129:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(sub, )
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
include/asm-generic/atomic-long.h:130:1: note: in expansion of macro 'ATOMIC_LONG_FETCH_OP'
ATOMIC_LONG_FETCH_OP(sub, _relaxed)
^~~~~~~~~~~~~~~~~~~~
include/asm-generic/atomic-long.h:118:36: error: unknown type name 'atomic_long_t'; did you mean 'atomic_long_xchg'?
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
^
vim +51 include/asm-generic/atomic-long.h
586b610e4 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 37
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 38 #define ATOMIC_LONG_READ_OP(mo) \
e3e72ab80 include/asm-generic/atomic-long.h Peter Zijlstra 2015-09-18 39 static inline long atomic_long_read##mo(const atomic_long_t *l) \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 40 { \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 41 ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 42 \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 43 return (long)ATOMIC_LONG_PFX(_read##mo)(v); \
d3cb48714 include/asm-generic/atomic.h Christoph Lameter 2006-01-06 44 }
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 45 ATOMIC_LONG_READ_OP()
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 @46 ATOMIC_LONG_READ_OP(_acquire)
d3cb48714 include/asm-generic/atomic.h Christoph Lameter 2006-01-06 47
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 48 #undef ATOMIC_LONG_READ_OP
d3cb48714 include/asm-generic/atomic.h Christoph Lameter 2006-01-06 49
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 50 #define ATOMIC_LONG_SET_OP(mo) \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 @51 static inline void atomic_long_set##mo(atomic_long_t *l, long i) \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 52 { \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 53 ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 54 \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 55 ATOMIC_LONG_PFX(_set##mo)(v, i); \
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 56 }
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 57 ATOMIC_LONG_SET_OP()
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 58 ATOMIC_LONG_SET_OP(_release)
6d79ef2d3 include/asm-generic/atomic-long.h Will Deacon 2015-08-06 59
:::::: The code at line 51 was first introduced by commit
:::::: 6d79ef2d30ee5af7315535d1e7bf6fce0008f815 locking, asm-generic: Add _{relaxed|acquire|release}() variants for 'atomic_long_t'
:::::: TO: Will Deacon <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Perhaps something to improve:
[auto build test WARNING on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
reproduce: make htmldocs
All warnings (new ones prefixed by >>):
WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org)
include/linux/kernel.h:251: warning: cannot understand function prototype: 'template<typename T> static inline T abs(T v) '
include/linux/kernel.h:251: warning: cannot understand function prototype: 'template<typename T> static inline T abs(T v) '
arch/x86/include/asm/uaccess.h:177: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int get_user(VAL &x, TYPE '
arch/x86/include/asm/uaccess.h:219: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int put_user(VAL x, TYPE '
arch/x86/include/asm/uaccess.h:315: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int __get_user_unsafe_nozero(VAL &x, const TYPE int err=-EFAULT) '
arch/x86/include/asm/uaccess.h:366: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int __get_user_unsafe(VAL &x, const TYPE int err=-EFAULT) '
arch/x86/include/asm/uaccess.h:438: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int __get_user(VAL &x, const TYPE '
arch/x86/include/asm/uaccess.h:452: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int __put_user_unsafe(VAL x, TYPE int err=-EFAULT) '
arch/x86/include/asm/uaccess.h:521: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline int __put_user(VAL x, TYPE int err=-EFAULT) '
arch/x86/include/asm/uaccess.h:540: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline void get_user_ex(VAL &x, const TYPE '
arch/x86/include/asm/uaccess.h:587: warning: cannot understand function prototype: 'template <typename VAL, typename TYPE> static inline void put_user_ex(VAL x, TYPE '
include/linux/rcupdate.h:424: warning: cannot understand function prototype: 'template <typename T> static inline void rcu_assign_pointer(T T '
include/linux/rcupdate.h:503: warning: cannot understand function prototype: 'template <typename T> T bool c) '
include/linux/rcupdate.h:844: warning: cannot understand function prototype: 'template <typename T> static inline void RCU_INIT_POINTER(T T '
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:477: warning: Function parameter or member 'cra_u.ablkcipher' not described in 'crypto_alg'
include/linux/crypto.h:477: warning: Function parameter or member 'cra_u.blkcipher' not described in 'crypto_alg'
include/linux/crypto.h:477: warning: Function parameter or member 'cra_u.cipher' not described in 'crypto_alg'
include/linux/crypto.h:477: warning: Function parameter or member 'cra_u.compress' not described in 'crypto_alg'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
>> include/linux/crypto.h:1038: warning: Function parameter or member 'c' not described in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/linux/crypto.h:1038: warning: Excess function parameter 'compl' description in 'ablkcipher_request_set_callback'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.ibss' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.connect' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.keys' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.ie' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.ie_len' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.bssid' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.prev_bssid' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.ssid' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.default_key' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.default_mgmt_key' not described in 'wireless_dev'
include/net/cfg80211.h:4129: warning: Function parameter or member 'wext.prev_bssid_valid' not described in 'wireless_dev'
include/net/mac80211.h:2263: warning: Function parameter or member 'radiotap_timestamp.units_pos' not described in 'ieee80211_hw'
include/net/mac80211.h:2263: warning: Function parameter or member 'radiotap_timestamp.accuracy' not described in 'ieee80211_hw'
include/net/mac80211.h:950: warning: Function parameter or member 'rates' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.rts_cts_rate_idx' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.use_rts' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.use_cts_prot' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.short_preamble' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.skip_table' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.jiffies' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.vif' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.hw_key' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.flags' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'control.enqueue_time' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'ack' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'ack.cookie' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.rates' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.ack_signal' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.ampdu_ack_len' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.ampdu_len' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.antenna' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status.tx_time' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'status_driver_data' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'driver_rates' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'pad' not described in 'ieee80211_tx_info'
include/net/mac80211.h:950: warning: Function parameter or member 'rate_driver_data' not described in 'ieee80211_tx_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'rx_stats_avg' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'rx_stats_avg.signal' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'rx_stats_avg.chain_signal' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.filtered' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.retry_failed' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.retry_count' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.lost_packets' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.last_tdls_pkt_time' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'msdu_retries' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'msdu_failed' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'status_stats.last_ack' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'tx_stats.packets' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'tx_stats.bytes' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'tx_stats.last_rate' not described in 'sta_info'
net/mac80211/sta_info.h:584: warning: Function parameter or member 'msdu' not described in 'sta_info'
include/linux/kernel.h:252: warning: cannot understand function prototype: 'template<typename T> static inline T abs(T v) '
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_excl.cb' not described in 'dma_buf'
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_excl.poll' not described in 'dma_buf'
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_excl.active' not described in 'dma_buf'
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_shared.cb' not described in 'dma_buf'
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_shared.poll' not described in 'dma_buf'
include/linux/dma-buf.h:307: warning: Function parameter or member 'cb_shared.active' not described in 'dma_buf'
include/linux/dma-fence-array.h:54: warning: Function parameter or member 'work' not described in 'dma_fence_array'
include/linux/gpio/driver.h:142: warning: Function parameter or member 'request_key' not described in 'gpio_irq_chip'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.sign' not described in 'iio_chan_spec'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.realbits' not described in 'iio_chan_spec'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.storagebits' not described in 'iio_chan_spec'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.shift' not described in 'iio_chan_spec'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.repeat' not described in 'iio_chan_spec'
include/linux/iio/iio.h:270: warning: Function parameter or member 'scan_type.endianness' not described in 'iio_chan_spec'
include/linux/iio/hw-consumer.h:1: warning: no structured comments found
include/linux/device.h:294: warning: Function parameter or member 'coredump' not described in 'device_driver'
include/linux/input/sparse-keymap.h:46: warning: Function parameter or member 'sw' not described in 'key_entry'
include/linux/mtd/rawnand.h:709: warning: Function parameter or member 'timings.sdr' not described in 'nand_data_interface'
include/linux/mtd/rawnand.h:774: warning: Function parameter or member 'buf' not described in 'nand_op_data_instr'
include/linux/mtd/rawnand.h:774: warning: Function parameter or member 'buf.in' not described in 'nand_op_data_instr'
include/linux/mtd/rawnand.h:774: warning: Function parameter or member 'buf.out' not described in 'nand_op_data_instr'
include/linux/mtd/rawnand.h:820: warning: Function parameter or member 'ctx' not described in 'nand_op_instr'
include/linux/mtd/rawnand.h:820: warning: Function parameter or member 'ctx.cmd' not described in 'nand_op_instr'
include/linux/mtd/rawnand.h:820: warning: Function parameter or member 'ctx.addr' not described in 'nand_op_instr'
include/linux/mtd/rawnand.h:820: warning: Function parameter or member 'ctx.data' not described in 'nand_op_instr'
include/linux/mtd/rawnand.h:820: warning: Function parameter or member 'ctx.waitrdy' not described in 'nand_op_instr'
include/linux/mtd/rawnand.h:967: warning: Function parameter or member 'ctx' not described in 'nand_op_parser_pattern_elem'
include/linux/mtd/rawnand.h:967: warning: Function parameter or member 'ctx.addr' not described in 'nand_op_parser_pattern_elem'
include/linux/mtd/rawnand.h:967: warning: Function parameter or member 'ctx.data' not described in 'nand_op_parser_pattern_elem'
include/linux/mtd/rawnand.h:1281: warning: Function parameter or member 'manufacturer.desc' not described in 'nand_chip'
include/linux/mtd/rawnand.h:1281: warning: Function parameter or member 'manufacturer.priv' not described in 'nand_chip'
include/linux/regulator/driver.h:221: warning: Function parameter or member 'resume_early' not described in 'regulator_ops'
drivers/regulator/core.c:4299: warning: Excess function parameter 'state' description in 'regulator_suspend_late'
arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw0' not described in 'irb'
arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw1' not described in 'irb'
arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw2' not described in 'irb'
arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.esw3' not described in 'irb'
arch/s390/include/asm/cio.h:245: warning: Function parameter or member 'esw.eadm' not described in 'irb'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_pin' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_unpin' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_res_obj' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_get_sg_table' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_import_sg_table' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_vmap' not described in 'drm_driver'
include/drm/drm_drv.h:610: warning: Function parameter or member 'gem_prime_vunmap' not described in 'drm_driver'
vim +1038 include/linux/crypto.h
32e3983f Herbert Xu 2007-03-24 1009
f13ec330 Stephan Mueller 2014-11-12 1010 /**
f13ec330 Stephan Mueller 2014-11-12 1011 * ablkcipher_request_set_callback() - set asynchronous callback function
f13ec330 Stephan Mueller 2014-11-12 1012 * @req: request handle
f13ec330 Stephan Mueller 2014-11-12 1013 * @flags: specify zero or an ORing of the flags
f13ec330 Stephan Mueller 2014-11-12 1014 * CRYPTO_TFM_REQ_MAY_BACKLOG the request queue may back log and
f13ec330 Stephan Mueller 2014-11-12 1015 * increase the wait queue beyond the initial maximum size;
f13ec330 Stephan Mueller 2014-11-12 1016 * CRYPTO_TFM_REQ_MAY_SLEEP the request processing may sleep
f13ec330 Stephan Mueller 2014-11-12 1017 * @compl: callback function pointer to be registered with the request handle
f13ec330 Stephan Mueller 2014-11-12 1018 * @data: The data pointer refers to memory that is not used by the kernel
f13ec330 Stephan Mueller 2014-11-12 1019 * crypto API, but provided to the callback function for it to use. Here,
f13ec330 Stephan Mueller 2014-11-12 1020 * the caller can provide a reference to memory the callback function can
f13ec330 Stephan Mueller 2014-11-12 1021 * operate on. As the callback function is invoked asynchronously to the
f13ec330 Stephan Mueller 2014-11-12 1022 * related functionality, it may need to access data structures of the
f13ec330 Stephan Mueller 2014-11-12 1023 * related functionality which can be referenced using this pointer. The
f13ec330 Stephan Mueller 2014-11-12 1024 * callback function can access the memory via the "data" field in the
f13ec330 Stephan Mueller 2014-11-12 1025 * crypto_async_request data structure provided to the callback function.
f13ec330 Stephan Mueller 2014-11-12 1026 *
f13ec330 Stephan Mueller 2014-11-12 1027 * This function allows setting the callback function that is triggered once the
f13ec330 Stephan Mueller 2014-11-12 1028 * cipher operation completes.
f13ec330 Stephan Mueller 2014-11-12 1029 *
f13ec330 Stephan Mueller 2014-11-12 1030 * The callback function is registered with the ablkcipher_request handle and
0184cfe7 Stephan Mueller 2016-10-21 1031 * must comply with the following template::
f13ec330 Stephan Mueller 2014-11-12 1032 *
f13ec330 Stephan Mueller 2014-11-12 1033 * void callback_function(struct crypto_async_request *req, int error)
f13ec330 Stephan Mueller 2014-11-12 1034 */
32e3983f Herbert Xu 2007-03-24 1035 static inline void ablkcipher_request_set_callback(
32e3983f Herbert Xu 2007-03-24 1036 struct ablkcipher_request *req,
72e380ca David Howells 2018-04-01 1037 u32 flags, crypto_completion_t c, void *data)
32e3983f Herbert Xu 2007-03-24 @1038 {
72e380ca David Howells 2018-04-01 1039 req->base.complete = c;
32e3983f Herbert Xu 2007-03-24 1040 req->base.data = data;
32e3983f Herbert Xu 2007-03-24 1041 req->base.flags = flags;
32e3983f Herbert Xu 2007-03-24 1042 }
32e3983f Herbert Xu 2007-03-24 1043
:::::: The code at line 1038 was first introduced by commit
:::::: 32e3983fe590ac4cd70c7728eb330d43cef031a7 [CRYPTO] api: Add async block cipher interface
:::::: TO: Herbert Xu <[email protected]>
:::::: CC: Herbert Xu <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi David,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.16-rc7]
[cannot apply to linus/master tip/x86/core tip/locking/core v4.16 next-20180329]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/David-Howells/C-Convert-the-kernel-to-C/20180402-120344
config: um-x86_64_defconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=um SUBARCH=x86_64
All errors (new ones prefixed by >>):
cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
cc1: warning: command line option '-fpermissive' is valid for C++/ObjC++ but not for C
In file included from arch/x86/um/user-offsets.c:20:0:
arch/x86/include/generated/asm/syscalls_64.h:135:1: error: implicit declaration of function '__NO_SYSCALL_'; did you mean '__SYSCALL_64'? [-Werror=implicit-function-declaration]
__NO_SYSCALL_(134)
^~~~~~~~~~~~~
__SYSCALL_64
>> arch/x86/um/user-offsets.c:18:37: error: subscripted value is neither array nor pointer nor vector
#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
^
arch/x86/include/generated/asm/syscalls_64.h:136:1: note: in expansion of macro '__SYSCALL_64'
__SYSCALL_64(135, sys_personality, )
^~~~~~~~~~~~
>> arch/x86/um/user-offsets.c:18:37: error: subscripted value is neither array nor pointer nor vector
#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
^
arch/x86/include/generated/asm/syscalls_64.h:176:1: note: in expansion of macro '__SYSCALL_64'
__SYSCALL_64(175, sys_init_module, )
^~~~~~~~~~~~
In file included from arch/x86/um/user-offsets.c:20:0:
arch/x86/include/generated/asm/syscalls_64.h:178:1: error: initializer element is not constant
__NO_SYSCALL_(177)
^~~~~~~~~~~~~
arch/x86/include/generated/asm/syscalls_64.h:178:1: note: (near initialization for 'syscalls[177]')
arch/x86/include/generated/asm/syscalls_64.h:179:1: error: expected '}' before '__NO_SYSCALL_'
__NO_SYSCALL_(178)
^~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [arch/x86/um/user-offsets.s] Error 1
make[1]: *** [arch/x86/um/user-offsets.s] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
vim +18 arch/x86/um/user-offsets.c
8d0b9dc9 arch/um/sys-x86_64/user-offsets.c Al Viro 2005-05-05 11
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 12 #ifdef __i386__
cfcbadb4 arch/x86/um/user-offsets.c Andy Lutomirski 2016-01-28 13 #define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 14 static char syscalls[] = {
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 15 #include <asm/syscalls_32.h>
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 16 };
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 17 #else
cfcbadb4 arch/x86/um/user-offsets.c Andy Lutomirski 2016-01-28 @18 #define __SYSCALL_64(nr, sym, qual) [nr] = 1,
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 19 static char syscalls[] = {
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 @20 #include <asm/syscalls_64.h>
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 21 };
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 22 #endif
45db1c61 arch/x86/um/user-offsets.c H. Peter Anvin 2011-12-05 23
:::::: The code at line 18 was first introduced by commit
:::::: cfcbadb49dabb05efa23e1a0f95f3391c0a815bc x86/syscalls: Add syscall entry qualifiers
:::::: TO: Andy Lutomirski <[email protected]>
:::::: CC: Ingo Molnar <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On 1 April 2018 at 22:40, David Howells <[email protected]> wrote:
>
> Here are a series of patches to start converting the kernel to C++. It
> requires g++ v8.
Nice!
I tried something similar a few years ago, but I don't think it was
nearly as neat. I did get RTTI and exceptions to work (using libcxxrt
+ libunwind), though. Having noticed that a lot of really trivial
kernel bugs are due to control flow issues (e.g. when somebody adds a
possibly-failing step to a function but forget to add a new label to
clean it up) I really wanted to see how/whether exceptions and RAII
could help in that space.
Just in case you want to compare notes, I've pushed my branch to:
https://github.com/vegard/linux-2.6/tree/cxx
I also started a little bit of work on converting a driver to use
RAII, and quickly ran into a few problems: C++ destructors don't take
arguments, which means that some objects would have to carry extra
state around because some of the information needed to destroy an
object resides with somebody else. This means that you would have to
do more refactoring work to avoid needing this in the first place,
i.e. mapping creation/destructing of various C-style structs to C++ is
_not_ straightforward.
Take dma_alloc_coherent() for example. It pairs up with
dma_free_coherent() and that one needs to know the device and buffer
size that you passed too:
void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
This means that if you have 1 device using 2 buffers of the same size
and the size is stored only by the device struct, then you must always
do the destruction from the device struct, since the individual
buffers don't know their size (unless you move the member there; but
it feels like a waste of memory if you could do it just fine in C).
Maybe there's a "proper" way to do it that I didn't see, but problems
like this turned me off the whole approach a little.
Another real bummer is the size and complexity of the RTTI and
unwinding support code. First of all, unwinding requires parsing and
executing DWARF code on the fly, and that just makes everything very
slow. Not to mention that it needs to be threading-aware and does a
lot of memory allocations. IIRC handling out-of-memory conditions was
extremely ugly (not that the kernel is perfect in this respect to
start with) and involved the use of "reserve buffers". I didn't like
it at all.
Also, for reference, I found a few other projects doing similar things
in the past:
https://github.com/veltzer/kcpp
http://www.drdobbs.com/cpp/c-exceptions-the-linux-kernel/229100146
https://pograph.wordpress.com/2009/04/05/porting-cpp-code-to-linux-kernel/
https://www.threatstack.com/blog/c-in-the-linux-kernel/
There's probably more, I seem to remember at least 1 commercial
product using C++ for their out-of-tree module (albeit without
RTTI/exceptions), but I can't find it right now.
Vegard
kbuild test robot <[email protected]> wrote:
> scripts/Makefile.kasan:17: Cannot use CONFIG_KASAN: -fsanitize=kernel-address is not supported by compiler
> cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
> cc1: warning: command line option '-fpermissive' is valid for C++/ObjC++ but not for C
It would need to use g++-8 to compile it ;-)
David
On Tue, Apr 03, 2018 at 02:16:50PM +0100, David Howells wrote:
>kbuild test robot <[email protected]> wrote:
>
>> scripts/Makefile.kasan:17: Cannot use CONFIG_KASAN: -fsanitize=kernel-address is not supported by compiler
>> cc1: warning: command line option '-fno-rtti' is valid for C++/ObjC++ but not for C
>> cc1: warning: command line option '-fpermissive' is valid for C++/ObjC++ but not for C
>
>It would need to use g++-8 to compile it ;-)
Awesome! :)
Cheers,
Fengguang
Hi David Howells.
[This is an automated email]
This commit has been processed by the -stable helper bot and determined
to be a high probability candidate for -stable trees. (score: 5.5190)
The bot has tested the following trees: v4.15.15, v4.14.32, v4.9.92, v4.4.126,
v4.15.15: Build OK!
v4.14.32: Build OK!
v4.9.92: Build OK!
v4.4.126: Failed to apply! Possible dependencies:
2e9d1e150abf: ("x86/entry: Avoid interrupt flag save and restore")
Please let us know if you'd like to have this patch included in a stable tree.
--
Thanks.
Sasha
Hi Fengguang,
There's another kbuild test that's probably worth adding if you don't do it
already: create a c++ source file that just #includes all the exported UAPI
headers and then try to build it. This should catch words like "private"
cropping up in structs.
Thanks,
David
Hi David,
On Tue, Apr 10, 2018 at 09:44:14AM +0100, David Howells wrote:
>Hi Fengguang,
>
>There's another kbuild test that's probably worth adding if you don't do it
>already: create a c++ source file that just #includes all the exported UAPI
>headers and then try to build it. This should catch words like "private"
>cropping up in structs.
That's a good idea! And it looks straightforward to do.
CC Philip (current LKP maintainer) for possible plans.
Thanks,
Fengguang
>
> Hi David,
>
> On Tue, Apr 10, 2018 at 09:44:14AM +0100, David Howells wrote:
> >Hi Fengguang,
> >
> >There's another kbuild test that's probably worth adding if you don't do it
> >already: create a c++ source file that just #includes all the exported UAPI
> >headers and then try to build it. This should catch words like "private"
> >cropping up in structs.
>
> That's a good idea! And it looks straightforward to do.
> CC Philip (current LKP maintainer) for possible plans.
Thanks David, we will look into this and planned with other priorities.
We will share estimation for possible target date next week.
>
> Thanks,
> Fengguang
Hi all, I'm going to stir the hornet's nest and make what has become the
ultimate sacrilege.
Andrew Pinski recently made aware of this thread. I realize it was
released on April 1, 2018, and either was a joke or might have been
taken as one. However, I think there is validity to it, and I'm going to
try to motivate my opinion here.
Both C and C++ has had a lot of development since 1999, and C++ has in
fact, in my personal opinion, finally "grown up" to be a better C for
the kind of embedded programming that an OS kernel epitomizes. I'm
saying that as the author of a very large number of macro and inline
assembly hacks in the kernel.
What really makes me say that is that a lot of things we have recently
asked for gcc-specific extensions are in fact relatively easy to
implement in standard C++ and, in many cases, allows for infrastructure
improvement *without* global code changes (see below.)
C++14 is in my option the "minimum" version that has reasonable
metaprogramming support has most of it without the type hell of earlier
versions (C++11 had most of it, but C++14 fills in some key missing pieces).
However C++20 is really the main game changer in my opinion; although
earlier versions could play a lot of SFINAE hacks they also gave
absolutely useless barf as error messages. C++20 adds concepts, which
makes it possible to actually get reasonable errors.
We do a lot of metaprogramming in the Linux kernel, implemented with
some often truly hideous macro hacks. These are also virtually
impossible to debug. Consider the uaccess.h type hacks, some of which I
designed and wrote. In C++, the various casts and case statements can be
unwound into separate template instances, and with some cleverness can
also strictly enforce things like user space vs kernel space pointers as
well as already-verified versus unverified user space pointers, not to
mention easily handle the case of 32-bit user space types in a 64-bit
kernel and make endianness conversion enforceable.
Now, "why not Rust"? First of all, Rust uses a different (often, in my
opinion, gratuitously so) syntax, and not only would all the kernel
developers need to become intimately familiar to the level of getting
the same kind of "feel" as we have for C, but converting C code to Rust
isn't something that can be done piecemeal, whereas with some cleanups
the existing C code can be compiled as C++.
However, I find that I disagree with some of David's conclusions; in
fact I believe David is unnecessarily *pessimistic* at least given
modern C++.
Note that no one in their sane mind would expect to use all the features
of C++. Just like we have "kernel C" (currently a subset of C11 with a
relatively large set of allowed compiler-specific extensions) we would
have "kernel C++", which I would suggest to be a strictly defined subset
of C++20 combined with a similar set of compiler extensions.) I realize
C++20 compiler support is still very new for obvious reasons, so at
least some of this is forward looking.
So, notes on this specific subset based on David's comments.
On 4/1/18 13:40, David Howells wrote:
>
> Here are a series of patches to start converting the kernel to C++. It
> requires g++ v8.
>
> What rocks:
>
> (1) Inline template functions, which makes implementation of things like
> cmpxchg() and get_user() much cleaner.
Much, much cleaner indeed. But it also allows for introducing things
like inline patching of immediates *without* having to change literally
every instance of a variable.
I wrote, in fact, such a patchset. It probably included the most awful
assembly hacks I have ever done, in order to implement the mechanics,
but what *really* made me give up on it was the fact that every site
where a patchable variable is invoked would have to be changed from, say:
foo = bar + some_init_offset;
.. to ...
foo = imm_add(bar, some_init_offset);
> (2) Inline overloaded functions, which makes implementation of things like
> static_branch_likely() cleaner.
Basically a subset of the above (it just means that for a specific set
of very common cases it isn't necessary to go all the way to using
templates, which makes the syntax nicer.)
> (3) Class inheritance. For instance, all those inode wrappers that require
> the base inode struct to be included and that has to be accessed with
> something like:
>
> inode->vfs_inode.i_mtime
>
> when you could instead do:
>
> inode->i_mtime
This is nice, but it is fundamentally syntactic sugar. Similar things
can be done with anonymous structures, *except* that C doesn't allow
another structure to be anonymously included; you have to have an
entirely new "struct" statement defining all the fields. Welcome to
macro hell.
> What I would disallow:
>
> (1) new and delete. There's no way to pass GFP_* flags in.
Yes, there is.
void * operator new (size_t count, gfp_flags_t flags);
void operator delete(void *ptr, ...whatever kfree/vfree/etc need, or a
suitable flag);
> (2) Constructors and destructors. Nests of implicit code makes the code less
> obvious, and the replacement of static initialisation with constructor
> calls would make the code size larger.
Yes and no. It also makes it *way* easier to convert to and from using
dedicated slabs; we already use semi-initialized slabs for some kinds of
objects, but it requires new code to make use of.
We already *do* use constructors and *especially* destructors for a lot
of objects, we just call them out.
Note that modern C++ also has the ability to construct and destruct
objects in-place, so allocation and construction/destruction aren't
necessarily related.
There is no reason you can't do static initialization where possible;
even constructors can be evaluated at compile time if they are constexpr.
Constructors (and destructors, for modules) in conjunction with gcc's
init_priority() extension is also a nice replacement for linker hack
tables to invoke intializer functions.
> (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
> exception handling is limited without it, and since destructors are not
> allowed, you still have to manually clean up after an error.
Agreed here, especially since on many platforms exception handling
relies on DWARF unwind information.
> (4) Operator overloading (except in special cases).
See the example of inline patching above. But yes, overloading and
*especially* operator overloading should be used only with care; this is
pretty much true across the board.
> (5) Function overloading (except in special inline cases).
I think we might find non-inline cases where it matters, too.
> (6) STL (though some type trait bits are needed to replace __builtins that
> don't exist in g++).
Just like there are parts of the C library which is really about the
compiler and not part of the library. <type_traits> is part of that for C++.
> (7) 'class', 'private', 'namespace'.
>
> (8) 'virtual'. Don't want virtual base classes, though virtual function
> tables might make operations tables more efficient.
Operations tables *are* virtual classes. virtual base classes make sense
in a lot of cases, and we de facto use them already.
However, Linux also does conversion of polymorphic objects from one type
to another -- that is for example how device nodes are implemented.
Using this with C++ polymorphism without RTTI does require some
compiler-specific hacks, unfortunately.
> Issues:
>
> (1) Need spaces inserting between strings and symbols.
I have to admit I don't really grok this?
> (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> g++ grudgingly permits it with -fpermissive. I would imagine that a
> compiler option could easily be added to hide the error entirely.
Seriously. It should also enforce that it should be a trivial type.
Unfortunately it doesn't look like there is a way to create user-defined
implicit conversions from one pointer to another (via a helper class),
which otherwise would have had some other nice applications.
> (3) Need gcc v8+ to statically initialise an object of any struct that's not
> really simple (e.g. if it's got an embedded union).
Worst case: constexpr constructor.
> (4) Symbol length. Really need to extern "C" everything to reduce the size
> of the symbols stored in the kernel image. This shouldn't be a problem
> if out-of-line function overloading isn't permitted.
This really would lose arguably the absolutely biggest advantage of C++:
type-safe linkage. This is the one reason why Linus actually tried to
use C++ in one single version of the kernel in the early days (0.99.14,
if I remember correctly.) At that time, g++ was nowhere near mature
enough, and it got dropped right away.
> So far, it gets as far as compiling init/main.c to a .o file.
;)
On Tue, Jan 9, 2024 at 11:57 AM H. Peter Anvin <[email protected]> wrote:
>
> Hi all, I'm going to stir the hornet's nest and make what has become the
> ultimate sacrilege.
>
> Andrew Pinski recently made aware of this thread. I realize it was
> released on April 1, 2018, and either was a joke or might have been
> taken as one. However, I think there is validity to it, and I'm going to
> try to motivate my opinion here.
>
> Both C and C++ has had a lot of development since 1999, and C++ has in
> fact, in my personal opinion, finally "grown up" to be a better C for
> the kind of embedded programming that an OS kernel epitomizes. I'm
> saying that as the author of a very large number of macro and inline
> assembly hacks in the kernel.
>
> What really makes me say that is that a lot of things we have recently
> asked for gcc-specific extensions are in fact relatively easy to
> implement in standard C++ and, in many cases, allows for infrastructure
> improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable
> metaprogramming support has most of it without the type hell of earlier
> versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>
> However C++20 is really the main game changer in my opinion; although
> earlier versions could play a lot of SFINAE hacks they also gave
> absolutely useless barf as error messages. C++20 adds concepts, which
> makes it possible to actually get reasonable errors.
>
> We do a lot of metaprogramming in the Linux kernel, implemented with
> some often truly hideous macro hacks. These are also virtually
> impossible to debug. Consider the uaccess.h type hacks, some of which I
> designed and wrote. In C++, the various casts and case statements can be
> unwound into separate template instances, and with some cleverness can
> also strictly enforce things like user space vs kernel space pointers as
> well as already-verified versus unverified user space pointers, not to
> mention easily handle the case of 32-bit user space types in a 64-bit
> kernel and make endianness conversion enforceable.
>
> Now, "why not Rust"? First of all, Rust uses a different (often, in my
> opinion, gratuitously so) syntax, and not only would all the kernel
> developers need to become intimately familiar to the level of getting
> the same kind of "feel" as we have for C, but converting C code to Rust
> isn't something that can be done piecemeal, whereas with some cleanups
> the existing C code can be compiled as C++.
>
> However, I find that I disagree with some of David's conclusions; in
> fact I believe David is unnecessarily *pessimistic* at least given
> modern C++.
>
> Note that no one in their sane mind would expect to use all the features
> of C++. Just like we have "kernel C" (currently a subset of C11 with a
> relatively large set of allowed compiler-specific extensions) we would
> have "kernel C++", which I would suggest to be a strictly defined subset
> of C++20 combined with a similar set of compiler extensions.) I realize
> C++20 compiler support is still very new for obvious reasons, so at
> least some of this is forward looking.
>
> So, notes on this specific subset based on David's comments.
>
> On 4/1/18 13:40, David Howells wrote:
> >
> > Here are a series of patches to start converting the kernel to C++. It
> > requires g++ v8.
> >
> > What rocks:
> >
> > (1) Inline template functions, which makes implementation of things like
> > cmpxchg() and get_user() much cleaner.
>
> Much, much cleaner indeed. But it also allows for introducing things
> like inline patching of immediates *without* having to change literally
> every instance of a variable.
>
> I wrote, in fact, such a patchset. It probably included the most awful
> assembly hacks I have ever done, in order to implement the mechanics,
> but what *really* made me give up on it was the fact that every site
> where a patchable variable is invoked would have to be changed from, say:
>
> foo = bar + some_init_offset;
>
> ... to ...
>
> foo = imm_add(bar, some_init_offset);
>
>
> > (2) Inline overloaded functions, which makes implementation of things like
> > static_branch_likely() cleaner.
>
> Basically a subset of the above (it just means that for a specific set
> of very common cases it isn't necessary to go all the way to using
> templates, which makes the syntax nicer.)
>
> > (3) Class inheritance. For instance, all those inode wrappers that require
> > the base inode struct to be included and that has to be accessed with
> > something like:
> >
> > inode->vfs_inode.i_mtime
> >
> > when you could instead do:
> >
> > inode->i_mtime
>
> This is nice, but it is fundamentally syntactic sugar. Similar things
> can be done with anonymous structures, *except* that C doesn't allow
> another structure to be anonymously included; you have to have an
> entirely new "struct" statement defining all the fields. Welcome to
> macro hell.
>
> > What I would disallow:
> >
> > (1) new and delete. There's no way to pass GFP_* flags in.
>
> Yes, there is.
>
> void * operator new (size_t count, gfp_flags_t flags);
> void operator delete(void *ptr, ...whatever kfree/vfree/etc need, or a
> suitable flag);
>
> > (2) Constructors and destructors. Nests of implicit code makes the code less
> > obvious, and the replacement of static initialisation with constructor
> > calls would make the code size larger.
>
> Yes and no. It also makes it *way* easier to convert to and from using
> dedicated slabs; we already use semi-initialized slabs for some kinds of
> objects, but it requires new code to make use of.
>
> We already *do* use constructors and *especially* destructors for a lot
> of objects, we just call them out.
>
> Note that modern C++ also has the ability to construct and destruct
> objects in-place, so allocation and construction/destruction aren't
> necessarily related.
>
> There is no reason you can't do static initialization where possible;
> even constructors can be evaluated at compile time if they are constexpr.
>
> Constructors (and destructors, for modules) in conjunction with gcc's
> init_priority() extension is also a nice replacement for linker hack
> tables to invoke intializer functions.
>
> > (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
> > exception handling is limited without it, and since destructors are not
> > allowed, you still have to manually clean up after an error.
>
> Agreed here, especially since on many platforms exception handling
> relies on DWARF unwind information.
Let me just add a few things about exceptions and RTTI.
In the darwin kernel, C++ is used for device drivers and both
exceptions and RTTI is not used there either. They have been using C++
for kernel drivers since the early 2000s even.
You can find out more at https://developer.apple.com/documentation/driverkit .
There even was a GCC option added an option which would also disable
RTTI and change the ABI to explicitly for the kernel.
-fapple-kext/-mkernel (the former is for only loadable modules while
the latter is for kernel too).
Note even in GCC, we disable exceptions and RTTI while building GCC.
This is specifically due to not wanting to use them and use other
methods to do that.
Note GDB on the other hand used to use setjmp/longjmp for their
exception handling in C and I think they moved over to using C++
exceptions which simplified things there. But as far as I know the
Linux kernel does not use a mechanism like that (I know of copy
from/to user using HW exceptions/error/interrupt handling but that is
a special case only).
>
> > (4) Operator overloading (except in special cases).
>
> See the example of inline patching above. But yes, overloading and
> *especially* operator overloading should be used only with care; this is
> pretty much true across the board.
>
> > (5) Function overloading (except in special inline cases).
>
> I think we might find non-inline cases where it matters, too.
>
> > (6) STL (though some type trait bits are needed to replace __builtins that
> > don't exist in g++).
>
> Just like there are parts of the C library which is really about the
> compiler and not part of the library. <type_traits> is part of that for C++.
There is an idea of a free standing C++ library. newer versions of
GCC/libstdc++ does support that but IIRC can only be configured at
compile time of GCC.
type_traits and a few other headers are included in that. I have not
looked into it fully though.
Thanks,
Andrew Pinski
>
> > (7) 'class', 'private', 'namespace'.
> >
> > (8) 'virtual'. Don't want virtual base classes, though virtual function
> > tables might make operations tables more efficient.
>
> Operations tables *are* virtual classes. virtual base classes make sense
> in a lot of cases, and we de facto use them already.
>
> However, Linux also does conversion of polymorphic objects from one type
> to another -- that is for example how device nodes are implemented.
> Using this with C++ polymorphism without RTTI does require some
> compiler-specific hacks, unfortunately.
>
> > Issues:
> >
> > (1) Need spaces inserting between strings and symbols.
>
> I have to admit I don't really grok this?
>
> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> > g++ grudgingly permits it with -fpermissive. I would imagine that a
> > compiler option could easily be added to hide the error entirely.
>
> Seriously. It should also enforce that it should be a trivial type.
> Unfortunately it doesn't look like there is a way to create user-defined
> implicit conversions from one pointer to another (via a helper class),
> which otherwise would have had some other nice applications.
>
> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
> > really simple (e.g. if it's got an embedded union).
>
> Worst case: constexpr constructor.
>
> > (4) Symbol length. Really need to extern "C" everything to reduce the size
> > of the symbols stored in the kernel image. This shouldn't be a problem
> > if out-of-line function overloading isn't permitted.
>
> This really would lose arguably the absolutely biggest advantage of C++:
> type-safe linkage. This is the one reason why Linus actually tried to
> use C++ in one single version of the kernel in the early days (0.99.14,
> if I remember correctly.) At that time, g++ was nowhere near mature
> enough, and it got dropped right away.
>
>
> > So far, it gets as far as compiling init/main.c to a .o file.
>
> ;)
H. Peter Anvin <[email protected]> wrote:
> Hi all, I'm going to stir the hornet's nest and make what has become the
> ultimate sacrilege.
:-)
> Both C and C++ has had a lot of development since 1999, and C++ has in fact,
> in my personal opinion, finally "grown up" to be a better C for the kind of
> embedded programming that an OS kernel epitomizes.
And gcc got rewritten in C++ some time back, so they have a vested interest.
> > (8) 'virtual'. Don't want virtual base classes, though virtual function
> > tables might make operations tables more efficient.
>
> Operations tables *are* virtual classes. virtual base classes make sense in a
> lot of cases, and we de facto use them already.
You end up adding storage for a 'this' pointer for each virtual base class, I
think - and then you may have extra fun if you inherit from two classes that
both inherit the same virtual base class. Abstract base classes that are just
ops tables are probably fine, though.
> > Issues:
> > (1) Need spaces inserting between strings and symbols.
>
> I have to admit I don't really grok this?
You're not allowed to do things like:
asm volatile("btl "__percpu_arg(2)",%1"
but rather have to do:
asm volatile("btl " __percpu_arg(2) ",%1"
as you're now allowed to specify type qualifiers. See
https://en.cppreference.com/w/cpp/language/user_literal
> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> > g++ grudgingly permits it with -fpermissive. I would imagine that a
> > compiler option could easily be added to hide the error entirely.
>
> Seriously. It should also enforce that it should be a trivial
> type. Unfortunately it doesn't look like there is a way to create user-defined
> implicit conversions from one pointer to another (via a helper class), which
> otherwise would have had some other nice applications.
Might require a compiler option to kill the warning. Inserting all the
missing casts would be a pain.
> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
> > really simple (e.g. if it's got an embedded union).
>
> Worst case: constexpr constructor.
There was also a problem with leaving gaps in static array initialisation and
a problem with statically initialising fields out of order (with respect to
the order they're declared in the struct declaration). Possibly these have
been fixed in g++.
> > (4) Symbol length. Really need to extern "C" everything to reduce the size
> > of the symbols stored in the kernel image. This shouldn't be a problem
> > if out-of-line function overloading isn't permitted.
>
> This really would lose arguably the absolutely biggest advantage of C++:
> type-safe linkage. This is the one reason why Linus actually tried to use C++
> in one single version of the kernel in the early days (0.99.14, if I remember
> correctly.) At that time, g++ was nowhere near mature enough, and it got
> dropped right away.
I know. It depends on how much you want to grow your symbol table by. Given
the number of struct pointers we use, it increases it a lot IIRC. Also, you
might want a demangler for stack traces.
David
Andrew Pinski <[email protected]> wrote:
> Note even in GCC, we disable exceptions and RTTI while building GCC.
> This is specifically due to not wanting to use them and use other
> methods to do that.
> Note GDB on the other hand used to use setjmp/longjmp for their
> exception handling in C and I think they moved over to using C++
> exceptions which simplified things there. But as far as I know the
> Linux kernel does not use a mechanism like that (I know of copy
> from/to user using HW exceptions/error/interrupt handling but that is
> a special case only).
If we were to allow exception handling, I wonder if we would actually need to
throw anything other than a signed long integer (e.g. an error code) and just
disable RTTI. Maybe something like:
long sys_rename(...)
{
struct rwsem_lock lock_a, lock_b;
struct inode *dir_a, *dir_b;
...
try {
if (dir_a > dir_b) {
lock_a.down_write_killable(dir_a);
lock_b.down_write_killable(dir_b);
} else {
lock_b.down_write_killable(dir_b);
lock_a.down_write_killable(dir_a);
}
} catch (-EINTR) {
throw -ERESTARTSYS;
}
...
}
then have a cut-down exception unwinder that only needs to deal with long
values.
However, I think rolling out exception handling in the kernel might be too big
a task, given the huge amount of code involved - however much we might like to
avoid all those return value checks.
David
On Tue, Jan 09, 2024 at 11:40:45PM +0000, David Howells wrote:
> There was also a problem with leaving gaps in static array initialisation and
> a problem with statically initialising fields out of order (with respect to
> the order they're declared in the struct declaration). Possibly these have
> been fixed in g++.
They weren't :-(
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113124
Right now g++ hard errors some patterns of C99 inititialisation which
clang++ allows (with warnings which can be turned off).
However, clang++ doesn't believe in pointer arithmetic on void*.
Hi,
On 09. 01. 24, 20:57, H. Peter Anvin wrote:
> What really makes me say that is that a lot of things we have recently
> asked for gcc-specific extensions are in fact relatively easy to
> implement in standard C++ and, in many cases, allows for infrastructure
> improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable
> metaprogramming support has most of it without the type hell of earlier
> versions (C++11 had most of it, but C++14 fills in some key missing
> pieces).
If you mean it, I do too. So I can only express my +1: yes, please.
I don't have much to add as you summarized most of it.
thanks,
--
js
suse labs
Hey all,
I would like to speak in support of this too. It is not uncommon
to see operating systems code written in C++ (notable examples are
Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
are benefits to C++ for Linux code. Modern C++ (such as C++14 and
newer), offers a lot of nice base language features that can make
some of the kind of stuff that Linux does easier (as H. Peter Anvin
has detailed in his post[1]).
While I personally have some experience in a variety of programming
languages, C++ and Python are my preferred tools, and I would
personally be much more interested in contributing in C++ than in C.
I imagine there are a lot of other folks out there who feel the same,
but just don't feel like they can say it. I'll stick my neck out for
those who won't. ;)
Even though this started out as a "joke"[2], I really would like to
see C++ code permitted in Linux.
Thanks in advance and best regards,
Neal
[1]: https://lore.kernel.org/lkml/[email protected]/
[2]: https://lore.kernel.org/lkml/152261521484.30503.16131389653845029164.stgit@warthog.procyon.org.uk/
--
真実はいつも一つ!/ Always, there's only one truth!
Hey,
While I have done no work on the linux kernel, I hope to add to this
discussion anyway. Forgive me if I'm intruding.
The arguments in favour of C++ so far focus on the technical and current
kernel developers aspects. An extra argument in favour of C++ is the
same one that Linus Torvalds recently mentioned in the keynote "Linus
Torvalds in Conversation With Dirk Hohndel" w.r.t. Rust's impact on the
Linux Kernel. Namely, to prevent stagnation for the Kernel as well as
continue to be interesting to new developers.
One of the things holding me back from developping things in the Kernel
is that C is, to put it bluntly, old and not interesting for my resume.
Now there is certainly an argument to be made for "don't fix what ain't
broken", as evidenced by the Kernel being in widespread use. But most of
the interesting programming language progress has happened in C++ and
other languages, unlike C. The aforementioned metaprogramming is one
such example, but things like RAII, smart pointers and things like
gsl::not_null would reduce the changes on kernel bugs, especially memory
safety related bugs that are known to be vulnerable to security issues.
On the other hand, the benefits I mention can also turn into downsides:
if constructs like gsl::not_null are desired, does that mean that there
will be a kernel-specific template library? A KTL instead of STL? That
might be yet another thing that increases the steepness of the kernel
development learning curve.
I also have a note on the following:
> However, Linux also does conversion of polymorphic objects from one
> type to another -- that is for example how device nodes are
> implemented. Using this with C++ polymorphism without RTTI does
> require some compiler-specific hacks, unfortunately.
Although compiler-specific, C++20 has enabled implementing RTTI without
RTTI as well as (partial) reflection. Examples include the JSON library
Glaze as well as my own Dependency Injection framework Ichor. See
https://godbolt.org/z/vaWszr9WG. On top of increasing the binary size,
this then becomes a discussion on what requirements the kernel puts on
compilers, as I'm sure that the kernel needs to be compiled for
architectures which have a less than stellar conformance to the C++
specification. Regardless, this is IMO good food for thought.
Cheers,
Michael de Lang
On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> Hey all,
>
> I would like to speak in support of this too. It is not uncommon
> to see operating systems code written in C++ (notable examples are
> Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> newer), offers a lot of nice base language features that can make
> some of the kind of stuff that Linux does easier (as H. Peter Anvin
> has detailed in his post[1]).
Me too. If we are serious considering Rust I think C++20 deserves a
fair shake as well. Especially since I heard the C++ working group is
apparently looking at future C++ extensions for Rust-esque memory
safety these days.
I personally think the kernel community would have an easier and more
incremental time swallowing C++ than it would Rust, and C++17 is
already mature with fully working stable compilers. In particular I
feel someone familiar with C would have a easier ramp up to some
imagined "kernel C++20 subset" than to Rust.
Further, I feell that having a single base line of "all code compiles
in a C++20 compiler" and localized variations of what idiomatic style
and features different parts use would be ultimately more maintainable
than intermixing C and Rust togther.
I've also got a fair bit of experience with C++17 and I would add to
HPA's note that the modern idiomatic usage of C++17 is *way* different
than older versions. If someone was traumatized by early 2000's or
1990's C++ then it is not entirely fair to carry that to modern
C++17. Especially when combined with a modern environment with
something like clangd to help grok the code. (Though SFINAE is still
an inscrutable terror)
Jason
SFINAE giving inscrutable errors is why I'm saying C++20, since "concept" means you can get usable error messages.
On Wed, Jan 10, 2024 at 10:52 AM Jason Gunthorpe <[email protected]> wrote:
>
> On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> > Hey all,
> >
> > I would like to speak in support of this too. It is not uncommon
> > to see operating systems code written in C++ (notable examples are
> > Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> > are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> > newer), offers a lot of nice base language features that can make
> > some of the kind of stuff that Linux does easier (as H. Peter Anvin
> > has detailed in his post[1]).
>
> Me too. If we are serious considering Rust I think C++20 deserves a
> fair shake as well. Especially since I heard the C++ working group is
> apparently looking at future C++ extensions for Rust-esque memory
> safety these days.
>
> I personally think the kernel community would have an easier and more
> incremental time swallowing C++ than it would Rust, and C++17 is
> already mature with fully working stable compilers. In particular I
> feel someone familiar with C would have a easier ramp up to some
> imagined "kernel C++20 subset" than to Rust.
>
> Further, I feell that having a single base line of "all code compiles
> in a C++20 compiler" and localized variations of what idiomatic style
> and features different parts use would be ultimately more maintainable
> than intermixing C and Rust togther.
>
> I've also got a fair bit of experience with C++17 and I would add to
> HPA's note that the modern idiomatic usage of C++17 is *way* different
> than older versions. If someone was traumatized by early 2000's or
> 1990's C++ then it is not entirely fair to carry that to modern
> C++17. Especially when combined with a modern environment with
> something like clangd to help grok the code. (Though SFINAE is still
> an inscrutable terror)
>
For what it's worth, I'm totally in favor of C++20 as well. I've
mostly written C++17 as of late and it is really nice to me, but I'm
genuinely excited about C++20 and newer revisions.
I also think that Linux adopting C++ and intentionally adopting safety
features that exist and are being added to C++ over time would also
further encourage the ecosystem to use them as well as make the Linux
codebase much easier to work with.
--
真実はいつも一つ!/ Always, there's only one truth!
On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
>
> For what it's worth, I'm totally in favor of C++20 as well. I've
> mostly written C++17 as of late and it is really nice to me, but I'm
> genuinely excited about C++20 and newer revisions.
>
> I also think that Linux adopting C++ and intentionally adopting safety
> features that exist and are being added to C++ over time would also
> further encourage the ecosystem to use them as well as make the Linux
> codebase much easier to work with.
Can someone speak to whether the C++ standards committee and C++
compiler implementations are more or less unreasonable compared to
their C counterparts regarding compilers being able to arbitrary
statement reordering, or other random futzing all in the name of
better benchmarks, but which make life a living nightmware for honest
kernel developers?
- Ted
On 1/9/24 11:57, H. Peter Anvin wrote:
> Hi all, I'm going to stir the hornet's nest and make what has become the ultimate sacrilege.
>
> Andrew Pinski recently made aware of this thread. I realize it was released on April 1, 2018, and either was a joke or might have been taken as one. However, I think there is validity to it, and I'm going to try to motivate my opinion here.
>
In 2018 it may have been taken as a joke, but in 2024 with Rust for Linux
upon us, C++ sounds just plain brilliant. Thank you so much for this proposal.
> Both C and C++ has had a lot of development since 1999, and C++ has in fact, in my personal opinion, finally "grown up" to be a better C for the kind of embedded programming that an OS kernel epitomizes. I'm saying that as the author of a very large number of macro and inline assembly hacks in the kernel.
>
> What really makes me say that is that a lot of things we have recently asked for gcc-specific extensions are in fact relatively easy to implement in standard C++ and, in many cases, allows for infrastructure improvement *without* global code changes (see below.)
>
> C++14 is in my option the "minimum" version that has reasonable metaprogramming support has most of it without the type hell of earlier versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>
> However C++20 is really the main game changer in my opinion; although earlier versions could play a lot of SFINAE hacks they also gave absolutely useless barf as error messages. C++20 adds concepts, which makes it possible to actually get reasonable errors.
I was writing a lot of C++ in the late 1990's and early 2000's, and personally
lived through the template error madness in particular. Verity Stob had a
wonderful riff on it in her 2001 "Double Plus Good?" article [1].
But one thing I do wonder about is the template linker bloat that was
endemic: multiple instantiations of templates were not de-duplicated
by the linkers of the day, and things were just huge. 20 years later,
perhaps it is all better I hope?
>
> We do a lot of metaprogramming in the Linux kernel, implemented with some often truly hideous macro hacks. These are also virtually impossible to debug. Consider the uaccess.h type hacks, some of which I designed and wrote. In C++, the various casts and case statements can be unwound into separate template instances, and with some cleverness can also strictly enforce things like user space vs kernel space pointers as well as already-verified versus unverified user space pointers, not to mention easily handle the case of 32-bit user space types in a 64-bit kernel and make endianness conversion enforceable.
>
This sounds glorious.
> Now, "why not Rust"? First of all, Rust uses a different (often, in my opinion, gratuitously so) syntax, and not only would all the kernel developers need to become intimately familiar to the level of getting the same kind of "feel" as we have for C, but converting C code to Rust isn't something that can be done piecemeal, whereas with some cleanups the existing C code can be compiled as C++.
>
Beyond the syntax, which I'm trying to force myself not to focus on, the
compatibility layers are turning out to be quite extensive. This is just
another way of saying that Rust is a deeply, completely different language.
Whereas C++ is closer to a dialect, as far as building and linking anyway.
> However, I find that I disagree with some of David's conclusions; in fact I believe David is unnecessarily *pessimistic* at least given modern C++.
>
> Note that no one in their sane mind would expect to use all the features of C++. Just like we have "kernel C" (currently a subset of C11 with a relatively large set of allowed compiler-specific extensions) we would have "kernel C++", which I would suggest to be a strictly defined subset of C++20 combined with a similar set of compiler extensions.) I realize C++20 compiler support is still very new for obvious reasons, so at least some of this is forward looking.
There was an effort to address this, and I remember we even tried to use
it: Embedded C++ [2]. This is very simplistic and completely out of date
compared to what is being considered here, but it does show that many
others have had the same reaction: the language is so large that it
wants to be constrained. We actually wrote to Bjarne Stroustrup around
that time and asked about both embedded C++ and coding standards, and
his reaction was, "don't limit the language, just use education instead".
However, in my experience since then, that fails, and you need at least
coding standards. Because people will use *everything* they have available,
unless they can't. :)
Tentatively, coding standards are a better way forward, as opposed to
actually constraining the language (and maybe finding out later that
you wish it was left unconstrained), IMHO.
[1] https://link.springer.com/chapter/10.1007/978-1-4302-0003-1_63
[2] https://en.wikipedia.org/wiki/Embedded_C%2B%2B
thanks,
--
John Hubbard
NVIDIA
> There was an effort to address this, and I remember we even tried to use
> it: Embedded C++ [2]. This is very simplistic and completely out of date
> compared to what is being considered here, but it does show that many
> others have had the same reaction: the language is so large that it
> wants to be constrained. We actually wrote to Bjarne Stroustrup around
> that time and asked about both embedded C++ and coding standards, and
> his reaction was, "don't limit the language, just use education instead".
>
> However, in my experience since then, that fails, and you need at least
> coding standards. Because people will use *everything* they have available,
> unless they can't. :)
You don't just need coding standards, you need a compiler that refuses
to compile that stuff.
If you want C++ to do what Rust could do, then you need the compiler
to stop the stupid before you can even write it, otherwise people will
still write the bad stuff and code review won't catch it all.
Can we get memory safety with C++ now? and also stop people coding C++
like it's 1994?
Kernel C has kinda become a thing without enforcing it, but C wasn't
really stopping anything bad, so having C that isn't quite kernel C
get into corners isn't that bad, but introducing C++ without any
history of kernel C++ is just asking for everyone to do their own
special things and defend their usage of every corner of the language
because they wanted to learn it.
Dave.
On Wed, Jan 10, 2024 at 08:04:53AM -0500, Neal Gompa wrote:
> Hey all,
Hi,
> I would like to speak in support of this too. It is not uncommon
> to see operating systems code written in C++ (notable examples are
> Haiku OS, Serenity OS, and Zircon/Fuschia) and I do feel that there
> are benefits to C++ for Linux code. Modern C++ (such as C++14 and
> newer), offers a lot of nice base language features that can make
> some of the kind of stuff that Linux does easier (as H. Peter Anvin
> has detailed in his post[1]).
>
> While I personally have some experience in a variety of programming
> languages, C++ and Python are my preferred tools, and I would
> personally be much more interested in contributing in C++ than in C.
> I imagine there are a lot of other folks out there who feel the same,
> but just don't feel like they can say it. I'll stick my neck out for
> those who won't. ;)
I had some doubts, when I've seen hpa's thread and first I've thought
of it rather as a threat. But now this paragraph totally convinced me.
> Even though this started out as a "joke"[2], I really would like to
> see C++ code permitted in Linux.
Great, let University of Minnesota contribute the code.
> Thanks in advance and best regards,
> Neal
>
> [1]: https://lore.kernel.org/lkml/[email protected]/
> [2]: https://lore.kernel.org/lkml/152261521484.30503.16131389653845029164.stgit@warthog.procyon.org.uk/
>
>
> --
> 真実はいつも一つ!/ Always, there's only one truth!
PS: IMO, Rust shouldn't have been allowed into the kernel tree (a gut
feeling). But who am I.
--
Regards,
Andreas
SUSE Software Solutions Germany GmbH
Frankenstrasse 146, 90461 Nürnberg, Germany
GF: Ivo Totev, Andrew McDonald, Werner Knoblich
(HRB 36809, AG Nürnberg)
> SFINAE giving inscrutable errors is why I'm saying C++20,
> since "concept" means you can get usable error messages.
I'd say concepts are irrelevant for the kernel where standard library is
tightly controlled by the same people who write rest of the kernel and
no external users.
static_assert() is all you need.
On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <[email protected]> wrote:
>
> > SFINAE giving inscrutable errors is why I'm saying C++20,
> > since "concept" means you can get usable error messages.
>
> I'd say concepts are irrelevant for the kernel where standard library is
> tightly controlled by the same people who write rest of the kernel and
> no external users.
>
> static_assert() is all you need.
We have external users all the time, though. People who write external
modules or new modules would fall in that classification. Why should
it be harder for them?
--
真実はいつも一つ!/ Always, there's only one truth!
On Thu, Jan 11, 2024 at 05:58:51AM -0500, Neal Gompa wrote:
> On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <[email protected]> wrote:
> >
> > > SFINAE giving inscrutable errors is why I'm saying C++20,
> > > since "concept" means you can get usable error messages.
> >
> > I'd say concepts are irrelevant for the kernel where standard library is
> > tightly controlled by the same people who write rest of the kernel and
> > no external users.
> >
> > static_assert() is all you need.
>
> We have external users all the time, though. People who write external
> modules or new modules would fall in that classification. Why should
> it be harder for them?
static_assert gives filename:line which clearly points to the source of
an error.
Concepts are SFINAE replacement but if there is little SFINAE there will
be little concepts too.
Another quite silly thing with concepts (and with noexcept propagation)
is that programmer has to write an implementation then chop control flow
and put everything else into the requires. And then to keep both in sync.
This is an example from cppreference:
template<typename T>
requires Addable<T>
T
add(T a, T b)
{
return a + b;
}
Guess what Addable<> is?
They are kind of nice for simple things:
template<typename It>
concept MinimalIterator = requires(It it) { ++it; *it; it++; };
On Thu, Jan 11, 2024 at 05:58:51AM -0500, Neal Gompa wrote:
> On Thu, Jan 11, 2024 at 5:56 AM Alexey Dobriyan <[email protected]> wrote:
> >
> > > SFINAE giving inscrutable errors is why I'm saying C++20,
> > > since "concept" means you can get usable error messages.
> >
> > I'd say concepts are irrelevant for the kernel where standard library is
> > tightly controlled by the same people who write rest of the kernel and
> > no external users.
> >
> > static_assert() is all you need.
>
> We have external users all the time, though. People who write external
> modules or new modules would fall in that classification. Why should
> it be harder for them?
I guess, I misunderstand something.
But WRT to the term 'external module' I have some comment.
My personal opinion is somewhat reflected in following article:
https://www.linuxfoundation.org/blog/blog/the-people-who-support-linux-snowden-revelations-spur-engineers-open-source-donation
(The People Who Support Linux: Snowden Revelations Spur Engineer's
Open Source Donation) [The Linux Foundation | 18 December 2013]
„“The public needs fully open source OSes, where experts can review
the whole code, to minimize the risk of hidden backdoors,” said
Kies.“
Thinking more about this.
What exactly was the reason to allow Rust in the kernel?
What exactly is the reason to allow C++ in the kernel?
Besides, I think in general that complexity can be destructive -- even
in a world without bad actors.
> --
> 真実はいつも一つ!/ Always, there's only one truth!
H. Peter Anvin writes:
>We already *do* use constructors and *especially* destructors for a
>lot of objects, we just call them out.
>
>Note that modern C++ also has the ability to construct and destruct
>objects in-place, so allocation and construction/destruction aren't
>necessarily related.
>
>There is no reason you can't do static initialization where possible;
>even constructors can be evaluated at compile time if they are
>constexpr.
Side note for the constructor and destructor discussion: should we be more
widely marketing the __cleanup() infrastructure that Peter added a year or so
ago? It likely helps a lot with at least some of these cases. In systemd we use
__attribute__((cleanup)) pretty widely and my experience is that it's made the
code a lot easier to both create and consume.
> You don't just need coding standards, you need a compiler that refuses
> to compile that stuff.
>
> If you want C++ to do what Rust could do, then you need the compiler
> to stop the stupid before you can even write it, otherwise people will
> still write the bad stuff and code review won't catch it all.
Completely agree with this by the way, if you could turn off features
easily via C++ compiler flags, etc. and make usage of the unwanted
features throw errors. There is a subset of C++ that would have been
useful in the kernel many years ago.
I think the C++ committee is coming around to this way of thinking with
profiles. But it should extend to more than just memory safety features
of course.
Some of the things I like about C++ over Rust:
- C++ interop with C is easier, you can just intertwine C and C++
together out of the box once your code is compiling with C++.
- It's already on the majority of platforms, even legacy ones.
But Rust is nice for other reasons.
But yeah something like this would need to be done like the Rust integration
effort and be an opt-in thing for new code, if it was done.
>
> Can we get memory safety with C++ now? and also stop people coding C++
> like it's 1994?
>
> Kernel C has kinda become a thing without enforcing it, but C wasn't
> really stopping anything bad, so having C that isn't quite kernel C
> get into corners isn't that bad, but introducing C++ without any
> history of kernel C++ is just asking for everyone to do their own
> special things and defend their usage of every corner of the language
> because they wanted to learn it.
>
> Dave.
From: Chris Down
> Sent: 11 January 2024 12:40
>
> H. Peter Anvin writes:
> >We already *do* use constructors and *especially* destructors for a
> >lot of objects, we just call them out.
> >
> >Note that modern C++ also has the ability to construct and destruct
> >objects in-place, so allocation and construction/destruction aren't
> >necessarily related.
> >
> >There is no reason you can't do static initialization where possible;
> >even constructors can be evaluated at compile time if they are
> >constexpr.
But the compiler often doesn't - look at the generated code and marvel
at all the constructors for static items.
Oh yes, and all the destructors that pretty much always get called
in the wrong order leading to SIGSEGV on exit().
C++ programs pretty much have close all files and use _exit().
> Side note for the constructor and destructor discussion: should we be more
> widely marketing the __cleanup() infrastructure that Peter added a year or so
> ago? It likely helps a lot with at least some of these cases. In systemd we use
> __attribute__((cleanup)) pretty widely and my experience is that it's made the
> code a lot easier to both create and consume.
And harder for us 'old fogies' to quickly read for correctness.
IIRC some bugs got committed during some 'simple applications'
because of the real hoops you have to go through to correctly
tidy up a malloc()ed buffer that might be passed on.
I've seen the same issue with some C++ code that was like:
(Pardon my C++ :-)
foo = new();
try {
add_foo_to_list(foo);
} except {
free(foo);
}
The problem is that you have no idea whether the exception was
thrown before or after 'foo' was saved.
Since pretty much everything can 'throw' you really can't tell.
OTOH if add_foo_to_list() returns an error code you can know
(and check) that zero is returned iff the pointer has been saved.
Then there is function and class member overloading.
How may times have you renamed a structure member (etc) and used
the compiler to find out where it is used?
I'm pretty sure that is hard work in C++.
And don't forget the default copy constructor...
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Andrew Pinski <[email protected]> writes:
> On Tue, Jan 9, 2024 at 11:57 AM H. Peter Anvin <[email protected]> wrote:
>>
>> Hi all, I'm going to stir the hornet's nest and make what has become the
>> ultimate sacrilege.
>>
>> Andrew Pinski recently made aware of this thread. I realize it was
>> released on April 1, 2018, and either was a joke or might have been
>> taken as one. However, I think there is validity to it, and I'm going to
>> try to motivate my opinion here.
>>
>> Both C and C++ has had a lot of development since 1999, and C++ has in
>> fact, in my personal opinion, finally "grown up" to be a better C for
>> the kind of embedded programming that an OS kernel epitomizes. I'm
>> saying that as the author of a very large number of macro and inline
>> assembly hacks in the kernel.
>>
>> What really makes me say that is that a lot of things we have recently
>> asked for gcc-specific extensions are in fact relatively easy to
>> implement in standard C++ and, in many cases, allows for infrastructure
>> improvement *without* global code changes (see below.)
>>
>> C++14 is in my option the "minimum" version that has reasonable
>> metaprogramming support has most of it without the type hell of earlier
>> versions (C++11 had most of it, but C++14 fills in some key missing pieces).
>>
>> However C++20 is really the main game changer in my opinion; although
>> earlier versions could play a lot of SFINAE hacks they also gave
>> absolutely useless barf as error messages. C++20 adds concepts, which
>> makes it possible to actually get reasonable errors.
>>
>> We do a lot of metaprogramming in the Linux kernel, implemented with
>> some often truly hideous macro hacks. These are also virtually
>> impossible to debug. Consider the uaccess.h type hacks, some of which I
>> designed and wrote. In C++, the various casts and case statements can be
>> unwound into separate template instances, and with some cleverness can
>> also strictly enforce things like user space vs kernel space pointers as
>> well as already-verified versus unverified user space pointers, not to
>> mention easily handle the case of 32-bit user space types in a 64-bit
>> kernel and make endianness conversion enforceable.
>>
>> Now, "why not Rust"? First of all, Rust uses a different (often, in my
>> opinion, gratuitously so) syntax, and not only would all the kernel
>> developers need to become intimately familiar to the level of getting
>> the same kind of "feel" as we have for C, but converting C code to Rust
>> isn't something that can be done piecemeal, whereas with some cleanups
>> the existing C code can be compiled as C++.
>>
>> However, I find that I disagree with some of David's conclusions; in
>> fact I believe David is unnecessarily *pessimistic* at least given
>> modern C++.
>>
>> Note that no one in their sane mind would expect to use all the features
>> of C++. Just like we have "kernel C" (currently a subset of C11 with a
>> relatively large set of allowed compiler-specific extensions) we would
>> have "kernel C++", which I would suggest to be a strictly defined subset
>> of C++20 combined with a similar set of compiler extensions.) I realize
>> C++20 compiler support is still very new for obvious reasons, so at
>> least some of this is forward looking.
>>
>> So, notes on this specific subset based on David's comments.
>>
>> On 4/1/18 13:40, David Howells wrote:
>> >
>> > Here are a series of patches to start converting the kernel to C++. It
>> > requires g++ v8.
>> >
>> > What rocks:
>> >
>> > (1) Inline template functions, which makes implementation of things like
>> > cmpxchg() and get_user() much cleaner.
>>
>> Much, much cleaner indeed. But it also allows for introducing things
>> like inline patching of immediates *without* having to change literally
>> every instance of a variable.
>>
>> I wrote, in fact, such a patchset. It probably included the most awful
>> assembly hacks I have ever done, in order to implement the mechanics,
>> but what *really* made me give up on it was the fact that every site
>> where a patchable variable is invoked would have to be changed from, say:
>>
>> foo = bar + some_init_offset;
>>
>> ... to ...
>>
>> foo = imm_add(bar, some_init_offset);
>>
>>
>> > (2) Inline overloaded functions, which makes implementation of things like
>> > static_branch_likely() cleaner.
>>
>> Basically a subset of the above (it just means that for a specific set
>> of very common cases it isn't necessary to go all the way to using
>> templates, which makes the syntax nicer.)
>>
>> > (3) Class inheritance. For instance, all those inode wrappers that require
>> > the base inode struct to be included and that has to be accessed with
>> > something like:
>> >
>> > inode->vfs_inode.i_mtime
>> >
>> > when you could instead do:
>> >
>> > inode->i_mtime
>>
>> This is nice, but it is fundamentally syntactic sugar. Similar things
>> can be done with anonymous structures, *except* that C doesn't allow
>> another structure to be anonymously included; you have to have an
>> entirely new "struct" statement defining all the fields. Welcome to
>> macro hell.
>>
>> > What I would disallow:
>> >
>> > (1) new and delete. There's no way to pass GFP_* flags in.
>>
>> Yes, there is.
>>
>> void * operator new (size_t count, gfp_flags_t flags);
>> void operator delete(void *ptr, ...whatever kfree/vfree/etc need, or a
>> suitable flag);
>>
>> > (2) Constructors and destructors. Nests of implicit code makes the code less
>> > obvious, and the replacement of static initialisation with constructor
>> > calls would make the code size larger.
>>
>> Yes and no. It also makes it *way* easier to convert to and from using
>> dedicated slabs; we already use semi-initialized slabs for some kinds of
>> objects, but it requires new code to make use of.
>>
>> We already *do* use constructors and *especially* destructors for a lot
>> of objects, we just call them out.
>>
>> Note that modern C++ also has the ability to construct and destruct
>> objects in-place, so allocation and construction/destruction aren't
>> necessarily related.
>>
>> There is no reason you can't do static initialization where possible;
>> even constructors can be evaluated at compile time if they are constexpr.
>>
>> Constructors (and destructors, for modules) in conjunction with gcc's
>> init_priority() extension is also a nice replacement for linker hack
>> tables to invoke intializer functions.
>>
>> > (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
>> > exception handling is limited without it, and since destructors are not
>> > allowed, you still have to manually clean up after an error.
>>
>> Agreed here, especially since on many platforms exception handling
>> relies on DWARF unwind information.
>
> Let me just add a few things about exceptions and RTTI.
> In the darwin kernel, C++ is used for device drivers and both
> exceptions and RTTI is not used there either. They have been using C++
> for kernel drivers since the early 2000s even.
> You can find out more at https://developer.apple.com/documentation/driverkit .
> There even was a GCC option added an option which would also disable
> RTTI and change the ABI to explicitly for the kernel.
> -fapple-kext/-mkernel (the former is for only loadable modules while
> the latter is for kernel too).
>
> Note even in GCC, we disable exceptions and RTTI while building GCC.
> This is specifically due to not wanting to use them and use other
> methods to do that.
> Note GDB on the other hand used to use setjmp/longjmp for their
> exception handling in C and I think they moved over to using C++
> exceptions which simplified things there. But as far as I know the
> Linux kernel does not use a mechanism like that (I know of copy
> from/to user using HW exceptions/error/interrupt handling but that is
> a special case only).
>
>
>>
>> > (4) Operator overloading (except in special cases).
>>
>> See the example of inline patching above. But yes, overloading and
>> *especially* operator overloading should be used only with care; this is
>> pretty much true across the board.
>>
>> > (5) Function overloading (except in special inline cases).
>>
>> I think we might find non-inline cases where it matters, too.
>>
>> > (6) STL (though some type trait bits are needed to replace __builtins that
>> > don't exist in g++).
>>
>> Just like there are parts of the C library which is really about the
>> compiler and not part of the library. <type_traits> is part of that for C++.
>
> There is an idea of a free standing C++ library. newer versions of
> GCC/libstdc++ does support that but IIRC can only be configured at
> compile time of GCC.
> type_traits and a few other headers are included in that. I have not
> looked into it fully though.
There is, and it's quite extensive (and I plan on extending it further
in GCC 15, if I get the chance to). The full list of headers libstdc++
exports for freestanding use is a bit larger than the standard one:
https://gcc.gnu.org/cgit/gcc/tree/libstdc++-v3/include/Makefile.am#n28
(note that some are partially supported.. I lack a full list of which)
Most (actually, nearly all) of the libstdc++ code works for kernel
environments, and it is very mature and well-tested, so it can and
should be used by kernels too. I haven't fully enabled using it in such
a manner yet, but
We could handle the kernel specific configuration via a multilib or so
(so, the multilib list becomes 32, 64, x32, and a new k64 or so on
amd64). Presumably, something like that could be done for libgcc too?
It is not necessarily only configurable at build-time, but the libstdc++
configuration augmented by -ffreestanding and the one generated by a
'proper' freestanding build of libstdc++ differ currently. Maybe they
can be brought together close enough for Linux?
Managarm, which is the kernel I had in mind when working on getting more
freestanding stuff has a dedicated kernel build of GCC, however, so I
didn't test this case much. I'd like to, sooner or later, consolidate
it into the normal managarm system GCC, as a multilib, but I haven't had
time to do so yet.
In any case, I strongly prefer configuring toolchains 'properly'.
> Thanks,
> Andrew Pinski
>
>>
>> > (7) 'class', 'private', 'namespace'.
>> >
>> > (8) 'virtual'. Don't want virtual base classes, though virtual function
>> > tables might make operations tables more efficient.
>>
>> Operations tables *are* virtual classes. virtual base classes make sense
>> in a lot of cases, and we de facto use them already.
>>
>> However, Linux also does conversion of polymorphic objects from one type
>> to another -- that is for example how device nodes are implemented.
>> Using this with C++ polymorphism without RTTI does require some
>> compiler-specific hacks, unfortunately.
>>
>> > Issues:
>> >
>> > (1) Need spaces inserting between strings and symbols.
>>
>> I have to admit I don't really grok this?
>>
>> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
>> > g++ grudgingly permits it with -fpermissive. I would imagine that a
>> > compiler option could easily be added to hide the error entirely.
>>
>> Seriously. It should also enforce that it should be a trivial type.
>> Unfortunately it doesn't look like there is a way to create user-defined
>> implicit conversions from one pointer to another (via a helper class),
>> which otherwise would have had some other nice applications.
>>
>> > (3) Need gcc v8+ to statically initialise an object of any struct that's not
>> > really simple (e.g. if it's got an embedded union).
>>
>> Worst case: constexpr constructor.
>>
>> > (4) Symbol length. Really need to extern "C" everything to reduce the size
>> > of the symbols stored in the kernel image. This shouldn't be a problem
>> > if out-of-line function overloading isn't permitted.
>>
>> This really would lose arguably the absolutely biggest advantage of C++:
>> type-safe linkage. This is the one reason why Linus actually tried to
>> use C++ in one single version of the kernel in the early days (0.99.14,
>> if I remember correctly.) At that time, g++ was nowhere near mature
>> enough, and it got dropped right away.
>>
>>
>> > So far, it gets as far as compiling init/main.c to a .o file.
>>
>> ;)
--
Arsen Arsenović
> Can we get memory safety with C++ now? and also stop people coding C++
> like it's 1994?
What is the run-time cost?
Things like 'smart pointers' are dumb!
CSTRING is an abomination.
I suspect you need to pass array_pointer:length pairs about in
order to get reasonably array bound checking.
So splitting C's pointer-array equivalence.
But you then need to efficiently return them from functions.
That really needs a register pair be used.
Typically two registers are reserved for function returns,
but are only ever used for double-sized integers.
Doing that without compiler support would be hard work.
The other elephant in the room is compilation speed.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
David Howells <[email protected]> writes:
> Here are a series of patches to start converting the kernel to C++. It
> requires g++ v8.
>
> What rocks:
>
> (1) Inline template functions, which makes implementation of things like
> cmpxchg() and get_user() much cleaner.
>
> (2) Inline overloaded functions, which makes implementation of things like
> static_branch_likely() cleaner.
>
> (3) Class inheritance. For instance, all those inode wrappers that require
> the base inode struct to be included and that has to be accessed with
> something like:
>
> inode->vfs_inode.i_mtime
>
> when you could instead do:
>
> inode->i_mtime
>
> What I would disallow:
>
> (1) new and delete. There's no way to pass GFP_* flags in.
>
> (2) Constructors and destructors. Nests of implicit code makes the code less
> obvious, and the replacement of static initialisation with constructor
> calls would make the code size larger.
This also disallows the primary benefit of C++ (RAII), though. A lot of
static initialization can be achieved using constexpr and consteval,
too.
It is incredibly useful to be able to express resource ownership in
terms of automatic storage duration.
> (3) Exceptions and RTTI. RTTI would bulk the kernel up too much and
> exception handling is limited without it, and since destructors are not
> allowed, you still have to manually clean up after an error.
>
> (4) Operator overloading (except in special cases).
>
> (5) Function overloading (except in special inline cases).
Generic code, another significant benefit of C++, requires function
overloading, though.
> (6) STL (though some type trait bits are needed to replace __builtins that
> don't exist in g++).
A lot of useful stuff that works fine in kernel contexts is in the STL,
though. For instance, nearly everything from the iterators, ranges,
utility, memory, and algorithms library works fine. Naturally,
concepts, type traits, and language support libraries are also fine.
> (7) 'class', 'private', 'namespace'.
'class' does nothing that struct doesn't do, private and namespace serve
simply for encapsulation, so I don't see why banning these is useful.
> (8) 'virtual'. Don't want virtual base classes, though virtual function
> tables might make operations tables more efficient.
Virtual base classes are seldom useful, but I see no reason to
blanket-ban them (and I suspect you'll never notice that they're not
banned).
> Issues:
>
> (1) Need spaces inserting between strings and symbols.
>
> (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> g++ grudgingly permits it with -fpermissive. I would imagine that a
> compiler option could easily be added to hide the error entirely.
This should never be useful.
Have a lovely night!
> (3) Need gcc v8+ to statically initialise an object of any struct that's not
> really simple (e.g. if it's got an embedded union).
>
> (4) Symbol length. Really need to extern "C" everything to reduce the size
> of the symbols stored in the kernel image. This shouldn't be a problem
> if out-of-line function overloading isn't permitted.
>
> So far, it gets as far as compiling init/main.c to a .o file.
>
> Seriously, though...
>
> Apart from the cleaner inline functions allowed by templating, I'm not sure
> there's a lot of the C++ language that we would want to use in the kernel
> unless we want to go for more advanced classes implementing interesting types.
>
> We could, for example, wrap things like userspace pointers, __be numbers,
> ioport addresses and control access to them that way, but I don't know that it
> gains a whole load that sparse doesn't give us.
>
> And finally, doing this did find a few minor things that can be fixed.
>
> David
> ---
> David Howells (45):
> Use UINT_MAX, not -1, to represent an invalid UID, GID or project ID
> Fix exception_enter() return value
> Fix loop var in be32_to_cpu_array() and cpu_to_be32_array()
> Fix use of ACPI_COMPANION_SET()
> C++: Set compilation as C++ for .c files
> C++: Do some basic C++ type definition
> C++: Define a header with some C++ type traits for type checking
> C++: Implement abs() as an inline template function
> C++: x86: Fix the x86 syscall table production for C++
> C++: x86: Turn xchg(), xadd() & co. into inline template functions
> C++: x86: Turn cmpxchg() & co. into inline template functions
> C++: x86: Turn cmpxchg_double() & co. into inline template functions
> C++: x86: Turn cmpxchg64() & co. into inline template functions
> C++: x86: Turn put_user(), get_user() & co. into inline template functions
> C++: Need space between string and symbol
> C++: Disable VERIFY_OCTAL_PERMISSIONS() for the moment
> C++: Turn READ_ONCE(), WRITE_ONCE() & co. into inline template functions
> C++: Turn RCU accessors into inline template functions
> C++: Turn ktime_add/sub_ns() into inline template functions
> C++: init/main: Constify pointers
> C++: Set the type of atomic64_t to s64
> C++: Define apic_intr_mode after the enum definition, not before
> C++: Don't do "extern asmlinkage"
> C++: Fix BUILD_BUG_ON_ZERO()
> C++: Fix void variables
> C++: Can't have variable/member names the same as typedef names
> C++: Disable __same_type() for the moment
> C++: Move ctx_state enum out of struct context_tracking
> C++: Move the print_line_t enum before first use
> C++: Include linux/hrtimer.h from linux/timer.h
> C++: Avoid using 'compl' and 'and' as names
> C++: __to_fd() needs to reduce the size of v for struct fd::flags
> C++: Move irqchip_irq_state enum
> C++: Fix up use of LIST_POISON*
> C++: Fix static_branch_likely/unlikely()
> C++: Fix kernfs_type() int->enum
> C++: Fix page_zonenum() int->enum
> C++: mutex_trylock_recursive_enum() int->enum
> C++: Fix spinlock initialisation
> C++: Fix sema_init()
> C++: Cast in bitops
> C++: Hide C++ keywords
> C++: Don't need to declare struct pgd_t after typedef
> C++: Can't declare unsized-array in struct cgroup
> C++: Move initcall_level_names[] to __initdata section
>
>
> Makefile | 13 -
> arch/x86/Makefile | 2
> arch/x86/entry/syscalls/Makefile | 8
> arch/x86/entry/syscalls/syscallhdr.pl | 73 ++++
> arch/x86/entry/syscalls/syscalltbl.pl | 95 +++++
> arch/x86/include/asm/alternative.h | 10 -
> arch/x86/include/asm/apic.h | 2
> arch/x86/include/asm/arch_hweight.h | 4
> arch/x86/include/asm/atomic.h | 2
> arch/x86/include/asm/atomic64_64.h | 12 -
> arch/x86/include/asm/cmpxchg.h | 430 +++++++++++-----------
> arch/x86/include/asm/cmpxchg_64.h | 28 +
> arch/x86/include/asm/hw_irq.h | 38 +-
> arch/x86/include/asm/percpu.h | 94 ++---
> arch/x86/include/asm/perf_event.h | 2
> arch/x86/include/asm/processor.h | 2
> arch/x86/include/asm/special_insns.h | 2
> arch/x86/include/asm/tlbflush.h | 1
> arch/x86/include/asm/uaccess.h | 630 +++++++++++++++++---------------
> arch/x86/include/asm/uaccess_64.h | 66 +--
> arch/x86/kernel/asm-offsets_32.c | 1
> arch/x86/kernel/asm-offsets_64.c | 1
> arch/x86/purgatory/Makefile | 2
> include/asm-generic/bitops/le.h | 32 +-
> include/asm-generic/sections.h | 2
> include/linux/acpi.h | 2
> include/linux/backing-dev-defs.h | 4
> include/linux/blkdev.h | 86 ++--
> include/linux/build_bug.h | 5
> include/linux/byteorder/generic.h | 4
> include/linux/cgroup-defs.h | 2
> include/linux/compat.h | 2
> include/linux/compiler-c++.h | 54 +++
> include/linux/compiler-gcc.h | 5
> include/linux/compiler.h | 93 +----
> include/linux/compiler_types.h | 2
> include/linux/context_tracking.h | 4
> include/linux/context_tracking_state.h | 14 -
> include/linux/cpumask.h | 4
> include/linux/crypto.h | 4
> include/linux/elevator.h | 82 ++--
> include/linux/file.h | 2
> include/linux/interrupt.h | 10 -
> include/linux/irq.h | 1
> include/linux/irqflags.h | 10 +
> include/linux/jump_label.h | 41 +-
> include/linux/kernel.h | 35 --
> include/linux/kernfs.h | 2
> include/linux/ktime.h | 12 +
> include/linux/list.h | 8
> include/linux/list_bl.h | 4
> include/linux/list_nulls.h | 2
> include/linux/lockdep.h | 2
> include/linux/mm.h | 2
> include/linux/mutex.h | 5
> include/linux/page-flags.h | 3
> include/linux/poison.h | 6
> include/linux/printk.h | 4
> include/linux/projid.h | 2
> include/linux/rculist.h | 4
> include/linux/rculist_bl.h | 2
> include/linux/rcupdate.h | 124 ++++--
> include/linux/sched/task.h | 2
> include/linux/semaphore.h | 5
> include/linux/spinlock.h | 2
> include/linux/spinlock_types.h | 4
> include/linux/start_kernel.h | 2
> include/linux/stddef.h | 12 -
> include/linux/sysctl.h | 6
> include/linux/timer.h | 1
> include/linux/trace_events.h | 16 -
> include/linux/types.h | 16 +
> include/linux/uidgid.h | 4
> init/main.c | 4
> scripts/checksyscalls.sh | 2
> tools/power/cpupower/Makefile | 1
> tools/virtio/Makefile | 2
> 77 files changed, 1269 insertions(+), 1010 deletions(-)
> create mode 100644 arch/x86/entry/syscalls/syscallhdr.pl
> create mode 100644 arch/x86/entry/syscalls/syscalltbl.pl
> create mode 100644 include/linux/compiler-c++.h
--
Arsen Arsenović
On 1/10/24 09:57, Theodore Ts'o wrote:
> On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
>>
>> For what it's worth, I'm totally in favor of C++20 as well. I've
>> mostly written C++17 as of late and it is really nice to me, but I'm
>> genuinely excited about C++20 and newer revisions.
>>
>> I also think that Linux adopting C++ and intentionally adopting safety
>> features that exist and are being added to C++ over time would also
>> further encourage the ecosystem to use them as well as make the Linux
>> codebase much easier to work with.
>
> Can someone speak to whether the C++ standards committee and C++
> compiler implementations are more or less unreasonable compared to
> their C counterparts regarding compilers being able to arbitrary
> statement reordering, or other random futzing all in the name of
> better benchmarks, but which make life a living nightmware for honest
> kernel developers?
>
I suspect that the gcc and clang developers are more motivated these
days about such issues since they are now using C++ as their own
implementation language.
I had a member of the C++ standards committee reach out to me already,
and I'm going to have a discussion with him next week.
I have a lot more to say in response to all the (excellent!) comments,
but I'm about to leave for a long birthday weekend, so my apologies if I
don't get back to things until next week.
-hpa
On 1/9/24 15:40, David Howells wrote:
>
>> Both C and C++ has had a lot of development since 1999, and C++ has in fact,
>> in my personal opinion, finally "grown up" to be a better C for the kind of
>> embedded programming that an OS kernel epitomizes.
>
> And gcc got rewritten in C++ some time back, so they have a vested interest.
>
Indeed.
>>> (8) 'virtual'. Don't want virtual base classes, though virtual function
>>> tables might make operations tables more efficient.
>>
>> Operations tables *are* virtual classes. virtual base classes make sense in a
>> lot of cases, and we de facto use them already.
>
> You end up adding storage for a 'this' pointer for each virtual base class, I
> think - and then you may have extra fun if you inherit from two classes that
> both inherit the same virtual base class. Abstract base classes that are just
> ops tables are probably fine, though.
My apologies, I meant *abstract* base classes, not *virtual*. To be
honest, I don't think I have ever used virtual base classes in any other
application than games (relating to physical objects), and barely even then.
-hpa
On 1/9/24 15:40, David Howells wrote:
>
>>> Issues:
>>> (1) Need spaces inserting between strings and symbols.
>>
>> I have to admit I don't really grok this?
>
> You're not allowed to do things like:
>
> asm volatile("btl "__percpu_arg(2)",%1"
>
> but rather have to do:
>
> asm volatile("btl " __percpu_arg(2) ",%1"
>
> as you're now allowed to specify type qualifiers. See
>
> https://en.cppreference.com/w/cpp/language/user_literal
>
Oh, right. This one should be easy enough to automate, though.
-hpa
On Thu, Jan 11, 2024 at 06:23:10PM -0800, H. Peter Anvin wrote:
>
>
> On 1/10/24 09:57, Theodore Ts'o wrote:
> > On Wed, Jan 10, 2024 at 11:25:29AM -0500, Neal Gompa wrote:
> > >
> > > For what it's worth, I'm totally in favor of C++20 as well. I've
> > > mostly written C++17 as of late and it is really nice to me, but I'm
> > > genuinely excited about C++20 and newer revisions.
> > >
> > > I also think that Linux adopting C++ and intentionally adopting safety
> > > features that exist and are being added to C++ over time would also
> > > further encourage the ecosystem to use them as well as make the Linux
> > > codebase much easier to work with.
> >
> > Can someone speak to whether the C++ standards committee and C++
> > compiler implementations are more or less unreasonable compared to
> > their C counterparts regarding compilers being able to arbitrary
> > statement reordering, or other random futzing all in the name of
> > better benchmarks, but which make life a living nightmware for honest
> > kernel developers?
> >
>
> I suspect that the gcc and clang developers are more motivated these days
> about such issues since they are now using C++ as their own implementation
> language.
>
> I had a member of the C++ standards committee reach out to me already, and
> I'm going to have a discussion with him next week.
>
> I have a lot more to say in response to all the (excellent!) comments, but
> I'm about to leave for a long birthday weekend, so my apologies if I don't
> get back to things until next week.
Happy birthday, Peter :)
Would this cause any issues for the Rust people, e.g. linking? I'd like
to hear their input.
One thing I forgot to mention that would be quite useful is careful use
of namespaces. For example, putting init functions in their own
namespace would have not only make it a lot harder to call init
functions from non-init functions by mistake (calling init::func()
explicitly is a highly visible "I really do mean to do this."
However, it also let us do separate init versions of functions like
cpu_feature_enable() that contain optimizations that aren't actually
usable at init time (alternatives have not been applied.) The idea is
*not* to change the code, but rather the compiler will simply prefer
init:: functions from inside other init:: functions (a direct
consequence of how namespaces work.)
-hpa
H. Peter Anvin <[email protected]> wrote:
> One thing I forgot to mention that would be quite useful is careful use of
> namespaces.
Just be aware that the use of namespaces would make the kernel image bigger if
symbols are included.
David
Arsen Arsenović <[email protected]> wrote:
> > (2) Constructors and destructors. Nests of implicit code makes the code less
> > obvious, and the replacement of static initialisation with constructor
> > calls would make the code size larger.
>
> This also disallows the primary benefit of C++ (RAII), though. A lot of
> static initialization can be achieved using constexpr and consteval,
> too.
Okay, let me downgrade that to "I wouldn't allow it at first". The primary
need for destructors, I think, is exception handling. And don't get me wrong,
I like the idea of exception handling - so many bugs come because we mischeck
or forget to check the error.
> It is incredibly useful to be able to express resource ownership in
> terms of automatic storage duration.
Oh, indeed, yes - but you also have to be careful:
(1) You don't always want to wait till the end of the scope before releasing
resources.
(2) Expressing ownership of something like a lock so that it is automatically
undone may require extra memory is currently unnecessary:
struct foo {
struct rwsem sem;
};
myfunc(struct foo *foo)
{
...
struct foo_shared_lock mylock(foo->sem);
...
}
This looks like a nice way to automatically take and hold a lock, but I
don't think it can be done without storing the address of the semaphore
in mylock - something that isn't strictly necessary since we can find sem
from foo.
(3) We could implement a magic pointer class that automatically does
reference wangling (kref done right) - but we would have to be very
careful using it because we want to do the minimum number of atomic ops
on its refcount that we can manage, firstly because atomic ops are slow
and secondly because the atomic counter must not overflow.
> > (5) Function overloading (except in special inline cases).
>
> Generic code, another significant benefit of C++, requires function
> overloading, though.
I know. But I was thinking that we might want to disable name mangling if we
can so as not to bloat the size of the kernel image. That said, I do like the
idea of being able to have related functions of the same name with different
arguments rather than having to name each one differently.
> > (7) 'class', 'private', 'namespace'.
>
> 'class' does nothing that struct doesn't do, private and namespace serve
> simply for encapsulation, so I don't see why banning these is useful.
Namespaces would lead to image bloat as they make the symbols bigger.
Remember, the symbol list uses up unswappable memory.
We use class and private a lot as symbols already, so to get my stuff to
compile I had to #define them. Granted there's nothing intrinsically
different about classes and we could rename every instance of the symbol in
the kernel first.
When it comes to 'private', actually, I might withdraw my objection to it: it
would help delineate internal fields - but we would then have to change
out-of-line functions that use it to be members of the class - again
potentially increasing the size of the symbol table.
> > (8) 'virtual'. Don't want virtual base classes, though virtual function
> > tables might make operations tables more efficient.
>
> Virtual base classes are seldom useful, but I see no reason to
> blanket-ban them (and I suspect you'll never notice that they're not
> banned).
You can end up increasing the size of your structure as you may need multiple
virtual method pointer tables - and we have to be very careful about that as
some structures (dentry, inode and page for example) we have a *lot* of
instances of in a running kernel.
> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
> > g++ grudgingly permits it with -fpermissive. I would imagine that a
> > compiler option could easily be added to hide the error entirely.
>
> This should never be useful.
It's not a matter of whether it should be useful - we do this an awful lot and
every case of assigning to/from a void pointer would require some sort of
cast.
David
Thanks for your reply.
>> Namely, to prevent stagnation for the Kernel as well as continue to be
>> interesting to new developers.
>
> Which stagnation are you talking about, exactly ?
While I do not know what Linus was exactly thinking about when he
mentioned stagnation, I assume he was looking at it from the lens of
long-term maintainers. I'm basing this on the 2021 discussion on lwn:
https://lwn.net/Articles/870581/. Obviously there are plenty of
contributors every kernel release and while I don't have any numbers
there, I don't think # of contributors or # of contributions is an issue.
Still, the idea of C discouraging people to contribute resonates with
me. That is largely based on subjectivity so feel free to ignore it.
>
> While I've got a long list of ideas for modernizing the kernel
> (which I'm lacking time to actually work on), I'm unsure whether
> C++ really would be of much benefit. Especially considering that for
> many things there's no way to know / define how things will really
> look like on binary level.
Do you have any examples on what exactly in C++ obfuscates the resulting
binary? Everything I can think of, also applies to C: anything
implementation-defined, e.g. struct layout, high-order bit propagation
for shift operations,
There are things in the STL that are implementation defined, but the
proposal excludes the STL.
> Personally, the opposite had been one my primary reasons.
> Because it's so simple to understand - in contrast to the usual C++
> monster's i've seen so often in the wild. (I usually try to keep far
> away from C++ projects).
I have never understood the sentiment that C is supposedly simple.
Looking at the macros used in the kernel is one obvious big argument
against using C, as macros can be considered their own
language-inside-a-language. Another big argument against the sentiment
is the loose type system, where void* casts are everywhere you want to
do anything remotely type-generic, losing type information and making it
harder to grok the original intent.
Creating a compiler for C is 'easier' than creating one for C++ (or Rust
for that matter), but coding in it as a user requires years of
experience to avoid a lot of the pitfalls. A simple language would be
something like golang, with its GC and prescribed coding patterns.
C is a language to be (ab)used like any other, the same goes for C++.
The kernel has shown that it is possible to create maintainable C, I
feel confident saying that it is also possible in C++.
> Note that C++ is a very complex language,
> and w/ STL it's even much, much more complex.
Note that the proposal here is to use C++ without the STL as well as
apply some other restrictions.
> Can't judge what you see as interesting, but frankly, I really don't
> have it on my list of interesting things - instead would prefer phasing
> C++ out in favour of many other languages.
I could give you concrete examples of C++ language addition examples,
but I don't think that adds much to the discussion. Many languages,
including C++, have additions that C does not have and provide benefits
such as reduced cognitive load, standardised ways to do things
preventing NIH syndrome and possibly enthuse more people to contribute
to the kernel.
The biggest merit of using C++ in the kernel is that in comparison to
other systems language (Zig, Rust, Swift to name a few) it requires the
least re-skilling of existing contributors. A close second would be the
low barrier to integrate various C++ and C codebases. Especially when
taking into account the architectures that the kernel needs to support
vs the other languages. Even Rust with its big push towards being a
replacement isn't there yet today (e.g. PA-RISC).
>
>> other languages, unlike C. The aforementioned metaprogramming is one
>
> Metaprogramming can be very interesting indeed - Oberon once made a
> really good show case, but I wouldn't dare trying that in kernel space.
> And it's hard to do that w/o causing extra performance penalties.
I believe this is a case of having to try it first before being able to
decisively say anything about the impact. Counter-examples have been
mentioned elsewhere in the thread.
>
>> such example, but things like RAII, smart pointers and things like
>> gsl::not_null would reduce the changes on kernel bugs, especially
>> memory safety related bugs that are known to be vulnerable to security
>> issues.
>
> These are exactly the things I would prefer keeping out of kernel space.
> Indeed there're several areas where it could be nice, but there're
> others where we really can't take it.
As you mention yourself, there are places where such constructs would be
a boon and places where we should not apply them. I have faith in the
Kernel processes to weed out using things where they should not, as is
presumably done already for certain C constructs today.
>
>> On the other hand, the benefits I mention can also turn into
>> downsides: if constructs like gsl::not_null are desired, does that
>> mean that there
>
> this seems to be pretty much an assert() - obviously something we really
> cannot have in the kernel.
gsl::not_null prevents constructing a pointer with NULL, ensuring at
compile-time that it never happens. As such, an assert() would be
superfluous. It is exactly an example of a C++ construct that has no
downsides and only upsides.
>
>> will be a kernel-specific template library? A KTL instead of STL? That
>> might be yet another thing that increases the steepness of the kernel
>> development learning curve.
>
> Most likely we'd need our own kernel specific library. (we also have one
> instead of libc). Some simple pieces might look similar to STL on the
> front, but it would have to be very different from userland.
>
> At that point, your previous argument about attracting more people
> who're already used to / like C++ breaks down, because it wouldn't be
> that C++ as usual C++ devs know it (IIRC, STL is integral part of the
> standard), but just the core lang plus some very custom template lib.
It's not that the argument breaks down, it's that it applies to a
smaller, but still greater than 0, target audience. There are plenty of
C++ programmers out there that disable the STL on purpose: game
developers, automotive engineers that I know and so on. You're going to
be hard-pressed to find concrete numbers, but the fact that the EASTL
and ETL exist shows the proliferation of non-STL C++ and that the STL
itself is not an integral part of C++. I recommend you check out ETL
specifically, I'm sure you'll be amazed at how much functionality it
has, especially geared for the embedded world.
>
>> Although compiler-specific, C++20 has enabled implementing RTTI
>> without RTTI as well as (partial) reflection.
>
> You name it: compiler specific.
>
> Is it even specified how this exactly looks at binary level, and methods
> to control the exact binary data structures ?
>
> The least thing's need to implement such things is some pointer or tag
> inside each struct/object instance - this would change struct layouts!
> Note that we often use structs to reflect HW specific data structures,
> so we'd need a way to have exact control over this. And then we need to
> be very careful on which instances have RTTI and which ones don't.
> I see debugging nightmares on the horizon ...
I could be convinced that RTTI of any sort is just a bad idea in the
kernel. It is one of the things that is first to be disabled in embedded
C++ usage, alongside exceptions. Still, it has its uses even in those
areas, but that's outside of the scope of this proposal I think.
>
>> On top of increasing the binary size,
>
> That's also a huge problem:
>
> Templates in general have the strong tendency of producing lots of
> duplicated code. That's what they're designed for: expressing similar
> things (that have to be different on binary level) by the same
> generic source code.
>
> It might be possible to write them in a way they don't increase binary
> size, but that's not entirely trivial, and so the actual gain of all
> of that becomes questionable again.
Hmm, explicit template instantiations are an 'easy' fix to taming the
code bloat, but any use of templates is going to mean _some_ extra code
generation. I do not have any concrete Kernel examples here, but I'm
sure there are switch/case statements somewhere in there that can be
optimized away by using templates. For those, the question is: code
bloat or run-time performance?
>
>> this then becomes a discussion on what requirements the kernel puts on
>> compilers, as I'm sure that the kernel needs to be compiled for
>> architectures which have a less than stellar conformance to the C++
>> specification.
> Indeed. Also think about embedded environments, where folks can't easily
> upgrade toolchains (e.g. due regulative constraints)
>
This argument also applies against using Rust and is directly opposed to
modern security practices. Updating to the latest version for
OS/compilers/libraries etc is pretty much a given since UN R155 and UN
R156 came into effect. Though those apply only to automotive so far, the
Cyber Resilience Act is going to force manufacturers of all kinds to
adhere to better security. There is definitely a whole debate we can
have just on the impacts of these regulations and what that should mean,
but I've already written a lot ;)
Cheers,
Michael de Lang
David Howells <[email protected]> writes:
> Arsen Arsenović <[email protected]> wrote:
>
>> > (2) Constructors and destructors. Nests of implicit code makes the code less
>> > obvious, and the replacement of static initialisation with constructor
>> > calls would make the code size larger.
>>
>> This also disallows the primary benefit of C++ (RAII), though. A lot of
>> static initialization can be achieved using constexpr and consteval,
>> too.
>
> Okay, let me downgrade that to "I wouldn't allow it at first". The primary
> need for destructors, I think, is exception handling.
I'm not sure I agree, the amount of 'goto err' constructs in the kernel
seems to indicate otherwise to me. This feels like the exact same code,
except more error prone.
> And don't get me wrong, I like the idea of exception handling - so
> many bugs come because we mischeck or forget to check the error.
C++ also provides possible alternative avenues for solving such
problems, such as, for instance, an expected type with monadic
operations: https://en.cppreference.com/w/cpp/utility/expected
IIRC, using std::expected in managarm (where we previously used the IMO
far less nice Frigg expected type) is what initially prompted me to
start enabling the use of a lot of libstdc++ in kernel contexts, and
indeed, it is enabled there:
https://gcc.gnu.org/cgit/gcc/tree/libstdc++-v3/include/Makefile.am#n25
>> It is incredibly useful to be able to express resource ownership in
>> terms of automatic storage duration.
>
> Oh, indeed, yes - but you also have to be careful:
>
> (1) You don't always want to wait till the end of the scope before releasing
> resources.
One could move a resource out, or call a function akin to the 'reset()'
method of std::unique_ptr.
> (2) Expressing ownership of something like a lock so that it is automatically
> undone may require extra memory is currently unnecessary:
>
> struct foo {
> struct rwsem sem;
> };
>
>
> myfunc(struct foo *foo)
> {
> ...
> struct foo_shared_lock mylock(foo->sem);
> ...
> }
>
> This looks like a nice way to automatically take and hold a lock, but I
> don't think it can be done without storing the address of the semaphore
> in mylock - something that isn't strictly necessary since we can find sem
> from foo.
The compiler can often get rid of it. Here's an example:
https://godbolt.org/z/1W7bnYY7a
Simple enough wrapper classes like these combined with a modern
compilers IPA and inlining can really do magic :-)
> (3) We could implement a magic pointer class that automatically does
> reference wangling (kref done right) - but we would have to be very
> careful using it because we want to do the minimum number of atomic ops
> on its refcount that we can manage, firstly because atomic ops are slow
> and secondly because the atomic counter must not overflow.
With move semantics, this could be quite effective and general. The
shared_ptr from the standard library, for instance, won't bump
reference counts if moved. And temporaries are automatically moved.
You could make the class move-only so that *all* reference incrementing
requires a method call (and hence, is clear and obvious), while still
permitting auto-decrementing and preventing reference leakage.
>> > (5) Function overloading (except in special inline cases).
>>
>> Generic code, another significant benefit of C++, requires function
>> overloading, though.
>
> I know. But I was thinking that we might want to disable name mangling if we
> can so as not to bloat the size of the kernel image. That said, I do like the
> idea of being able to have related functions of the same name with different
> arguments rather than having to name each one differently.
Hmm, I can understand the symbol table size being an issue.
>> > (7) 'class', 'private', 'namespace'.
>>
>> 'class' does nothing that struct doesn't do, private and namespace serve
>> simply for encapsulation, so I don't see why banning these is useful.
>
> Namespaces would lead to image bloat as they make the symbols bigger.
> Remember, the symbol list uses up unswappable memory.
Ah, I was not aware of this restriction of the kernel (my understanding
was that the symbol table is outside of the kernel image). That poses a
problem, yes. I wonder if a big part of the symbol table (or even the
entirety of it) could be dropped from the kernel. I must say, I do not
know why the kernel has it, so I cannot speak on this issue.
> We use class and private a lot as symbols already, so to get my stuff to
> compile I had to #define them. Granted there's nothing intrinsically
> different about classes and we could rename every instance of the symbol in
> the kernel first.
I see. That is quite understandable then, especially if temporary.
> When it comes to 'private', actually, I might withdraw my objection to it: it
> would help delineate internal fields - but we would then have to change
> out-of-line functions that use it to be members of the class - again
> potentially increasing the size of the symbol table.
This is what I like about it too.
>> > (8) 'virtual'. Don't want virtual base classes, though virtual function
>> > tables might make operations tables more efficient.
>>
>> Virtual base classes are seldom useful, but I see no reason to
>> blanket-ban them (and I suspect you'll never notice that they're not
>> banned).
>
> You can end up increasing the size of your structure as you may need multiple
> virtual method pointer tables - and we have to be very careful about that as
> some structures (dentry, inode and page for example) we have a *lot* of
> instances of in a running kernel.
I retract what I said about virtual classes - I had, indeed, forgotten
about that issue (but, again, I doubt anyone will miss them ;-) ).
>> > (2) Direct assignment of pointers to/from void* isn't allowed by C++, though
>> > g++ grudgingly permits it with -fpermissive. I would imagine that a
>> > compiler option could easily be added to hide the error entirely.
>>
>> This should never be useful.
>
> It's not a matter of whether it should be useful - we do this an awful lot and
> every case of assigning to/from a void pointer would require some sort of
> cast.
I see. That could pose significant trouble.
Ideally, nearly all uses of void* could be lost sooner or later, as C++
has a more flexible (despite being stricter) type system.
Have a lovely day!
> David
--
Arsen Arsenović
Arsen Arsenović <[email protected]> wrote:
> >> > (7) 'class', 'private', 'namespace'.
> >>
> >> 'class' does nothing that struct doesn't do, private and namespace serve
> >> simply for encapsulation, so I don't see why banning these is useful.
> >
> > Namespaces would lead to image bloat as they make the symbols bigger.
> > Remember, the symbol list uses up unswappable memory.
>
> Ah, I was not aware of this restriction of the kernel (my understanding
> was that the symbol table is outside of the kernel image). That poses a
> problem, yes. I wonder if a big part of the symbol table (or even the
> entirety of it) could be dropped from the kernel. I must say, I do not
> know why the kernel has it, so I cannot speak on this issue.
You need at least a partial symbol table for module loading and we also have
the symbol table optionally included for oops message generation.
David
On January 12, 2024 12:52:03 AM PST, David Howells <[email protected]> wrote:
>H. Peter Anvin <[email protected]> wrote:
>
>> One thing I forgot to mention that would be quite useful is careful use of
>> namespaces.
>
>Just be aware that the use of namespaces would make the kernel image bigger if
>symbols are included.
>
>David
>
If we can leverage data compression it probably would be a lot of space due to the highly repetitive nature of most symbols. To allow for random access that requires a bit of sophistication, but nothing that couldn't be solved.
On 11. 01. 24, 20:40, David Laight wrote:
> I've seen the same issue with some C++ code that was like:
> (Pardon my C++ :-)
> foo = new();
> try {
> add_foo_to_list(foo);
> } except {
> free(foo);
> }
> The problem is that you have no idea whether the exception was
> thrown before or after 'foo' was saved.
> Since pretty much everything can 'throw' you really can't tell.
I don't follow, you can catch() specific (e.g. ENotAdded) exceptions.
> OTOH if add_foo_to_list() returns an error code you can know
> (and check) that zero is returned iff the pointer has been saved.
There is no difference between throwing exceptions (you can as well
embed an error code in a generic exception, if you want) and throwing
error numbers directly.
A different question is whether we want exceptions (RTTI) in the kernel
at all. Not sure about gcc, but for example LLVM does not.
regards,
--
js
suse labs