mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 16:35:28 +00:00
parent
e67016ca08
commit
4a1c218fd0
237
base-hw/src/core/kernel/object.h
Normal file
237
base-hw/src/core/kernel/object.h
Normal 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_ */
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user