svn commit: r349763 - in stable/12/sys: kern sys

Hans Petter Selasky hselasky at FreeBSD.org
Fri Jul 5 12:26:32 UTC 2019


Author: hselasky
Date: Fri Jul  5 12:26:30 2019
New Revision: 349763
URL: https://svnweb.freebsd.org/changeset/base/349763

Log:
  MFC r340404, r340415, r340417, r340419 and r340420:
  Synchronize epoch(9) code with -head to make merging new patches
  and features easier.
  The FreeBSD version has been bumped to force recompilation of
  external kernel modules.
  
  Sponsored by:	Mellanox Technologies
  
  MFC r340404:
  Uninline epoch(9) entrance and exit. There is no proof that modern
  processors would benefit from avoiding a function call, but bloating
  code. In fact, clang created an uninlined real function for many
  object files in the network stack.
  
  - Move epoch_private.h into subr_epoch.c. Code copied exactly, avoiding
    any changes, including style(9).
  - Remove private copies of critical_enter/exit.
  
  Reviewed by:	kib, jtl
  Differential Revision:	https://reviews.freebsd.org/D17879
  
  MFC r340415:
  The dualism between epoch_tracker and epoch_thread is fragile and
  unnecessary. So, expose CK types to kernel and use a single normal
  structure for epoch_tracker.
  
  Reviewed by:	jtl, gallatin
  
  MFC r340417:
  With epoch not inlined, there is no point in using _lite KPI. While here,
  remove some unnecessary casts.
  
  MFC r340419:
  style(9), mostly adjusting overly long lines.
  
  MFC r340420:
  epoch(9) revert r340097 - no longer a need for multiple sections per cpu
  
  I spoke with Samy Bahra and recent changes to CK to make ck_epoch_call and
  ck_epoch_poll not modify the record have eliminated the need for this.

Deleted:
  stable/12/sys/sys/epoch_private.h
Modified:
  stable/12/sys/kern/genoffset.c
  stable/12/sys/kern/subr_epoch.c
  stable/12/sys/sys/epoch.h
  stable/12/sys/sys/param.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/kern/genoffset.c
==============================================================================
--- stable/12/sys/kern/genoffset.c	Fri Jul  5 10:31:37 2019	(r349762)
+++ stable/12/sys/kern/genoffset.c	Fri Jul  5 12:26:30 2019	(r349763)
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/assym.h>
 #include <sys/proc.h>
 
-OFFSYM(td_pre_epoch_prio, thread, u_char);
 OFFSYM(td_priority, thread, u_char);
 OFFSYM(td_epochnest, thread, u_char);
 OFFSYM(td_critnest, thread, u_int);

Modified: stable/12/sys/kern/subr_epoch.c
==============================================================================
--- stable/12/sys/kern/subr_epoch.c	Fri Jul  5 10:31:37 2019	(r349762)
+++ stable/12/sys/kern/subr_epoch.c	Fri Jul  5 12:26:30 2019	(r349763)
@@ -55,6 +55,27 @@ __FBSDID("$FreeBSD$");
 
 static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
 
+#ifdef __amd64__
+#define EPOCH_ALIGN CACHE_LINE_SIZE*2
+#else
+#define EPOCH_ALIGN CACHE_LINE_SIZE
+#endif
+
+TAILQ_HEAD (epoch_tdlist, epoch_tracker);
+typedef struct epoch_record {
+	ck_epoch_record_t er_record;
+	volatile struct epoch_tdlist er_tdlist;
+	volatile uint32_t er_gen;
+	uint32_t er_cpuid;
+} __aligned(EPOCH_ALIGN)     *epoch_record_t;
+
+struct epoch {
+	struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
+	epoch_record_t e_pcpu_record;
+	int	e_idx;
+	int	e_flags;
+};
+
 /* arbitrary --- needs benchmarking */
 #define MAX_ADAPTIVE_SPIN 100
 #define MAX_EPOCHS 64
@@ -119,11 +140,15 @@ epoch_init(void *arg __unused)
 	epoch_call_count = counter_u64_alloc(M_WAITOK);
 	epoch_call_task_count = counter_u64_alloc(M_WAITOK);
 
