PERFORCE change 96929 for review

John Birrell jb at FreeBSD.org
Wed May 10 22:05:09 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=96929

Change 96929 by jb at jb_freebsd2 on 2006/05/10 22:04:53

	Implement the software interrupts CY_LOW_LEVEL and CY_LOCK_LEVEL.
	Map them to SWI_TQ and SWI_TQ_FAST.
	
	Enable the semaphores.
	
	This brings us to another milestone... the 'profile' provider works
	now. Only on a single CPU machine though. We still need a way to
	execute a task on another CPU.

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/i386/cyclic_machdep.c#2 edit
.. //depot/projects/dtrace/src/sys/cddl/kern/cyclic.c#2 edit
.. //depot/projects/dtrace/src/sys/cddl/kern/kern_cyclic.c#2 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/i386/cyclic_machdep.c#2 (text+ko) ====

@@ -29,8 +29,10 @@
 #include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
 #include <sys/pcpu.h>
-#include <sys/kernel.h>
 #include <sys/cyclic_impl.h>
 
 extern	cyclic_clock_func_t     lapic_cyclic_clock_func;
@@ -62,8 +64,29 @@
 	NULL		/* cyb_arg_t cyb_arg */
 };
 
+static hrtime_t resolution;
 static int	hpet_present	= 0;
-static hrtime_t resolution;
+static void	*cyclic_lock_ih;
+static void	*cyclic_low_ih;
+
+/*
+ * Software interrupt callbacks.
+ */
+static void
+cyclic_swi_low(void *dummy)
+{
+	cpu_t *c = pcpu_find(curcpu);
+
+	cyclic_softint(c, CY_LOW_LEVEL);
+}
+
+static void
+cyclic_swi_lock(void *dummy)
+{
+	cpu_t *c = pcpu_find(curcpu);
+
+	cyclic_softint(c, CY_LOCK_LEVEL);
+}
 
 /*
  *  Machine dependent cyclic subsystem initialisation.
@@ -76,6 +99,15 @@
 
 	/* XXX Need to check here if the HPET is available. */
 
+	/*
+	 * Add a software interrupt handlers for low priority cyclic
+	 * events.
+	 */
+	swi_add(&clk_intr_event, "low cyclic", cyclic_swi_low, NULL,
+	    SWI_TQ, 0, &cyclic_low_ih);
+	swi_add(&clk_intr_event, "lock cyclic", cyclic_swi_lock, NULL,
+	    SWI_TQ_FAST, 0, &cyclic_lock_ih);
+
 	/* Register the cyclic backend. */
 	cyclic_init(&be, resolution);
 
@@ -93,6 +125,10 @@
 
 	/* De-register the cyclic backend. */
 	cyclic_uninit();
+
+	/* Remove the software interrupt handlers. */
+	swi_remove(cyclic_low_ih);
+	swi_remove(cyclic_lock_ih);
 }
 
 static cyb_arg_t configure(cpu_t *c)
@@ -125,7 +161,21 @@
 
 static void softint(cyb_arg_t arg, cyc_level_t level)
 {
-	printf("%s:%s(%d): Huh?\n",__FUNCTION__,__FILE__,__LINE__);
+	/*
+	 * Schedule the software interrupt processing at the
+	 * requested level.
+	 */
+	switch (level) {
+	case CY_LOW_LEVEL:
+		swi_sched(cyclic_low_ih, 0);
+		break;
+	case CY_LOCK_LEVEL:
+		swi_sched(cyclic_lock_ih, 0);
+		break;
+	default:
+		printf("%s:%s(%d): unexpected soft level %d\n",__FUNCTION__,__FILE__,__LINE__,level);
+		break;
+	}
 }
 
 static cyc_cookie_t set_level(cyb_arg_t arg, cyc_level_t level)

==== //depot/projects/dtrace/src/sys/cddl/kern/cyclic.c#2 (text+ko) ====

