alloc: expose CHERIOTHeapMinChunkSize And document the relevant implications of our allocator's design that might necessitate knowing this value.
diff --git a/sdk/core/allocator/alloc.h b/sdk/core/allocator/alloc.h index 8ab0c09..69f2726 100644 --- a/sdk/core/allocator/alloc.h +++ b/sdk/core/allocator/alloc.h
@@ -683,6 +683,8 @@ // the minimum size of a chunk (excluding the header) constexpr size_t MinRequest = MinChunkSize - sizeof(MChunkHeader); +static_assert(MinChunkSize == CHERIOTHeapMinChunkSize); + // true if cap address a has acceptable alignment static inline bool is_aligned(CHERI::Capability<void> a) {
diff --git a/sdk/include/stdlib.h b/sdk/include/stdlib.h index adc2143..54a9dc6 100644 --- a/sdk/include/stdlib.h +++ b/sdk/include/stdlib.h
@@ -11,6 +11,13 @@ #include <timeout.h> /** + * The SDK allocator implementation works in terms of "chunks" and has minimum + * size requirements for these. This is occasionally visible to its clients, + * as documented on interface functions below. + */ +static const size_t CHERIOTHeapMinChunkSize = 16; + +/** * `MALLOC_QUOTA` sets the quota for the current compartment for use with * malloc and free. This defaults to 4 KiB. */ @@ -135,9 +142,16 @@ }; /** - * Non-standard allocation API. Allocates `size` bytes. Blocking behaviour is - * controlled by the `flags` and the `timeout` parameters. + * Non-standard allocation API. Allocates `size` bytes. * + * The `heapCapability` quota object must have remaining capacity sufficient + * for the requested `size` as well as any padding required by the CHERIoT + * capability encoding (see its ISA document for details) and any additional + * space required by the allocator's internal layout, which may be up to + * `CHERIOTHeapMinChunkSize` bytes. Not all of these padding bytes may be + * available for use via the returned capability. + * + * Blocking behaviour is controlled by the `flags` and the `timeout` parameters. * Specifically, the `flags` parameter defines on which conditions to wait, and * the `timeout` parameter how long to wait. * @@ -172,11 +186,11 @@ * checking for arithmetic overflow. Similarly to `heap_allocate`, blocking * behaviour is controlled by the `flags` and the `timeout` parameters. * - * See `heap_allocate` for more information on the blocking behavior. One - * difference between this and `heap_allocate` is the definition of when the - * allocation cannot be satisfied under any circumstances, which is here if - * `nmemb` * `size` is larger than the total heap size, or if `nmemb` * `size` - * overflows. + * See `heap_allocate` for more information on the padding and blocking + * behavior. One difference between this and `heap_allocate` is the definition + * of when the allocation cannot be satisfied under any circumstances, which is + * here if `nmemb` * `size` is larger than the total heap size, or if `nmemb` * + * `size` overflows. * * Similarly to `heap_allocate`, `-ENOTENOUGHSTACK` may be returned if the * stack is insufficiently large to run the function. See `heap_allocate`. @@ -195,9 +209,11 @@ * provided by the first argument until a corresponding call to `heap_free`. * Note that this can be used with interior pointers. * - * This will return the size of the allocation claimed on success, 0 on error - * (if `heapCapability` or `pointer` is not valid, etc.), or `-ENOTENOUGHSTACK` - * if the stack is insufficiently large to run the function. + * This will return the size of the allocation claimed on success (which may be + * larger than the size requested in the original `heap_allocate` call; see its + * documentation for more information), 0 on error (if `heapCapability` or + * `pointer` is not valid, etc.), or `-ENOTENOUGHSTACK` if the stack is + * insufficiently large to run the function. */ ssize_t __cheri_compartment("alloc") heap_claim(struct SObjStruct *heapCapability, void *pointer);