Fixes/improvements to RB-tree implementation:
1. Fix inverted node order, so that negative value from comparison operator would represent lower (left) node, and positive - higher (right) node. 2. Add an argument (i.e. "context"), passed to comparison operators. 3. Change rb_tree_insert_node() to return a node - either inserted one or already existing one. 4. Amend the interface to manipulate the actual object, instead of the rb_node (in a similar way as Patricia-tree interface does). 5. Update all RB-tree users accordingly. XXX: Perhaps rename rb.h to rbtree.h, since cleaning-up.. 1-3 address the PR/43488 by Jeremy Huddleston. Passes RB-tree regression tests. Reviewed by: matt@, christos@
This commit is contained in:
parent
0a37c83ff1
commit
879d5dfb5e
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp $ */
|
||||
/* $NetBSD: rb.c,v 1.7 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
@ -87,11 +87,17 @@ static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *,
|
||||
#define rb_tree_check_node(a, b, c, d) true
|
||||
#endif
|
||||
|
||||
#define RB_NODETOITEM(rbto, rbn) \
|
||||
((void *)((uintptr_t)(rbn) - (rbto)->rbto_node_offset))
|
||||
#define RB_ITEMTONODE(rbto, rbn) \
|
||||
((rb_node_t *)((uintptr_t)(rbn) + (rbto)->rbto_node_offset))
|
||||
|
||||
#define RB_SENTINEL_NODE NULL
|
||||
|
||||
void
|
||||
rb_tree_init(struct rb_tree *rbt, const struct rb_tree_ops *ops)
|
||||
rb_tree_init(struct rb_tree *rbt, const rb_tree_ops_t *ops)
|
||||
{
|
||||
|
||||
rbt->rbt_ops = ops;
|
||||
*((const struct rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
|
||||
RB_TAILQ_INIT(&rbt->rbt_nodes);
|
||||
@ -110,65 +116,73 @@ rb_tree_init(struct rb_tree *rbt, const struct rb_tree_ops *ops)
|
||||
#endif
|
||||
}
|
||||
|
||||
struct rb_node *
|
||||
void *
|
||||
rb_tree_find_node(struct rb_tree *rbt, const void *key)
|
||||
{
|
||||
rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
|
||||
struct rb_node *parent = rbt->rbt_root;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
void *pobj = RB_NODETOITEM(rbto, parent);
|
||||
const signed int diff = (*compare_key)(rbto->rbto_context,
|
||||
pobj, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
return pobj;
|
||||
parent = parent->rb_nodes[diff < 0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct rb_node *
|
||||
|
||||
void *
|
||||
rb_tree_find_node_geq(struct rb_tree *rbt, const void *key)
|
||||
{
|
||||
rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
struct rb_node *parent = rbt->rbt_root;
|
||||
struct rb_node *last = NULL;
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
|
||||
struct rb_node *parent = rbt->rbt_root, *last = NULL;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
void *pobj = RB_NODETOITEM(rbto, parent);
|
||||
const signed int diff = (*compare_key)(rbto->rbto_context,
|
||||
pobj, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
if (diff < 0)
|
||||
last = parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
struct rb_node *
|
||||
rb_tree_find_node_leq(struct rb_tree *rbt, const void *key)
|
||||
{
|
||||
rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
struct rb_node *parent = rbt->rbt_root;
|
||||
struct rb_node *last = NULL;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
return pobj;
|
||||
if (diff > 0)
|
||||
last = parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
parent = parent->rb_nodes[diff < 0];
|
||||
}
|
||||
|
||||
return last;
|
||||
return RB_NODETOITEM(rbto, last);
|
||||
}
|
||||
|
||||
bool
|
||||
rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
|
||||
void *
|
||||
rb_tree_find_node_leq(struct rb_tree *rbt, const void *key)
|
||||
{
|
||||
rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
|
||||
struct rb_node *parent, *tmp;
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
|
||||
struct rb_node *parent = rbt->rbt_root, *last = NULL;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
void *pobj = RB_NODETOITEM(rbto, parent);
|
||||
const signed int diff = (*compare_key)(rbto->rbto_context,
|
||||
pobj, key);
|
||||
if (diff == 0)
|
||||
return pobj;
|
||||
if (diff < 0)
|
||||
last = parent;
|
||||
parent = parent->rb_nodes[diff < 0];
|
||||
}
|
||||
|
||||
return RB_NODETOITEM(rbto, last);
|
||||
}
|
||||
|
||||
void *
|
||||
rb_tree_insert_node(struct rb_tree *rbt, void *object)
|
||||
{
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes;
|
||||
struct rb_node *parent, *tmp, *self = RB_ITEMTONODE(rbto, object);
|
||||
unsigned int position;
|
||||
bool rebalance;
|
||||
|
||||
@ -189,15 +203,17 @@ rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
* Find out where to place this new leaf.
|
||||
*/
|
||||
while (!RB_SENTINEL_P(tmp)) {
|
||||
const signed int diff = (*compare_nodes)(tmp, self);
|
||||
void *tobj = RB_NODETOITEM(rbto, tmp);
|
||||
const signed int diff = (*compare_nodes)(rbto->rbto_context,
|
||||
tobj, object);
|
||||
if (__predict_false(diff == 0)) {
|
||||
/*
|
||||
* Node already exists; don't insert.
|
||||
* Node already exists; return it.
|
||||
*/
|
||||
return false;
|
||||
return tobj;
|
||||
}
|
||||
parent = tmp;
|
||||
position = (diff > 0);
|
||||
position = (diff < 0);
|
||||
tmp = parent->rb_nodes[position];
|
||||
}
|
||||
|
||||
@ -221,8 +237,10 @@ rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
prev = TAILQ_PREV(next, rb_node_qh, rb_link);
|
||||
KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
|
||||
KASSERT(next == NULL || !RB_SENTINEL_P(next));
|
||||
KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
|
||||
KASSERT(next == NULL || (*compare_nodes)(self, next) > 0);
|
||||
KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0);
|
||||
KASSERT(next == NULL || (*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, self), RB_NODETOITEM(rbto, next)) < 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -270,10 +288,14 @@ rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
if (RB_ROOT_P(rbt, self)) {
|
||||
RB_TAILQ_INSERT_HEAD(&rbt->rbt_nodes, self, rb_link);
|
||||
} else if (position == RB_DIR_LEFT) {
|
||||
KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
|
||||
KASSERT((*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, self),
|
||||
RB_NODETOITEM(rbto, RB_FATHER(self))) < 0);
|
||||
RB_TAILQ_INSERT_BEFORE(RB_FATHER(self), self, rb_link);
|
||||
} else {
|
||||
KASSERT((*compare_nodes)(RB_FATHER(self), self) > 0);
|
||||
KASSERT((*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, RB_FATHER(self)),
|
||||
RB_NODETOITEM(rbto, self)) < 0);
|
||||
RB_TAILQ_INSERT_AFTER(&rbt->rbt_nodes, RB_FATHER(self),
|
||||
self, rb_link);
|
||||
}
|
||||
@ -288,9 +310,10 @@ rb_tree_insert_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
KASSERT(rb_tree_check_node(rbt, self, NULL, true));
|
||||
}
|
||||
|
||||
return true;
|
||||
/* Succesfully inserted, return our node pointer. */
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Swap the location and colors of 'self' and its child @ which. The child
|
||||
* can not be a sentinel node. This is our rotation function. However,
|
||||
@ -316,7 +339,8 @@ rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father,
|
||||
|
||||
KASSERT(rb_tree_check_node(rbt, old_father, NULL, false));
|
||||
KASSERT(rb_tree_check_node(rbt, old_child, NULL, false));
|
||||
KASSERT(RB_ROOT_P(rbt, old_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
KASSERT(RB_ROOT_P(rbt, old_father) ||
|
||||
rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
|
||||
/*
|
||||
* Exchange descendant linkages.
|
||||
@ -358,9 +382,10 @@ rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father,
|
||||
|
||||
KASSERT(rb_tree_check_node(rbt, new_father, NULL, false));
|
||||
KASSERT(rb_tree_check_node(rbt, new_child, NULL, false));
|
||||
KASSERT(RB_ROOT_P(rbt, new_father) || rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
KASSERT(RB_ROOT_P(rbt, new_father) ||
|
||||
rb_tree_check_node(rbt, grandpa, NULL, false));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
|
||||
{
|
||||
@ -466,7 +491,7 @@ rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
|
||||
*/
|
||||
RB_MARK_BLACK(rbt->rbt_root);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance)
|
||||
{
|
||||
@ -515,7 +540,7 @@ rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance)
|
||||
rb_tree_removal_rebalance(rbt, father, which);
|
||||
KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When deleting an interior node
|
||||
*/
|
||||
@ -716,13 +741,12 @@ rb_tree_prune_blackred_branch(struct rb_tree *rbt, struct rb_node *self,
|
||||
KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
|
||||
KASSERT(rb_tree_check_node(rbt, son, NULL, true));
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
rb_tree_remove_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
rb_tree_remove_node(struct rb_tree *rbt, void *object)
|
||||
{
|
||||
struct rb_node *standin;
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
struct rb_node *standin, *self = RB_ITEMTONODE(rbto, object);
|
||||
unsigned int which;
|
||||
|
||||
KASSERT(!RB_SENTINEL_P(self));
|
||||
@ -779,7 +803,7 @@ rb_tree_remove_node(struct rb_tree *rbt, struct rb_node *self)
|
||||
* Let's find the node closes to us opposite of our parent
|
||||
* Now swap it with ourself, "prune" it, and rebalance, if needed.
|
||||
*/
|
||||
standin = rb_tree_iterate(rbt, self, which);
|
||||
standin = RB_ITEMTONODE(rbto, rb_tree_iterate(rbt, object, which));
|
||||
rb_tree_swap_prune_and_rebalance(rbt, self, standin);
|
||||
}
|
||||
|
||||
@ -934,27 +958,30 @@ rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent,
|
||||
KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
|
||||
}
|
||||
|
||||
struct rb_node *
|
||||
rb_tree_iterate(struct rb_tree *rbt, struct rb_node *self,
|
||||
const unsigned int direction)
|
||||
void *
|
||||
rb_tree_iterate(struct rb_tree *rbt, void *object, const unsigned int direction)
|
||||
{
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
const unsigned int other = direction ^ RB_DIR_OTHER;
|
||||
struct rb_node *self;
|
||||
|
||||
KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
|
||||
|
||||
if (self == NULL) {
|
||||
if (object == NULL) {
|
||||
#ifndef RBSMALL
|
||||
if (RB_SENTINEL_P(rbt->rbt_root))
|
||||
return NULL;
|
||||
return rbt->rbt_minmax[direction];
|
||||
return RB_NODETOITEM(rbto, rbt->rbt_minmax[direction]);
|
||||
#else
|
||||
self = rbt->rbt_root;
|
||||
if (RB_SENTINEL_P(self))
|
||||
return NULL;
|
||||
while (!RB_SENTINEL_P(self->rb_nodes[direction]))
|
||||
self = self->rb_nodes[direction];
|
||||
return self;
|
||||
return RB_NODETOITEM(rbto, self);
|
||||
#endif /* !RBSMALL */
|
||||
}
|
||||
self = RB_ITEMTONODE(rbto, object);
|
||||
KASSERT(!RB_SENTINEL_P(self));
|
||||
/*
|
||||
* We can't go any further in this direction. We proceed up in the
|
||||
@ -963,7 +990,7 @@ rb_tree_iterate(struct rb_tree *rbt, struct rb_node *self,
|
||||
if (RB_SENTINEL_P(self->rb_nodes[direction])) {
|
||||
while (!RB_ROOT_P(rbt, self)) {
|
||||
if (other == RB_POSITION(self))
|
||||
return RB_FATHER(self);
|
||||
return RB_NODETOITEM(rbto, RB_FATHER(self));
|
||||
self = RB_FATHER(self);
|
||||
}
|
||||
return NULL;
|
||||
@ -977,7 +1004,7 @@ rb_tree_iterate(struct rb_tree *rbt, struct rb_node *self,
|
||||
KASSERT(!RB_SENTINEL_P(self));
|
||||
while (!RB_SENTINEL_P(self->rb_nodes[other]))
|
||||
self = self->rb_nodes[other];
|
||||
return self;
|
||||
return RB_NODETOITEM(rbto, self);
|
||||
}
|
||||
|
||||
#ifdef RBDEBUG
|
||||
@ -1047,10 +1074,12 @@ static bool
|
||||
rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
|
||||
const struct rb_node *prev, bool red_check)
|
||||
{
|
||||
rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
|
||||
const rb_tree_ops_t *rbto = rbt->rbt_ops;
|
||||
rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes;
|
||||
|
||||
KASSERT(!RB_SENTINEL_P(self));
|
||||
KASSERT(prev == NULL || (*compare_nodes)(prev, self) > 0);
|
||||
KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0);
|
||||
|
||||
/*
|
||||
* Verify our relationship to our parent.
|
||||
@ -1061,13 +1090,17 @@ rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
|
||||
KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
|
||||
KASSERT(RB_FATHER(self) == (const struct rb_node *) &rbt->rbt_root);
|
||||
} else {
|
||||
int diff = (*compare_nodes)(rbto->rbto_context,
|
||||
RB_NODETOITEM(rbto, self),
|
||||
RB_NODETOITEM(rbto, RB_FATHER(self)));
|
||||
|
||||
KASSERT(self != rbt->rbt_root);
|
||||
KASSERT(!RB_FATHER_SENTINEL_P(self));
|
||||
if (RB_POSITION(self) == RB_DIR_LEFT) {
|
||||
KASSERT((*compare_nodes)(self, RB_FATHER(self)) > 0);
|
||||
KASSERT(diff < 0);
|
||||
KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
|
||||
} else {
|
||||
KASSERT((*compare_nodes)(self, RB_FATHER(self)) < 0);
|
||||
KASSERT(diff > 0);
|
||||
KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_RIGHT] == self);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: prop_dictionary.c,v 1.35 2009/04/14 02:53:41 haad Exp $ */
|
||||
/* $NetBSD: prop_dictionary.c,v 1.36 2010/09/24 22:51:52 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
@ -66,10 +66,6 @@ struct _prop_dictionary_keysym {
|
||||
/* actually variable length */
|
||||
};
|
||||
|
||||
#define RBNODE_TO_PDK(n) \
|
||||
((struct _prop_dictionary_keysym *) \
|
||||
((uintptr_t)n - offsetof(struct _prop_dictionary_keysym, pdk_link)))
|
||||
|
||||
/* pdk_key[1] takes care of the NUL */
|
||||
#define PDK_SIZE_16 (sizeof(struct _prop_dictionary_keysym) + 16)
|
||||
#define PDK_SIZE_32 (sizeof(struct _prop_dictionary_keysym) + 32)
|
||||
@ -176,28 +172,32 @@ struct _prop_dictionary_iterator {
|
||||
*/
|
||||
|
||||
static int
|
||||
_prop_dict_keysym_rb_compare_nodes(const struct rb_node *n1,
|
||||
const struct rb_node *n2)
|
||||
/*ARGSUSED*/
|
||||
_prop_dict_keysym_rb_compare_nodes(void *ctx __unused,
|
||||
const void *n1, const void *n2)
|
||||
{
|
||||
const prop_dictionary_keysym_t pdk1 = RBNODE_TO_PDK(n1);
|
||||
const prop_dictionary_keysym_t pdk2 = RBNODE_TO_PDK(n2);
|
||||
const struct _prop_dictionary_keysym *pdk1 = n1;
|
||||
const struct _prop_dictionary_keysym *pdk2 = n2;
|
||||
|
||||
return (strcmp(pdk1->pdk_key, pdk2->pdk_key));
|
||||
return strcmp(pdk1->pdk_key, pdk2->pdk_key);
|
||||
}
|
||||
|
||||
static int
|
||||
_prop_dict_keysym_rb_compare_key(const struct rb_node *n,
|
||||
const void *v)
|
||||
/*ARGSUSED*/
|
||||
_prop_dict_keysym_rb_compare_key(void *ctx __unused,
|
||||
const void *n, const void *v)
|
||||
{
|
||||
const prop_dictionary_keysym_t pdk = RBNODE_TO_PDK(n);
|
||||
const struct _prop_dictionary_keysym *pdk = n;
|
||||
const char *cp = v;
|
||||
|
||||
return (strcmp(pdk->pdk_key, cp));
|
||||
return strcmp(pdk->pdk_key, cp);
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops _prop_dict_keysym_rb_tree_ops = {
|
||||
static const rb_tree_ops_t _prop_dict_keysym_rb_tree_ops = {
|
||||
.rbto_compare_nodes = _prop_dict_keysym_rb_compare_nodes,
|
||||
.rbto_compare_key = _prop_dict_keysym_rb_compare_key,
|
||||
.rbto_compare_key = _prop_dict_keysym_rb_compare_key,
|
||||
.rbto_node_offset = offsetof(struct _prop_dictionary_keysym, pdk_link),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static struct rb_tree _prop_dict_keysym_tree;
|
||||
@ -235,7 +235,7 @@ _prop_dict_keysym_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_dictionary_keysym_t pdk = *obj;
|
||||
|
||||
_prop_rb_tree_remove_node(&_prop_dict_keysym_tree, &pdk->pdk_link);
|
||||
_prop_rb_tree_remove_node(&_prop_dict_keysym_tree, pdk);
|
||||
_prop_dict_keysym_put(pdk);
|
||||
|
||||
return _PROP_OBJECT_FREE_DONE;
|
||||
@ -282,10 +282,8 @@ _prop_dict_keysym_equals(prop_object_t v1, prop_object_t v2,
|
||||
static prop_dictionary_keysym_t
|
||||
_prop_dict_keysym_alloc(const char *key)
|
||||
{
|
||||
prop_dictionary_keysym_t opdk, pdk;
|
||||
const struct rb_node *n;
|
||||
prop_dictionary_keysym_t opdk, pdk, rpdk;
|
||||
size_t size;
|
||||
bool rv;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_dict_init_once, _prop_dict_init);
|
||||
|
||||
@ -294,9 +292,8 @@ _prop_dict_keysym_alloc(const char *key)
|
||||
* we just retain it and return it.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
|
||||
n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (n != NULL) {
|
||||
opdk = RBNODE_TO_PDK(n);
|
||||
opdk = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (opdk != NULL) {
|
||||
prop_object_retain(opdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
return (opdk);
|
||||
@ -331,16 +328,15 @@ _prop_dict_keysym_alloc(const char *key)
|
||||
* we have to check again if it is in the tree.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_dict_keysym_tree_mutex);
|
||||
n = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (n != NULL) {
|
||||
opdk = RBNODE_TO_PDK(n);
|
||||
opdk = _prop_rb_tree_find(&_prop_dict_keysym_tree, key);
|
||||
if (opdk != NULL) {
|
||||
prop_object_retain(opdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
_prop_dict_keysym_put(pdk);
|
||||
return (opdk);
|
||||
}
|
||||
rv = _prop_rb_tree_insert_node(&_prop_dict_keysym_tree, &pdk->pdk_link);
|
||||
_PROP_ASSERT(rv == true);
|
||||
rpdk = _prop_rb_tree_insert_node(&_prop_dict_keysym_tree, pdk);
|
||||
_PROP_ASSERT(rpdk == pdk);
|
||||
_PROP_MUTEX_UNLOCK(_prop_dict_keysym_tree_mutex);
|
||||
return (pdk);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: prop_number.c,v 1.22 2009/03/15 22:29:11 cegger Exp $ */
|
||||
/* $NetBSD: prop_number.c,v 1.23 2010/09/24 22:51:52 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
@ -58,10 +58,6 @@ struct _prop_number {
|
||||
} pn_value;
|
||||
};
|
||||
|
||||
#define RBNODE_TO_PN(n) \
|
||||
((struct _prop_number *) \
|
||||
((uintptr_t)n - offsetof(struct _prop_number, pn_link)))
|
||||
|
||||
_PROP_POOL_INIT(_prop_number_pool, sizeof(struct _prop_number), "propnmbr")
|
||||
|
||||
static _prop_object_free_rv_t
|
||||
@ -122,28 +118,31 @@ _prop_number_compare_values(const struct _prop_number_value *pnv1,
|
||||
}
|
||||
|
||||
static int
|
||||
_prop_number_rb_compare_nodes(const struct rb_node *n1,
|
||||
const struct rb_node *n2)
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_nodes(void *ctx __unused,
|
||||
const void *n1, const void *n2)
|
||||
{
|
||||
const prop_number_t pn1 = RBNODE_TO_PN(n1);
|
||||
const prop_number_t pn2 = RBNODE_TO_PN(n2);
|
||||
const struct _prop_number *pn1 = n1;
|
||||
const struct _prop_number *pn2 = n2;
|
||||
|
||||
return (_prop_number_compare_values(&pn1->pn_value, &pn2->pn_value));
|
||||
return _prop_number_compare_values(&pn1->pn_value, &pn2->pn_value);
|
||||
}
|
||||
|
||||
static int
|
||||
_prop_number_rb_compare_key(const struct rb_node *n,
|
||||
const void *v)
|
||||
/*ARGSUSED*/
|
||||
_prop_number_rb_compare_key(void *ctx __unused, const void *n, const void *v)
|
||||
{
|
||||
const prop_number_t pn = RBNODE_TO_PN(n);
|
||||
const struct _prop_number *pn = n;
|
||||
const struct _prop_number_value *pnv = v;
|
||||
|
||||
return (_prop_number_compare_values(&pn->pn_value, pnv));
|
||||
return _prop_number_compare_values(&pn->pn_value, pnv);
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops _prop_number_rb_tree_ops = {
|
||||
static const rb_tree_ops_t _prop_number_rb_tree_ops = {
|
||||
.rbto_compare_nodes = _prop_number_rb_compare_nodes,
|
||||
.rbto_compare_key = _prop_number_rb_compare_key,
|
||||
.rbto_compare_key = _prop_number_rb_compare_key,
|
||||
.rbto_node_offset = offsetof(struct _prop_number, pn_link),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static struct rb_tree _prop_number_tree;
|
||||
@ -155,7 +154,7 @@ _prop_number_free(prop_stack_t stack, prop_object_t *obj)
|
||||
{
|
||||
prop_number_t pn = *obj;
|
||||
|
||||
_prop_rb_tree_remove_node(&_prop_number_tree, &pn->pn_link);
|
||||
_prop_rb_tree_remove_node(&_prop_number_tree, pn);
|
||||
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
|
||||
@ -169,8 +168,7 @@ _prop_number_init(void)
|
||||
{
|
||||
|
||||
_PROP_MUTEX_INIT(_prop_number_tree_mutex);
|
||||
_prop_rb_tree_init(&_prop_number_tree,
|
||||
&_prop_number_rb_tree_ops);
|
||||
_prop_rb_tree_init(&_prop_number_tree, &_prop_number_rb_tree_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -271,9 +269,7 @@ _prop_number_equals(prop_object_t v1, prop_object_t v2,
|
||||
static prop_number_t
|
||||
_prop_number_alloc(const struct _prop_number_value *pnv)
|
||||
{
|
||||
prop_number_t opn, pn;
|
||||
struct rb_node *n;
|
||||
bool rv;
|
||||
prop_number_t opn, pn, rpn;
|
||||
|
||||
_PROP_ONCE_RUN(_prop_number_init_once, _prop_number_init);
|
||||
|
||||
@ -282,9 +278,8 @@ _prop_number_alloc(const struct _prop_number_value *pnv)
|
||||
* we just retain it and return it.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
n = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (n != NULL) {
|
||||
opn = RBNODE_TO_PN(n);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (opn);
|
||||
@ -308,16 +303,15 @@ _prop_number_alloc(const struct _prop_number_value *pnv)
|
||||
* we have to check again if it is in the tree.
|
||||
*/
|
||||
_PROP_MUTEX_LOCK(_prop_number_tree_mutex);
|
||||
n = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (n != NULL) {
|
||||
opn = RBNODE_TO_PN(n);
|
||||
opn = _prop_rb_tree_find(&_prop_number_tree, pnv);
|
||||
if (opn != NULL) {
|
||||
prop_object_retain(opn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
_PROP_POOL_PUT(_prop_number_pool, pn);
|
||||
return (opn);
|
||||
}
|
||||
rv = _prop_rb_tree_insert_node(&_prop_number_tree, &pn->pn_link);
|
||||
_PROP_ASSERT(rv == true);
|
||||
rpn = _prop_rb_tree_insert_node(&_prop_number_tree, pn);
|
||||
_PROP_ASSERT(rpn == pn);
|
||||
_PROP_MUTEX_UNLOCK(_prop_number_tree_mutex);
|
||||
return (pn);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udf.h,v 1.41 2010/02/25 16:15:57 reinoud Exp $ */
|
||||
/* $NetBSD: udf.h,v 1.42 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
@ -357,12 +357,6 @@ struct udf_mount {
|
||||
void *strategy_private;
|
||||
};
|
||||
|
||||
|
||||
#define RBTOUDFNODE(node) \
|
||||
((node) ? \
|
||||
(void *)((uintptr_t)(node) - offsetof(struct udf_node, rbnode)) \
|
||||
: NULL)
|
||||
|
||||
/*
|
||||
* UDF node describing a file/directory.
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udf_subr.c,v 1.107 2010/07/21 17:52:11 hannken Exp $ */
|
||||
/* $NetBSD: udf_subr.c,v 1.108 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2008 Reinoud Zandijk
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.107 2010/07/21 17:52:11 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.108 2010/09/24 22:51:50 rmind Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
|
||||
@ -3396,34 +3396,37 @@ udf_compare_icb(const struct long_ad *a, const struct long_ad *b)
|
||||
|
||||
|
||||
static int
|
||||
udf_compare_rbnodes(const struct rb_node *a, const struct rb_node *b)
|
||||
udf_compare_rbnodes(void *ctx, const void *a, const void *b)
|
||||
{
|
||||
struct udf_node *a_node = RBTOUDFNODE(a);
|
||||
struct udf_node *b_node = RBTOUDFNODE(b);
|
||||
const struct udf_node *a_node = a;
|
||||
const struct udf_node *b_node = b;
|
||||
|
||||
return udf_compare_icb(&a_node->loc, &b_node->loc);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udf_compare_rbnode_icb(const struct rb_node *a, const void *key)
|
||||
udf_compare_rbnode_icb(void *ctx, const void *a, const void *key)
|
||||
{
|
||||
struct udf_node *a_node = RBTOUDFNODE(a);
|
||||
const struct udf_node *a_node = a;
|
||||
const struct long_ad * const icb = key;
|
||||
|
||||
return udf_compare_icb(&a_node->loc, icb);
|
||||
}
|
||||
|
||||
|
||||
static const struct rb_tree_ops udf_node_rbtree_ops = {
|
||||
static const rb_tree_ops_t udf_node_rbtree_ops = {
|
||||
.rbto_compare_nodes = udf_compare_rbnodes,
|
||||
.rbto_compare_key = udf_compare_rbnode_icb,
|
||||
.rbto_compare_key = udf_compare_rbnode_icb,
|
||||
.rbto_node_offset = offsetof(struct udf_node, rbnode),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
udf_init_nodes_tree(struct udf_mount *ump)
|
||||
{
|
||||
|
||||
rb_tree_init(&ump->udf_node_tree, &udf_node_rbtree_ops);
|
||||
}
|
||||
|
||||
@ -3431,16 +3434,14 @@ udf_init_nodes_tree(struct udf_mount *ump)
|
||||
static struct udf_node *
|
||||
udf_node_lookup(struct udf_mount *ump, struct long_ad *icbptr)
|
||||
{
|
||||
struct rb_node *rb_node;
|
||||
struct udf_node *udf_node;
|
||||
struct vnode *vp;
|
||||
|
||||
loop:
|
||||
mutex_enter(&ump->ihash_lock);
|
||||
|
||||
rb_node = rb_tree_find_node(&ump->udf_node_tree, icbptr);
|
||||
if (rb_node) {
|
||||
udf_node = RBTOUDFNODE(rb_node);
|
||||
udf_node = rb_tree_find_node(&ump->udf_node_tree, icbptr);
|
||||
if (udf_node) {
|
||||
vp = udf_node->vnode;
|
||||
assert(vp);
|
||||
mutex_enter(&vp->v_interlock);
|
||||
@ -3462,7 +3463,7 @@ udf_register_node(struct udf_node *udf_node)
|
||||
|
||||
/* add node to the rb tree */
|
||||
mutex_enter(&ump->ihash_lock);
|
||||
rb_tree_insert_node(&ump->udf_node_tree, &udf_node->rbnode);
|
||||
rb_tree_insert_node(&ump->udf_node_tree, udf_node);
|
||||
mutex_exit(&ump->ihash_lock);
|
||||
}
|
||||
|
||||
@ -3474,7 +3475,7 @@ udf_deregister_node(struct udf_node *udf_node)
|
||||
|
||||
/* remove node from the rb tree */
|
||||
mutex_enter(&ump->ihash_lock);
|
||||
rb_tree_remove_node(&ump->udf_node_tree, &udf_node->rbnode);
|
||||
rb_tree_remove_node(&ump->udf_node_tree, udf_node);
|
||||
mutex_exit(&ump->ihash_lock);
|
||||
}
|
||||
|
||||
@ -6367,7 +6368,7 @@ derailed:
|
||||
KASSERT(mutex_owned(&mntvnode_lock));
|
||||
|
||||
DPRINTF(SYNC, ("sync_pass %d\n", pass));
|
||||
udf_node = RBTOUDFNODE(RB_TREE_MIN(&ump->udf_node_tree));
|
||||
udf_node = RB_TREE_MIN(&ump->udf_node_tree);
|
||||
for (;udf_node; udf_node = n_udf_node) {
|
||||
DPRINTF(SYNC, ("."));
|
||||
|
||||
@ -6375,9 +6376,8 @@ derailed:
|
||||
vp = udf_node->vnode;
|
||||
|
||||
mutex_enter(&vp->v_interlock);
|
||||
n_udf_node = RBTOUDFNODE(rb_tree_iterate(
|
||||
&ump->udf_node_tree, &udf_node->rbnode,
|
||||
RB_DIR_RIGHT));
|
||||
n_udf_node = rb_tree_iterate(&ump->udf_node_tree,
|
||||
udf_node, RB_DIR_RIGHT);
|
||||
|
||||
if (n_udf_node)
|
||||
n_udf_node->i_flags |= IN_SYNCED;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: subr_lockdebug.c,v 1.41 2009/11/03 00:29:11 dyoung Exp $ */
|
||||
/* $NetBSD: subr_lockdebug.c,v 1.42 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
@ -34,7 +34,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.41 2009/11/03 00:29:11 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_lockdebug.c,v 1.42 2010/09/24 22:51:50 rmind Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
@ -68,7 +68,7 @@ unsigned int ld_panic;
|
||||
#define LD_WRITE_LOCK 0x80000000
|
||||
|
||||
typedef struct lockdebug {
|
||||
struct rb_node ld_rb_node; /* must be the first member */
|
||||
struct rb_node ld_rb_node;
|
||||
__cpu_simple_lock_t ld_spinlock;
|
||||
_TAILQ_ENTRY(struct lockdebug, volatile) ld_chain;
|
||||
_TAILQ_ENTRY(struct lockdebug, volatile) ld_achain;
|
||||
@ -103,39 +103,41 @@ static int lockdebug_more(int);
|
||||
static void lockdebug_init(void);
|
||||
|
||||
static signed int
|
||||
ld_rbto_compare_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
ld_rbto_compare_nodes(void *ctx, const void *n1, const void *n2)
|
||||
{
|
||||
const lockdebug_t *ld1 = (const void *)n1;
|
||||
const lockdebug_t *ld2 = (const void *)n2;
|
||||
const lockdebug_t *ld1 = n1;
|
||||
const lockdebug_t *ld2 = n2;
|
||||
const uintptr_t a = (uintptr_t)ld1->ld_lock;
|
||||
const uintptr_t b = (uintptr_t)ld2->ld_lock;
|
||||
|
||||
if (a < b)
|
||||
return 1;
|
||||
if (a > b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static signed int
|
||||
ld_rbto_compare_key(const struct rb_node *n, const void *key)
|
||||
ld_rbto_compare_key(void *ctx, const void *n, const void *key)
|
||||
{
|
||||
const lockdebug_t *ld = (const void *)n;
|
||||
const lockdebug_t *ld = n;
|
||||
const uintptr_t a = (uintptr_t)ld->ld_lock;
|
||||
const uintptr_t b = (uintptr_t)key;
|
||||
|
||||
if (a < b)
|
||||
return 1;
|
||||
if (a > b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rb_tree ld_rb_tree;
|
||||
static rb_tree_t ld_rb_tree;
|
||||
|
||||
static const struct rb_tree_ops ld_rb_tree_ops = {
|
||||
static const rb_tree_ops_t ld_rb_tree_ops = {
|
||||
.rbto_compare_nodes = ld_rbto_compare_nodes,
|
||||
.rbto_compare_key = ld_rbto_compare_key,
|
||||
.rbto_node_offset = offsetof(lockdebug_t, ld_rb_node),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static inline lockdebug_t *
|
||||
@ -189,8 +191,10 @@ lockdebug_lookup(volatile void *lock, uintptr_t where)
|
||||
lockdebug_t *ld;
|
||||
|
||||
ld = lockdebug_lookup1(lock);
|
||||
if (ld == NULL)
|
||||
panic("lockdebug_lookup: uninitialized lock (lock=%p, from=%08"PRIxPTR")", lock, where);
|
||||
if (ld == NULL) {
|
||||
panic("lockdebug_lookup: uninitialized lock "
|
||||
"(lock=%p, from=%08"PRIxPTR")", lock, where);
|
||||
}
|
||||
return ld;
|
||||
}
|
||||
|
||||
@ -292,7 +296,7 @@ lockdebug_alloc(volatile void *lock, lockops_t *lo, uintptr_t initaddr)
|
||||
ld->ld_initaddr = initaddr;
|
||||
ld->ld_flags = (lo->lo_type == LOCKOPS_SLEEP ? LD_SLEEPER : 0);
|
||||
lockdebug_lock_cpus();
|
||||
rb_tree_insert_node(&ld_rb_tree, __UNVOLATILE(&ld->ld_rb_node));
|
||||
(void)rb_tree_insert_node(&ld_rb_tree, __UNVOLATILE(ld));
|
||||
lockdebug_unlock_cpus();
|
||||
__cpu_simple_unlock(&ld_mod_lk);
|
||||
|
||||
@ -330,7 +334,7 @@ lockdebug_free(volatile void *lock)
|
||||
return;
|
||||
}
|
||||
lockdebug_lock_cpus();
|
||||
rb_tree_remove_node(&ld_rb_tree, __UNVOLATILE(&ld->ld_rb_node));
|
||||
rb_tree_remove_node(&ld_rb_tree, __UNVOLATILE(ld));
|
||||
lockdebug_unlock_cpus();
|
||||
ld->ld_lock = NULL;
|
||||
TAILQ_INSERT_TAIL(&ld_free, ld, ld_chain);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: npf_session.c,v 1.2 2010/09/16 04:53:27 rmind Exp $ */
|
||||
/* $NetBSD: npf_session.c,v 1.3 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.2 2010/09/16 04:53:27 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.3 2010/09/24 22:51:50 rmind Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -139,17 +139,13 @@ struct npf_session {
|
||||
struct timespec s_atime;
|
||||
};
|
||||
|
||||
/* Return pointer to npf_session_t from RB-tree node. (XXX fix rb-tree) */
|
||||
#define NPF_RBN2SESENT(n) \
|
||||
(npf_session_t *)((uintptr_t)n - offsetof(npf_session_t, se_entry.rbnode))
|
||||
|
||||
LIST_HEAD(npf_sesslist, npf_session);
|
||||
|
||||
#define SESS_HASH_BUCKETS 1024 /* XXX tune + make tunable */
|
||||
#define SESS_HASH_MASK (SESS_HASH_BUCKETS - 1)
|
||||
|
||||
typedef struct {
|
||||
struct rb_tree sh_tree;
|
||||
rb_tree_t sh_tree;
|
||||
krwlock_t sh_lock;
|
||||
u_int sh_count;
|
||||
} npf_sess_hash_t;
|
||||
@ -229,10 +225,10 @@ npf_session_sysfini(void)
|
||||
*/
|
||||
|
||||
static signed int
|
||||
sess_rbtree_cmp_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
sess_rbtree_cmp_nodes(void *ctx, const void *n1, const void *n2)
|
||||
{
|
||||
const npf_session_t * const se1 = NPF_RBN2SESENT(n1);
|
||||
const npf_session_t * const se2 = NPF_RBN2SESENT(n2);
|
||||
const npf_session_t * const se1 = n1;
|
||||
const npf_session_t * const se2 = n2;
|
||||
|
||||
/*
|
||||
* Note: must compare equivalent streams.
|
||||
@ -269,9 +265,9 @@ sess_rbtree_cmp_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
}
|
||||
|
||||
static signed int
|
||||
sess_rbtree_cmp_key(const struct rb_node *n1, const void *key)
|
||||
sess_rbtree_cmp_key(void *ctx, const void *n1, const void *key)
|
||||
{
|
||||
const npf_session_t * const se = NPF_RBN2SESENT(n1);
|
||||
const npf_session_t * const se = n1;
|
||||
const npf_cache_t * const npc = key;
|
||||
in_port_t sport, dport;
|
||||
in_addr_t src, dst;
|
||||
@ -302,9 +298,11 @@ sess_rbtree_cmp_key(const struct rb_node *n1, const void *key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops sess_rbtree_ops = {
|
||||
static const rb_tree_ops_t sess_rbtree_ops = {
|
||||
.rbto_compare_nodes = sess_rbtree_cmp_nodes,
|
||||
.rbto_compare_key = sess_rbtree_cmp_key
|
||||
.rbto_compare_key = sess_rbtree_cmp_key,
|
||||
.rbto_node_offset = offsetof(npf_session_t, se_entry.rbnode),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
static inline npf_sess_hash_t *
|
||||
@ -484,7 +482,6 @@ npf_session_inspect(npf_cache_t *npc, nbuf_t *nbuf,
|
||||
struct ifnet *ifp, const int di)
|
||||
{
|
||||
npf_sess_hash_t *sh;
|
||||
struct rb_node *nd;
|
||||
npf_session_t *se;
|
||||
|
||||
/* Attempt to fetch and cache all relevant IPv4 data. */
|
||||
@ -519,12 +516,11 @@ npf_session_inspect(npf_cache_t *npc, nbuf_t *nbuf,
|
||||
|
||||
/* Lookup the tree for a state entry. */
|
||||
rw_enter(&sh->sh_lock, RW_READER);
|
||||
nd = rb_tree_find_node(&sh->sh_tree, key);
|
||||
if (nd == NULL) {
|
||||
se = rb_tree_find_node(&sh->sh_tree, key);
|
||||
if (se == NULL) {
|
||||
rw_exit(&sh->sh_lock);
|
||||
return NULL;
|
||||
}
|
||||
se = NPF_RBN2SESENT(nd);
|
||||
|
||||
/* Inspect the protocol data and handle state changes. */
|
||||
if (npf_session_pstate(npc, se, di)) {
|
||||
@ -606,7 +602,7 @@ npf_session_establish(const npf_cache_t *npc, npf_nat_t *nt, const int di)
|
||||
/* Find the hash bucket and insert the state into the tree. */
|
||||
sh = sess_hash_bucket(npc);
|
||||
rw_enter(&sh->sh_lock, RW_WRITER);
|
||||
ok = rb_tree_insert_node(&sh->sh_tree, &se->se_entry.rbnode);
|
||||
ok = rb_tree_insert_node(&sh->sh_tree, se) == se;
|
||||
if (__predict_true(ok)) {
|
||||
sh->sh_count++;
|
||||
DPRINTF(("NPF: new se %p (link %p, nat %p)\n",
|
||||
@ -727,7 +723,7 @@ static void
|
||||
npf_session_gc(struct npf_sesslist *gc_list, bool flushall)
|
||||
{
|
||||
struct timespec tsnow;
|
||||
npf_session_t *se;
|
||||
npf_session_t *se, *nse;
|
||||
u_int i;
|
||||
|
||||
getnanouptime(&tsnow);
|
||||
@ -735,7 +731,6 @@ npf_session_gc(struct npf_sesslist *gc_list, bool flushall)
|
||||
/* Scan each session in the hash table. */
|
||||
for (i = 0; i < SESS_HASH_BUCKETS; i++) {
|
||||
npf_sess_hash_t *sh;
|
||||
struct rb_node *nd;
|
||||
|
||||
sh = &sess_hashtbl[i];
|
||||
if (sh->sh_count == 0) {
|
||||
@ -743,17 +738,16 @@ npf_session_gc(struct npf_sesslist *gc_list, bool flushall)
|
||||
}
|
||||
rw_enter(&sh->sh_lock, RW_WRITER);
|
||||
/* For each (left -> right) ... */
|
||||
nd = rb_tree_iterate(&sh->sh_tree, NULL, RB_DIR_LEFT);
|
||||
while (nd != NULL) {
|
||||
se = rb_tree_iterate(&sh->sh_tree, NULL, RB_DIR_LEFT);
|
||||
while (se != NULL) {
|
||||
/* Get item, pre-iterate, skip if not expired. */
|
||||
se = NPF_RBN2SESENT(nd);
|
||||
nd = rb_tree_iterate(&sh->sh_tree, nd, RB_DIR_RIGHT);
|
||||
nse = rb_tree_iterate(&sh->sh_tree, se, RB_DIR_RIGHT);
|
||||
if (!npf_session_expired(se, &tsnow) && !flushall) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Expired - move to G/C list. */
|
||||
rb_tree_remove_node(&sh->sh_tree, &se->se_entry.rbnode);
|
||||
rb_tree_remove_node(&sh->sh_tree, se);
|
||||
LIST_INSERT_HEAD(gc_list, se, se_entry.gclist);
|
||||
sh->sh_count--;
|
||||
|
||||
@ -765,6 +759,7 @@ npf_session_gc(struct npf_sesslist *gc_list, bool flushall)
|
||||
se, se->s_nat_se));
|
||||
se->s_nat_se = NULL;
|
||||
}
|
||||
se = nse;
|
||||
}
|
||||
KASSERT(!flushall || sh->sh_count == 0);
|
||||
rw_exit(&sh->sh_lock);
|
||||
@ -845,7 +840,6 @@ void
|
||||
npf_sessions_dump(void)
|
||||
{
|
||||
npf_sess_hash_t *sh;
|
||||
struct rb_node *nd;
|
||||
npf_session_t *se;
|
||||
struct timespec tsnow;
|
||||
|
||||
@ -862,13 +856,11 @@ npf_sessions_dump(void)
|
||||
continue;
|
||||
}
|
||||
printf("s_bucket %d (count = %d)\n", i, sh->sh_count);
|
||||
RB_TREE_FOREACH(nd, &sh->sh_tree) {
|
||||
RB_TREE_FOREACH(se, &sh->sh_tree) {
|
||||
struct timespec tsdiff;
|
||||
struct in_addr ip;
|
||||
int etime;
|
||||
|
||||
se = NPF_RBN2SESENT(nd);
|
||||
|
||||
timespecsub(&tsnow, &se->s_atime, &tsdiff);
|
||||
etime = (se->s_state == SE_ESTABLISHED) ?
|
||||
sess_expire_table[se->s_type] : 10;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: npf_tableset.c,v 1.1 2010/08/22 18:56:23 rmind Exp $ */
|
||||
/* $NetBSD: npf_tableset.c,v 1.2 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.1 2010/08/22 18:56:23 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.2 2010/09/24 22:51:50 rmind Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -62,19 +62,16 @@ __KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.1 2010/08/22 18:56:23 rmind Exp $
|
||||
|
||||
/* Table entry structure. */
|
||||
struct npf_tblent {
|
||||
/* IPv4 CIDR block. */
|
||||
in_addr_t te_addr;
|
||||
in_addr_t te_mask;
|
||||
/* Hash/tree entry. */
|
||||
union {
|
||||
LIST_ENTRY(npf_tblent) hashq;
|
||||
struct rb_node rbnode;
|
||||
} te_entry;
|
||||
/* IPv4 CIDR block. */
|
||||
in_addr_t te_addr;
|
||||
in_addr_t te_mask;
|
||||
};
|
||||
|
||||
/* Return pointer to npf_tblent_t from RB-tree node. (XXX fix rb-tree) */
|
||||
#define NPF_RBN2TBLENT(n) \
|
||||
(npf_tblent_t *)((uintptr_t)n - offsetof(npf_tblent_t, te_entry.rbnode))
|
||||
|
||||
LIST_HEAD(npf_hashl, npf_tblent);
|
||||
|
||||
/* Table structure. */
|
||||
@ -89,7 +86,7 @@ struct npf_table {
|
||||
u_int t_type;
|
||||
struct npf_hashl * t_hashl;
|
||||
u_long t_hashmask;
|
||||
struct rb_tree t_rbtree;
|
||||
rb_tree_t t_rbtree;
|
||||
};
|
||||
|
||||
/* Global table array and its lock. */
|
||||
@ -201,37 +198,39 @@ npf_tableset_reload(npf_tableset_t *tblset)
|
||||
*/
|
||||
|
||||
static signed int
|
||||
table_rbtree_cmp_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
table_rbtree_cmp_nodes(void *ctx, const void *n1, const void *n2)
|
||||
{
|
||||
const npf_tblent_t *te1 = NPF_RBN2TBLENT(n1);
|
||||
const npf_tblent_t *te2 = NPF_RBN2TBLENT(n2);
|
||||
const npf_tblent_t * const te1 = n1;
|
||||
const npf_tblent_t * const te2 = n2;
|
||||
const in_addr_t x = te1->te_addr & te1->te_mask;
|
||||
const in_addr_t y = te2->te_addr & te2->te_mask;
|
||||
|
||||
if (x < y)
|
||||
return 1;
|
||||
if (x > y)
|
||||
return -1;
|
||||
if (x > y)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static signed int
|
||||
table_rbtree_cmp_key(const struct rb_node *n1, const void *key)
|
||||
table_rbtree_cmp_key(void *ctx, const void *n1, const void *key)
|
||||
{
|
||||
const npf_tblent_t *te = NPF_RBN2TBLENT(n1);
|
||||
const npf_tblent_t * const te = n1;
|
||||
const in_addr_t x = te->te_addr & te->te_mask;
|
||||
const in_addr_t y = *(const in_addr_t *)key;
|
||||
|
||||
if (x < y)
|
||||
return 1;
|
||||
if (x > y)
|
||||
return -1;
|
||||
if (x > y)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops table_rbtree_ops = {
|
||||
static const rb_tree_ops_t table_rbtree_ops = {
|
||||
.rbto_compare_nodes = table_rbtree_cmp_nodes,
|
||||
.rbto_compare_key = table_rbtree_cmp_key
|
||||
.rbto_compare_key = table_rbtree_cmp_key,
|
||||
.rbto_node_offset = offsetof(npf_tblent_t, te_entry.rbnode),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
/*
|
||||
@ -285,7 +284,6 @@ void
|
||||
npf_table_destroy(npf_table_t *t)
|
||||
{
|
||||
npf_tblent_t *e;
|
||||
struct rb_node *nd;
|
||||
u_int n;
|
||||
|
||||
switch (t->t_type) {
|
||||
@ -299,10 +297,9 @@ npf_table_destroy(npf_table_t *t)
|
||||
hashdone(t->t_hashl, HASH_LIST, t->t_hashmask);
|
||||
break;
|
||||
case NPF_TABLE_RBTREE:
|
||||
while ((nd = rb_tree_iterate(&t->t_rbtree, NULL,
|
||||
RB_DIR_RIGHT)) != NULL) {
|
||||
e = NPF_RBN2TBLENT(nd);
|
||||
rb_tree_remove_node(&t->t_rbtree, &e->te_entry.rbnode);
|
||||
while ((e = rb_tree_iterate(&t->t_rbtree, NULL,
|
||||
RB_DIR_LEFT)) != NULL) {
|
||||
rb_tree_remove_node(&t->t_rbtree, e);
|
||||
pool_cache_put(tblent_cache, e);
|
||||
}
|
||||
break;
|
||||
@ -442,7 +439,7 @@ npf_table_add_v4cidr(npf_tableset_t *tset, u_int tid,
|
||||
break;
|
||||
case NPF_TABLE_RBTREE:
|
||||
/* Insert entry. Returns false, if duplicate. */
|
||||
if (!rb_tree_insert_node(&t->t_rbtree, &e->te_entry.rbnode)) {
|
||||
if (rb_tree_insert_node(&t->t_rbtree, e) != e) {
|
||||
error = EEXIST;
|
||||
}
|
||||
break;
|
||||
@ -465,7 +462,6 @@ npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
||||
in_addr_t addr, in_addr_t mask)
|
||||
{
|
||||
struct npf_hashl *htbl;
|
||||
struct rb_node *nd;
|
||||
npf_tblent_t *e;
|
||||
npf_table_t *t;
|
||||
in_addr_t val;
|
||||
@ -497,10 +493,9 @@ npf_table_rem_v4cidr(npf_tableset_t *tset, u_int tid,
|
||||
case NPF_TABLE_RBTREE:
|
||||
/* Key: (address & mask). */
|
||||
val = addr & mask;
|
||||
nd = rb_tree_find_node(&t->t_rbtree, &val);
|
||||
if (__predict_true(nd != NULL)) {
|
||||
e = NPF_RBN2TBLENT(nd);
|
||||
rb_tree_remove_node(&t->t_rbtree, &e->te_entry.rbnode);
|
||||
e = rb_tree_find_node(&t->t_rbtree, &val);
|
||||
if (__predict_true(e != NULL)) {
|
||||
rb_tree_remove_node(&t->t_rbtree, e);
|
||||
} else {
|
||||
error = ESRCH;
|
||||
}
|
||||
@ -525,7 +520,6 @@ int
|
||||
npf_table_match_v4addr(u_int tid, in_addr_t ip4addr)
|
||||
{
|
||||
struct npf_hashl *htbl;
|
||||
struct rb_node *nd;
|
||||
npf_tblent_t *e;
|
||||
npf_table_t *t;
|
||||
|
||||
@ -546,8 +540,7 @@ npf_table_match_v4addr(u_int tid, in_addr_t ip4addr)
|
||||
}
|
||||
break;
|
||||
case NPF_TABLE_RBTREE:
|
||||
nd = rb_tree_find_node(&t->t_rbtree, &ip4addr);
|
||||
e = NPF_RBN2TBLENT(nd);
|
||||
e = rb_tree_find_node(&t->t_rbtree, &ip4addr);
|
||||
KASSERT((ip4addr & e->te_mask) == e->te_addr);
|
||||
break;
|
||||
default:
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nfs_node.c,v 1.113 2010/07/21 17:52:13 hannken Exp $ */
|
||||
/* $NetBSD: nfs_node.c,v 1.114 2010/09/24 22:51:50 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.113 2010/07/21 17:52:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.114 2010/09/24 22:51:50 rmind Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_nfs.h"
|
||||
@ -106,9 +106,6 @@ nfs_node_done(void)
|
||||
workqueue_destroy(nfs_sillyworkq);
|
||||
}
|
||||
|
||||
#define RBTONFSNODE(node) \
|
||||
(void *)((uintptr_t)(node) - offsetof(struct nfsnode, n_rbnode))
|
||||
|
||||
struct fh_match {
|
||||
nfsfh_t *fhm_fhp;
|
||||
size_t fhm_fhsize;
|
||||
@ -116,10 +113,10 @@ struct fh_match {
|
||||
};
|
||||
|
||||
static int
|
||||
nfs_compare_nodes(const struct rb_node *parent, const struct rb_node *node)
|
||||
nfs_compare_nodes(void *ctx, const void *parent, const void *node)
|
||||
{
|
||||
const struct nfsnode * const pnp = RBTONFSNODE(parent);
|
||||
const struct nfsnode * const np = RBTONFSNODE(node);
|
||||
const struct nfsnode * const pnp = parent;
|
||||
const struct nfsnode * const np = node;
|
||||
|
||||
if (pnp->n_fhsize != np->n_fhsize)
|
||||
return np->n_fhsize - pnp->n_fhsize;
|
||||
@ -128,9 +125,9 @@ nfs_compare_nodes(const struct rb_node *parent, const struct rb_node *node)
|
||||
}
|
||||
|
||||
static int
|
||||
nfs_compare_node_fh(const struct rb_node *b, const void *key)
|
||||
nfs_compare_node_fh(void *ctx, const void *b, const void *key)
|
||||
{
|
||||
const struct nfsnode * const pnp = RBTONFSNODE(b);
|
||||
const struct nfsnode * const pnp = b;
|
||||
const struct fh_match * const fhm = key;
|
||||
|
||||
if (pnp->n_fhsize != fhm->fhm_fhsize)
|
||||
@ -139,18 +136,20 @@ nfs_compare_node_fh(const struct rb_node *b, const void *key)
|
||||
return memcmp(fhm->fhm_fhp, pnp->n_fhp, pnp->n_fhsize);
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops nfs_node_rbtree_ops = {
|
||||
static const rb_tree_ops_t nfs_node_rbtree_ops = {
|
||||
.rbto_compare_nodes = nfs_compare_nodes,
|
||||
.rbto_compare_key = nfs_compare_node_fh,
|
||||
.rbto_node_offset = offsetof(struct nfsnode, n_rbnode),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
void
|
||||
nfs_rbtinit(struct nfsmount *nmp)
|
||||
{
|
||||
|
||||
rb_tree_init(&nmp->nm_rbtree, &nfs_node_rbtree_ops);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Look up a vnode/nfsnode by file handle.
|
||||
* Callers must check for mount points!!
|
||||
@ -158,23 +157,22 @@ nfs_rbtinit(struct nfsmount *nmp)
|
||||
* nfsnode structure is returned.
|
||||
*/
|
||||
int
|
||||
nfs_nget1(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int lkflags)
|
||||
nfs_nget1(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp,
|
||||
int lkflags)
|
||||
{
|
||||
struct nfsnode *np;
|
||||
struct vnode *vp;
|
||||
struct nfsmount *nmp = VFSTONFS(mntp);
|
||||
int error;
|
||||
struct fh_match fhm;
|
||||
struct rb_node *node;
|
||||
|
||||
fhm.fhm_fhp = fhp;
|
||||
fhm.fhm_fhsize = fhsize;
|
||||
|
||||
loop:
|
||||
rw_enter(&nmp->nm_rbtlock, RW_READER);
|
||||
node = rb_tree_find_node(&nmp->nm_rbtree, &fhm);
|
||||
if (node != NULL) {
|
||||
np = RBTONFSNODE(node);
|
||||
np = rb_tree_find_node(&nmp->nm_rbtree, &fhm);
|
||||
if (np != NULL) {
|
||||
vp = NFSTOV(np);
|
||||
mutex_enter(&vp->v_interlock);
|
||||
rw_exit(&nmp->nm_rbtlock);
|
||||
@ -234,7 +232,7 @@ loop:
|
||||
VOP_LOCK(vp, LK_EXCLUSIVE);
|
||||
NFS_INVALIDATE_ATTRCACHE(np);
|
||||
uvm_vnp_setsize(vp, 0);
|
||||
rb_tree_insert_node(&nmp->nm_rbtree, &np->n_rbnode);
|
||||
(void)rb_tree_insert_node(&nmp->nm_rbtree, np);
|
||||
rw_exit(&nmp->nm_rbtlock);
|
||||
|
||||
*npp = np;
|
||||
@ -294,7 +292,7 @@ nfs_reclaim(void *v)
|
||||
vprint("nfs_reclaim: pushing active", vp);
|
||||
|
||||
rw_enter(&nmp->nm_rbtlock, RW_WRITER);
|
||||
rb_tree_remove_node(&nmp->nm_rbtree, &np->n_rbnode);
|
||||
rb_tree_remove_node(&nmp->nm_rbtree, np);
|
||||
rw_exit(&nmp->nm_rbtlock);
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vm.c,v 1.95 2010/09/09 12:23:06 pooka Exp $ */
|
||||
/* $NetBSD: vm.c,v 1.96 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
|
||||
@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.95 2010/09/09 12:23:06 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.96 2010/09/24 22:51:51 rmind Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/atomic.h>
|
||||
@ -106,29 +106,31 @@ static struct pglist vmpage_lruqueue;
|
||||
static unsigned vmpage_onqueue;
|
||||
|
||||
static int
|
||||
pg_compare_key(const struct rb_node *n, const void *key)
|
||||
pg_compare_key(void *ctx, const void *n, const void *key)
|
||||
{
|
||||
voff_t a = ((const struct vm_page *)n)->offset;
|
||||
voff_t b = *(const voff_t *)key;
|
||||
|
||||
if (a < b)
|
||||
return 1;
|
||||
else if (a > b)
|
||||
return -1;
|
||||
else if (a > b)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pg_compare_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
pg_compare_nodes(void *ctx, const void *n1, const void *n2)
|
||||
{
|
||||
|
||||
return pg_compare_key(n1, &((const struct vm_page *)n2)->offset);
|
||||
return pg_compare_key(ctx, n1, &((const struct vm_page *)n2)->offset);
|
||||
}
|
||||
|
||||
const struct rb_tree_ops uvm_page_tree_ops = {
|
||||
const rb_tree_ops_t uvm_page_tree_ops = {
|
||||
.rbto_compare_nodes = pg_compare_nodes,
|
||||
.rbto_compare_key = pg_compare_key,
|
||||
.rbto_node_offset = offsetof(struct vm_page, rb_node),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
/*
|
||||
@ -177,7 +179,7 @@ uvm_pagealloc_strat(struct uvm_object *uobj, voff_t off, struct vm_anon *anon,
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&uobj->memq, pg, listq.queue);
|
||||
rb_tree_insert_node(&uobj->rb_tree, &pg->rb_node);
|
||||
(void)rb_tree_insert_node(&uobj->rb_tree, pg);
|
||||
|
||||
/*
|
||||
* Don't put anons on the LRU page queue. We can't flush them
|
||||
@ -215,7 +217,7 @@ uvm_pagefree(struct vm_page *pg)
|
||||
TAILQ_REMOVE(&uobj->memq, pg, listq.queue);
|
||||
|
||||
uobj->uo_npages--;
|
||||
rb_tree_remove_node(&uobj->rb_tree, &pg->rb_node);
|
||||
rb_tree_remove_node(&uobj->rb_tree, pg);
|
||||
|
||||
if (!UVM_OBJ_IS_AOBJ(uobj)) {
|
||||
TAILQ_REMOVE(&vmpage_lruqueue, pg, pageq.queue);
|
||||
@ -468,7 +470,7 @@ uvm_pagelookup(struct uvm_object *uobj, voff_t off)
|
||||
{
|
||||
struct vm_page *pg;
|
||||
|
||||
pg = (struct vm_page *)rb_tree_find_node(&uobj->rb_tree, &off);
|
||||
pg = rb_tree_find_node(&uobj->rb_tree, &off);
|
||||
if (pg && !UVM_OBJ_IS_AOBJ(pg->uobject)) {
|
||||
mutex_enter(&uvm_pageqlock);
|
||||
TAILQ_REMOVE(&vmpage_lruqueue, pg, pageq.queue);
|
||||
|
61
sys/sys/rb.h
61
sys/sys/rb.h
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp $ */
|
||||
/* $NetBSD: rb.h,v 1.14 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
@ -28,6 +28,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_RB_H_
|
||||
#define _SYS_RB_H_
|
||||
|
||||
@ -40,7 +41,9 @@
|
||||
#include <sys/queue.h>
|
||||
#include <sys/endian.h>
|
||||
|
||||
struct rb_node {
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef struct rb_node {
|
||||
struct rb_node *rb_nodes[2];
|
||||
#define RB_DIR_LEFT 0
|
||||
#define RB_DIR_RIGHT 1
|
||||
@ -95,7 +98,7 @@ struct rb_node {
|
||||
#ifdef RBDEBUG
|
||||
TAILQ_ENTRY(rb_node) rb_link;
|
||||
#endif
|
||||
};
|
||||
} rb_node_t;
|
||||
|
||||
#define RB_TREE_MIN(T) rb_tree_iterate((T), NULL, RB_DIR_LEFT)
|
||||
#define RB_TREE_MAX(T) rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
|
||||
@ -124,29 +127,31 @@ TAILQ_HEAD(rb_node_qh, rb_node);
|
||||
|
||||
/*
|
||||
* rbto_compare_nodes_fn:
|
||||
* return a positive value if the first node < the second node.
|
||||
* return a negative value if the first node > the second node.
|
||||
* return a positive value if the first node > the second node.
|
||||
* return a negative value if the first node < the second node.
|
||||
* return 0 if they are considered same.
|
||||
*
|
||||
* rbto_compare_key_fn:
|
||||
* return a positive value if the node < the key.
|
||||
* return a negative value if the node > the key.
|
||||
* return a positive value if the node > the key.
|
||||
* return a negative value if the node < the key.
|
||||
* return 0 if they are considered same.
|
||||
*/
|
||||
|
||||
typedef signed int (*const rbto_compare_nodes_fn)(const struct rb_node *,
|
||||
const struct rb_node *);
|
||||
typedef signed int (*const rbto_compare_key_fn)(const struct rb_node *,
|
||||
const void *);
|
||||
typedef signed int (*const rbto_compare_nodes_fn)(void *,
|
||||
const void *, const void *);
|
||||
typedef signed int (*const rbto_compare_key_fn)(void *,
|
||||
const void *, const void *);
|
||||
|
||||
struct rb_tree_ops {
|
||||
typedef struct {
|
||||
rbto_compare_nodes_fn rbto_compare_nodes;
|
||||
rbto_compare_key_fn rbto_compare_key;
|
||||
};
|
||||
size_t rbto_node_offset;
|
||||
void *rbto_context;
|
||||
} rb_tree_ops_t;
|
||||
|
||||
struct rb_tree {
|
||||
typedef struct rb_tree {
|
||||
struct rb_node *rbt_root;
|
||||
const struct rb_tree_ops *rbt_ops;
|
||||
const rb_tree_ops_t *rbt_ops;
|
||||
struct rb_node *rbt_minmax[2];
|
||||
#ifdef RBDEBUG
|
||||
struct rb_node_qh rbt_nodes;
|
||||
@ -160,7 +165,7 @@ struct rb_tree {
|
||||
unsigned int rbt_removal_rebalance_calls;
|
||||
unsigned int rbt_removal_rebalance_passes;
|
||||
#endif
|
||||
};
|
||||
} rb_tree_t;
|
||||
|
||||
#ifdef RBSTATS
|
||||
#define RBSTAT_INC(v) ((void)((v)++))
|
||||
@ -170,22 +175,20 @@ struct rb_tree {
|
||||
#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
|
||||
void rb_tree_init(struct rb_tree *, const struct rb_tree_ops *);
|
||||
bool rb_tree_insert_node(struct rb_tree *, struct rb_node *);
|
||||
struct rb_node *
|
||||
rb_tree_find_node(struct rb_tree *, const void *);
|
||||
struct rb_node *
|
||||
rb_tree_find_node_geq(struct rb_tree *, const void *);
|
||||
struct rb_node *
|
||||
rb_tree_find_node_leq(struct rb_tree *, const void *);
|
||||
void rb_tree_remove_node(struct rb_tree *, struct rb_node *);
|
||||
struct rb_node *
|
||||
rb_tree_iterate(struct rb_tree *, struct rb_node *, const unsigned int);
|
||||
void rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
|
||||
void * rb_tree_insert_node(rb_tree_t *, void *);
|
||||
void * rb_tree_find_node(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_geq(rb_tree_t *, const void *);
|
||||
void * rb_tree_find_node_leq(rb_tree_t *, const void *);
|
||||
void rb_tree_remove_node(rb_tree_t *, void *);
|
||||
void * rb_tree_iterate(rb_tree_t *, void *, const unsigned int);
|
||||
#ifdef RBDEBUG
|
||||
void rb_tree_check(const struct rb_tree *, bool);
|
||||
void rb_tree_check(const rb_tree_t *, bool);
|
||||
#endif
|
||||
#ifdef RBSTATS
|
||||
void rb_tree_depths(const struct rb_tree *, size_t *);
|
||||
void rb_tree_depths(const rb_tree_t *, size_t *);
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _SYS_RB_H_*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_map.c,v 1.292 2010/06/22 18:34:50 rmind Exp $ */
|
||||
/* $NetBSD: uvm_map.c,v 1.293 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Charles D. Cranor and Washington University.
|
||||
@ -71,7 +71,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.292 2010/06/22 18:34:50 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.293 2010/09/24 22:51:51 rmind Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_uvmhist.h"
|
||||
@ -318,53 +318,56 @@ int _uvm_map_sanity(struct vm_map *);
|
||||
int _uvm_tree_sanity(struct vm_map *);
|
||||
static vsize_t uvm_rb_maxgap(const struct vm_map_entry *);
|
||||
|
||||
CTASSERT(offsetof(struct vm_map_entry, rb_node) == 0);
|
||||
#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))
|
||||
? 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)
|
||||
uvm_map_compare_nodes(void *ctx, const void *nparent, const void *nkey)
|
||||
{
|
||||
const struct vm_map_entry *eparent = (const void *) nparent;
|
||||
const struct vm_map_entry *ekey = (const void *) nkey;
|
||||
const struct vm_map_entry *eparent = nparent;
|
||||
const struct vm_map_entry *ekey = nkey;
|
||||
|
||||
KASSERT(eparent->start < ekey->start || eparent->start >= ekey->end);
|
||||
KASSERT(ekey->start < eparent->start || ekey->start >= eparent->end);
|
||||
|
||||
if (ekey->start < eparent->start)
|
||||
if (eparent->start < ekey->start)
|
||||
return -1;
|
||||
if (ekey->start >= eparent->end)
|
||||
if (eparent->end >= ekey->start)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
uvm_map_compare_key(const struct rb_node *nparent, const void *vkey)
|
||||
uvm_map_compare_key(void *ctx, const void *nparent, const void *vkey)
|
||||
{
|
||||
const struct vm_map_entry *eparent = (const void *) nparent;
|
||||
const struct vm_map_entry *eparent = nparent;
|
||||
const vaddr_t va = *(const vaddr_t *) vkey;
|
||||
|
||||
if (va < eparent->start)
|
||||
if (eparent->start < va)
|
||||
return -1;
|
||||
if (va >= eparent->end)
|
||||
if (eparent->end >= va)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rb_tree_ops uvm_map_tree_ops = {
|
||||
static const rb_tree_ops_t uvm_map_tree_ops = {
|
||||
.rbto_compare_nodes = uvm_map_compare_nodes,
|
||||
.rbto_compare_key = uvm_map_compare_key,
|
||||
.rbto_node_offset = offsetof(struct vm_map_entry, rb_node),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* uvm_rb_gap: return the gap size between our entry and next entry.
|
||||
*/
|
||||
static inline vsize_t
|
||||
uvm_rb_gap(const struct vm_map_entry *entry)
|
||||
{
|
||||
|
||||
KASSERT(entry->next != NULL);
|
||||
return entry->next->start - entry->end;
|
||||
}
|
||||
@ -402,16 +405,18 @@ uvm_rb_fixup(struct vm_map *map, struct vm_map_entry *entry)
|
||||
while ((parent = PARENT_ENTRY(map, entry)) != NULL) {
|
||||
struct vm_map_entry *brother;
|
||||
vsize_t maxgap = parent->gap;
|
||||
unsigned int which;
|
||||
|
||||
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.
|
||||
* Since we work towards the root, we know entry's maxgap
|
||||
* value is OK, but its brothers may now be out-of-date due
|
||||
* to rebalancing. So refresh it.
|
||||
*/
|
||||
brother = (struct vm_map_entry *)parent->rb_node.rb_nodes[RB_POSITION(&entry->rb_node) ^ RB_DIR_OTHER];
|
||||
which = RB_POSITION(&entry->rb_node) ^ RB_DIR_OTHER;
|
||||
brother = (struct vm_map_entry *)parent->rb_node.rb_nodes[which];
|
||||
if (brother != NULL) {
|
||||
KDASSERT(brother->gap == uvm_rb_gap(brother));
|
||||
brother->maxgap = uvm_rb_maxgap(brother);
|
||||
@ -427,12 +432,16 @@ uvm_rb_fixup(struct vm_map *map, struct vm_map_entry *entry)
|
||||
static void
|
||||
uvm_rb_insert(struct vm_map *map, struct vm_map_entry *entry)
|
||||
{
|
||||
struct vm_map_entry *ret;
|
||||
|
||||
entry->gap = entry->maxgap = uvm_rb_gap(entry);
|
||||
if (entry->prev != &map->header)
|
||||
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);
|
||||
ret = rb_tree_insert_node(&map->rb_tree, entry);
|
||||
KASSERTMSG(ret == entry,
|
||||
("uvm_rb_insert: map %p: duplicate entry %p", map, ret)
|
||||
);
|
||||
|
||||
/*
|
||||
* If the previous entry is not our immediate left child, then it's an
|
||||
@ -460,7 +469,7 @@ uvm_rb_remove(struct vm_map *map, struct vm_map_entry *entry)
|
||||
if (entry->next != &map->header)
|
||||
next_parent = PARENT_ENTRY(map, entry->next);
|
||||
|
||||
rb_tree_remove_node(&map->rb_tree, &entry->rb_node);
|
||||
rb_tree_remove_node(&map->rb_tree, entry);
|
||||
|
||||
/*
|
||||
* If the previous node has a new parent, fixup the tree starting
|
||||
@ -598,8 +607,7 @@ _uvm_tree_sanity(struct vm_map *map)
|
||||
|
||||
for (tmp = map->header.next; tmp != &map->header;
|
||||
tmp = tmp->next, i++) {
|
||||
trtmp = (void *) rb_tree_iterate(&map->rb_tree, &tmp->rb_node,
|
||||
RB_DIR_LEFT);
|
||||
trtmp = rb_tree_iterate(&map->rb_tree, tmp, RB_DIR_LEFT);
|
||||
if (trtmp == NULL)
|
||||
trtmp = &map->header;
|
||||
if (tmp->prev != trtmp) {
|
||||
@ -607,8 +615,7 @@ _uvm_tree_sanity(struct vm_map *map)
|
||||
i, tmp, tmp->prev, trtmp);
|
||||
goto error;
|
||||
}
|
||||
trtmp = (void *) rb_tree_iterate(&map->rb_tree, &tmp->rb_node,
|
||||
RB_DIR_RIGHT);
|
||||
trtmp = rb_tree_iterate(&map->rb_tree, tmp, RB_DIR_RIGHT);
|
||||
if (trtmp == NULL)
|
||||
trtmp = &map->header;
|
||||
if (tmp->next != trtmp) {
|
||||
@ -616,7 +623,7 @@ _uvm_tree_sanity(struct vm_map *map)
|
||||
i, tmp, tmp->next, trtmp);
|
||||
goto error;
|
||||
}
|
||||
trtmp = (void *)rb_tree_find_node(&map->rb_tree, &tmp->start);
|
||||
trtmp = rb_tree_find_node(&map->rb_tree, &tmp->start);
|
||||
if (trtmp != tmp) {
|
||||
printf("lookup: %d: %p - %p: %p\n", i, tmp, trtmp,
|
||||
PARENT_ENTRY(map, tmp));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_object.h,v 1.26 2008/06/04 15:06:04 ad Exp $ */
|
||||
/* $NetBSD: uvm_object.h,v 1.27 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -105,7 +105,7 @@ extern const struct uvm_pagerops aobj_pager;
|
||||
#define UVM_OBJ_IS_AOBJ(uobj) \
|
||||
((uobj)->pgops == &aobj_pager)
|
||||
|
||||
extern const struct rb_tree_ops uvm_page_tree_ops;
|
||||
extern const rb_tree_ops_t uvm_page_tree_ops;
|
||||
|
||||
#define UVM_OBJ_INIT(uobj, ops, refs) \
|
||||
do { \
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_page.c,v 1.155 2010/04/25 15:54:14 ad Exp $ */
|
||||
/* $NetBSD: uvm_page.c,v 1.156 2010/09/24 22:51:51 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 The NetBSD Foundation, Inc.
|
||||
@ -97,7 +97,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.155 2010/04/25 15:54:14 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.156 2010/09/24 22:51:51 rmind Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_uvmhist.h"
|
||||
@ -186,37 +186,39 @@ static void uvm_pageremove(struct uvm_object *, struct vm_page *);
|
||||
*/
|
||||
|
||||
static signed int
|
||||
uvm_page_compare_nodes(const struct rb_node *n1, const struct rb_node *n2)
|
||||
uvm_page_compare_nodes(void *ctx, const void *n1, const void *n2)
|
||||
{
|
||||
const struct vm_page *pg1 = (const void *)n1;
|
||||
const struct vm_page *pg2 = (const void *)n2;
|
||||
const struct vm_page *pg1 = n1;
|
||||
const struct vm_page *pg2 = n2;
|
||||
const voff_t a = pg1->offset;
|
||||
const voff_t b = pg2->offset;
|
||||
|
||||
if (a < b)
|
||||
return 1;
|
||||
if (a > b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static signed int
|
||||
uvm_page_compare_key(const struct rb_node *n, const void *key)
|
||||
uvm_page_compare_key(void *ctx, const void *n, const void *key)
|
||||
{
|
||||
const struct vm_page *pg = (const void *)n;
|
||||
const struct vm_page *pg = n;
|
||||
const voff_t a = pg->offset;
|
||||
const voff_t b = *(const voff_t *)key;
|
||||
|
||||
if (a < b)
|
||||
return 1;
|
||||
if (a > b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct rb_tree_ops uvm_page_tree_ops = {
|
||||
const rb_tree_ops_t uvm_page_tree_ops = {
|
||||
.rbto_compare_nodes = uvm_page_compare_nodes,
|
||||
.rbto_compare_key = uvm_page_compare_key,
|
||||
.rbto_node_offset = offsetof(struct vm_page, rb_node),
|
||||
.rbto_context = NULL
|
||||
};
|
||||
|
||||
/*
|
||||
@ -270,11 +272,11 @@ uvm_pageinsert_list(struct uvm_object *uobj, struct vm_page *pg,
|
||||
static inline void
|
||||
uvm_pageinsert_tree(struct uvm_object *uobj, struct vm_page *pg)
|
||||
{
|
||||
bool success;
|
||||
struct vm_page *ret;
|
||||
|
||||
KASSERT(uobj == pg->uobject);
|
||||
success = rb_tree_insert_node(&uobj->rb_tree, &pg->rb_node);
|
||||
KASSERT(success);
|
||||
ret = rb_tree_insert_node(&uobj->rb_tree, pg);
|
||||
KASSERT(ret == pg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -328,7 +330,7 @@ uvm_pageremove_tree(struct uvm_object *uobj, struct vm_page *pg)
|
||||
{
|
||||
|
||||
KASSERT(uobj == pg->uobject);
|
||||
rb_tree_remove_node(&uobj->rb_tree, &pg->rb_node);
|
||||
rb_tree_remove_node(&uobj->rb_tree, pg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -1726,12 +1728,12 @@ uvm_pagelookup(struct uvm_object *obj, voff_t off)
|
||||
|
||||
KASSERT(mutex_owned(&obj->vmobjlock));
|
||||
|
||||
pg = (struct vm_page *)rb_tree_find_node(&obj->rb_tree, &off);
|
||||
pg = rb_tree_find_node(&obj->rb_tree, &off);
|
||||
|
||||
KASSERT(pg == NULL || obj->uo_npages != 0);
|
||||
KASSERT(pg == NULL || (pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||
|
||||
(pg->flags & PG_BUSY) != 0);
|
||||
return(pg);
|
||||
return pg;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user