From f47aa584a8b447d8225fc5b09afb2d1fe6764c1d Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 3 Apr 2022 10:48:14 +0100 Subject: buflib: add pin/unpin operation An allocation is pinned by calling buflib_pin() to up its pin count. The pin count is like a reference count: when above 0, buflib won't move the allocation and won't call its move callbacks. This makes it safe to hold the pointer returned by buflib_get_data() across yields or allocations. Note that pinned allocations can still shrink because there are some use cases where this would be valid, if buffer users coordinate with the shrink callback. Change-Id: I0d0c2a8ac7d891d3ad6b3d0eb80c5b5a1b4b9a9d --- firmware/include/buflib.h | 20 ++++++++++++++++++++ firmware/include/core_alloc.h | 3 +++ 2 files changed, 23 insertions(+) (limited to 'firmware/include') diff --git a/firmware/include/buflib.h b/firmware/include/buflib.h index 45446c3b86..d2231ab79d 100644 --- a/firmware/include/buflib.h +++ b/firmware/include/buflib.h @@ -38,6 +38,7 @@ union buflib_data intptr_t val; /* length of the block in n*sizeof(union buflib_data). Includes buflib metadata overhead. A negative value indicates block is unallocated */ + volatile unsigned pincount; /* number of pins */ struct buflib_callbacks* ops; /* callback functions for move and shrink. Can be NULL */ char* alloc; /* start of allocated memory area */ union buflib_data *handle; /* pointer to entry in the handle table. @@ -291,6 +292,25 @@ static inline void* buflib_get_data(struct buflib_context *ctx, int handle) */ bool buflib_shrink(struct buflib_context *ctx, int handle, void* newstart, size_t new_size); +/** + * Increment the pin count for a handle. When pinned the handle will not + * be moved and move callbacks will not be triggered, allowing a pointer + * to the buffer to be kept across yields or used for I/O. + * + * Note that shrink callbacks can still be invoked for pinned handles. + */ +void buflib_pin(struct buflib_context *ctx, int handle); + +/** + * Decrement the pin count for a handle. + */ +void buflib_unpin(struct buflib_context *ctx, int handle); + +/** + * Get the current pin count of a handle. Zero means the handle is not pinned. + */ +unsigned buflib_pin_count(struct buflib_context *ctx, int handle); + /** * Frees memory associated with the given handle * diff --git a/firmware/include/core_alloc.h b/firmware/include/core_alloc.h index f535fc1f6e..87246bcbd6 100644 --- a/firmware/include/core_alloc.h +++ b/firmware/include/core_alloc.h @@ -14,6 +14,9 @@ int core_alloc(const char* name, size_t size); int core_alloc_ex(const char* name, size_t size, struct buflib_callbacks *ops); int core_alloc_maximum(const char* name, size_t *size, struct buflib_callbacks *ops); bool core_shrink(int handle, void* new_start, size_t new_size); +void core_pin(int handle); +void core_unpin(int handle); +unsigned core_pin_count(int handle); int core_free(int handle); size_t core_available(void); size_t core_allocatable(void); -- cgit v1.2.3