-	pcpu_zone_record = uma_zcreate("epoch_record pcpu", sizeof(struct epoch_record),
-	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_PCPU);
+	pcpu_zone_record = uma_zcreate("epoch_record pcpu",
+	    sizeof(struct epoch_record), NULL, NULL, NULL, NULL,
+	    UMA_ALIGN_PTR, UMA_ZONE_PCPU);
 	CPU_FOREACH(cpu) {
-		GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0, epoch_call_task, NULL);
-		taskqgroup_attach_cpu(qgroup_softirq, DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1, "epoch call task");
+		GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0,
+		    epoch_call_task, NULL);
+		taskqgroup_attach_cpu(qgroup_softirq,
+		    DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1,
+		    "epoch call task");
 	}
 	inited = 1;
 	global_epoch = epoch_alloc(0);
@@ -156,6 +181,15 @@ epoch_ctor(epoch_t epoch)
 	}
 }
 
+static void
+epoch_adjust_prio(struct thread *td, u_char prio)
+{
+
+	thread_lock(td);
+	sched_prio(td, prio);
+	thread_unlock(td);
+}
+
 epoch_t
 epoch_alloc(int flags)
 {
@@ -191,45 +225,120 @@ epoch_free(epoch_t epoch)
 	free(epoch, M_EPOCH);
 }
 
+static epoch_record_t
+epoch_currecord(epoch_t epoch)
+{
+
+	return (zpcpu_get_cpu(epoch->e_pcpu_record, curcpu));
+}
+
+#define INIT_CHECK(epoch)					\
+	do {							\
+		if (__predict_false((epoch) == NULL))		\
+			return;					\
+	} while (0)
+
 void
-epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
 {
+	struct epoch_record *er;
+	struct thread *td;
 
-	epoch_enter_preempt(epoch, et);
+	MPASS(cold || epoch != NULL);
+	INIT_CHECK(epoch);
+	MPASS(epoch->e_flags & EPOCH_PREEMPT);
+#ifdef EPOCH_TRACKER_DEBUG
+	et->et_magic_pre = EPOCH_MAGIC0;
+	et->et_magic_post = EPOCH_MAGIC1;
+#endif
+	td = curthread;
+	et->et_td = td;
+	td->td_epochnest++;
+	critical_enter();
+	sched_pin();
+
+	td->td_pre_epoch_prio = td->td_priority;
+	er = epoch_currecord(epoch);
+	TAILQ_INSERT_TAIL(&er->er_tdlist, et, et_link);
+	ck_epoch_begin(&er->er_record, &et->et_section);
+	critical_exit();
 }
 
 void
-epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter(epoch_t epoch)
 {
+	struct thread *td;
+	epoch_record_t er;
 
-	epoch_exit_preempt(epoch, et);
+	MPASS(cold || epoch != NULL);
+	INIT_CHECK(epoch);
+	td = curthread;
+
+	td->td_epochnest++;
+	critical_enter();
+	er = epoch_currecord(epoch);
+	ck_epoch_begin(&er->er_record, NULL);
 }
 
 void
-epoch_enter_KBI(epoch_t epoch)
+epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
 {
+	struct epoch_record *er;
+	struct thread *td;
 
-	epoch_enter(epoch);
+	INIT_CHECK(epoch);
+	td = curthread;
+	critical_enter();
+	sched_unpin();
+	MPASS(td->td_epochnest);
+	td->td_epochnest--;
+	er = epoch_currecord(epoch);
+	MPASS(epoch->e_flags & EPOCH_PREEMPT);
+	MPASS(et != NULL);
+	MPASS(et->et_td == td);
+#ifdef EPOCH_TRACKER_DEBUG
+	MPASS(et->et_magic_pre == EPOCH_MAGIC0);
+	MPASS(et->et_magic_post == EPOCH_MAGIC1);
+	et->et_magic_pre = 0;
+	et->et_magic_post = 0;
+#endif
+#ifdef INVARIANTS
+	et->et_td = (void*)0xDEADBEEF;
+#endif
+	ck_epoch_end(&er->er_record, &et->et_section);
+	TAILQ_REMOVE(&er->er_tdlist, et, et_link);
+	er->er_gen++;
+	if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
+		epoch_adjust_prio(td, td->td_pre_epoch_prio);
+	critical_exit();
 }
 
 void
