version 1.59, 2011/07/26 13:09:11 |
version 1.60, 2011/08/23 22:00:57 |
Line 171 struct vmem_btag { |
|
Line 171 struct vmem_btag { |
|
#define BT_TYPE_BUSY 4 |
#define BT_TYPE_BUSY 4 |
#define BT_ISSPAN_P(bt) ((bt)->bt_type <= BT_TYPE_SPAN_STATIC) |
#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; |
typedef struct vmem_btag bt_t; |
|
|
Line 717 vmem_rehash(vmem_t *vm, size_t newhashsi |
|
Line 717 vmem_rehash(vmem_t *vm, size_t newhashsi |
|
*/ |
*/ |
|
|
static vmem_addr_t |
static vmem_addr_t |
vmem_fit(const bt_t *bt, vmem_size_t size, vmem_size_t align, vmem_size_t phase, |
vmem_fit(const bt_t const *bt, vmem_size_t size, vmem_size_t align, |
vmem_size_t nocross, vmem_addr_t minaddr, vmem_addr_t maxaddr) |
vmem_size_t phase, vmem_size_t nocross, |
|
vmem_addr_t minaddr, vmem_addr_t maxaddr) |
{ |
{ |
vmem_addr_t start; |
vmem_addr_t start; |
vmem_addr_t end; |
vmem_addr_t end; |
|
|
|
KASSERT(size > 0); |
KASSERT(bt->bt_size >= size); /* caller's responsibility */ |
KASSERT(bt->bt_size >= size); /* caller's responsibility */ |
|
|
/* |
/* |
Line 735 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
Line 737 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
start = minaddr; |
start = minaddr; |
} |
} |
end = BT_END(bt); |
end = BT_END(bt); |
if (end > maxaddr - 1) { |
if (end > maxaddr) { |
end = maxaddr - 1; |
end = maxaddr; |
} |
} |
if (start >= end) { |
if (start > end) { |
return VMEM_ADDR_NULL; |
return VMEM_ADDR_NULL; |
} |
} |
|
|
Line 750 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
Line 752 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
KASSERT(align < nocross); |
KASSERT(align < nocross); |
start = VMEM_ALIGNUP(start - phase, nocross) + phase; |
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((start & (align - 1)) == phase); |
KASSERT(!VMEM_CROSS_P(start, start + size - 1, nocross)); |
KASSERT(!VMEM_CROSS_P(start, start + size - 1, nocross)); |
KASSERT(minaddr <= start); |
KASSERT(minaddr <= start); |
KASSERT(maxaddr == 0 || start + size <= maxaddr); |
KASSERT(maxaddr == 0 || start + size - 1 <= maxaddr); |
KASSERT(bt->bt_start <= start); |
KASSERT(bt->bt_start <= start); |
KASSERT(start + size <= BT_END(bt)); |
KASSERT(BT_END(bt) - start >= size - 1); |
return start; |
return start; |
} |
} |
return VMEM_ADDR_NULL; |
return VMEM_ADDR_NULL; |
Line 887 vmem_alloc(vmem_t *vm, vmem_size_t size, |
|
Line 889 vmem_alloc(vmem_t *vm, vmem_size_t size, |
|
} |
} |
#endif /* defined(QCACHE) */ |
#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_addr_t |
vmem_xalloc(vmem_t *vm, vmem_size_t size0, vmem_size_t align, vmem_size_t phase, |
vmem_xalloc(vmem_t *vm, const vmem_size_t size0, vmem_size_t align, |
vmem_size_t nocross, vmem_addr_t minaddr, vmem_addr_t maxaddr, |
const vmem_size_t phase, const vmem_size_t nocross, |
vm_flag_t flags) |
const vmem_addr_t minaddr, const vmem_addr_t maxaddr, const vm_flag_t flags) |
{ |
{ |
struct vmem_freelist *list; |
struct vmem_freelist *list; |
struct vmem_freelist *first; |
struct vmem_freelist *first; |
Line 918 vmem_xalloc(vmem_t *vm, vmem_size_t size |
|
Line 921 vmem_xalloc(vmem_t *vm, vmem_size_t size |
|
KASSERT((nocross & (nocross - 1)) == 0); |
KASSERT((nocross & (nocross - 1)) == 0); |
KASSERT((align == 0 && phase == 0) || phase < align); |
KASSERT((align == 0 && phase == 0) || phase < align); |
KASSERT(nocross == 0 || nocross >= size); |
KASSERT(nocross == 0 || nocross >= size); |
KASSERT(maxaddr == 0 || minaddr < maxaddr); |
KASSERT(minaddr <= maxaddr); |
KASSERT(!VMEM_CROSS_P(phase, phase + size - 1, nocross)); |
KASSERT(!VMEM_CROSS_P(phase, phase + size - 1, nocross)); |
|
|
if (align == 0) { |
if (align == 0) { |
|
|
} |
} |
#endif |
#endif |
if (align != vm->vm_quantum_mask + 1 || phase != 0 || |
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 |
* XXX should try to import a region large enough to |
|
|
|
|
goto fail; |
goto fail; |
} |
} |
|
/* XXX eeek, minaddr & maxaddr not respected */ |
if (vmem_import(vm, size, flags) == 0) { |
if (vmem_import(vm, size, flags) == 0) { |
goto retry; |
goto retry; |
} |
} |
Line 1118 vmem_xfree(vmem_t *vm, vmem_addr_t addr, |
|
Line 1122 vmem_xfree(vmem_t *vm, vmem_addr_t addr, |
|
/* coalesce */ |
/* coalesce */ |
t = CIRCLEQ_NEXT(bt, bt_seglist); |
t = CIRCLEQ_NEXT(bt, bt_seglist); |
if (t != NULL && t->bt_type == BT_TYPE_FREE) { |
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_remfree(vm, t); |
bt_remseg(vm, t); |
bt_remseg(vm, t); |
bt->bt_size += t->bt_size; |
bt->bt_size += t->bt_size; |
Line 1126 vmem_xfree(vmem_t *vm, vmem_addr_t addr, |
|
Line 1130 vmem_xfree(vmem_t *vm, vmem_addr_t addr, |
|
} |
} |
t = CIRCLEQ_PREV(bt, bt_seglist); |
t = CIRCLEQ_PREV(bt, bt_seglist); |
if (t != NULL && t->bt_type == BT_TYPE_FREE) { |
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_remfree(vm, t); |
bt_remseg(vm, t); |
bt_remseg(vm, t); |
bt->bt_size += t->bt_size; |
bt->bt_size += t->bt_size; |
Line 1321 vmem_whatis_lookup(vmem_t *vm, uintptr_t |
|
Line 1325 vmem_whatis_lookup(vmem_t *vm, uintptr_t |
|
if (BT_ISSPAN_P(bt)) { |
if (BT_ISSPAN_P(bt)) { |
continue; |
continue; |
} |
} |
if (bt->bt_start <= addr && addr < BT_END(bt)) { |
if (bt->bt_start <= addr && addr <= BT_END(bt)) { |
return bt; |
return bt; |
} |
} |
} |
} |
Line 1367 vmem_print(uintptr_t addr, const char *m |
|
Line 1371 vmem_print(uintptr_t addr, const char *m |
|
} |
} |
#endif /* defined(DDB) */ |
#endif /* defined(DDB) */ |
|
|
#if !defined(_KERNEL) |
#if defined(_KERNEL) |
|
#define vmem_printf printf |
|
#else |
#include <stdio.h> |
#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) |
#if defined(VMEM_SANITY) |
|
|
Line 1381 vmem_check_sanity(vmem_t *vm) |
|
Line 1397 vmem_check_sanity(vmem_t *vm) |
|
KASSERT(vm != NULL); |
KASSERT(vm != NULL); |
|
|
CIRCLEQ_FOREACH(bt, &vm->vm_seglist, bt_seglist) { |
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"); |
printf("corrupted tag\n"); |
bt_dump(bt, (void *)printf); |
bt_dump(bt, vmem_printf); |
return false; |
return false; |
} |
} |
} |
} |
Line 1395 vmem_check_sanity(vmem_t *vm) |
|
Line 1411 vmem_check_sanity(vmem_t *vm) |
|
if (BT_ISSPAN_P(bt) != BT_ISSPAN_P(bt2)) { |
if (BT_ISSPAN_P(bt) != BT_ISSPAN_P(bt2)) { |
continue; |
continue; |
} |
} |
if (bt->bt_start < BT_END(bt2) && |
if (bt->bt_start <= BT_END(bt2) && |
bt2->bt_start < BT_END(bt)) { |
bt2->bt_start <= BT_END(bt)) { |
printf("overwrapped tags\n"); |
printf("overwrapped tags\n"); |
bt_dump(bt, (void *)printf); |
bt_dump(bt, vmem_printf); |
bt_dump(bt2, (void *)printf); |
bt_dump(bt2, vmem_printf); |
return false; |
return false; |
} |
} |
} |
} |
|
|
printf("vmem_create\n"); |
printf("vmem_create\n"); |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
} |
} |
vmem_dump(vm, (void *)printf); |
vmem_dump(vm, vmem_printf); |
|
|
p = vmem_add(vm, 100, 200, VM_SLEEP); |
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, 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); |
p = vmem_add(vm, 10000, 10000, VM_SLEEP); |
|
assert(p != VMEM_ADDR_NULL); |
p = vmem_add(vm, 500, 1000, VM_SLEEP); |
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 (;;) { |
for (;;) { |
struct reg *r; |
struct reg *r; |
int t = rand() % 100; |
int t = rand() % 100; |
|
|
nocross)) { |
nocross)) { |
nocross = 0; |
nocross = 0; |
} |
} |
minaddr = rand() % 50000; |
do { |
maxaddr = rand() % 70000; |
minaddr = rand() % 50000; |
if (minaddr > maxaddr) { |
maxaddr = rand() % 70000; |
minaddr = 0; |
} while (minaddr > maxaddr); |
maxaddr = 0; |
|
} |
|
printf("=== xalloc %" PRIu64 |
printf("=== xalloc %" PRIu64 |
" align=%" PRIu64 ", phase=%" PRIu64 |
" align=%" PRIu64 ", phase=%" PRIu64 |
", nocross=%" PRIu64 ", min=%" PRIu64 |
", nocross=%" PRIu64 ", min=%" PRIu64 |
|
|
p = vmem_alloc(vm, sz, strat|VM_SLEEP); |
p = vmem_alloc(vm, sz, strat|VM_SLEEP); |
} |
} |
printf("-> %" PRIu64 "\n", (uint64_t)p); |
printf("-> %" PRIu64 "\n", (uint64_t)p); |
vmem_dump(vm, (void *)printf); |
vmem_dump(vm, vmem_printf); |
if (p == VMEM_ADDR_NULL) { |
if (p == VMEM_ADDR_NULL) { |
if (x) { |
if (x) { |
continue; |
continue; |
|
|
vmem_free(vm, r->p, r->sz); |
vmem_free(vm, r->p, r->sz); |
} |
} |
total -= r->sz; |
total -= r->sz; |
vmem_dump(vm, (void *)printf); |
vmem_dump(vm, vmem_printf); |
*r = reg[nreg - 1]; |
*r = reg[nreg - 1]; |
nreg--; |
nreg--; |
nfree++; |
nfree++; |