genode/repos/base/src/core/include/core_mem_alloc.h

322 lines
8.6 KiB
C
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Allocator infrastructure for core
* \author Norman Feske
* \author Stefan Kalkowski
2011-12-22 16:19:25 +01:00
* \date 2009-10-12
*/
/*
* Copyright (C) 2009-2017 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2011-12-22 16:19:25 +01:00
*/
#ifndef _CORE__INCLUDE__CORE_MEM_ALLOC_H_
#define _CORE__INCLUDE__CORE_MEM_ALLOC_H_
#include <base/lock.h>
#include <base/allocator_avl.h>
#include <synced_range_allocator.h>
#include <util.h>
2011-12-22 16:19:25 +01:00
namespace Genode {
class Core_mem_translator;
class Core_mem_allocator;
struct Metadata;
class Mapped_mem_allocator;
class Mapped_avl_allocator;
using Page_allocator = Allocator_avl_tpl<Empty, get_page_size()>;
using Phys_allocator = Synced_range_allocator<Page_allocator>;
using Synced_mapped_allocator =
Synced_range_allocator<Mapped_avl_allocator>;
};
2011-12-22 16:19:25 +01:00
/**
* Interface of an allocator that allows to return physical addresses
* of its used virtual address ranges, and vice versa.
*/
class Genode::Core_mem_translator : public Genode::Range_allocator
{
public:
/**
* Returns physical address for given virtual one
*
* \param addr virtual address
*/
virtual void * phys_addr(void * addr) = 0;
/**
* Returns virtual address for given physical one
*
* \param addr physical address
*/
virtual void * virt_addr(void * addr) = 0;
};
/**
* Metadata for allocator blocks that stores a related address
*/
struct Genode::Metadata { void * map_addr; };
/**
* Page-size granular allocator that links ranges to related ones.
*/
class Genode::Mapped_avl_allocator
: public Genode::Allocator_avl_tpl<Genode::Metadata, Genode::get_page_size()>
{
friend class Mapped_mem_allocator;
public:
/**
* Constructor
*
* \param md_alloc metadata allocator
*/
explicit Mapped_avl_allocator(Allocator *md_alloc)
: Allocator_avl_tpl<Metadata, get_page_size()>(md_alloc) {}
/**
* Returns related address for allocated range
*
* \param addr address within allocated range
*/
void * map_addr(void * addr);
};
/**
* Unsynchronized allocator for core-mapped memory
*
* This is an allocator of core-mapped memory. It is meant to be used as
* meta-data allocator for the other allocators and as back end for core's
* synchronized memory allocator.
*/
class Genode::Mapped_mem_allocator : public Genode::Core_mem_translator
{
private:
Mapped_avl_allocator *_phys_alloc;
Mapped_avl_allocator *_virt_alloc;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
/*
* Noncopyable
*/
Mapped_mem_allocator(Mapped_mem_allocator const &);
Mapped_mem_allocator &operator = (Mapped_mem_allocator const &);
public:
/**
* Constructor
*
* \param phys_alloc allocator of physical memory
* \param virt_alloc allocator of core-local virtual memory ranges
*/
Mapped_mem_allocator(Synced_mapped_allocator &phys_alloc,
Synced_mapped_allocator &virt_alloc)
: _phys_alloc(&phys_alloc._alloc), _virt_alloc(&virt_alloc._alloc) { }
/**
* Establish mapping between physical and virtual address range
*
* Note: has to be implemented by platform specific code
*
* \param virt_addr start address of virtual range
* \param phys_addr start address of physical range
* \param size size of range
*/
bool _map_local(addr_t virt_addr, addr_t phys_addr, unsigned size);
/**
* Destroy mapping between physical and virtual address range
*
* Note: has to be implemented by platform specific code
*
* \param virt_addr start address of virtual range
* \param phys_addr start address of physical range
* \param size size of range
*/
bool _unmap_local(addr_t virt_addr, addr_t phys_addr, unsigned size);
/***********************************
** Core_mem_translator interface **
***********************************/
void * phys_addr(void * addr) override {
return _virt_alloc->map_addr(addr); }
void * virt_addr(void * addr) override {
return _phys_alloc->map_addr(addr); }
/*******************************
** Range allocator interface **
*******************************/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
int add_range(addr_t, size_t) override { return -1; }
int remove_range(addr_t, size_t) override { return -1; }
Alloc_return alloc_aligned(size_t, void **, int, addr_t from = 0,
addr_t to = ~0UL) override;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Alloc_return alloc_addr(size_t, addr_t) override {
return Alloc_return::RANGE_CONFLICT; }
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
void free(void *) override;
size_t avail() const override { return _phys_alloc->avail(); }
bool valid_addr(addr_t addr) const override {
return _virt_alloc->valid_addr(addr); }
/*************************
** Allocator interface **
*************************/
bool alloc(size_t size, void **out_addr) override {
return alloc_aligned(size, out_addr, log2(sizeof(addr_t))).ok(); }
void free(void *addr, size_t) override;
size_t consumed() const override { return _phys_alloc->consumed(); }
size_t overhead(size_t size) const override {
return _phys_alloc->overhead(size); }
bool need_size_for_free() const override {
return _phys_alloc->need_size_for_free(); }
};
/**
* Allocators for physical memory, core's virtual address space,
* and core-local memory. The interface of this class is thread safe.
* The class itself implements a ready-to-use memory allocator for
* core that allows to allocate memory at page granularity only.
*/
class Genode::Core_mem_allocator : public Genode::Core_mem_translator
{
protected:
/**
* Lock used for synchronization of all operations on the
* embedded allocators.
*/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Lock _lock { };
/**
* Synchronized allocator of physical memory ranges
*
* This allocator must only be used to allocate memory
* ranges at page granularity.
*/
Synced_mapped_allocator _phys_alloc;
/**
* Synchronized allocator of core's virtual memory ranges
*
* This allocator must only be used to allocate memory
* ranges at page granularity.
*/
Synced_mapped_allocator _virt_alloc;
/**
* Unsynchronized core-mapped memory allocator
*
* This allocator is internally used within this class for
* allocating meta data for the other allocators. It is not
* synchronized to avoid nested locking. The lock-guarded
* access to this allocator from the outer world is
* provided via the 'Allocator' interface implemented by
* 'Core_mem_allocator'. The allocator works at byte
* granularity.
*/
Mapped_mem_allocator _mem_alloc;
public:
/**
* Constructor
*/
Core_mem_allocator()
: _phys_alloc(_lock, &_mem_alloc),
_virt_alloc(_lock, &_mem_alloc),
_mem_alloc(_phys_alloc, _virt_alloc) { }
/**
* Access physical-memory allocator
*/
Synced_mapped_allocator &phys_alloc() { return _phys_alloc; }
/**
* Access core's virtual-memory allocator
*/
Synced_mapped_allocator &virt_alloc() { return _virt_alloc; }
/***********************************
** Core_mem_translator interface **
***********************************/
void * phys_addr(void * addr) override
{
return _virt_alloc()->map_addr(addr);
}
void * virt_addr(void * addr) override
{
return _phys_alloc()->map_addr(addr);
}
/*******************************
** Range allocator interface **
*******************************/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
int add_range(addr_t, size_t) override { return -1; }
int remove_range(addr_t, size_t) override { return -1; }
Alloc_return alloc_addr(size_t, addr_t) override {
return Alloc_return::RANGE_CONFLICT; }
Alloc_return alloc_aligned(size_t size, void **out_addr, int align,
addr_t from = 0, addr_t to = ~0UL) override
{
Lock::Guard lock_guard(_lock);
return _mem_alloc.alloc_aligned(size, out_addr, align, from, to);
}
void free(void *addr) override
{
Lock::Guard lock_guard(_lock);
return _mem_alloc.free(addr);
}
size_t avail() const override { return _phys_alloc.avail(); }
bool valid_addr(addr_t addr) const override { return _virt_alloc.valid_addr(addr); }
/*************************
** Allocator interface **
*************************/
bool alloc(size_t size, void **out_addr) override {
return alloc_aligned(size, out_addr, log2(sizeof(addr_t))).ok(); }
void free(void *addr, size_t size) override
{
Lock::Guard lock_guard(_lock);
return _mem_alloc.free(addr, size);
}
size_t consumed() const override { return _phys_alloc.consumed(); }
size_t overhead(size_t size) const override { return _phys_alloc.overhead(size); }
bool need_size_for_free() const override {
return _phys_alloc.need_size_for_free(); }
};
2011-12-22 16:19:25 +01:00
#endif /* _CORE__INCLUDE__CORE_MEM_ALLOC_H_ */