/* * \brief Allocator for anonymous memory used by libc * \author Norman Feske * \date 2012-05-18 */ #ifndef _LIBC_MEM_ALLOC_H_ #define _LIBC_MEM_ALLOC_H_ /* Genode includes */ #include #include #include #include #include #include namespace Libc { struct Mem_alloc { virtual void *alloc(Genode::size_t size, Genode::size_t align_log2) = 0; virtual void free(void *ptr) = 0; virtual Genode::size_t size_at(void const *ptr) const = 0; }; /** * Return singleton instance of the memory allocator */ Mem_alloc *mem_alloc(); class Mem_alloc_impl : public Mem_alloc { private: enum { MIN_CHUNK_SIZE = 4*1024, /* in machine words */ MAX_CHUNK_SIZE = 1024*1024 }; class Dataspace : public Genode::List::Element { public: Genode::Ram_dataspace_capability cap; void *local_addr; Dataspace(Genode::Ram_dataspace_capability c, void *a) : cap(c), local_addr(a) {} inline void * operator new(Genode::size_t, void* addr) { return addr; } inline void operator delete(void*) { } }; class Dataspace_pool : public Genode::List { private: Genode::Ram_session *_ram_session; /* ram session for backing store */ Genode::Rm_session *_rm_session; /* region manager */ public: /** * Constructor */ Dataspace_pool(Genode::Ram_session *ram_session, Genode::Rm_session *rm_session): _ram_session(ram_session), _rm_session(rm_session) { } /** * Destructor */ ~Dataspace_pool(); /** * Expand dataspace by specified size * * \param size number of bytes to add to the dataspace pool * \param md_alloc allocator to expand. This allocator is also * used for meta data allocation (only after * being successfully expanded). * \throw Rm_session::Invalid_dataspace, * Rm_session::Region_conflict * \return 0 on success or negative error code */ int expand(Genode::size_t size, Genode::Range_allocator *alloc); void reassign_resources(Genode::Ram_session *ram, Genode::Rm_session *rm) { _ram_session = ram, _rm_session = rm; } }; Genode::Lock mutable _lock; Dataspace_pool _ds_pool; /* list of dataspaces */ Genode::Allocator_avl _alloc; /* local allocator */ Genode::size_t _chunk_size; /** * Try to allocate block at our local allocator * * \return true on success * * This function is a utility used by 'alloc' to avoid * code duplication. */ bool _try_local_alloc(Genode::size_t size, void **out_addr); public: Mem_alloc_impl(Genode::Rm_session * rm = Genode::env()->rm_session(), Genode::Ram_session * ram = Genode::env()->ram_session()) : _ds_pool(ram, rm), _alloc(0), _chunk_size(MIN_CHUNK_SIZE) { } void *alloc(Genode::size_t size, Genode::size_t align_log2); void free(void *ptr); Genode::size_t size_at(void const *ptr) const; }; } #endif /* _LIBC_MEM_ALLOC_H_ */