-epoch_exit_KBI(epoch_t epoch)
+epoch_exit(epoch_t epoch)
 {
+	struct thread *td;
+	epoch_record_t er;
 
-	epoch_exit(epoch);
+	INIT_CHECK(epoch);
+	td = curthread;
+	MPASS(td->td_epochnest);
+	td->td_epochnest--;
+	er = epoch_currecord(epoch);
+	ck_epoch_end(&er->er_record, NULL);
+	critical_exit();
 }
 
 /*
- * epoch_block_handler_preempt is a callback from the ck code when another thread is
- * currently in an epoch section.
+ * epoch_block_handler_preempt() is a callback from the CK code when another
+ * thread is currently in an epoch section.
  */
 static void
-epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t *cr,
-    void *arg __unused)
+epoch_block_handler_preempt(struct ck_epoch *global __unused,
+    ck_epoch_record_t *cr, void *arg __unused)
 {
 	epoch_record_t record;
 	struct thread *td, *owner, *curwaittd;
-	struct epoch_thread *tdwait;
+	struct epoch_tracker *tdwait;
 	struct turnstile *ts;
 	struct lock_object *lock;
 	int spincount, gen;
@@ -317,25 +426,27 @@ epoch_block_handler_preempt(struct ck_epoch *global __
 		if (TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd) &&
 		    ((ts = curwaittd->td_blocked) != NULL)) {
 			/*
-			 * We unlock td to allow turnstile_wait to reacquire the
-			 * the thread lock. Before unlocking it we enter a critical
-			 * section to prevent preemption after we reenable interrupts
-			 * by dropping the thread lock in order to prevent curwaittd
-			 * from getting to run.
+			 * We unlock td to allow turnstile_wait to reacquire
+			 * the thread lock. Before unlocking it we enter a
+			 * critical section to prevent preemption after we
+			 * reenable interrupts by dropping the thread lock in
+			 * order to prevent curwaittd from getting to run.
 			 */
 			critical_enter();
 			thread_unlock(td);
 			owner = turnstile_lock(ts, &lock);
 			/*
-			 * The owner pointer indicates that the lock succeeded. Only
-			 * in case we hold the lock and the turnstile we locked is still
-			 * the one that curwaittd is blocked on can we continue. Otherwise
-			 * The turnstile pointer has been changed out from underneath
-			 * us, as in the case where the lock holder has signalled curwaittd,
+			 * The owner pointer indicates that the lock succeeded.
+			 * Only in case we hold the lock and the turnstile we
+			 * locked is still the one that curwaittd is blocked on
+			 * can we continue. Otherwise the turnstile pointer has
+			 * been changed out from underneath us, as in the case
+			 * where the lock holder has signalled curwaittd,
 			 * and we need to continue.
 			 */
 			if (owner != NULL && ts == curwaittd->td_blocked) {
-				MPASS(TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd));
+				MPASS(TD_IS_INHIBITED(curwaittd) &&
+				    TD_ON_LOCK(curwaittd));
 				critical_exit();
 				turnstile_wait(ts, owner, curwaittd->td_tsqueue);
 				counter_u64_add(turnstile_count, 1);
@@ -385,9 +496,8 @@ epoch_wait_preempt(epoch_t epoch)
 	if ((epoch->e_flags & EPOCH_LOCKED) == 0)
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 		    "epoch_wait() can be long running");
-	KASSERT(!in_epoch(epoch),
-			("epoch_wait_preempt() called in the middle "
-			 "of an epoch section of the same epoch"));
+	KASSERT(!in_epoch(epoch), ("epoch_wait_preempt() called in the middle "
+	    "of an epoch section of the same epoch"));
 #endif
 	thread_lock(td);
 	DROP_GIANT();
@@ -400,7 +510,8 @@ epoch_wait_preempt(epoch_t epoch)
 	td->td_pinned = 0;
 	sched_bind(td, old_cpu);
 
-	ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt, NULL);
+	ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt,
+	    NULL);
 
 	/* restore CPU binding, if any */
 	if (was_bound != 0) {
@@ -501,7 +612,7 @@ epoch_call_task(void *arg __unused)
 	head = ck_stack_batch_pop_npsc(&cb_stack);
 	for (cursor = head; cursor != NULL; cursor = next) {
 		struct ck_epoch_entry *entry =
-		ck_epoch_entry_container(cursor);
+		    ck_epoch_entry_container(cursor);
 
 		next = CK_STACK_NEXT(cursor);
 		entry->function(entry);
@@ -511,7 +622,7 @@ epoch_call_task(void *arg __unused)
 int
 in_epoch_verbose(epoch_t epoch, int dump_onfail)
 {
-	struct epoch_thread *tdwait;
+	struct epoch_tracker *tdwait;
 	struct thread *td;
 	epoch_record_t er;
 
@@ -544,12 +655,4 @@ int
 in_epoch(epoch_t epoch)
 {
 	return (in_epoch_verbose(epoch, 0));
-}
-
-void
-epoch_adjust_prio(struct thread *td, u_char prio)
-{
-	thread_lock(td);
-	sched_prio(td, prio);
-	thread_unlock(td);
 }

Modified: stable/12/sys/sys/epoch.h
==============================================================================
--- stable/12/sys/sys/epoch.h	Fri Jul  5 10:31:37 2019	(r349762)
+++ stable/12/sys/sys/epoch.h	Fri Jul  5 12:26:30 2019	(r349763)
@@ -29,10 +29,17 @@
 
 #ifndef _SYS_EPOCH_H_
 #define _SYS_EPOCH_H_
+
+struct epoch_context {
+	void   *data[2];
+} __aligned(sizeof(void *));
+
+typedef struct epoch_context *epoch_context_t;
+
 #ifdef _KERNEL
 #include <sys/lock.h>
 #include <sys/pcpu.h>
-#endif
+#include <ck_epoch.h>
 
 struct epoch;
 typedef struct epoch *epoch_t;
@@ -43,22 +50,19 @@ typedef struct epoch *epoch_t;
 extern epoch_t global_epoch;
 extern epoch_t global_epoch_preempt;
 
-struct epoch_context {
-	void   *data[2];
-} __aligned(sizeof(void *));
-
-typedef struct epoch_context *epoch_context_t;
-
-
 struct epoch_tracker {
-	void *datap[3];
-#ifdef EPOCH_TRACKER_DEBUG
-	int datai[5];
-#else
-	int datai[1];
+#ifdef	EPOCH_TRACKER_DEBUG
+#define	EPOCH_MAGIC0 0xFADECAFEF00DD00D
+#define	EPOCH_MAGIC1 0xBADDBABEDEEDFEED
+	uint64_t et_magic_pre;
 #endif
+	TAILQ_ENTRY(epoch_tracker) et_link;
+	struct thread *et_td;
+	ck_epoch_section_t et_section;
+#ifdef	EPOCH_TRACKER_DEBUG
+	uint64_t et_magic_post;
+#endif
 }  __aligned(sizeof(void *));
-
 typedef struct epoch_tracker *epoch_tracker_t;
 
 epoch_t	epoch_alloc(int flags);
@@ -68,26 +72,15 @@ void	epoch_wait_preempt(epoch_t epoch);
 void	epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t));
 int	in_epoch(epoch_t epoch);
 int in_epoch_verbose(epoch_t epoch, int dump_onfail);
-#ifdef _KERNEL
 DPCPU_DECLARE(int, epoch_cb_count);
 DPCPU_DECLARE(struct grouptask, epoch_cb_task);
 #define EPOCH_MAGIC0 0xFADECAFEF00DD00D
 #define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
 
-void epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_enter_KBI(epoch_t epoch);
-void epoch_exit_KBI(epoch_t epoch);
+void epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_enter(epoch_t epoch);
+void epoch_exit(epoch_t epoch);
 
-
-#if defined(KLD_MODULE) && !defined(KLD_TIED)
-#define epoch_enter_preempt(e, t)	epoch_enter_preempt_KBI((e), (t))
-#define epoch_exit_preempt(e, t)	epoch_exit_preempt_KBI((e), (t))
-#define epoch_enter(e)	epoch_enter_KBI((e))
-#define epoch_exit(e)	epoch_exit_KBI((e))
-#else
-#include <sys/epoch_private.h>
-#endif /* KLD_MODULE */
-
-#endif /* _KERNEL */
-#endif
+#endif	/* _KERNEL */
+#endif	/* _SYS_EPOCH_H_ */

Modified: stable/12/sys/sys/param.h
==============================================================================
--- stable/12/sys/sys/param.h	Fri Jul  5 10:31:37 2019	(r349762)
+++ stable/12/sys/sys/param.h	Fri Jul  5 12:26:30 2019	(r349763)
@@ -60,7 +60,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1200512	/* Master, propagated to newvers */
+#define __FreeBSD_version 1200513	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,


More information about the svn-src-stable-12 mailing list