175 lines
6.1 KiB
C
175 lines
6.1 KiB
C
/*
|
|
* Copyright (c) 2012, ETH Zurich.
|
|
* All rights reserved.
|
|
*
|
|
* This file is distributed under the terms in the attached LICENSE file.
|
|
* If you do not find this file, copies can be found by writing to:
|
|
* ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
|
|
*/
|
|
|
|
#ifndef LIBMDB_MDB_TREE_H
|
|
#define LIBMDB_MDB_TREE_H
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <errors/errno.h>
|
|
#include <aos/types.h>
|
|
#include <mdb/types.h>
|
|
|
|
__BEGIN_DECLS
|
|
|
|
struct capability;
|
|
struct cte;
|
|
|
|
#define mdb_invariants(f) \
|
|
/* All checked invariants hold*/\
|
|
f(MDB_INVARIANT_OK) \
|
|
/* A node with level > 0 must have both children*/\
|
|
f(MDB_INVARIANT_BOTHCHILDREN) \
|
|
/* The level of a node's left child must be lt the node's level*/\
|
|
f(MDB_INVARIANT_LEFT_LEVEL_LESS) \
|
|
/* The level of a node's right child must be leq the node's level*/\
|
|
f(MDB_INVARIANT_RIGHT_LEVEL_LEQ) \
|
|
/* The level of a node's right grandchildren must bt lt the node's level*/\
|
|
f(MDB_INVARIANT_RIGHTRIGHT_LEVEL_LESS) \
|
|
f(MDB_INVARIANT_RIGHTLEFT_LEVEL_LESS) \
|
|
/* The node's "end" value must be the maximum of the subtree's ends*/\
|
|
f(MDB_INVARIANT_END_IS_MAX) \
|
|
/* The left child of a node must be earlier in the ordering*/\
|
|
f(MDB_INVARIANT_LEFT_SMALLER) \
|
|
/* The right child of a node must be later in the ordering*/\
|
|
f(MDB_INVARIANT_RIGHT_GREATER)
|
|
|
|
#define f_enum(x) x,
|
|
enum mdb_invariant {
|
|
mdb_invariants(f_enum)
|
|
};
|
|
#undef f_enum
|
|
|
|
#define f_str(x) #x,
|
|
static const char *mdb_invariant_str[] = { mdb_invariants(f_str) };
|
|
#undef f_str
|
|
|
|
#undef mdb_invariants
|
|
|
|
static inline const char *mdb_invariant_to_str(enum mdb_invariant i)
|
|
{
|
|
return mdb_invariant_str[i];
|
|
}
|
|
|
|
enum {
|
|
// No cap was found covering the specified region
|
|
MDB_RANGE_NOT_FOUND = 0,
|
|
// A cap was found covering at least the entire specified region
|
|
MDB_RANGE_FOUND_SURROUNDING = 1,
|
|
// A cap was found that is inside the specified region
|
|
MDB_RANGE_FOUND_INNER = 2,
|
|
// A cap was found that overlaps with one of the specified region's ends
|
|
MDB_RANGE_FOUND_PARTIAL = 3,
|
|
};
|
|
|
|
#if IN_KERNEL
|
|
// kcb defined else-where
|
|
struct kcb;
|
|
#else
|
|
// create mini kcb that can be used to set root node in user space mdb
|
|
struct kcb {
|
|
lvaddr_t mdb_root;
|
|
};
|
|
#endif
|
|
|
|
// Restore mdb state by passing in the address of the root node
|
|
// requires: mdb not initialized
|
|
// ensures: mdb_check_invariants() && mdb_is_sane()
|
|
errval_t mdb_init(struct kcb *k);
|
|
|
|
// Print the specified subtree
|
|
void mdb_dump(struct cte *cte, int indent);
|
|
// Print the complete tree
|
|
void mdb_dump_all_the_things(void);
|
|
// Check that the invariants hold. The return value indicates the first issue
|
|
// that was encountered.
|
|
int mdb_check_invariants(void);
|
|
|
|
// Insert a cap into the tree. An error (MDB_DUPLICATE_ENTRY) is returned iff
|
|
// the cap is already present in the tree.
|
|
errval_t mdb_insert(struct cte *new_node);
|
|
// Remove a cap from the tree. An error (MDB_ENTRY_NOTFOUND) is returned iff
|
|
// the cap is not present in the tree.
|
|
errval_t mdb_remove(struct cte *node);
|
|
|
|
struct cte *mdb_predecessor(struct cte *current);
|
|
struct cte *mdb_successor(struct cte *current);
|
|
|
|
// Find a cap in the tree that compares equal to the given cap. Returns NULL if
|
|
// no such cap is found.
|
|
struct cte *mdb_find_equal(struct capability *cap);
|
|
// Find the greatest cap in the tree that is earlier in the ordering. Returns
|
|
// NULL if no matching cap is found.
|
|
// @param equal_ok If true, will return a copy of the passed cap if it is
|
|
// present.
|
|
struct cte *mdb_find_less(struct capability *cap, bool equal_ok);
|
|
// Find the smallest cap in the tree that is later in the ordering. Returns
|
|
// NULL if no matching cap is found.
|
|
// @param equal_ok If true, will return a copy of the passed cap if it is
|
|
// present.
|
|
struct cte *mdb_find_greater(struct capability *cap, bool equal_ok);
|
|
|
|
// Find a cap in the given range.
|
|
// @param root indicates which type tree root to search through (usually
|
|
// `get_type_root(ObjType_PhysAddr)`).
|
|
// @param max_result Indicates the maximum outcome (not found, surrounding...)
|
|
// for which a cap should be returned. If an result is found that is
|
|
// greater than max_result, this function returns immediately with the
|
|
// given result and NULL cte. The semantics/uses for individual
|
|
// max_result values are thus:
|
|
// - MDB_RANGE_NOT_FOUND: A simple test whether the given region is
|
|
// covered by a cap.
|
|
// - MDB_RANGE_FOUND_SURROUNDING: Can be used to check if a region can
|
|
// be retyped.
|
|
// - MDB_RANGE_FOUND_INNER: Useful for iterating through *immediate*
|
|
// descendants.
|
|
errval_t mdb_find_range(mdb_root_t root, genpaddr_t address, gensize_t size,
|
|
int max_result, struct cte **ret_node, int *result);
|
|
|
|
errval_t mdb_find_cap_for_address(genpaddr_t address, struct cte **ret_node);
|
|
|
|
bool mdb_reachable(struct cte *cte);
|
|
|
|
/**
|
|
* Call-back function for tree traversals.
|
|
* @param cte The current tree entry.
|
|
* @param data User provided data pointer.
|
|
*/
|
|
typedef errval_t (*mdb_tree_traversal_fn)(struct cte *cte, void *data);
|
|
|
|
enum mdb_tree_traversal_order {
|
|
MDB_TRAVERSAL_ORDER_ASCENDING, ///< Traverse the tree in ascending order
|
|
MDB_TRAVERSAL_ORDER_DESCENDING ///< Traverse the tree in descending order
|
|
};
|
|
|
|
/**
|
|
* Traverse the mdb tree using some order with a call-back function and
|
|
* user-provided data. This function starts at the root of the tree.
|
|
* @param order The order to traverse the tree in.
|
|
* @param cb The call-back to execute for every node in the tree.
|
|
* @parm data User-provided data pointer.
|
|
*/
|
|
errval_t mdb_traverse(enum mdb_tree_traversal_order order, mdb_tree_traversal_fn cb, void *data);
|
|
|
|
/**
|
|
* Traverse an mdb sub tree using some order with a call-back function and
|
|
* user-provided data.
|
|
* @param cte The subtree to traverse. The call-back will be executed on this node.
|
|
* @param order The order to traverse the tree in.
|
|
* @param cb The call-back to execute for every node in the tree.
|
|
* @parm data User-provided data pointer.
|
|
*/
|
|
errval_t mdb_traverse_subtree(struct cte *cte, enum mdb_tree_traversal_order order, mdb_tree_traversal_fn cb, void *data);
|
|
|
|
errval_t mdb_size(size_t *count);
|
|
|
|
__END_DECLS
|
|
|
|
#endif // LIBMDB_MDB_TREE_H
|