version 1.254.4.1, 2008/06/23 04:32:06 |
version 1.254.4.2, 2008/09/18 04:37:06 |
Line 95 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 95 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#endif |
#endif |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
#undef RB_AUGMENT |
|
#define RB_AUGMENT(x) uvm_rb_augment(x) |
|
|
|
#ifdef DDB |
#ifdef DDB |
#include <uvm/uvm_ddb.h> |
#include <uvm/uvm_ddb.h> |
Line 131 UVMMAP_EVCNT_DEFINE(knomerge) |
|
Line 129 UVMMAP_EVCNT_DEFINE(knomerge) |
|
UVMMAP_EVCNT_DEFINE(map_call) |
UVMMAP_EVCNT_DEFINE(map_call) |
UVMMAP_EVCNT_DEFINE(mlk_call) |
UVMMAP_EVCNT_DEFINE(mlk_call) |
UVMMAP_EVCNT_DEFINE(mlk_hint) |
UVMMAP_EVCNT_DEFINE(mlk_hint) |
|
UVMMAP_EVCNT_DEFINE(mlk_list) |
|
UVMMAP_EVCNT_DEFINE(mlk_tree) |
|
UVMMAP_EVCNT_DEFINE(mlk_treeloop) |
|
UVMMAP_EVCNT_DEFINE(mlk_listloop) |
|
|
UVMMAP_EVCNT_DEFINE(uke_alloc) |
UVMMAP_EVCNT_DEFINE(uke_alloc) |
UVMMAP_EVCNT_DEFINE(uke_free) |
UVMMAP_EVCNT_DEFINE(uke_free) |
Line 297 static void uvm_map_unreference_amap(str |
|
Line 299 static void uvm_map_unreference_amap(str |
|
|
|
int _uvm_map_sanity(struct vm_map *); |
int _uvm_map_sanity(struct vm_map *); |
int _uvm_tree_sanity(struct vm_map *); |
int _uvm_tree_sanity(struct vm_map *); |
static vsize_t uvm_rb_subtree_space(const struct vm_map_entry *); |
static vsize_t uvm_rb_maxgap(const struct vm_map_entry *); |
|
|
static inline int |
CTASSERT(offsetof(struct vm_map_entry, rb_node) == 0); |
uvm_compare(const struct vm_map_entry *a, const struct vm_map_entry *b) |
#define ROOT_ENTRY(map) ((struct vm_map_entry *)(map)->rb_tree.rbt_root) |
|
#define LEFT_ENTRY(entry) ((struct vm_map_entry *)(entry)->rb_node.rb_left) |
|
#define RIGHT_ENTRY(entry) ((struct vm_map_entry *)(entry)->rb_node.rb_right) |
|
#define PARENT_ENTRY(map, entry) \ |
|
(ROOT_ENTRY(map) == (entry) \ |
|
? NULL \ |
|
: (struct vm_map_entry *)RB_FATHER(&(entry)->rb_node)) |
|
|
|
static int |
|
uvm_map_compare_nodes(const struct rb_node *nparent, |
|
const struct rb_node *nkey) |
{ |
{ |
|
const struct vm_map_entry *eparent = (const void *) nparent; |
|
const struct vm_map_entry *ekey = (const void *) nkey; |
|
|
if (a->start < b->start) |
KASSERT(eparent->start < ekey->start || eparent->start >= ekey->end); |
return (-1); |
KASSERT(ekey->start < eparent->start || ekey->start >= eparent->end); |
else if (a->start > b->start) |
|
return (1); |
|
|
|
return (0); |
if (ekey->start < eparent->start) |
|
return -1; |
|
if (ekey->start >= eparent->end) |
|
return 1; |
|
return 0; |
} |
} |
|
|
static inline void |
static int |
uvm_rb_augment(struct vm_map_entry *entry) |
uvm_map_compare_key(const struct rb_node *nparent, const void *vkey) |
{ |
{ |
|
const struct vm_map_entry *eparent = (const void *) nparent; |
|
const vaddr_t va = *(const vaddr_t *) vkey; |
|
|
entry->space = uvm_rb_subtree_space(entry); |
if (va < eparent->start) |
|
return -1; |
|
if (va >= eparent->end) |
|
return 1; |
|
return 0; |
} |
} |
|
|
RB_PROTOTYPE(uvm_tree, vm_map_entry, rb_entry, uvm_compare); |
static const struct rb_tree_ops uvm_map_tree_ops = { |
|
.rbto_compare_nodes = uvm_map_compare_nodes, |
RB_GENERATE(uvm_tree, vm_map_entry, rb_entry, uvm_compare); |
.rbto_compare_key = uvm_map_compare_key, |
|
}; |
|
|
static inline vsize_t |
static inline vsize_t |
uvm_rb_space(const struct vm_map *map, const struct vm_map_entry *entry) |
uvm_rb_gap(const struct vm_map_entry *entry) |
{ |
{ |
/* XXX map is not used */ |
|
|
|
KASSERT(entry->next != NULL); |
KASSERT(entry->next != NULL); |
return entry->next->start - entry->end; |
return entry->next->start - entry->end; |
} |
} |
|
|
static vsize_t |
static vsize_t |
uvm_rb_subtree_space(const struct vm_map_entry *entry) |
uvm_rb_maxgap(const struct vm_map_entry *entry) |
{ |
{ |
vaddr_t space, tmp; |
struct vm_map_entry *child; |
|
vsize_t maxgap = entry->gap; |
|
|
space = entry->ownspace; |
/* |
if (RB_LEFT(entry, rb_entry)) { |
* We need maxgap to be the largest gap of us or any of our |
tmp = RB_LEFT(entry, rb_entry)->space; |
* descendents. Since each of our children's maxgap is the |
if (tmp > space) |
* cached value of their largest gap of themselves or their |
space = tmp; |
* descendents, we can just use that value and avoid recursing |
} |
* down the tree to calculate it. |
|
*/ |
|
if ((child = LEFT_ENTRY(entry)) != NULL && maxgap < child->maxgap) |
|
maxgap = child->maxgap; |
|
|
if (RB_RIGHT(entry, rb_entry)) { |
if ((child = RIGHT_ENTRY(entry)) != NULL && maxgap < child->maxgap) |
tmp = RB_RIGHT(entry, rb_entry)->space; |
maxgap = child->maxgap; |
if (tmp > space) |
|
space = tmp; |
|
} |
|
|
|
return (space); |
return maxgap; |
} |
} |
|
|
static inline void |
static void |
uvm_rb_fixup(struct vm_map *map, struct vm_map_entry *entry) |
uvm_rb_fixup(struct vm_map *map, struct vm_map_entry *entry) |
{ |
{ |
/* We need to traverse to the very top */ |
struct vm_map_entry *parent; |
do { |
|
entry->ownspace = uvm_rb_space(map, entry); |
KASSERT(entry->gap == uvm_rb_gap(entry)); |
entry->space = uvm_rb_subtree_space(entry); |
entry->maxgap = uvm_rb_maxgap(entry); |
} while ((entry = RB_PARENT(entry, rb_entry)) != NULL); |
|
|
while ((parent = PARENT_ENTRY(map, entry)) != NULL) { |
|
struct vm_map_entry *brother; |
|
vsize_t maxgap = parent->gap; |
|
|
|
KDASSERT(parent->gap == uvm_rb_gap(parent)); |
|
if (maxgap < entry->maxgap) |
|
maxgap = entry->maxgap; |
|
/* |
|
* Since we work our towards the root, we know entry's maxgap |
|
* value is ok but its brothers may now be out-of-date due |
|
* rebalancing. So refresh it. |
|
*/ |
|
brother = (struct vm_map_entry *)parent->rb_node.rb_nodes[RB_POSITION(&entry->rb_node) ^ RB_DIR_OTHER]; |
|
if (brother != NULL) { |
|
KDASSERT(brother->gap == uvm_rb_gap(brother)); |
|
brother->maxgap = uvm_rb_maxgap(brother); |
|
if (maxgap < brother->maxgap) |
|
maxgap = brother->maxgap; |
|
} |
|
|
|
parent->maxgap = maxgap; |
|
entry = parent; |
|
} |
} |
} |
|
|
static void |
static void |
uvm_rb_insert(struct vm_map *map, struct vm_map_entry *entry) |
uvm_rb_insert(struct vm_map *map, struct vm_map_entry *entry) |
{ |
{ |
vaddr_t space = uvm_rb_space(map, entry); |
entry->gap = entry->maxgap = uvm_rb_gap(entry); |
struct vm_map_entry *tmp; |
|
|
|
entry->ownspace = entry->space = space; |
|
tmp = RB_INSERT(uvm_tree, &(map)->rbhead, entry); |
|
#ifdef DIAGNOSTIC |
|
if (tmp != NULL) |
|
panic("uvm_rb_insert: duplicate entry?"); |
|
#endif |
|
uvm_rb_fixup(map, entry); |
|
if (entry->prev != &map->header) |
if (entry->prev != &map->header) |
uvm_rb_fixup(map, entry->prev); |
entry->prev->gap = uvm_rb_gap(entry->prev); |
|
|
|
if (!rb_tree_insert_node(&map->rb_tree, &entry->rb_node)) |
|
panic("uvm_rb_insert: map %p: duplicate entry?", map); |
|
|
|
/* |
|
* If the previous entry is not our immediate left child, then it's an |
|
* ancestor and will be fixed up on the way to the root. We don't |
|
* have to check entry->prev against &map->header since &map->header |
|
* will never be in the tree. |
|
*/ |
|
uvm_rb_fixup(map, |
|
LEFT_ENTRY(entry) == entry->prev ? entry->prev : entry); |
} |
} |
|
|
static void |
static void |
uvm_rb_remove(struct vm_map *map, struct vm_map_entry *entry) |
uvm_rb_remove(struct vm_map *map, struct vm_map_entry *entry) |
{ |
{ |
struct vm_map_entry *parent; |
struct vm_map_entry *prev_parent = NULL, *next_parent = NULL; |
|
|
parent = RB_PARENT(entry, rb_entry); |
/* |
RB_REMOVE(uvm_tree, &(map)->rbhead, entry); |
* If we are removing an interior node, then an adjacent node will |
|
* be used to replace its position in the tree. Therefore we will |
|
* need to fixup the tree starting at the parent of the replacement |
|
* node. So record their parents for later use. |
|
*/ |
if (entry->prev != &map->header) |
if (entry->prev != &map->header) |
|
prev_parent = PARENT_ENTRY(map, entry->prev); |
|
if (entry->next != &map->header) |
|
next_parent = PARENT_ENTRY(map, entry->next); |
|
|
|
rb_tree_remove_node(&map->rb_tree, &entry->rb_node); |
|
|
|
/* |
|
* If the previous node has a new parent, fixup the tree starting |
|
* at the previous node's old parent. |
|
*/ |
|
if (entry->prev != &map->header) { |
|
/* |
|
* Update the previous entry's gap due to our absence. |
|
*/ |
|
entry->prev->gap = uvm_rb_gap(entry->prev); |
uvm_rb_fixup(map, entry->prev); |
uvm_rb_fixup(map, entry->prev); |
if (parent) |
if (prev_parent != NULL |
uvm_rb_fixup(map, parent); |
&& prev_parent != entry |
|
&& prev_parent != PARENT_ENTRY(map, entry->prev)) |
|
uvm_rb_fixup(map, prev_parent); |
|
} |
|
|
|
/* |
|
* If the next node has a new parent, fixup the tree starting |
|
* at the next node's old parent. |
|
*/ |
|
if (entry->next != &map->header) { |
|
uvm_rb_fixup(map, entry->next); |
|
if (next_parent != NULL |
|
&& next_parent != entry |
|
&& next_parent != PARENT_ENTRY(map, entry->next)) |
|
uvm_rb_fixup(map, next_parent); |
|
} |
} |
} |
|
|
#if defined(DEBUG) |
#if defined(DEBUG) |
Line 455 _uvm_tree_sanity(struct vm_map *map) |
|
Line 537 _uvm_tree_sanity(struct vm_map *map) |
|
struct vm_map_entry *tmp, *trtmp; |
struct vm_map_entry *tmp, *trtmp; |
int n = 0, i = 1; |
int n = 0, i = 1; |
|
|
RB_FOREACH(tmp, uvm_tree, &map->rbhead) { |
for (tmp = map->header.next; tmp != &map->header; tmp = tmp->next) { |
if (tmp->ownspace != uvm_rb_space(map, tmp)) { |
if (tmp->gap != uvm_rb_gap(tmp)) { |
printf("%d/%d ownspace %lx != %lx %s\n", |
printf("%d/%d gap %lx != %lx %s\n", |
n + 1, map->nentries, |
n + 1, map->nentries, |
(ulong)tmp->ownspace, (ulong)uvm_rb_space(map, tmp), |
(ulong)tmp->gap, (ulong)uvm_rb_gap(tmp), |
tmp->next == &map->header ? "(last)" : ""); |
tmp->next == &map->header ? "(last)" : ""); |
goto error; |
goto error; |
} |
} |
|
/* |
|
* If any entries are out of order, tmp->gap will be unsigned |
|
* and will likely exceed the size of the map. |
|
*/ |
|
KASSERT(tmp->gap < map->size); |
|
n++; |
|
} |
|
|
|
if (n != map->nentries) { |
|
printf("nentries: %d vs %d\n", n, map->nentries); |
|
goto error; |
} |
} |
|
|
trtmp = NULL; |
trtmp = NULL; |
RB_FOREACH(tmp, uvm_tree, &map->rbhead) { |
for (tmp = map->header.next; tmp != &map->header; tmp = tmp->next) { |
if (tmp->space != uvm_rb_subtree_space(tmp)) { |
if (tmp->maxgap != uvm_rb_maxgap(tmp)) { |
printf("space %lx != %lx\n", |
printf("maxgap %lx != %lx\n", |
(ulong)tmp->space, |
(ulong)tmp->maxgap, |
(ulong)uvm_rb_subtree_space(tmp)); |
(ulong)uvm_rb_maxgap(tmp)); |
goto error; |
goto error; |
} |
} |
if (trtmp != NULL && trtmp->start >= tmp->start) { |
if (trtmp != NULL && trtmp->start >= tmp->start) { |
Line 477 _uvm_tree_sanity(struct vm_map *map) |
|
Line 571 _uvm_tree_sanity(struct vm_map *map) |
|
trtmp->start, tmp->start); |
trtmp->start, tmp->start); |
goto error; |
goto error; |
} |
} |
n++; |
|
|
|
trtmp = tmp; |
trtmp = tmp; |
} |
} |
|
|
if (n != map->nentries) { |
for (tmp = map->header.next; tmp != &map->header; |
printf("nentries: %d vs %d\n", n, map->nentries); |
|
goto error; |
|
} |
|
|
|
for (tmp = map->header.next; tmp && tmp != &map->header; |
|
tmp = tmp->next, i++) { |
tmp = tmp->next, i++) { |
trtmp = RB_FIND(uvm_tree, &map->rbhead, tmp); |
trtmp = (void *) rb_tree_iterate(&map->rb_tree, &tmp->rb_node, |
|
RB_DIR_LEFT); |
|
if (trtmp == NULL) |
|
trtmp = &map->header; |
|
if (tmp->prev != trtmp) { |
|
printf("lookup: %d: %p->prev=%p: %p\n", |
|
i, tmp, tmp->prev, trtmp); |
|
goto error; |
|
} |
|
trtmp = (void *) rb_tree_iterate(&map->rb_tree, &tmp->rb_node, |
|
RB_DIR_RIGHT); |
|
if (trtmp == NULL) |
|
trtmp = &map->header; |
|
if (tmp->next != trtmp) { |
|
printf("lookup: %d: %p->next=%p: %p\n", |
|
i, tmp, tmp->next, trtmp); |
|
goto error; |
|
} |
|
trtmp = (void *)rb_tree_find_node(&map->rb_tree, &tmp->start); |
if (trtmp != tmp) { |
if (trtmp != tmp) { |
printf("lookup: %d: %p - %p: %p\n", i, tmp, trtmp, |
printf("lookup: %d: %p - %p: %p\n", i, tmp, trtmp, |
RB_PARENT(tmp, rb_entry)); |
PARENT_ENTRY(map, tmp)); |
goto error; |
goto error; |
} |
} |
} |
} |
Line 1064 uvm_map(struct vm_map *map, vaddr_t *sta |
|
Line 1170 uvm_map(struct vm_map *map, vaddr_t *sta |
|
* for pager_map, allocate the new entry first to avoid sleeping |
* for pager_map, allocate the new entry first to avoid sleeping |
* for memory while we have the map locked. |
* for memory while we have the map locked. |
* |
* |
* besides, because we allocates entries for in-kernel maps |
* Also, because we allocate entries for in-kernel maps |
* a bit differently (cf. uvm_kmapent_alloc/free), we need to |
* a bit differently (cf. uvm_kmapent_alloc/free), we need to |
* allocate them before locking the map. |
* allocate them before locking the map. |
*/ |
*/ |
Line 1338 uvm_map_enter(struct vm_map *map, const |
|
Line 1444 uvm_map_enter(struct vm_map *map, const |
|
if (uobj && uobj->pgops->pgo_detach) |
if (uobj && uobj->pgops->pgo_detach) |
uobj->pgops->pgo_detach(uobj); |
uobj->pgops->pgo_detach(uobj); |
|
|
|
/* |
|
* Now that we've merged the entries, note that we've grown |
|
* and our gap has shrunk. Then fix the tree. |
|
*/ |
prev_entry->end += size; |
prev_entry->end += size; |
|
prev_entry->gap -= size; |
uvm_rb_fixup(map, prev_entry); |
uvm_rb_fixup(map, prev_entry); |
|
|
uvm_map_check(map, "map backmerged"); |
uvm_map_check(map, "map backmerged"); |
|
|
} |
} |
} else { |
} else { |
prev_entry->next->start -= size; |
prev_entry->next->start -= size; |
if (prev_entry != &map->header) |
if (prev_entry != &map->header) { |
|
prev_entry->gap -= size; |
|
KASSERT(prev_entry->gap == uvm_rb_gap(prev_entry)); |
uvm_rb_fixup(map, prev_entry); |
uvm_rb_fixup(map, prev_entry); |
|
} |
if (uobj) |
if (uobj) |
prev_entry->next->offset = uoffset; |
prev_entry->next->offset = uoffset; |
} |
} |
|
|
* uvm_map_lookup_entry_bytree: lookup an entry in tree |
* uvm_map_lookup_entry_bytree: lookup an entry in tree |
*/ |
*/ |
|
|
static bool |
static inline bool |
uvm_map_lookup_entry_bytree(struct vm_map *map, vaddr_t address, |
uvm_map_lookup_entry_bytree(struct vm_map *map, vaddr_t address, |
struct vm_map_entry **entry /* OUT */) |
struct vm_map_entry **entry /* OUT */) |
{ |
{ |
struct vm_map_entry *prev = &map->header; |
struct vm_map_entry *prev = &map->header; |
struct vm_map_entry *cur = RB_ROOT(&map->rbhead); |
struct vm_map_entry *cur = ROOT_ENTRY(map); |
|
|
while (cur) { |
while (cur) { |
|
UVMMAP_EVCNT_INCR(mlk_treeloop); |
if (address >= cur->start) { |
if (address >= cur->start) { |
if (address < cur->end) { |
if (address < cur->end) { |
*entry = cur; |
*entry = cur; |
return true; |
return true; |
} |
} |
prev = cur; |
prev = cur; |
cur = RB_RIGHT(cur, rb_entry); |
cur = RIGHT_ENTRY(cur); |
} else |
} else |
cur = RB_LEFT(cur, rb_entry); |
cur = LEFT_ENTRY(cur); |
} |
} |
*entry = prev; |
*entry = prev; |
return false; |
return false; |
Line 1658 uvm_map_lookup_entry(struct vm_map *map, |
|
Line 1773 uvm_map_lookup_entry(struct vm_map *map, |
|
return (true); |
return (true); |
} |
} |
|
|
if (map->nentries > 30) |
if (map->nentries > 15) |
use_tree = true; |
use_tree = true; |
} else { |
} else { |
|
|
Line 1675 uvm_map_lookup_entry(struct vm_map *map, |
|
Line 1790 uvm_map_lookup_entry(struct vm_map *map, |
|
* Simple lookup in the tree. Happens when the hint is |
* Simple lookup in the tree. Happens when the hint is |
* invalid, or nentries reach a threshold. |
* invalid, or nentries reach a threshold. |
*/ |
*/ |
|
UVMMAP_EVCNT_INCR(mlk_tree); |
if (uvm_map_lookup_entry_bytree(map, address, entry)) { |
if (uvm_map_lookup_entry_bytree(map, address, entry)) { |
goto got; |
goto got; |
} else { |
} else { |
Line 1686 uvm_map_lookup_entry(struct vm_map *map, |
|
Line 1802 uvm_map_lookup_entry(struct vm_map *map, |
|
* search linearly |
* search linearly |
*/ |
*/ |
|
|
|
UVMMAP_EVCNT_INCR(mlk_list); |
while (cur != &map->header) { |
while (cur != &map->header) { |
|
UVMMAP_EVCNT_INCR(mlk_listloop); |
if (cur->end > address) { |
if (cur->end > address) { |
if (address >= cur->start) { |
if (address >= cur->start) { |
/* |
/* |
Line 1914 uvm_map_findspace(struct vm_map *map, va |
|
Line 2032 uvm_map_findspace(struct vm_map *map, va |
|
nextgap: |
nextgap: |
KDASSERT((flags & UVM_FLAG_FIXED) == 0); |
KDASSERT((flags & UVM_FLAG_FIXED) == 0); |
/* If there is not enough space in the whole tree, we fail */ |
/* If there is not enough space in the whole tree, we fail */ |
tmp = RB_ROOT(&map->rbhead); |
tmp = ROOT_ENTRY(map); |
if (tmp == NULL || tmp->space < length) |
if (tmp == NULL || tmp->maxgap < length) |
goto notfound; |
goto notfound; |
|
|
prev = NULL; /* previous candidate */ |
prev = NULL; /* previous candidate */ |
|
|
/* Find an entry close to hint that has enough space */ |
/* Find an entry close to hint that has enough space */ |
for (; tmp;) { |
for (; tmp;) { |
KASSERT(tmp->next->start == tmp->end + tmp->ownspace); |
KASSERT(tmp->next->start == tmp->end + tmp->gap); |
if (topdown) { |
if (topdown) { |
if (tmp->next->start < hint + length && |
if (tmp->next->start < hint + length && |
(prev == NULL || tmp->end > prev->end)) { |
(prev == NULL || tmp->end > prev->end)) { |
if (tmp->ownspace >= length) |
if (tmp->gap >= length) |
prev = tmp; |
prev = tmp; |
else if ((child = RB_LEFT(tmp, rb_entry)) |
else if ((child = LEFT_ENTRY(tmp)) != NULL |
!= NULL && child->space >= length) |
&& child->maxgap >= length) |
prev = tmp; |
prev = tmp; |
} |
} |
} else { |
} else { |
if (tmp->end >= hint && |
if (tmp->end >= hint && |
(prev == NULL || tmp->end < prev->end)) { |
(prev == NULL || tmp->end < prev->end)) { |
if (tmp->ownspace >= length) |
if (tmp->gap >= length) |
prev = tmp; |
prev = tmp; |
else if ((child = RB_RIGHT(tmp, rb_entry)) |
else if ((child = RIGHT_ENTRY(tmp)) != NULL |
!= NULL && child->space >= length) |
&& child->maxgap >= length) |
prev = tmp; |
prev = tmp; |
} |
} |
} |
} |
if (tmp->next->start < hint + length) |
if (tmp->next->start < hint + length) |
child = RB_RIGHT(tmp, rb_entry); |
child = RIGHT_ENTRY(tmp); |
else if (tmp->end > hint) |
else if (tmp->end > hint) |
child = RB_LEFT(tmp, rb_entry); |
child = LEFT_ENTRY(tmp); |
else { |
else { |
if (tmp->ownspace >= length) |
if (tmp->gap >= length) |
break; |
break; |
if (topdown) |
if (topdown) |
child = RB_LEFT(tmp, rb_entry); |
child = LEFT_ENTRY(tmp); |
else |
else |
child = RB_RIGHT(tmp, rb_entry); |
child = RIGHT_ENTRY(tmp); |
} |
} |
if (child == NULL || child->space < length) |
if (child == NULL || child->maxgap < length) |
break; |
break; |
tmp = child; |
tmp = child; |
} |
} |
|
|
case -1: |
case -1: |
goto wraparound; |
goto wraparound; |
} |
} |
if (tmp->ownspace >= length) |
if (tmp->gap >= length) |
goto listsearch; |
goto listsearch; |
} |
} |
if (prev == NULL) |
if (prev == NULL) |
|
|
case -1: |
case -1: |
goto wraparound; |
goto wraparound; |
} |
} |
if (prev->ownspace >= length) |
if (prev->gap >= length) |
goto listsearch; |
goto listsearch; |
|
|
if (topdown) |
if (topdown) |
tmp = RB_LEFT(prev, rb_entry); |
tmp = LEFT_ENTRY(prev); |
else |
else |
tmp = RB_RIGHT(prev, rb_entry); |
tmp = RIGHT_ENTRY(prev); |
for (;;) { |
for (;;) { |
KASSERT(tmp && tmp->space >= length); |
KASSERT(tmp && tmp->maxgap >= length); |
if (topdown) |
if (topdown) |
child = RB_RIGHT(tmp, rb_entry); |
child = RIGHT_ENTRY(tmp); |
else |
else |
child = RB_LEFT(tmp, rb_entry); |
child = LEFT_ENTRY(tmp); |
if (child && child->space >= length) { |
if (child && child->maxgap >= length) { |
tmp = child; |
tmp = child; |
continue; |
continue; |
} |
} |
if (tmp->ownspace >= length) |
if (tmp->gap >= length) |
break; |
break; |
if (topdown) |
if (topdown) |
tmp = RB_LEFT(tmp, rb_entry); |
tmp = LEFT_ENTRY(tmp); |
else |
else |
tmp = RB_RIGHT(tmp, rb_entry); |
tmp = RIGHT_ENTRY(tmp); |
} |
} |
|
|
if (topdown) { |
if (topdown) { |
|
|
|
|
va = args.uma_start; |
va = args.uma_start; |
|
|
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE); |
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), |
|
VM_PROT_READ|VM_PROT_WRITE|PMAP_KMPAGE); |
pmap_update(vm_map_pmap(map)); |
pmap_update(vm_map_pmap(map)); |
|
|
ukh = (void *)va; |
ukh = (void *)va; |
Line 5032 uvm_map_setup(struct vm_map *map, vaddr_ |
|
Line 5151 uvm_map_setup(struct vm_map *map, vaddr_ |
|
{ |
{ |
int ipl; |
int ipl; |
|
|
RB_INIT(&map->rbhead); |
rb_tree_init(&map->rb_tree, &uvm_map_tree_ops); |
map->header.next = map->header.prev = &map->header; |
map->header.next = map->header.prev = &map->header; |
map->nentries = 0; |
map->nentries = 0; |
map->size = 0; |
map->size = 0; |