Date: Sun, 27 Mar 2011 21:36:39 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 190649 for review Message-ID: <201103272136.p2RLadlP044941@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@190649?ac=10 Change 190649 by jhb@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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103272136.p2RLadlP044941>