mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 14:13:09 +00:00
131 lines
3.2 KiB
C++
131 lines
3.2 KiB
C++
/*
|
|
* \brief Capability index allocator for Fiasco.OC.
|
|
* \author Stefan Kalkowski
|
|
* \date 2012-02-16
|
|
*/
|
|
|
|
/*
|
|
* 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 _INCLUDE__BASE__CAP_ALLOC_H_
|
|
#define _INCLUDE__BASE__CAP_ALLOC_H_
|
|
|
|
#include <base/cap_map.h>
|
|
#include <base/native_types.h>
|
|
#include <util/assert.h>
|
|
|
|
namespace Genode {
|
|
|
|
/**
|
|
* Cap_index_allocator_tpl implements the Cap_index_allocator for Fiasco.OC.
|
|
*
|
|
* It's designed as a template because we need two distinguished versions
|
|
* for core and non-core processes with respect to dimensioning. Moreover,
|
|
* core needs more information within a Cap_index object, than the base
|
|
* class provides.
|
|
*
|
|
* \param T Cap_index specialization to use
|
|
* \param SZ size of Cap_index array used by the allocator
|
|
*/
|
|
template <typename T, unsigned SZ>
|
|
class Cap_index_allocator_tpl : public Cap_index_allocator
|
|
{
|
|
private:
|
|
|
|
Spin_lock _lock; /* used very early in initialization,
|
|
where normal lock isn't feasible */
|
|
|
|
enum {
|
|
/* everything above START_IDX is managed by core */
|
|
START_IDX = Fiasco::USER_BASE_CAP >> Fiasco::L4_CAP_SHIFT
|
|
};
|
|
|
|
protected:
|
|
|
|
unsigned char _data[SZ*sizeof(T)];
|
|
T* _indices;
|
|
|
|
public:
|
|
|
|
Cap_index_allocator_tpl() : _indices(reinterpret_cast<T*>(&_data)) {
|
|
memset(&_data, 0, sizeof(_data)); }
|
|
|
|
|
|
/***********************************
|
|
** Cap_index_allocator interface **
|
|
***********************************/
|
|
|
|
Cap_index* alloc_range(size_t cnt)
|
|
{
|
|
Lock_guard<Spin_lock> guard(_lock);
|
|
|
|
/*
|
|
* iterate through array and find unused, consecutive entries
|
|
*/
|
|
for (unsigned i = START_IDX, j = 0; (i+cnt) < SZ; i+=j+1, j=0) {
|
|
for (; j < cnt; j++)
|
|
if (_indices[i+j].used())
|
|
break;
|
|
|
|
/* if we found a fitting hole, initialize the objects */
|
|
if (j == cnt) {
|
|
for (j = 0; j < cnt; j++)
|
|
new (&_indices[i+j]) T();
|
|
return &_indices[i];
|
|
}
|
|
}
|
|
ASSERT(0, "cap index allocation failed");
|
|
return 0;
|
|
}
|
|
|
|
Cap_index* alloc(addr_t addr)
|
|
{
|
|
Lock_guard<Spin_lock> guard(_lock);
|
|
|
|
/*
|
|
* construct the Cap_index pointer from the given
|
|
* address in capability space
|
|
*/
|
|
T* obj = reinterpret_cast<T*>(kcap_to_idx(addr));
|
|
|
|
if (obj < &_indices[0] || obj >= &_indices[SZ]) {
|
|
ASSERT(0, "cap index out of bounds");
|
|
throw Index_out_of_bounds();
|
|
}
|
|
|
|
return new (obj) T();
|
|
}
|
|
|
|
void free(Cap_index* idx, size_t cnt)
|
|
{
|
|
Lock_guard<Spin_lock> guard(_lock);
|
|
|
|
T* obj = static_cast<T*>(idx);
|
|
for (size_t i = 0; i < cnt; obj++, i++) {
|
|
/* range check given pointer address */
|
|
if (obj < &_indices[0] || obj >= &_indices[SZ]) {
|
|
ASSERT(0, "cap index out of bounds");
|
|
throw Index_out_of_bounds();
|
|
}
|
|
delete obj;
|
|
}
|
|
}
|
|
|
|
addr_t idx_to_kcap(Cap_index *idx) {
|
|
return ((T*)idx - &_indices[0]) << Fiasco::L4_CAP_SHIFT;
|
|
}
|
|
|
|
Cap_index* kcap_to_idx(addr_t kcap) {
|
|
return &_indices[kcap >> Fiasco::L4_CAP_SHIFT]; }
|
|
|
|
bool static_idx(Cap_index *idx) {
|
|
return ((T*)idx) < &_indices[START_IDX]; }
|
|
};
|
|
}
|
|
|
|
#endif /* _INCLUDE__BASE__CAP_ALLOC_H_ */
|