Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jul 2002 15:34:33 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        John Baldwin <jhb@FreeBSD.ORG>
Cc:        Alfred Perlstein <bright@mu.org>, freebsd-current@FreeBSD.ORG, Peter Wemm <peter@FreeBSD.ORG>, Julian Elischer <julian@elischer.org>
Subject:   Proposed fix for SMP vm_zeroidle.c
Message-ID:  <200207112234.g6BMYXnH012160@apollo.backplane.com>
References:   <XFMail.20020708204655.jhb@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
    Here is my proposed fix for the page-zeroing problem w/ SMP.  It
    is untested (I'm about to test it)... I'm looking for comments on
    the concept.  If the comments are positive and my testing succeeds I
    will commit it tonight.

    Basically the idea is simple.  Provide a function that mi_switch() can
    call when switching in a thread.  The page zeroing code sets this
    function to cpu_invlpg(CADDR3) on switch-in, thus dealing with any
    potential switch between cpu's with virtually no overhead (no overhead
    that we care about anyway).

    I daresay that this mechanism could be used for a number of other
    purposes as well.

    What do you think?

					-Matt

Index: i386/i386/pmap.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/pmap.c,v
retrieving revision 1.335
diff -u -r1.335 pmap.c
--- i386/i386/pmap.c	8 Jul 2002 04:24:25 -0000	1.335
+++ i386/i386/pmap.c	11 Jul 2002 22:23:22 -0000
@@ -2687,6 +2687,21 @@
 	*CMAP2 = 0;
 }
 
+#ifdef SMP
+
+/*
+ *	Called with the scheduler lock held when pmap_zero_page_idle() is
+ *	switched in, to ensure that we are not working with a stale TLB
+ *	entry if we switch cpus.
+ */
+static void
+pmap_zpi_switchin(void)
+{
+	cpu_invlpg(CADDR3);
+}
+
+#endif
+
 /*
  *	pmap_zero_page_idle zeros the specified hardware page by mapping 
  *	the page into KVM and using bzero to clear its contents.  This
@@ -2703,12 +2718,9 @@
 
 	*CMAP3 = PG_V | PG_RW | phys | PG_A | PG_M;
 #ifdef SMP
-	mtx_lock(&Giant);	/* IPI sender not MPSAFE */
-#endif
-	invltlb_1pg((vm_offset_t)CADDR3);
-#ifdef SMP
-	mtx_unlock(&Giant);
+	curthread->td_switchin = pmap_zpi_switchin;
 #endif
+	cpu_invlpg(CADDR3);
 
 #if defined(I686_CPU)
 	if (cpu_class == CPUCLASS_686)
@@ -2716,6 +2728,9 @@
 	else
 #endif
 		bzero(CADDR3, PAGE_SIZE);
+#ifdef SMP
+	curthread->td_switchin = NULL;
+#endif
 	*CMAP3 = 0;
 }
 
Index: kern/kern_synch.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_synch.c,v
retrieving revision 1.182
diff -u -r1.182 kern_synch.c
--- kern/kern_synch.c	6 Jul 2002 08:47:24 -0000	1.182
+++ kern/kern_synch.c	11 Jul 2002 22:15:05 -0000
@@ -892,6 +892,13 @@
 	if (PCPU_GET(switchtime.sec) == 0)
 		binuptime(PCPU_PTR(switchtime));
 	PCPU_SET(switchticks, ticks);
+
+	/*
+	 * Call the switchin function while still holding the scheduler lock
+	 * (used by the idlezero code)
+	 */
+	if (td->td_switchin)
+		td->td_switchin();
 }
 
 /*
Index: sys/proc.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/proc.h,v
retrieving revision 1.227
diff -u -r1.227 proc.h
--- sys/proc.h	8 Jul 2002 01:49:49 -0000	1.227
+++ sys/proc.h	11 Jul 2002 22:13:13 -0000
@@ -285,6 +285,7 @@
 	int		td_intr_nesting_level; /* (k) Interrupt recursion. */
 	void 		*td_mailbox;	/* the userland mailbox address */
 	struct ucred	*td_ucred;	/* (k) Reference to credentials. */
+	void		(*td_switchin)(void); /* (k) switchin special func */
 #define	td_endzero td_md
 
 #define	td_startcopy td_endzero
Index: vm/vm_zeroidle.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_zeroidle.c,v
retrieving revision 1.13
diff -u -r1.13 vm_zeroidle.c
--- vm/vm_zeroidle.c	8 Jul 2002 23:12:37 -0000	1.13
+++ vm/vm_zeroidle.c	11 Jul 2002 22:11:50 -0000
@@ -30,11 +30,7 @@
 SYSCTL_INT(_vm_stats_misc, OID_AUTO,
 	cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, "");
 
-#ifdef SMP
-static int idlezero_enable = 0;
-#else
 static int idlezero_enable = 1;
-#endif
 SYSCTL_INT(_vm, OID_AUTO, idlezero_enable, CTLFLAG_RW, &idlezero_enable, 0, "");
 TUNABLE_INT("vm.idlezero_enable", &idlezero_enable);
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200207112234.g6BMYXnH012160>