version 1.42, 2008/03/17 08:27:50 |
version 1.42.10.1, 2008/12/13 01:15:08 |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#define VMEM_DEBUG |
|
#if defined(_KERNEL) |
#if defined(_KERNEL) |
#include "opt_ddb.h" |
#include "opt_ddb.h" |
#define QCACHE |
#define QCACHE |
Line 575 vmem_add1(vmem_t *vm, vmem_addr_t addr, |
|
Line 574 vmem_add1(vmem_t *vm, vmem_addr_t addr, |
|
|
|
KASSERT((flags & (VM_SLEEP|VM_NOSLEEP)) != 0); |
KASSERT((flags & (VM_SLEEP|VM_NOSLEEP)) != 0); |
KASSERT((~flags & (VM_SLEEP|VM_NOSLEEP)) != 0); |
KASSERT((~flags & (VM_SLEEP|VM_NOSLEEP)) != 0); |
|
KASSERT(spanbttype == BT_TYPE_SPAN || spanbttype == BT_TYPE_SPAN_STATIC); |
|
|
btspan = bt_alloc(vm, flags); |
btspan = bt_alloc(vm, flags); |
if (btspan == NULL) { |
if (btspan == NULL) { |
Line 744 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
Line 744 vmem_fit(const bt_t *bt, vmem_size_t siz |
|
return VMEM_ADDR_NULL; |
return VMEM_ADDR_NULL; |
} |
} |
|
|
|
#if !defined(VMEM_DEBUG) |
|
#define vmem_check_sanity(vm) true |
|
#else |
|
|
|
static bool |
|
vmem_check_spanoverlap(const char *func, const vmem_t *vm, |
|
const bt_t *bt, const bt_t *bt2) |
|
{ |
|
switch (bt->bt_type) { |
|
case BT_TYPE_BUSY: |
|
case BT_TYPE_FREE: |
|
if (BT_ISSPAN_P(bt2)) |
|
return true; |
|
break; |
|
case BT_TYPE_SPAN: |
|
case BT_TYPE_SPAN_STATIC: |
|
if (bt2->bt_type == BT_TYPE_BUSY |
|
|| bt2->bt_type == BT_TYPE_FREE) |
|
return true; |
|
break; |
|
} |
|
|
|
if (bt->bt_start > bt2->bt_start) { |
|
if (bt->bt_start >= BT_END(bt2)) |
|
return true; |
|
|
|
printf("%s: overlapping VMEM '%s' span 0x%" |
|
PRIx64" - 0x%"PRIx64" %s\n", |
|
func, vm->vm_name, |
|
(uint64_t)bt->bt_start, |
|
(uint64_t)BT_END(bt), |
|
(bt->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
printf("%s: overlapping VMEM '%s' span 0x%" |
|
PRIx64" - 0x%"PRIx64" %s\n", |
|
func, vm->vm_name, |
|
(uint64_t)bt2->bt_start, |
|
(uint64_t)BT_END(bt2), |
|
(bt2->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt2->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt2->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
return false; |
|
} |
|
if (BT_END(bt) > bt2->bt_start) { |
|
printf("%s: overlapping VMEM '%s' span 0x%" |
|
PRIx64" - 0x%"PRIx64" %s\n", |
|
func, vm->vm_name, |
|
(uint64_t)bt->bt_start, |
|
(uint64_t)BT_END(bt), |
|
(bt->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
printf("%s: overlapping VMEM '%s' span 0x%" |
|
PRIx64" - 0x%"PRIx64" %s\n", |
|
func, vm->vm_name, |
|
(uint64_t)bt2->bt_start, |
|
(uint64_t)BT_END(bt2), |
|
(bt2->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt2->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt2->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
static bool |
|
vmem_check_sanity(vmem_t *vm) |
|
{ |
|
const bt_t *bt, *bt2; |
|
|
|
KASSERT(vm != NULL); |
|
|
|
CIRCLEQ_FOREACH(bt, &vm->vm_seglist, bt_seglist) { |
|
if (bt->bt_start >= BT_END(bt)) { |
|
printf("%s: bogus VMEM '%s' span 0x%"PRIx64 |
|
" - 0x%"PRIx64" %s\n", |
|
__func__, vm->vm_name, |
|
(uint64_t)bt->bt_start, (uint64_t)BT_END(bt), |
|
(bt->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
return false; |
|
} |
|
|
|
CIRCLEQ_FOREACH(bt2, &vm->vm_seglist, bt_seglist) { |
|
if (bt2->bt_start >= BT_END(bt2)) { |
|
printf("%s: bogus VMEM '%s' span 0x%"PRIx64 |
|
" - 0x%"PRIx64" %s\n", |
|
__func__, vm->vm_name, |
|
(uint64_t)bt2->bt_start, |
|
(uint64_t)BT_END(bt2), |
|
(bt2->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt2->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt2->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
return false; |
|
} |
|
if (bt == bt2) |
|
continue; |
|
|
|
if (vmem_check_spanoverlap(__func__, vm, bt, bt2) |
|
== false) |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
#endif /* VMEM_DEBUG */ |
|
|
/* ---- vmem API */ |
/* ---- vmem API */ |
|
|
/* |
/* |
|
|
retry: |
retry: |
bt = NULL; |
bt = NULL; |
VMEM_LOCK(vm); |
VMEM_LOCK(vm); |
|
KASSERT(vmem_check_sanity(vm)); |
if (strat == VM_INSTANTFIT) { |
if (strat == VM_INSTANTFIT) { |
for (list = first; list < end; list++) { |
for (list = first; list < end; list++) { |
bt = LIST_FIRST(list); |
bt = LIST_FIRST(list); |
|
|
KASSERT(bt->bt_type == BT_TYPE_FREE); |
KASSERT(bt->bt_type == BT_TYPE_FREE); |
KASSERT(bt->bt_size >= size); |
KASSERT(bt->bt_size >= size); |
bt_remfree(vm, bt); |
bt_remfree(vm, bt); |
|
KASSERT(vmem_check_sanity(vm)); |
if (bt->bt_start != start) { |
if (bt->bt_start != start) { |
btnew2->bt_type = BT_TYPE_FREE; |
btnew2->bt_type = BT_TYPE_FREE; |
btnew2->bt_start = bt->bt_start; |
btnew2->bt_start = bt->bt_start; |
|
|
bt_insfree(vm, btnew2); |
bt_insfree(vm, btnew2); |
bt_insseg(vm, btnew2, CIRCLEQ_PREV(bt, bt_seglist)); |
bt_insseg(vm, btnew2, CIRCLEQ_PREV(bt, bt_seglist)); |
btnew2 = NULL; |
btnew2 = NULL; |
|
KASSERT(vmem_check_sanity(vm)); |
} |
} |
KASSERT(bt->bt_start == start); |
KASSERT(bt->bt_start == start); |
if (bt->bt_size != size && bt->bt_size - size > vm->vm_quantum_mask) { |
if (bt->bt_size != size && bt->bt_size - size > vm->vm_quantum_mask) { |
|
|
bt_insfree(vm, bt); |
bt_insfree(vm, bt); |
bt_insseg(vm, btnew, CIRCLEQ_PREV(bt, bt_seglist)); |
bt_insseg(vm, btnew, CIRCLEQ_PREV(bt, bt_seglist)); |
bt_insbusy(vm, btnew); |
bt_insbusy(vm, btnew); |
|
KASSERT(vmem_check_sanity(vm)); |
VMEM_UNLOCK(vm); |
VMEM_UNLOCK(vm); |
} else { |
} else { |
bt->bt_type = BT_TYPE_BUSY; |
bt->bt_type = BT_TYPE_BUSY; |
bt_insbusy(vm, bt); |
bt_insbusy(vm, bt); |
|
KASSERT(vmem_check_sanity(vm)); |
VMEM_UNLOCK(vm); |
VMEM_UNLOCK(vm); |
bt_free(vm, btnew); |
bt_free(vm, btnew); |
btnew = bt; |
btnew = bt; |
|
|
KASSERT(btnew->bt_size >= size); |
KASSERT(btnew->bt_size >= size); |
btnew->bt_type = BT_TYPE_BUSY; |
btnew->bt_type = BT_TYPE_BUSY; |
|
|
|
KASSERT(vmem_check_sanity(vm)); |
return btnew->bt_start; |
return btnew->bt_start; |
} |
} |
|
|
Line 1236 vmem_whatis(uintptr_t addr, void (*pr)(c |
|
Line 1371 vmem_whatis(uintptr_t addr, void (*pr)(c |
|
(bt->bt_type == BT_TYPE_BUSY) ? "allocated" : "free"); |
(bt->bt_type == BT_TYPE_BUSY) ? "allocated" : "free"); |
} |
} |
} |
} |
|
|
|
static void |
|
vmem_showall(void (*pr)(const char *, ...)) |
|
{ |
|
vmem_t *vm; |
|
|
|
LIST_FOREACH(vm, &vmem_list, vm_alllist) { |
|
(*pr)("VMEM '%s' at %p\n", vm->vm_name, vm); |
|
if (vm->vm_source) |
|
(*pr)(" VMEM backend '%s' at %p\n", |
|
vm->vm_source->vm_name, vm->vm_source); |
|
} |
|
} |
|
|
|
static void |
|
vmem_show(uintptr_t addr, void (*pr)(const char *, ...)) |
|
{ |
|
vmem_t *vm; |
|
bt_t *bt = NULL; |
|
|
|
LIST_FOREACH(vm, &vmem_list, vm_alllist) { |
|
if ((uintptr_t)vm == addr) |
|
goto found; |
|
} |
|
|
|
LIST_FOREACH(vm, &vmem_list, vm_alllist) { |
|
bt = vmem_whatis_lookup(vm, addr); |
|
if (bt != NULL) |
|
goto found; |
|
} |
|
|
|
return; |
|
found: |
|
|
|
(*pr)("VMEM '%s' spans\n", vm->vm_name); |
|
CIRCLEQ_FOREACH(bt, &vm->vm_seglist, bt_seglist) { |
|
(*pr)(" 0x%"PRIx64" - 0x%"PRIx64" %s\n", |
|
bt->bt_start, BT_END(bt), |
|
(bt->bt_type == BT_TYPE_BUSY) ? |
|
"allocated" : |
|
(bt->bt_type == BT_TYPE_FREE) ? |
|
"free" : |
|
(bt->bt_type == BT_TYPE_SPAN) ? |
|
"span" : "static span"); |
|
} |
|
} |
|
|
|
void |
|
vmem_print(uintptr_t addr, const char *modif, void (*pr)(const char *, ...)) |
|
{ |
|
if (modif[0] == 'a') { |
|
vmem_showall(pr); |
|
return; |
|
} |
|
|
|
vmem_show(addr, pr); |
|
} |
#endif /* defined(DDB) */ |
#endif /* defined(DDB) */ |
|
|
#if defined(VMEM_DEBUG) |
#if defined(VMEM_DEBUG) |