Custom global allocator - allocating with additional memory attributes

Hi there,

I've implemented a custom memory allocator for a bare metal embedded Rust based kernel. And this is working like a charm. However, implementing a kernel does also require to sometimes pass/request specific memory attributes while allocating memory. Eg. requesting memory that is cacheable, shared, executable etc. As the core::alloc::Layout structure does not support this kind of features is there any way to pass this kind of requirement ?
I've seen functions std::alloc::alloc() and I'm wondering why this is not art of the core::alloc crate, but the std::alloc ? Would be the recommended way to just implement my own alloc() function to allow passing memory attributes?
It might be worth a consideration for future Rust enhancements to also provide a possibility to pass memory attribute requirements to a custom global allocator or would this be to specific to the target platform ?

core is by design for platforms that don't have an allocator, so core::alloc wouldn't make sense. There's a separate alloc crate you can use alongside core.

There's no way to pass custom attributes to standard library types. With some care, you could allocate raw memory from your allocator directly, and then use methods like Box::from_raw to make objects use it.

3 Likes

Hi, thanks for the response.
I'll then go and try the Box::from_raw approach with my custom allocation function :slight_smile:

Hey, as a followup question, when creating an object with Box::from_raw based on a given heap memory address. What happens if I "move" the box around in function calls. Does the underlying memory address keep the same or is rust free to move the memory address using memcpy for example?

Taking this "pseudo" code. Does the thing in the foo function still "point" to the original allocated memory location or do I need to use Pin for the guarantee to be upheld by the compiler?

fn allocate_special<T>() -> Box<T> {
   let ptr = customallocator::alloc(some_size, some_alignment, some_attributes);
   unsafe {
      Box::from_raw(ptr as *mut T)
   }
}

fn foo(thing: Box<T>) {
   // does thing still point to the original position in heap?
}

struct Bar;

fn main() {
  let bar: Box<Bar> = allocate_special();
  foo(bar);
}

Yep, thing points to the same location on the heap. Moving never does anything to heap allocations, with std containers or any others - it will only ever change the location of things on the stack (like the pointer to the heap data).

This is actually a hard guarantee of the Rust language: moving values around has no side effects.

3 Likes

Box is just a pointer, so moving Box copies the pointer around.

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.