* Re: [PATCH 34/45] C++: Fix up use of LIST_POISON*
@ 2018-04-01 21:28 Alexey Dobriyan
0 siblings, 0 replies; 2+ messages in thread
From: Alexey Dobriyan @ 2018-04-01 21:28 UTC (permalink / raw)
To: dhowells; +Cc: linux-kernel
> - 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 */
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH 00/45] C++: Convert the kernel to C++
@ 2018-04-01 20:40 David Howells
2018-04-01 20:43 ` [PATCH 34/45] C++: Fix up use of LIST_POISON* David Howells
0 siblings, 1 reply; 2+ messages in thread
From: David Howells @ 2018-04-01 20:40 UTC (permalink / raw)
To: linux-kernel
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
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH 34/45] C++: Fix up use of LIST_POISON*
2018-04-01 20:40 [PATCH 00/45] C++: Convert the kernel to C++ David Howells
@ 2018-04-01 20:43 ` David Howells
0 siblings, 0 replies; 2+ messages in thread
From: David Howells @ 2018-04-01 20:43 UTC (permalink / raw)
To: linux-kernel
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 <dhowells@redhat.com>
---
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));
}
/**
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-04-01 21:28 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-01 21:28 [PATCH 34/45] C++: Fix up use of LIST_POISON* Alexey Dobriyan
-- strict thread matches above, loose matches on Subject: below --
2018-04-01 20:40 [PATCH 00/45] C++: Convert the kernel to C++ David Howells
2018-04-01 20:43 ` [PATCH 34/45] C++: Fix up use of LIST_POISON* David Howells
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox