PERFORCE change 190649 for review

John Baldwin jhb at FreeBSD.org
Sun Mar 27 21:36:40 UTC 2011


http://p4web.freebsd.org/@@190649?ac=10

Change 190649 by jhb at jhb_fiver on 2011/03/27 21:35:47

	Checkpoint work on rman_release_region().  Need to flesh out regression tests.

Affected files ...

.. //depot/projects/pci/sys/kern/subr_rman.c#4 edit
.. //depot/projects/pci/sys/modules/rman/rman.c#5 edit
.. //depot/projects/pci/sys/sys/rman.h#3 edit

Differences ...

==== //depot/projects/pci/sys/kern/subr_rman.c#4 (text+ko) ====

@@ -227,6 +227,85 @@
 }
 
 int
+rman_release_region(struct rman *rm, u_long start, u_long end)
+{
+	struct resource_i *r, *s;
+
+	DPRINTF(("rman_release_region: <%s> request: start %#lx, end %#lx\n",
+	    rm->rm_descr, start, end));
+	
+	mtx_lock(rm->rm_mtx);
+
+	/* Skip entries before us. */
+	TAILQ_FOREACH(r, &rm->rm_list, r_link) {
+		if (r->r_end == ULONG_MAX)
+			break;
+		if (r->r_end + 1 >= start)
+			break;
+	}
+
+	/* If no entry found, this region is not managed. */
+	if (r == NULL) {
+		mtx_unlock(rm->rm_mtx);
+		return (ENOENT);
+	}
+
+	/* Ensure the entire range is managed. */
+	if (r->r_start > start) {
+		mtx_unlock(rm->rm_mtx);
+		return (ENOENT);
+	}
+	s = r;
+	while (s->r_end < end) {
+		t = TAILQ_NEXT(s, r_link);
+		if (t == NULL || t->r_start != s->r_end + 1) {
+			mtx_unlock(rm->rm_mtx);
+			return (ENOENT);
+		}
+		s = t;
+	}
+
+	/* Check if any part of the region is allocated. */
+	if (r->r_flags & RF_ALLOCATED || r->r_end < end) {
+		if (!(r->r_flags & RF_ALLOCATED))
+			KASSERT(TAILQ_NEXT(r, r_link)->r_flags & RF_ALLOCATED,
+			    ("adjacent free regions"));
+		mtx_unlock(rm->rm_mtx);
+		return (ENOENT);
+	}
+
+	/*
+	 * If the range exactly matches 'r', remove it, otherwise
+	 * adjust 'r', possibly splitting it.
+	 */
+	if (r->r_start == start && r->r_end == end) {
+		TAILQ_REMOVE(r, r_link);
+		free(r, M_RMAN);
+	} else if (r->r_start == start) {
+		KASSERT(end > r->r_end, ("resource entry too small"));
+		r->r_start = end + 1;
+	} else if (r->r_end == end) {
+		KASSERT(start < r->r_start, ("resource entry too small"));
+		r->r_end = start - 1;
+	} else {
+		KASSERT(r->r_start < start && end < r->r_end, ("resource entry too small"));
+		s = int_alloc_resource(M_NOWAIT);
+		if (s == NULL) {
+			mtx_unlock(rm->rm_mtx);
+			return (ENOMEM);
+		}
+		s->r_start = end + 1;
+		s->r_end = r->r_end;
+		s->r_rm = rm;
+		r->r_end = start - 1;
+		TAILQ_INSERT_AFTER(&rm->rm_list, r, s, r_link);
+	}
+	mtx_unlock(rm->rm_mtx);
+
+	return (0);
+}
+
+int
 rman_init_from_resource(struct rman *rm, struct resource *r)
 {
 	int rv;

==== //depot/projects/pci/sys/modules/rman/rman.c#5 (text+ko) ====

@@ -150,7 +150,7 @@
 }
 
 static void
-regression_tests(void)
+adjust_regression_tests(void)
 {
 	int error;
 
@@ -295,6 +295,24 @@
 	assert_rman_ok();
 }
 
+static void
+region_regression_tests(void)
+{
+
+	/* Clear any released resources. */
+	if (r != NULL) {
+		rman_release_resource(r);
+		r = NULL;
+	}
+	if (s != NULL) {
+		rman_release_resource(s);
+		s = NULL;
+	}
+	assert_rman_ok();
+
+	
+}
+
 static int
 sysctl_rman_test(SYSCTL_HANDLER_ARGS)
 {
@@ -303,12 +321,32 @@
 	error = sysctl_handle_int(oidp, &i, sizeof(i), req);
 	if (error || req->newptr == NULL || i == 0)
 		return (error);
-	regression_tests();
+	switch (oip->arg2) {
+	case 0:
+		adjust_regression_tests();
+		break;
+	case 1:
+		region_regression_tests();
+		break;
+	}
 	return (error);
 }
-SYSCTL_PROC(_debug_rman, OID_AUTO, test, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
-    sysctl_rman_test, "I", "run regression tests");
+SYSCTL_PROC(_debug_rman, OID_AUTO, test_adjust, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
+    sysctl_rman_test, "I", "run regression tests for rman_adjust_resource()");
+SYSCTL_PROC(_debug_rman, OID_AUTO, test_region, CTLTYPE_INT | CTLFLAG_RW, 0, 1,
+    sysctl_rman_test, "I", "run regression tests for rman_release_region()");
+
+static int
+sysctl_rman_test_region(SYSCTL_HANDLER_ARGS)
+{
+	int error, i = 0;
 
+	error = sysctl_handle_int(oidp, &i, sizeof(i), req);
+	if (error || req->newptr == NULL || i == 0)
+		return (error);
+	region_regression_tests();
+	return (error);
+}
 
 static int
 load(void)

==== //depot/projects/pci/sys/sys/rman.h#3 (text+ko) ====

@@ -134,6 +134,7 @@
 uint32_t rman_make_alignment_flags(uint32_t size);
 int	rman_manage_region(struct rman *rm, u_long start, u_long end);
 int	rman_is_region_manager(struct resource *r, struct rman *rm);
+int	rman_release_region(struct rman *rm, u_long start, u_long end);
 int	rman_release_resource(struct resource *r);
 struct resource *rman_reserve_resource(struct rman *rm, u_long start,
 					u_long end, u_long count,


More information about the p4-projects mailing list