/* * \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 #include #include #include 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 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 below 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(&_data)) { memset(&_data, 0, sizeof(_data)); } /*********************************** ** Cap_index_allocator interface ** ***********************************/ Cap_index* alloc_range(size_t cnt) { Lock_guard 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 guard(_lock); /* * construct the Cap_index pointer from the given * address in capability space */ T* obj = reinterpret_cast(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 guard(_lock); T* obj = static_cast(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]; } void reinit() { construct_at >(this); } }; } #endif /* _INCLUDE__BASE__CAP_ALLOC_H_ */