Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108588440
D29467.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D29467.diff
View Options
diff --git a/sys/compat/linuxkpi/common/include/linux/sched.h b/sys/compat/linuxkpi/common/include/linux/sched.h
--- a/sys/compat/linuxkpi/common/include/linux/sched.h
+++ b/sys/compat/linuxkpi/common/include/linux/sched.h
@@ -82,6 +82,7 @@
int bsd_interrupt_value;
struct work_struct *work; /* current work struct, if set */
struct task_struct *group_leader;
+ unsigned rcu_section[TS_RCU_TYPE_MAX];
};
#define current ({ \
diff --git a/sys/compat/linuxkpi/common/src/linux_rcu.c b/sys/compat/linuxkpi/common/src/linux_rcu.c
--- a/sys/compat/linuxkpi/common/src/linux_rcu.c
+++ b/sys/compat/linuxkpi/common/src/linux_rcu.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io)
- * Copyright (c) 2017-2020 Hans Petter Selasky (hselasky@freebsd.org)
+ * Copyright (c) 2017-2021 Hans Petter Selasky (hselasky@freebsd.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -85,6 +85,15 @@
*/
CTASSERT(sizeof(struct rcu_head) == sizeof(struct callback_head));
+/*
+ * Verify that "rcu_section[0]" has the same size as
+ * "ck_epoch_section_t". This has been done to avoid having to add
+ * special compile flags for including ck_epoch.h to all clients of
+ * the LinuxKPI.
+ */
+CTASSERT(sizeof(((struct task_struct *)0)->rcu_section[0] ==
+ sizeof(ck_epoch_section_t)));
+
/*
* Verify that "epoch_record" is at beginning of "struct
* linux_epoch_record":
@@ -189,6 +198,14 @@
if (RCU_SKIP())
return;
+ ts = current;
+
+ /* assert valid refcount */
+ MPASS(ts->rcu_recurse[type] != INT_MAX);
+
+ if (++(ts->rcu_recurse[type]) != 1)
+ return;
+
/*
* Pin thread to current CPU so that the unlock code gets the
* same per-CPU epoch record:
@@ -196,17 +213,15 @@
sched_pin();
record = &DPCPU_GET(linux_epoch_record[type]);
- ts = current;
/*
* Use a critical section to prevent recursion inside
* ck_epoch_begin(). Else this function supports recursion.
*/
critical_enter();
- ck_epoch_begin(&record->epoch_record, NULL);
- ts->rcu_recurse[type]++;
- if (ts->rcu_recurse[type] == 1)
- TAILQ_INSERT_TAIL(&record->ts_head, ts, rcu_entry[type]);
+ ck_epoch_begin(&record->epoch_record,
+ (ck_epoch_section_t *)&ts->rcu_section[type]);
+ TAILQ_INSERT_TAIL(&record->ts_head, ts, rcu_entry[type]);
critical_exit();
}
@@ -221,18 +236,24 @@
if (RCU_SKIP())
return;
- record = &DPCPU_GET(linux_epoch_record[type]);
ts = current;
+ /* assert valid refcount */
+ MPASS(ts->rcu_recurse[type] > 0);
+
+ if (--(ts->rcu_recurse[type]) != 0)
+ return;
+
+ record = &DPCPU_GET(linux_epoch_record[type]);
+
/*
* Use a critical section to prevent recursion inside
* ck_epoch_end(). Else this function supports recursion.
*/
critical_enter();
- ck_epoch_end(&record->epoch_record, NULL);
- ts->rcu_recurse[type]--;
- if (ts->rcu_recurse[type] == 0)
- TAILQ_REMOVE(&record->ts_head, ts, rcu_entry[type]);
+ ck_epoch_end(&record->epoch_record,
+ (ck_epoch_section_t *)&ts->rcu_section[type]);
+ TAILQ_REMOVE(&record->ts_head, ts, rcu_entry[type]);
critical_exit();
sched_unpin();
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 4:51 PM (6 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16201209
Default Alt Text
D29467.diff (3 KB)
Attached To
Mode
D29467: Reduce chance of RCU deadlock in the LinuxKPI by implementing the section feature of the concurrency kit, CK.
Attached
Detach File
Event Timeline
Log In to Comment