Module Name: src Committed By: dyoung Date: Tue Aug 23 22:00:58 UTC 2011
Modified Files: src/share/man/man9: vmem.9 src/sys/kern: subr_vmem.c src/sys/rump/net/lib/libshmif: if_shmem.c src/sys/sys: vmem.h Log Message: Introduce a couple of new constants, VMEM_ADDR_MIN (the least possible address in a vmem(9) arena, 0) and VMEM_ADDR_MAX (the maximum possible address, currently 0xFFFFFFFF). Modify several boundary conditions so that a vmem(9) arena can allocate ranges including VMEM_ADDR_MAX. Update documentation and tests. These changes pass the tests in sys/kern/subr_vmem.c. To compile the and run the test program, run "cd sys/kern/ && gcc -DVMEM_SANITY -o subr_vmem ./subr_vmem.c && ./subr_vmem". To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/share/man/man9/vmem.9 cvs rdiff -u -r1.59 -r1.60 src/sys/kern/subr_vmem.c cvs rdiff -u -r1.40 -r1.41 src/sys/rump/net/lib/libshmif/if_shmem.c cvs rdiff -u -r1.12 -r1.13 src/sys/sys/vmem.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man9/vmem.9 diff -u src/share/man/man9/vmem.9:1.9 src/share/man/man9/vmem.9:1.10 --- src/share/man/man9/vmem.9:1.9 Thu Dec 2 12:54:13 2010 +++ src/share/man/man9/vmem.9 Tue Aug 23 22:00:57 2011 @@ -1,4 +1,4 @@ -.\" $NetBSD: vmem.9,v 1.9 2010/12/02 12:54:13 wiz Exp $ +.\" $NetBSD: vmem.9,v 1.10 2011/08/23 22:00:57 dyoung Exp $ .\" .\" Copyright (c)2006 YAMAMOTO Takashi, .\" All rights reserved. @@ -228,9 +228,13 @@ .Fa nocross aligned boundary. .It Fa minaddr -If non-zero, specify the minimum address which can be allocated. +Specify the minimum address which can be allocated, or +.Dv VMEM_ADDR_MIN +if the caller does not care. .It Fa maxaddr -If non-zero, specify the maximum address + 1 which can be allocated. +Specify the maximum address which can be allocated, or +.Dv VMEM_ADDR_MAX +if the caller does not care. .It Fa flags A bitwise OR of an allocation strategy and a sleep flag. .Pp Index: src/sys/kern/subr_vmem.c diff -u src/sys/kern/subr_vmem.c:1.59 src/sys/kern/subr_vmem.c:1.60 --- src/sys/kern/subr_vmem.c:1.59 Tue Jul 26 13:09:11 2011 +++ src/sys/kern/subr_vmem.c Tue Aug 23 22:00:57 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_vmem.c,v 1.59 2011/07/26 13:09:11 yamt Exp $ */ +/* $NetBSD: subr_vmem.c,v 1.60 2011/08/23 22:00:57 dyoung Exp $ */ /*- * Copyright (c)2006,2007,2008,2009 YAMAMOTO Takashi, @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.59 2011/07/26 13:09:11 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.60 2011/08/23 22:00:57 dyoung Exp $"); #if defined(_KERNEL) #include "opt_ddb.h" @@ -171,7 +171,7 @@ #define BT_TYPE_BUSY 4 #define BT_ISSPAN_P(bt) ((bt)->bt_type <= BT_TYPE_SPAN_STATIC) -#define BT_END(bt) ((bt)->bt_start + (bt)->bt_size) +#define BT_END(bt) ((bt)->bt_start + (bt)->bt_size - 1) typedef struct vmem_btag bt_t; @@ -717,12 +717,14 @@ */ static vmem_addr_t -vmem_fit(const bt_t *bt, vmem_size_t size, vmem_size_t align, vmem_size_t phase, - vmem_size_t nocross, vmem_addr_t minaddr, vmem_addr_t maxaddr) +vmem_fit(const bt_t const *bt, vmem_size_t size, vmem_size_t align, + vmem_size_t phase, vmem_size_t nocross, + vmem_addr_t minaddr, vmem_addr_t maxaddr) { vmem_addr_t start; vmem_addr_t end; + KASSERT(size > 0); KASSERT(bt->bt_size >= size); /* caller's responsibility */ /* @@ -735,10 +737,10 @@ start = minaddr; } end = BT_END(bt); - if (end > maxaddr - 1) { - end = maxaddr - 1; + if (end > maxaddr) { + end = maxaddr; } - if (start >= end) { + if (start > end) { return VMEM_ADDR_NULL; } @@ -750,13 +752,13 @@ KASSERT(align < nocross); start = VMEM_ALIGNUP(start - phase, nocross) + phase; } - if (start < end && end - start >= size) { + if (start <= end && end - start >= size - 1) { KASSERT((start & (align - 1)) == phase); KASSERT(!VMEM_CROSS_P(start, start + size - 1, nocross)); KASSERT(minaddr <= start); - KASSERT(maxaddr == 0 || start + size <= maxaddr); + KASSERT(maxaddr == 0 || start + size - 1 <= maxaddr); KASSERT(bt->bt_start <= start); - KASSERT(start + size <= BT_END(bt)); + KASSERT(BT_END(bt) - start >= size - 1); return start; } return VMEM_ADDR_NULL; @@ -887,13 +889,14 @@ } #endif /* defined(QCACHE) */ - return vmem_xalloc(vm, size, 0, 0, 0, 0, 0, flags); + return vmem_xalloc(vm, size, 0, 0, 0, VMEM_ADDR_MIN, VMEM_ADDR_MAX, + flags); } vmem_addr_t -vmem_xalloc(vmem_t *vm, vmem_size_t size0, vmem_size_t align, vmem_size_t phase, - vmem_size_t nocross, vmem_addr_t minaddr, vmem_addr_t maxaddr, - vm_flag_t flags) +vmem_xalloc(vmem_t *vm, const vmem_size_t size0, vmem_size_t align, + const vmem_size_t phase, const vmem_size_t nocross, + const vmem_addr_t minaddr, const vmem_addr_t maxaddr, const vm_flag_t flags) { struct vmem_freelist *list; struct vmem_freelist *first; @@ -918,7 +921,7 @@ KASSERT((nocross & (nocross - 1)) == 0); KASSERT((align == 0 && phase == 0) || phase < align); KASSERT(nocross == 0 || nocross >= size); - KASSERT(maxaddr == 0 || minaddr < maxaddr); + KASSERT(minaddr <= maxaddr); KASSERT(!VMEM_CROSS_P(phase, phase + size - 1, nocross)); if (align == 0) { @@ -1005,7 +1008,7 @@ } #endif if (align != vm->vm_quantum_mask + 1 || phase != 0 || - nocross != 0 || minaddr != 0 || maxaddr != 0) { + nocross != 0) { /* * XXX should try to import a region large enough to @@ -1014,6 +1017,7 @@ goto fail; } + /* XXX eeek, minaddr & maxaddr not respected */ if (vmem_import(vm, size, flags) == 0) { goto retry; } @@ -1118,7 +1122,7 @@ /* coalesce */ t = CIRCLEQ_NEXT(bt, bt_seglist); if (t != NULL && t->bt_type == BT_TYPE_FREE) { - KASSERT(BT_END(bt) == t->bt_start); + KASSERT(BT_END(bt) < t->bt_start); /* YYY */ bt_remfree(vm, t); bt_remseg(vm, t); bt->bt_size += t->bt_size; @@ -1126,7 +1130,7 @@ } t = CIRCLEQ_PREV(bt, bt_seglist); if (t != NULL && t->bt_type == BT_TYPE_FREE) { - KASSERT(BT_END(t) == bt->bt_start); + KASSERT(BT_END(t) < bt->bt_start); /* YYY */ bt_remfree(vm, t); bt_remseg(vm, t); bt->bt_size += t->bt_size; @@ -1321,7 +1325,7 @@ if (BT_ISSPAN_P(bt)) { continue; } - if (bt->bt_start <= addr && addr < BT_END(bt)) { + if (bt->bt_start <= addr && addr <= BT_END(bt)) { return bt; } } @@ -1367,9 +1371,21 @@ } #endif /* defined(DDB) */ -#if !defined(_KERNEL) +#if defined(_KERNEL) +#define vmem_printf printf +#else #include <stdio.h> -#endif /* !defined(_KERNEL) */ +#include <stdarg.h> + +static void +vmem_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} +#endif #if defined(VMEM_SANITY) @@ -1381,9 +1397,9 @@ KASSERT(vm != NULL); CIRCLEQ_FOREACH(bt, &vm->vm_seglist, bt_seglist) { - if (bt->bt_start >= BT_END(bt)) { + if (bt->bt_start > BT_END(bt)) { printf("corrupted tag\n"); - bt_dump(bt, (void *)printf); + bt_dump(bt, vmem_printf); return false; } } @@ -1395,11 +1411,11 @@ if (BT_ISSPAN_P(bt) != BT_ISSPAN_P(bt2)) { continue; } - if (bt->bt_start < BT_END(bt2) && - bt2->bt_start < BT_END(bt)) { + if (bt->bt_start <= BT_END(bt2) && + bt2->bt_start <= BT_END(bt)) { printf("overwrapped tags\n"); - bt_dump(bt, (void *)printf); - bt_dump(bt2, (void *)printf); + bt_dump(bt, vmem_printf); + bt_dump(bt2, vmem_printf); return false; } } @@ -1446,14 +1462,33 @@ printf("vmem_create\n"); exit(EXIT_FAILURE); } - vmem_dump(vm, (void *)printf); + vmem_dump(vm, vmem_printf); p = vmem_add(vm, 100, 200, VM_SLEEP); + assert(p != VMEM_ADDR_NULL); p = vmem_add(vm, 2000, 1, VM_SLEEP); - p = vmem_add(vm, 40000, 0x10000000>>12, VM_SLEEP); + assert(p != VMEM_ADDR_NULL); + p = vmem_add(vm, 40000, 65536, VM_SLEEP); + assert(p != VMEM_ADDR_NULL); p = vmem_add(vm, 10000, 10000, VM_SLEEP); + assert(p != VMEM_ADDR_NULL); p = vmem_add(vm, 500, 1000, VM_SLEEP); - vmem_dump(vm, (void *)printf); + assert(p != VMEM_ADDR_NULL); + p = vmem_add(vm, 0xffffff00, 0x100, VM_SLEEP); + assert(p != VMEM_ADDR_NULL); + p = vmem_xalloc(vm, 0x101, 0, 0, 0, + 0xffffff00, 0xffffffff, strat|VM_SLEEP); + assert(p == VMEM_ADDR_NULL); + p = vmem_xalloc(vm, 0x100, 0, 0, 0, + 0xffffff01, 0xffffffff, strat|VM_SLEEP); + assert(p == VMEM_ADDR_NULL); + p = vmem_xalloc(vm, 0x100, 0, 0, 0, + 0xffffff00, 0xfffffffe, strat|VM_SLEEP); + assert(p == VMEM_ADDR_NULL); + p = vmem_xalloc(vm, 0x100, 0, 0, 0, + 0xffffff00, 0xffffffff, strat|VM_SLEEP); + assert(p != VMEM_ADDR_NULL); + vmem_dump(vm, vmem_printf); for (;;) { struct reg *r; int t = rand() % 100; @@ -1478,12 +1513,10 @@ nocross)) { nocross = 0; } - minaddr = rand() % 50000; - maxaddr = rand() % 70000; - if (minaddr > maxaddr) { - minaddr = 0; - maxaddr = 0; - } + do { + minaddr = rand() % 50000; + maxaddr = rand() % 70000; + } while (minaddr > maxaddr); printf("=== xalloc %" PRIu64 " align=%" PRIu64 ", phase=%" PRIu64 ", nocross=%" PRIu64 ", min=%" PRIu64 @@ -1502,7 +1535,7 @@ p = vmem_alloc(vm, sz, strat|VM_SLEEP); } printf("-> %" PRIu64 "\n", (uint64_t)p); - vmem_dump(vm, (void *)printf); + vmem_dump(vm, vmem_printf); if (p == VMEM_ADDR_NULL) { if (x) { continue; @@ -1528,7 +1561,7 @@ vmem_free(vm, r->p, r->sz); } total -= r->sz; - vmem_dump(vm, (void *)printf); + vmem_dump(vm, vmem_printf); *r = reg[nreg - 1]; nreg--; nfree++; Index: src/sys/rump/net/lib/libshmif/if_shmem.c diff -u src/sys/rump/net/lib/libshmif/if_shmem.c:1.40 src/sys/rump/net/lib/libshmif/if_shmem.c:1.41 --- src/sys/rump/net/lib/libshmif/if_shmem.c:1.40 Sun Aug 7 14:03:16 2011 +++ src/sys/rump/net/lib/libshmif/if_shmem.c Tue Aug 23 22:00:57 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: if_shmem.c,v 1.40 2011/08/07 14:03:16 rmind Exp $ */ +/* $NetBSD: if_shmem.c,v 1.41 2011/08/23 22:00:57 dyoung Exp $ */ /* * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.40 2011/08/07 14:03:16 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.41 2011/08/23 22:00:57 dyoung Exp $"); #include <sys/param.h> #include <sys/atomic.h> @@ -293,7 +293,7 @@ return error; } - unit = vmem_xalloc(shmif_units, 1, 0, 0, 0, 0, 0, + unit = vmem_xalloc(shmif_units, 1, 0, 0, 0, 0, ~(vmem_addr_t)0, VM_INSTANTFIT | VM_SLEEP) - 1; if ((error = allocif(unit, &sc)) != 0) { @@ -332,11 +332,9 @@ * Otherwise the wildcard-side of things might get the same one. * This is slightly offset-happy due to vmem. First, we offset * the range of unit numbers by +1 since vmem cannot deal with - * ranges starting from 0. Second, since vmem_xalloc() allocates - * from [min,max) (half-*open* interval), we need to add one extra - * to the one extra we add to maxaddr. Talk about uuuh. + * ranges starting from 0. Talk about uuuh. */ - unit2 = vmem_xalloc(shmif_units, 1, 0, 0, 0, unit+1, unit+3, + unit2 = vmem_xalloc(shmif_units, 1, 0, 0, 0, unit+1, unit+1, VM_SLEEP | VM_INSTANTFIT); KASSERT(unit2-1 == unit); Index: src/sys/sys/vmem.h diff -u src/sys/sys/vmem.h:1.12 src/sys/sys/vmem.h:1.13 --- src/sys/sys/vmem.h:1.12 Wed Feb 18 13:31:59 2009 +++ src/sys/sys/vmem.h Tue Aug 23 22:00:57 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vmem.h,v 1.12 2009/02/18 13:31:59 yamt Exp $ */ +/* $NetBSD: vmem.h,v 1.13 2011/08/23 22:00:57 dyoung Exp $ */ /*- * Copyright (c)2006 YAMAMOTO Takashi, @@ -42,6 +42,8 @@ typedef uintptr_t vmem_addr_t; typedef size_t vmem_size_t; #define VMEM_ADDR_NULL 0 +#define VMEM_ADDR_MIN 0 +#define VMEM_ADDR_MAX (~(vmem_addr_t)0) vmem_t *vmem_create(const char *, vmem_addr_t, vmem_size_t, vmem_size_t, vmem_addr_t (*)(vmem_t *, vmem_size_t, vmem_size_t *, vm_flag_t),