@@ -484,7 +484,7 @@
  *
  *  cyclic_expand() blocks on the cyp_modify_wait semaphore (a semaphore is
  *  used instead of a condition variable because of the race between the
- *  sema_p() in cyclic_expand() and the sema_v() in cyclic_softint()).  This
+ *  sema_wait() in cyclic_expand() and the sema_post() in cyclic_softint()).  This
  *  allows cyclic_expand() to know when the resize operation is complete;
  *  all of the old buffers (the heap, the cyclics array and the producer/
  *  consumer buffers) can be freed.
@@ -560,12 +560,14 @@
 #include <sys/types.h>
 #include <sys/kernel.h>
 #include <sys/kmem.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/pcpu.h>
 #include <sys/smp.h>
 #include <sys/stdint.h>
 #include <sys/time.h>
 #include <sys/cyclic_impl.h>
+#include <machine/atomic.h>
 
 MALLOC_DECLARE(M_CYCLIC);
 MALLOC_DEFINE(M_CYCLIC, "cyclic", "Cyclic Subsystem");
@@ -811,8 +813,6 @@
 	cyc_backend_t *be = cpu->cyp_backend;
 	cyc_level_t level = cyclic->cy_level;
 
-/* XXX Force everything via the CY_HIGH_LEVEL */
-level = CY_HIGH_LEVEL;
 	/*
 	 * If this is a CY_HIGH_LEVEL cyclic, just call the handler; we don't
 	 * need to worry about the pend count for CY_HIGH_LEVEL cyclics.
@@ -979,7 +979,6 @@
 	c->pc_ncyclic = cpu->cyp_nelems;
 }
 
-#ifdef DOODAD
 static void
 cyclic_remove_pend(cyc_cpu_t *cpu, cyc_level_t level, cyclic_t *cyclic)
 {
@@ -1007,7 +1006,7 @@
 	/*
 	 * We can now let the remove operation complete.
 	 */
-	sema_v(&cpu->cyp_modify_wait);
+	sema_post(&cpu->cyp_modify_wait);
 }
 
 /*
@@ -1061,7 +1060,7 @@
 void
 cyclic_softint(cpu_t *c, cyc_level_t level)
 {
-	cyc_cpu_t *cpu = c->cpu_cyclic;
+	cyc_cpu_t *cpu = c->pc_cyclic;
 	cyc_softbuf_t *softbuf;
 	int soft, *buf, consndx, resized = 0, intr_resized = 0;
 	cyc_pcbuffer_t *pc;
@@ -1157,7 +1156,7 @@
 			}
 
 			if ((opend =
-			    cas32(&cyclic->cy_pend, pend, npend)) != pend) {
+			    atomic_cmpset_int(&cyclic->cy_pend, pend, npend)) != pend) {
 				/*
 				 * Our cas32 can fail for one of several
 				 * reasons:
@@ -1249,7 +1248,7 @@
 		do {
 			lev = cpu->cyp_modify_levels;
 			nlev = lev + 1;
-		} while (cas32(&cpu->cyp_modify_levels, lev, nlev) != lev);
+		} while (atomic_cmpset_int(&cpu->cyp_modify_levels, lev, nlev) != lev);
 
 		/*
 		 * If we are the last soft level to see the modification,
@@ -1258,7 +1257,7 @@
 		 */
 		if (nlev == CY_SOFT_LEVELS) {
 			CYC_TRACE0(cpu, level, "resize-kick");
-			sema_v(&cpu->cyp_modify_wait);
+			sema_post(&cpu->cyp_modify_wait);
 		} else {
 			ASSERT(nlev < CY_SOFT_LEVELS);
 			if (level != CY_LOW_LEVEL) {
@@ -1270,7 +1269,6 @@
 		}
 	}
 }
-#endif
 
 static void
 cyclic_expand_xcall(cyc_xcallarg_t *arg)
@@ -1436,9 +1434,7 @@
 	/*
 	 * Now block, waiting for the resize operation to complete.
 	 */
