mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-06 11:10:24 +00:00
allocator_avl: use Attempt for size_at
Fixes ambiguous interpretation of returned 0. genodelabs/genode#4393
This commit is contained in:
parent
5aa0fea29b
commit
db3a647c6d
@ -104,8 +104,14 @@ namespace Genode {
|
|||||||
* Determine size of a core local mapping required for a
|
* Determine size of a core local mapping required for a
|
||||||
* core_rm_session detach().
|
* core_rm_session detach().
|
||||||
*/
|
*/
|
||||||
size_t region_alloc_size_at(void * addr) {
|
size_t region_alloc_size_at(void * addr)
|
||||||
return (_core_mem_alloc.virt_alloc())()->size_at(addr); }
|
{
|
||||||
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
|
|
||||||
|
return (_core_mem_alloc.virt_alloc())()->size_at(addr).convert<size_t>(
|
||||||
|
[ ] (size_t s) { return s; },
|
||||||
|
[ ] (Size_at_error) { return 0U; });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return kernel CPU ID for given Genode CPU
|
* Return kernel CPU ID for given Genode CPU
|
||||||
|
@ -276,8 +276,14 @@ class Genode::Platform : public Platform_generic
|
|||||||
* Determine size of a core local mapping required for a
|
* Determine size of a core local mapping required for a
|
||||||
* core_rm_session detach().
|
* core_rm_session detach().
|
||||||
*/
|
*/
|
||||||
size_t region_alloc_size_at(void * addr) {
|
size_t region_alloc_size_at(void * addr)
|
||||||
return (_core_mem_alloc.virt_alloc())()->size_at(addr); }
|
{
|
||||||
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
|
|
||||||
|
return (_core_mem_alloc.virt_alloc())()->size_at(addr).convert<size_t>(
|
||||||
|
[ ] (size_t s) { return s; },
|
||||||
|
[ ] (Size_at_error) { return 0U; });
|
||||||
|
}
|
||||||
|
|
||||||
size_t max_caps() const override
|
size_t max_caps() const override
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,15 @@ namespace Genode {
|
|||||||
|
|
||||||
class Genode::Allocator_avl_base : public Range_allocator
|
class Genode::Allocator_avl_base : public Range_allocator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Size_at_error {
|
||||||
|
UNKNOWN_ADDR, /* no allocation at specified address */
|
||||||
|
MISMATCHING_ADDR, /* specified address is not the start of a block */
|
||||||
|
};
|
||||||
|
|
||||||
|
using Size_at_result = Attempt<size_t, Size_at_error>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static bool _sum_in_range(addr_t addr, addr_t offset) {
|
static bool _sum_in_range(addr_t addr, addr_t offset) {
|
||||||
@ -287,7 +296,7 @@ class Genode::Allocator_avl_base : public Range_allocator
|
|||||||
/**
|
/**
|
||||||
* Return size of block at specified address
|
* Return size of block at specified address
|
||||||
*/
|
*/
|
||||||
size_t size_at(void const *addr) const;
|
Size_at_result size_at(void const *addr) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the memory overhead per Block
|
* Return the memory overhead per Block
|
||||||
|
@ -394,15 +394,18 @@ void Allocator_avl_base::free(void *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t Allocator_avl_base::size_at(void const *addr) const
|
Allocator_avl_base::Size_at_result Allocator_avl_base::size_at(void const *addr) const
|
||||||
{
|
{
|
||||||
/* lookup corresponding block */
|
/* lookup corresponding block */
|
||||||
Block *b = _find_by_address(reinterpret_cast<addr_t>(addr));
|
Block *b = _find_by_address(reinterpret_cast<addr_t>(addr));
|
||||||
|
|
||||||
if (b && (b->addr() != (addr_t)addr))
|
if (b && (b->addr() != (addr_t)addr))
|
||||||
return 0;
|
return Size_at_error::MISMATCHING_ADDR;
|
||||||
|
|
||||||
return (b && b->used()) ? b->size() : 0;
|
if (b && b->used())
|
||||||
|
return b->size();
|
||||||
|
|
||||||
|
return Size_at_error::UNKNOWN_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,14 +255,27 @@ void Heap::free(void *addr, size_t)
|
|||||||
/* serialize access of heap functions */
|
/* serialize access of heap functions */
|
||||||
Mutex::Guard guard(_mutex);
|
Mutex::Guard guard(_mutex);
|
||||||
|
|
||||||
/* try to find the size in our local allocator */
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
size_t const size = _alloc->size_at(addr);
|
|
||||||
|
|
||||||
if (size != 0) {
|
Allocator_avl::Size_at_result size_at_result = _alloc->size_at(addr);
|
||||||
|
|
||||||
|
if (size_at_result.ok()) {
|
||||||
|
/* forward request to our local allocator */
|
||||||
|
size_at_result.with_result(
|
||||||
|
[&] (size_t size) {
|
||||||
/* forward request to our local allocator */
|
/* forward request to our local allocator */
|
||||||
_alloc->free(addr, size);
|
_alloc->free(addr, size);
|
||||||
_quota_used -= size;
|
_quota_used -= size;
|
||||||
|
},
|
||||||
|
[&] (Size_at_error) { });
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size_at_result == Size_at_error::MISMATCHING_ADDR) {
|
||||||
|
/* address was found in local allocator but is not a block start address */
|
||||||
|
error("heap could not free memory block: given address ", addr,
|
||||||
|
" is not a block start adress");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +291,7 @@ void Heap::free(void *addr, size_t)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
warning("heap could not free memory block");
|
warning("heap could not free memory block: invalid address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,17 +173,24 @@ bool Lx_kit::Mem_allocator::free(const void * ptr)
|
|||||||
if (!_mem.valid_addr((addr_t)ptr))
|
if (!_mem.valid_addr((addr_t)ptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_mem.size_at(ptr))
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
return true;
|
|
||||||
|
_mem.size_at(ptr).with_result(
|
||||||
|
[&] (size_t) { _mem.free(const_cast<void*>(ptr)); },
|
||||||
|
[ ] (Size_at_error) { });
|
||||||
|
|
||||||
_mem.free(const_cast<void*>(ptr));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Genode::size_t Lx_kit::Mem_allocator::size(const void * ptr)
|
Genode::size_t Lx_kit::Mem_allocator::size(const void * ptr)
|
||||||
{
|
{
|
||||||
return ptr ? _mem.size_at(ptr) : 0;
|
if (!ptr) return 0;
|
||||||
|
|
||||||
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
|
|
||||||
|
return _mem.size_at(ptr).convert<size_t>([ ] (size_t s) { return s; },
|
||||||
|
[ ] (Size_at_error) { return 0U; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,9 +28,12 @@ namespace Libc {
|
|||||||
|
|
||||||
struct Mem_alloc
|
struct Mem_alloc
|
||||||
{
|
{
|
||||||
|
using Size_at_error = Allocator_avl::Size_at_error;
|
||||||
|
using Size_at_result = Allocator_avl::Size_at_result;
|
||||||
|
|
||||||
virtual void *alloc(size_t size, size_t align_log2) = 0;
|
virtual void *alloc(size_t size, size_t align_log2) = 0;
|
||||||
virtual void free(void *ptr) = 0;
|
virtual void free(void *ptr) = 0;
|
||||||
virtual size_t size_at(void const *ptr) const = 0;
|
virtual Size_at_result size_at(void const *ptr) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +127,7 @@ namespace Libc {
|
|||||||
|
|
||||||
void *alloc(size_t size, size_t align_log2);
|
void *alloc(size_t size, size_t align_log2);
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
size_t size_at(void const *ptr) const;
|
Size_at_result size_at(void const *ptr) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ void Libc::Mem_alloc_impl::free(void *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t Libc::Mem_alloc_impl::size_at(void const *addr) const
|
Libc::Mem_alloc::Size_at_result Libc::Mem_alloc_impl::size_at(void const *addr) const
|
||||||
{
|
{
|
||||||
/* serialize access of heap functions */
|
/* serialize access of heap functions */
|
||||||
Mutex::Guard guard(_mutex);
|
Mutex::Guard guard(_mutex);
|
||||||
|
@ -2429,12 +2429,23 @@ void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags
|
|||||||
|
|
||||||
int Libc::Vfs_plugin::munmap(void *addr, ::size_t)
|
int Libc::Vfs_plugin::munmap(void *addr, ::size_t)
|
||||||
{
|
{
|
||||||
if (mem_alloc()->size_at(addr) > 0) {
|
using Size_at_error = Mem_alloc::Size_at_error;
|
||||||
|
|
||||||
|
Mem_alloc::Size_at_result const size_at_result = mem_alloc()->size_at(addr);
|
||||||
|
|
||||||
|
if (size_at_result.ok()) {
|
||||||
/* private mapping */
|
/* private mapping */
|
||||||
mem_alloc()->free(addr);
|
size_at_result.with_result(
|
||||||
|
[&] (size_t) { mem_alloc()->free(addr); },
|
||||||
|
[&] (Size_at_error) { });
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return error if addr is not a block start address */
|
||||||
|
if (size_at_result == Size_at_error::MISMATCHING_ADDR)
|
||||||
|
return Errno(EINVAL);
|
||||||
|
|
||||||
/* shared mapping */
|
/* shared mapping */
|
||||||
|
|
||||||
Vfs::Vfs_handle *reference_handle = nullptr;
|
Vfs::Vfs_handle *reference_handle = nullptr;
|
||||||
|
@ -109,8 +109,12 @@ extern "C" void *realloc(void *ptr, ::size_t size)
|
|||||||
unsigned long old_size = size;
|
unsigned long old_size = size;
|
||||||
|
|
||||||
if (!initial_memory(ptr)) {
|
if (!initial_memory(ptr)) {
|
||||||
|
using Size_at_error = Libc::Mem_alloc::Size_at_error;
|
||||||
|
|
||||||
/* determine size of old block content (without header) */
|
/* determine size of old block content (without header) */
|
||||||
old_size = memory()->size_at(ptr);
|
old_size = memory()->size_at(ptr).convert<size_t>(
|
||||||
|
[ ] (size_t s) { return s; },
|
||||||
|
[ ] (Size_at_error) { return 0U; });
|
||||||
|
|
||||||
/* do not reallocate if new size is less than the current size */
|
/* do not reallocate if new size is less than the current size */
|
||||||
if (size <= old_size)
|
if (size <= old_size)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user