diff --git a/base/include/base/allocator.h b/base/include/base/allocator.h index 5aa82e939..c59aeee37 100644 --- a/base/include/base/allocator.h +++ b/base/include/base/allocator.h @@ -19,186 +19,185 @@ namespace Genode { - class Allocator + struct Deallocator { - public: + /** + * Free block a previously allocated block + */ + virtual void free(void *addr, size_t size) = 0; - /********************* - ** Exception types ** - *********************/ - - class Out_of_memory : public Exception { }; - - /** - * Destructor - */ - virtual ~Allocator() { } - - /** - * Allocate block - * - * \param size block size to allocate - * \param out_addr resulting pointer to the new block, - * undefined in the error case - * \return true on success - */ - virtual bool alloc(size_t size, void **out_addr) = 0; - - /** - * Allocate typed block - * - * This template allocates a typed block returned as a pointer to - * a non-void type. By providing this function, we prevent the - * compiler from warning us about "dereferencing type-punned - * pointer will break strict-aliasing rules". - */ - template bool alloc(size_t size, T **out_addr) - { - void *addr = 0; - bool ret = alloc(size, &addr); - *out_addr = (T *)addr; - return ret; - } - - /** - * Free block a previously allocated block - */ - virtual void free(void *addr, size_t size) = 0; - - /** - * Return total amount of backing store consumed by the allocator - */ - virtual size_t consumed() { return 0; } - - /** - * Return meta-data overhead per block - */ - virtual size_t overhead(size_t size) = 0; - - /** - * Return true if the size argument of 'free' is required - * - * The generic 'Allocator' interface requires the caller of 'free' - * to supply a valid size argument but not all implementations make - * use of this argument. If this function returns false, it is safe - * to call 'free' with an invalid size. - * - * Allocators that rely on the size argument must not be used for - * constructing objects whose constructors may throw exceptions. - * See the documentation of 'operator delete(void *, Allocator *)' - * below for more details. - */ - virtual bool need_size_for_free() const { return true; } - - - /*************************** - ** Convenience functions ** - ***************************/ - - /** - * Allocate block and signal error as an exception - * - * \param size block size to allocate - * \return pointer to the new block - * \throw Out_of_memory - */ - void *alloc(size_t size) - { - void *result = 0; - if (!alloc(size, &result)) - throw Out_of_memory(); - - return result; - } + /** + * Return true if the size argument of 'free' is required + * + * The generic 'Allocator' interface requires the caller of 'free' + * to supply a valid size argument but not all implementations make + * use of this argument. If this function returns false, it is safe + * to call 'free' with an invalid size. + * + * Allocators that rely on the size argument must not be used for + * constructing objects whose constructors may throw exceptions. + * See the documentation of 'operator delete(void *, Allocator *)' + * below for more details. + */ + virtual bool need_size_for_free() const { return true; } }; - class Range_allocator : public Allocator + struct Allocator : Deallocator { - public: + /** + * Exception type + */ + class Out_of_memory : public Exception { }; - /** - * Destructor - */ - virtual ~Range_allocator() { } + /** + * Destructor + */ + virtual ~Allocator() { } - /** - * Add free address range to allocator - */ - virtual int add_range(addr_t base, size_t size) = 0; + /** + * Allocate block + * + * \param size block size to allocate + * \param out_addr resulting pointer to the new block, + * undefined in the error case + * \return true on success + */ + virtual bool alloc(size_t size, void **out_addr) = 0; - /** - * Remove address range from allocator - */ - virtual int remove_range(addr_t base, size_t size) = 0; + /** + * Allocate typed block + * + * This template allocates a typed block returned as a pointer to + * a non-void type. By providing this function, we prevent the + * compiler from warning us about "dereferencing type-punned + * pointer will break strict-aliasing rules". + */ + template bool alloc(size_t size, T **out_addr) + { + void *addr = 0; + bool ret = alloc(size, &addr); + *out_addr = (T *)addr; + return ret; + } - /** - * Return value of allocation functons - * - * 'OK' on success, or - * 'OUT_OF_METADATA' if meta-data allocation failed, or - * 'RANGE_CONFLICT' if no fitting address range is found - */ - struct Alloc_return - { - enum Value { OK = 0, OUT_OF_METADATA = -1, RANGE_CONFLICT = -2 }; - Value const value; - Alloc_return(Value value) : value(value) { } + /** + * Return total amount of backing store consumed by the allocator + */ + virtual size_t consumed() { return 0; } - bool is_ok() const { return value == OK; } - bool is_error() const { return !is_ok(); } - }; + /** + * Return meta-data overhead per block + */ + virtual size_t overhead(size_t size) = 0; - /** - * Allocate block - * - * \param size size of new block - * \param out_addr start address of new block, - * undefined in the error case - * \param align alignment of new block specified - * as the power of two - */ - virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0) = 0; - /** - * Allocate block at address - * - * \param size size of new block - * \param addr desired address of block - * - * \return 'ALLOC_OK' on success, or - * 'OUT_OF_METADATA' if meta-data allocation failed, or - * 'RANGE_CONFLICT' if specified range is occupied - */ - virtual Alloc_return alloc_addr(size_t size, addr_t addr) = 0; + /*************************** + ** Convenience functions ** + ***************************/ - /** - * Free a previously allocated block - * - * NOTE: We have to declare the 'Allocator::free(void *)' function - * here as well to make the compiler happy. Otherwise the C++ - * overload resolution would not find 'Allocator::free(void *)'. - */ - virtual void free(void *addr) = 0; - virtual void free(void *addr, size_t size) = 0; + /** + * Allocate block and signal error as an exception + * + * \param size block size to allocate + * \return pointer to the new block + * \throw Out_of_memory + */ + void *alloc(size_t size) + { + void *result = 0; + if (!alloc(size, &result)) + throw Out_of_memory(); - /** - * Return the sum of available memory - * - * Note that the returned value is not neccessarily allocatable - * because the memory may be fragmented. - */ - virtual size_t avail() = 0; + return result; + } + }; - /** - * Check if address is inside an allocated block - * - * \param addr address to check - * - * \return true if address is inside an allocated block, false - * otherwise - */ - virtual bool valid_addr(addr_t addr) = 0; + + struct Range_allocator : Allocator + { + /** + * Destructor + */ + virtual ~Range_allocator() { } + + /** + * Add free address range to allocator + */ + virtual int add_range(addr_t base, size_t size) = 0; + + /** + * Remove address range from allocator + */ + virtual int remove_range(addr_t base, size_t size) = 0; + + /** + * Return value of allocation functons + * + * 'OK' on success, or + * 'OUT_OF_METADATA' if meta-data allocation failed, or + * 'RANGE_CONFLICT' if no fitting address range is found + */ + struct Alloc_return + { + enum Value { OK = 0, OUT_OF_METADATA = -1, RANGE_CONFLICT = -2 }; + Value const value; + Alloc_return(Value value) : value(value) { } + + bool is_ok() const { return value == OK; } + bool is_error() const { return !is_ok(); } + }; + + /** + * Allocate block + * + * \param size size of new block + * \param out_addr start address of new block, + * undefined in the error case + * \param align alignment of new block specified + * as the power of two + */ + virtual Alloc_return alloc_aligned(size_t size, void **out_addr, int align = 0) = 0; + + /** + * Allocate block at address + * + * \param size size of new block + * \param addr desired address of block + * + * \return 'ALLOC_OK' on success, or + * 'OUT_OF_METADATA' if meta-data allocation failed, or + * 'RANGE_CONFLICT' if specified range is occupied + */ + virtual Alloc_return alloc_addr(size_t size, addr_t addr) = 0; + + /** + * Free a previously allocated block + * + * NOTE: We have to declare the 'Allocator::free(void *)' function + * here as well to make the compiler happy. Otherwise the C++ + * overload resolution would not find 'Allocator::free(void *)'. + */ + virtual void free(void *addr) = 0; + virtual void free(void *addr, size_t size) = 0; + + /** + * Return the sum of available memory + * + * Note that the returned value is not neccessarily allocatable + * because the memory may be fragmented. + */ + virtual size_t avail() = 0; + + /** + * Check if address is inside an allocated block + * + * \param addr address to check + * + * \return true if address is inside an allocated block, false + * otherwise + */ + virtual bool valid_addr(addr_t addr) = 0; }; @@ -216,7 +215,7 @@ namespace Genode { * \param obj object to destroy */ template - void destroy(Allocator *alloc, T *obj) + void destroy(Deallocator *dealloc, T *obj) { if (!obj) return; @@ -225,12 +224,15 @@ namespace Genode { obj->~T(); /* free memory at the allocator */ - alloc->free(obj, sizeof(T)); + dealloc->free(obj, sizeof(T)); } } -void *operator new (Genode::size_t size, Genode::Allocator *allocator); -void *operator new [] (Genode::size_t size, Genode::Allocator *allocator); +void *operator new (Genode::size_t, Genode::Allocator *); +void *operator new [] (Genode::size_t, Genode::Allocator *); + +void *operator new (Genode::size_t, Genode::Allocator &); +void *operator new [] (Genode::size_t, Genode::Allocator &); /** diff --git a/base/src/base/cxx/new_delete.cc b/base/src/base/cxx/new_delete.cc index bbc3119a8..aea374909 100644 --- a/base/src/base/cxx/new_delete.cc +++ b/base/src/base/cxx/new_delete.cc @@ -14,25 +14,26 @@ #include #include +using Genode::size_t; +using Genode::Allocator; -void *operator new(Genode::size_t size, Genode::Allocator *allocator) + +static void *try_alloc(Allocator *alloc, size_t size) { - if (!allocator) - throw Genode::Allocator::Out_of_memory(); + if (!alloc) + throw Allocator::Out_of_memory(); - return allocator->alloc(size); -} - -void *operator new [] (Genode::size_t size, Genode::Allocator *allocator) -{ - if (!allocator) - throw Genode::Allocator::Out_of_memory(); - - return allocator->alloc(size); + return alloc->alloc(size); } -void operator delete (void *ptr, Genode::Allocator *alloc) +void *operator new (size_t s, Allocator *a) { return try_alloc(a, s); } +void *operator new [] (size_t s, Allocator *a) { return try_alloc(a, s); } +void *operator new (size_t s, Allocator &a) { return a.alloc(s); } +void *operator new [] (size_t s, Allocator &a) { return a.alloc(s); } + + +void operator delete (void *ptr, Allocator *alloc) { /* * Warn on the attempt to use an allocator that relies on the size