-#ifdef DOODAD
-	sema_p(&cpu->cyp_modify_wait);
-#endif
+	sema_wait(&cpu->cyp_modify_wait);
 	ASSERT(cpu->cyp_modify_levels == CY_SOFT_LEVELS);
 
 	/*
@@ -1879,10 +1875,8 @@
 		return (0);
 	}
 
-#ifdef DOODAD
 	if (cpu->cyp_rpend != 0)
-		sema_p(&cpu->cyp_modify_wait);
-#endif
+		sema_wait(&cpu->cyp_modify_wait);
 
 	ASSERT(cpu->cyp_state == CYS_REMOVING);
 
@@ -1969,9 +1963,7 @@
 		if (delay > (cyclic->cy_interval >> 1))
 			delay = cyclic->cy_interval >> 1;
 
-#ifdef DOODAD
-		drv_usecwait((clock_t)(delay / (NANOSEC / MICROSEC)));
-#endif
+		DELAY((int)(delay / (NANOSEC / MICROSEC)));
 	}
 
 	/*
@@ -2148,9 +2140,7 @@
 
 	cpu->cyp_cpu = c;
 
-#ifdef DOODAD
-	sema_init(&cpu->cyp_modify_wait, 0, NULL, SEMA_DEFAULT, NULL);
-#endif
+	sema_init(&cpu->cyp_modify_wait, 0, "cyclic modify");
 
 	cpu->cyp_size = 1;
 	cpu->cyp_heap = kmem_zalloc(sizeof (cyc_index_t), KM_SLEEP);
@@ -2231,6 +2221,8 @@
 		pc->cypc_buf = NULL;
 	}
 
+	sema_destroy(&cpu->cyp_modify_wait);
+
 	/*
 	 * Finally, clean up our remaining dynamic structures and NULL out
 	 * the cpu_cyclic pointer.
@@ -2637,19 +2629,20 @@
 cyclic_add_omni(cyc_omni_handler_t *omni)
 {
 	cyc_id_t *idp = cyclic_new_id();
-printf("%s: DOODAD\n",__FUNCTION__);
-#ifdef DOODAD
 	cyc_cpu_t *cpu;
 	cpu_t *c;
+	int id;
 
 	ASSERT(MUTEX_HELD(&cpu_lock));
 	ASSERT(omni != NULL && omni->cyo_online != NULL);
 
 	idp->cyi_omni_hdlr = *omni;
 
-	c = cpu_list;
-	do {
-		if ((cpu = c->cpu_cyclic) == NULL)
+	for (id = 0; id <= mp_maxid; id++) {
+		if ((c = pcpu_find(id)) == NULL)
+			continue;
+
+		if ((cpu = c->pc_cyclic) == NULL)
 			continue;
 
 		if (cpu->cyp_state != CYS_ONLINE) {
@@ -2658,7 +2651,7 @@
 		}
 
 		cyclic_omni_start(idp, cpu);
-	} while ((c = c->cpu_next) != cpu_list);
+	}
 
 	/*
 	 * We must have found at least one online CPU on which to run
@@ -2666,7 +2659,6 @@
 	 */
 	ASSERT(idp->cyi_omni_list != NULL);
 	ASSERT(idp->cyi_cpu == NULL);
-#endif
 
 	return ((uintptr_t)idp);
 }

==== //depot/projects/dtrace/src/sys/cddl/kern/kern_cyclic.c#2 (text+ko) ====

@@ -30,9 +30,9 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
-#include <sys/pcpu.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
+#include <sys/pcpu.h>
 #include <sys/cyclic.h>
 
 /*
@@ -41,6 +41,7 @@
 static void
 cyclic_load(void *dummy)
 {
+	/* Initialise the machine-dependent backend. */
 	cyclic_machdep_init();
 }
 
@@ -49,8 +50,10 @@
 static void
 cyclic_unload(void)
 {
+	/* Uninitialise the machine-dependent backend. */
 	cyclic_machdep_uninit();
 }
+
 SYSUNINIT(ata_unregister, SI_SUB_CLOCKS, SI_ORDER_SECOND, cyclic_unload, NULL);
 
 /*


More information about the p4-projects mailing list