Commit 6c0c9fc0 authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan
Browse files

generalized-allocator: Add resource tree implementation.

This is a thin wrapper around Linux's interval tree.
parent 4d114c0e
/*
* resource_tree.c
*
* Implementation of liblcd resource tree. This is
* utilized for doing address -> cptr translation.
*
* Copyright: University of Utah
*/
#include <linux/slab.h>
#include <linux/interval_tree.h>
#include <linux/rb_tree.h>
#include <libcap.h>
#include <lcd-domains/liblcd.h>
int lcd_resource_tree_init(struct lcd_resource_tree *t)
{
/*
* Init interval tree.
*/
t->root = RB_ROOT;
return 0;
}
void lcd_resource_tree_insert(struct lcd_resource_tree *t,
struct lcd_resource_node *n)
{
/*
* Insert into interval tree
*/
interval_tree_insert(&n->it_node, &t->root);
}
int lcd_resource_tree_search(struct lcd_resource_tree *t,
unsigned long addr,
struct lcd_resource_node **n_out)
{
/*
* Stab the intervals to see if any contain addr. Because
* our intervals are non-overlapping, there will be
* at most one match.
*/
struct interval_tree_node *match;
match = interval_tree_first(&t->root, addr, addr);
if (match) {
n_out = container_of(match, struct lcd_resource_node,
it_node);
return 0;
} else {
return -1; /* not found */
}
}
struct lcd_resource_node *
lcd_resource_tree_first(struct lcd_resource_tree *t)
{
struct rb_node *n;
n = rb_first(&t->root);
if (n)
return container_of(
container_of(n, struct interval_tree_node, rb),
struct lcd_resource_node,
it_node);
else
return NULL; /* empty tree */
}
struct lcd_resource_node *
lcd_resource_tree_next(struct lcd_resource_node *n)
{
return container_of(
container_of(rb_next(n), struct interval_tree_node, rb),
struct lcd_resource_node,
it_node);
}
void lcd_resource_tree_remove(struct lcd_resource_tree *t,
struct lcd_resource_node *n)
{
interval_tree_remove(&n->it_node, &t->root);
}
/* EXPORTS -------------------------------------------------- */
EXPORT_SYMBOL(lcd_resource_tree_init);
EXPORT_SYMBOL(lcd_resource_tree_insert);
EXPORT_SYMBOL(lcd_resource_tree_search);
EXPORT_SYMBOL(lcd_resource_tree_first);
EXPORT_SYMBOL(lcd_resource_tree_next);
EXPORT_SYMBOL(lcd_resource_tree_remove);
/*
* resource_tree.h
*
* Data structure for doing address -> cptr translation.
* Data structure for tracking memory objects tracked
* by the microkernel and accessible to a thread. This
* is primarily used for doing address -> cptr translation.
*
* We re-use interval trees from Linux.
*
* No locking (just like the other bare bones data structures).
*
* Copyright: University of Utah
*/
#include <libcap.h>
#include <linux/rb_tree.h>
#include <linux/interval_tree.h>
struct lcd_resource_node {
struct interval_tree_node resource_tree_node;
unsigned long nr_pages_order;
cptr_t cptr;
};
/**
* struct lcd_resource_tree
*
* Represents root of resource tree. You are responsible
* for allocating this struct in any way you like. But you
* should call lcd_resource_tree_init before using it.
*/
struct lcd_resource_tree {
struct rb_root root;
};
/* what about when setting up heap? can't kmalloc data */
/**
* struct lcd_resource_node
*
* Represents node in LCD resource interval tree. Before
* you insert this node into the tree, you should initialize:
*
* -- it_node's start and last (see linux/interval_tree.h)
* -- nr_pages_order: the size of the memory resource is
* 2^nr_pages_order
* -- cptr is the cptr to the capability in the thread's cspace
*
* You are responsible for allocating these things and freeing
* them when you're done with them.
*/
struct lcd_resource_node {
struct interval_tree_node it_node;
unsigned long nr_pages_order;
cptr_t cptr;
};
int lcd_resource_tree_alloc(struct lcd_resource_tree **t_out);
/* INTERFACE -------------------------------------------------- */
/**
* lcd_resource_tree_init -- Initialize tree
* @t: the tree to init
*
* Call this before using any other functions on tree.
*/
int lcd_resource_tree_init(struct lcd_resource_tree *t);
int lcd_resource_tree_destroy(struct lcd_resource_tree *t);
int lcd_resource_tree_free(struct lcd_resource_tree *t);
int lcd_resource_tree_insert(struct lcd_resource_tree *t,
/**
* lcd_resource_tree_insert -- Insert interval into tree
* @t: the tree to insert into
* @n: the node to insert
*
* You should initialize the resource node before invoking
* insert. See the doc for struct lcd_resource_node.
* The tree will become invalid if you fail to do so.
*/
void lcd_resource_tree_insert(struct lcd_resource_tree *t,
struct lcd_resource_node *n);
/**
* lcd_resource_tree_search -- See if @addr is contained in an interval in tree
* @t: the tree to search in
* @addr: the address to search for
* @n_out: out param, interval containing @addr if found
*
* Returns 0 if found, -1 if not found.
*/
int lcd_resource_tree_search(struct lcd_resource_tree *t,
unsigned long addr,
struct lcd_resource_node **n_out);
void lcd_resource_tree_delete(struct lcd_resource_tree *t,
/**
* lcd_resource_tree_first -- Return first node in tree
* @t: the tree
*
* This is a wrapper around rb_first (*not* interval_tree_first).
* See its documentation. This is for iterating over the whole tree.
*
* Returns NULL if tree is empty.
*/
struct lcd_resource_node *
lcd_resource_tree_first(struct lcd_resource_tree *t);
/**
* lcd_resource_tree_next -- Return next node in iteration
* @n: the node to compute next for
*
* This is a wrapper around rb_next (*not* interval_tree_next). See
* its documentation.
*
* Returns NULL if there are no more nodes.
*
* Here is an iteration example:
*
* struct lcd_resource_node *node;
* for (node = lcd_resource_tree_first(&mytree);
* node;
* node = lcd_resource_tree_next(node)) {
*
* ... do something with node ...
* }
*/
struct lcd_resource_node *
lcd_resource_tree_next(struct lcd_resource_node *n);
/**
* lcd_resource_tree_remove -- Remove node from tree
* @t: tree to remove node from
* @n: node to remove
*
* This will not free @n. You are responsible for the mem
* mgt of @n.
*/
void lcd_resource_tree_remove(struct lcd_resource_tree *t,
struct lcd_resource_node *n);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment