hw: object in extra header & asserts reviewed

ref #528
This commit is contained in:
Martin Stein 2013-09-03 12:32:38 +02:00 committed by Norman Feske
parent e67016ca08
commit 4a1c218fd0
2 changed files with 242 additions and 211 deletions

View File

@ -0,0 +1,237 @@
/*
* \brief Objects that are findable through unique IDs
* \author Martin Stein
* \date 2012-11-30
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _KERNEL__OBJECT_H_
#define _KERNEL__OBJECT_H_
/* Genode includes */
#include <util/avl_tree.h>
#include <base/printf.h>
/* core includes */
#include <assert.h>
/* base-hw includes */
#include <singleton.h>
namespace Kernel
{
template <typename T> class Avl_tree : public Genode::Avl_tree<T> { };
template <typename T> class Avl_node : public Genode::Avl_node<T> { };
/**
* Map unique sortable IDs to objects
*
* \param T object type that inherits from Object_pool<T>::Item
*/
template <typename T>
class Object_pool;
/**
* Manage allocation of a static set of IDs
*
* \param SIZE amount of allocatable IDs
*/
template <unsigned SIZE>
class Id_allocator;
/**
* Make all objects of a deriving class findable through unique IDs
*/
template <typename T, unsigned MAX_INSTANCES>
class Object;
}
template <typename T>
class Kernel::Object_pool
{
public:
/**
* Enable a deriving class T to be inserted into an Object_pool<T>
*/
class Item;
/**
* Insert 'object' into pool
*/
void insert(T * const object) { _tree.insert(object); }
/**
* Remove 'object' from pool
*/
void remove(T * const object) { _tree.remove(object); }
/**
* Return object with ID 'id', or 0 if such an object doesn't exist
*/
T * object(unsigned const id) const
{
Item * const root = _tree.first();
if (!root) { return 0; }
return static_cast<T *>(root->find(id));
}
private:
Avl_tree<Item> _tree;
};
template <typename T>
class Kernel::Object_pool<T>::Item : public Avl_node<Item>
{
protected:
unsigned _id;
public:
/**
* Constructor
*/
Item(unsigned const id) : _id(id) { }
/**
* Find entry with 'object_id' within this AVL subtree
*/
Item * find(unsigned const object_id)
{
if (object_id == id()) { return this; }
Item * const subtree = Avl_node<Item>::child(object_id > id());
if (!subtree) { return 0; }
return subtree->find(object_id);
}
/**
* ID of this object
*/
unsigned id() const { return _id; }
/************************
* 'Avl_node' interface *
************************/
bool higher(Item * i) const { return i->id() > id(); }
};
template <unsigned SIZE>
class Kernel::Id_allocator
{
private:
enum {
MIN = 1,
MAX = MIN + SIZE - 1
};
bool _free[MAX + 1];
unsigned _free_id;
/**
* Return wether 'id' is a valid ID
*/
bool _valid_id(unsigned const id) const
{
return id >= MIN && id <= MAX;
}
public:
/**
* Constructor
*/
Id_allocator() : _free_id(MIN)
{
/* free all IDs */
for (unsigned i = MIN; i <= MAX; i++) { _free[i] = 1; }
}
/**
* Allocate a free ID
*
* \return ID that has been allocated by the call
*/
unsigned alloc()
{
/* FIXME: let userland donate RAM to avoid out of mem */
if (!_valid_id(_free_id)) {
PERR("failed to allocate ID");
while (1) { }
}
/* allocate _free_id */
_free[_free_id] = 0;
unsigned const id = _free_id;
/* update _free_id */
_free_id++;
for (; _free_id <= MAX && !_free[_free_id]; _free_id++) { }
return id;
}
/**
* Free ID 'id'
*/
void free(unsigned const id)
{
assert(_valid_id(id));
_free[id] = 1;
if (id < _free_id) { _free_id = id; }
}
};
template <typename T, unsigned MAX_INSTANCES>
class Kernel::Object : public Object_pool<T>::Item
{
private :
class Id_allocator : public Kernel::Id_allocator<MAX_INSTANCES> { };
/**
* Unique-ID allocator for objects of T
*/
static Id_allocator * _id_allocator()
{
return unsynchronized_singleton<Id_allocator>();
}
public:
typedef Object_pool<T> Pool;
/**
* Map of unique IDs to objects of T
*/
static Pool * pool() { return unsynchronized_singleton<Pool>(); }
protected:
/**
* Constructor
*/
Object() : Pool::Item(_id_allocator()->alloc())
{
pool()->insert(static_cast<T *>(this));
}
/**
* Destructor
*/
~Object()
{
pool()->remove(static_cast<T *>(this));
_id_allocator()->free(Pool::Item::id());
}
};
#endif /* _KERNEL__OBJECT_H_ */

View File

@ -16,7 +16,6 @@
/* Genode includes */
#include <util/fifo.h>
#include <util/avl_tree.h>
/* core includes */
#include <cpu.h>
@ -25,9 +24,7 @@
#include <timer.h>
#include <assert.h>
#include <kernel/configuration.h>
/* base-hw includes */
#include <singleton.h>
#include <kernel/object.h>
namespace Genode
{
@ -43,211 +40,8 @@ namespace Kernel
typedef Genode::Pagefault Pagefault;
typedef Genode::Native_utcb Native_utcb;
template <typename T> class Avl_tree : public Genode::Avl_tree<T> { };
template <typename T> class Avl_node : public Genode::Avl_node<T> { };
template <typename T> class Fifo : public Genode::Fifo<T> { };
/**
* Map unique sortable IDs to object pointers
*
* \param OBJECT_T object type that should be inherited
* from 'Object_pool::Entry'
*/
template <typename _OBJECT_T>
class Object_pool
{
typedef _OBJECT_T Object;
public:
enum { INVALID_ID = 0 };
/**
* Provide 'Object_pool'-entry compliance by inheritance
*/
class Entry : public Avl_node<Entry>
{
protected:
unsigned _id;
public:
/**
* Constructors
*/
Entry(unsigned const id) : _id(id) { }
/**
* Find entry with 'object_id' within this AVL subtree
*/
Entry * find(unsigned const object_id)
{
if (object_id == id()) return this;
Entry * const subtree = Avl_node<Entry>::child(object_id > id());
return subtree ? subtree->find(object_id) : 0;
}
/**
* ID of this object
*/
unsigned id() const { return _id; }
/************************
* 'Avl_node' interface *
************************/
bool higher(Entry *e) { return e->id() > id(); }
};
private:
Avl_tree<Entry> _tree;
public:
/**
* Add 'object' to pool
*/
void insert(Object * const object) { _tree.insert(object); }
/**
* Remove 'object' from pool
*/
void remove(Object * const object) { _tree.remove(object); }
/**
* Lookup object
*/
Object * object(unsigned const id)
{
Entry * object = _tree.first();
return (Object *)(object ? object->find(id) : 0);
}
};
/**
* Manage allocation of a static set of IDs
*
* \param _SIZE How much IDs shall be assignable simultaneously
*/
template <unsigned _SIZE>
class Id_allocator
{
enum { MIN = 1, MAX = _SIZE };
bool _free[MAX + 1]; /* assignability bitmap */
unsigned _first_free_id; /* hint to optimze access */
/**
* Update first free ID after assignment
*/
void _first_free_id_assigned()
{
_first_free_id++;
while (_first_free_id <= MAX) {
if (_free[_first_free_id]) break;
_first_free_id++;
}
}
/**
* Validate ID
*/
bool _valid_id(unsigned const id) const
{ return id >= MIN && id <= MAX; }
public:
/**
* Constructor, makes all IDs unassigned
*/
Id_allocator() : _first_free_id(MIN)
{ for (unsigned i = MIN; i <= MAX; i++) _free[i] = 1; }
/**
* Allocate an unassigned ID
*
* \return ID that has been allocated by the call
*/
unsigned alloc()
{
assert(_valid_id(_first_free_id));
_free[_first_free_id] = 0;
unsigned const id = _first_free_id;
_first_free_id_assigned();
return id;
}
/**
* Free a given ID
*/
void free(unsigned const id)
{
if (!_valid_id(id)) return;
_free[id] = 1;
if (id < _first_free_id) _first_free_id = id;
}
};
/**
* Provides kernel object management for 'T'-objects if 'T' derives from it
*/
template <typename T, unsigned MAX_INSTANCES>
class Object : public Object_pool<T>::Entry
{
typedef Id_allocator<MAX_INSTANCES> Id_alloc;
/**
* Allocator for unique IDs for all instances of 'T'
*/
static Id_alloc * _id_alloc()
{
return unsynchronized_singleton<Id_alloc>();
}
public:
typedef Object_pool<T> Pool;
/**
* Gets every instance of 'T' by its ID
*/
static Pool * pool()
{
return unsynchronized_singleton<Pool>();
}
/**
* Placement new
*
* Kernel objects are normally constructed on a memory
* donation so we must be enabled to place them explicitly.
*/
void * operator new (size_t, void * p) { return p; }
protected:
/**
* Constructor
*
* Ensures that we have a unique ID and
* can be found through the static object pool.
*/
Object() : Pool::Entry(_id_alloc()->alloc()) {
pool()->insert(static_cast<T *>(this)); }
/**
* Destructor
*/
~Object()
{
pool()->remove(static_cast<T *>(this));
_id_alloc()->free(Pool::Entry::id());
}
};
/**
* Double connected list
*
@ -642,7 +436,7 @@ namespace Kernel
/**
* Exclusive ownership and handling of one IRQ per instance at a max
*/
class Irq_owner : public Object_pool<Irq_owner>::Entry
class Irq_owner : public Object_pool<Irq_owner>::Item
{
/**
* To get any instance of this class by its ID
@ -663,19 +457,19 @@ namespace Kernel
public:
/**
* Translate 'Irq_owner_pool'-entry ID to IRQ ID
* Translate 'Irq_owner_pool'-item ID to IRQ ID
*/
static unsigned id_to_irq(unsigned id) { return id - 1; }
/**
* Translate IRQ ID to 'Irq_owner_pool'-entry ID
* Translate IRQ ID to 'Irq_owner_pool'-item ID
*/
static unsigned irq_to_id(unsigned irq) { return irq + 1; }
/**
* Constructor
*/
Irq_owner() : Pool::Entry(0) { }
Irq_owner() : Pool::Item(0) { }
/**
* Destructor