Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+79 -4
+41 -4
firmware/buflib.c
··· 102 102 #define PARANOIA_CHECK_HANDLE (1 << 1) 103 103 #define PARANOIA_CHECK_BLOCK_HANDLE (1 << 2) 104 104 #define PARANOIA_CHECK_CRC (1 << 3) 105 + #define PARANOIA_CHECK_PINNING (1 << 4) 105 106 /* Bitmask of enabled paranoia checks */ 106 107 #define BUFLIB_PARANOIA \ 107 108 (PARANOIA_CHECK_LENGTH | PARANOIA_CHECK_HANDLE | \ 108 - PARANOIA_CHECK_BLOCK_HANDLE | PARANOIA_CHECK_CRC) 109 + PARANOIA_CHECK_BLOCK_HANDLE | PARANOIA_CHECK_CRC | \ 110 + PARANOIA_CHECK_PINNING) 109 111 110 112 #if BUFLIB_PARANOIA & PARANOIA_CHECK_CRC 111 113 # define BUFLIB_HAS_CRC ··· 122 124 /* Backward indices, used to index a block end pointer as block[-bidx_XXX] */ 123 125 enum { 124 126 bidx_USER, /* dummy to get below fields to be 1-based */ 127 + bidx_PIN, /* pin count */ 125 128 #ifdef BUFLIB_HAS_CRC 126 129 bidx_CRC, /* CRC, protects all metadata behind it */ 127 130 #endif ··· 132 135 * accounted for using the BSIZE field. Note that bidx_USER is not an 133 136 * actual field so it is not included in the count. */ 134 137 #ifdef BUFLIB_HAS_CRC 135 - # define BUFLIB_NUM_FIELDS 5 138 + # define BUFLIB_NUM_FIELDS 6 136 139 #else 137 - # define BUFLIB_NUM_FIELDS 4 140 + # define BUFLIB_NUM_FIELDS 5 138 141 #endif 139 142 140 143 struct buflib_callbacks buflib_ops_locked = { ··· 394 397 union buflib_data *block_end = h_entry_to_block_end(ctx, h_entry); 395 398 check_block_crc(ctx, block, block_end); 396 399 397 - if (!IS_MOVABLE(block)) 400 + if (!IS_MOVABLE(block) || block_end[-bidx_PIN].pincount > 0) 398 401 return false; 399 402 400 403 int handle = ctx->handle_table - h_entry; ··· 751 754 752 755 size_t bsize = BUFLIB_NUM_FIELDS + name_len/sizeof(union buflib_data); 753 756 union buflib_data *block_end = block + bsize; 757 + block_end[-bidx_PIN].pincount = 0; 754 758 block_end[-bidx_BSIZE].val = bsize; 755 759 update_block_crc(ctx, block, block_end); 756 760 ··· 1048 1052 } 1049 1053 1050 1054 return true; 1055 + } 1056 + 1057 + void buflib_pin(struct buflib_context *ctx, int handle) 1058 + { 1059 + if ((BUFLIB_PARANOIA & PARANOIA_CHECK_PINNING) && handle <= 0) 1060 + buflib_panic(ctx, "invalid handle pin: %d", handle); 1061 + 1062 + union buflib_data *data = handle_to_block_end(ctx, handle); 1063 + data[-bidx_PIN].pincount++; 1064 + } 1065 + 1066 + void buflib_unpin(struct buflib_context *ctx, int handle) 1067 + { 1068 + if ((BUFLIB_PARANOIA & PARANOIA_CHECK_PINNING) && handle <= 0) 1069 + buflib_panic(ctx, "invalid handle unpin: %d", handle); 1070 + 1071 + union buflib_data *data = handle_to_block_end(ctx, handle); 1072 + if (BUFLIB_PARANOIA & PARANOIA_CHECK_PINNING) 1073 + { 1074 + if (data[-bidx_PIN].pincount == 0) 1075 + buflib_panic(ctx, "handle pin underflow: %d", handle); 1076 + } 1077 + 1078 + data[-bidx_PIN].pincount--; 1079 + } 1080 + 1081 + unsigned buflib_pin_count(struct buflib_context *ctx, int handle) 1082 + { 1083 + if ((BUFLIB_PARANOIA & PARANOIA_CHECK_PINNING) && handle <= 0) 1084 + buflib_panic(ctx, "invalid handle: %d", handle); 1085 + 1086 + union buflib_data *data = handle_to_block_end(ctx, handle); 1087 + return data[-bidx_PIN].pincount; 1051 1088 } 1052 1089 1053 1090 const char* buflib_get_name(struct buflib_context *ctx, int handle)
+15
firmware/core_alloc.c
··· 104 104 return buflib_shrink(&core_ctx, handle, new_start, new_size); 105 105 } 106 106 107 + void core_pin(int handle) 108 + { 109 + buflib_pin(&core_ctx, handle); 110 + } 111 + 112 + void core_unpin(int handle) 113 + { 114 + buflib_unpin(&core_ctx, handle); 115 + } 116 + 117 + unsigned core_pin_count(int handle) 118 + { 119 + return buflib_pin_count(&core_ctx, handle); 120 + } 121 + 107 122 const char* core_get_name(int handle) 108 123 { 109 124 const char *name = buflib_get_name(&core_ctx, handle);
+20
firmware/include/buflib.h
··· 38 38 intptr_t val; /* length of the block in n*sizeof(union buflib_data). 39 39 Includes buflib metadata overhead. A negative value 40 40 indicates block is unallocated */ 41 + volatile unsigned pincount; /* number of pins */ 41 42 struct buflib_callbacks* ops; /* callback functions for move and shrink. Can be NULL */ 42 43 char* alloc; /* start of allocated memory area */ 43 44 union buflib_data *handle; /* pointer to entry in the handle table. ··· 290 291 * 291 292 */ 292 293 bool buflib_shrink(struct buflib_context *ctx, int handle, void* newstart, size_t new_size); 294 + 295 + /** 296 + * Increment the pin count for a handle. When pinned the handle will not 297 + * be moved and move callbacks will not be triggered, allowing a pointer 298 + * to the buffer to be kept across yields or used for I/O. 299 + * 300 + * Note that shrink callbacks can still be invoked for pinned handles. 301 + */ 302 + void buflib_pin(struct buflib_context *ctx, int handle); 303 + 304 + /** 305 + * Decrement the pin count for a handle. 306 + */ 307 + void buflib_unpin(struct buflib_context *ctx, int handle); 308 + 309 + /** 310 + * Get the current pin count of a handle. Zero means the handle is not pinned. 311 + */ 312 + unsigned buflib_pin_count(struct buflib_context *ctx, int handle); 293 313 294 314 /** 295 315 * Frees memory associated with the given handle
+3
firmware/include/core_alloc.h
··· 14 14 int core_alloc_ex(const char* name, size_t size, struct buflib_callbacks *ops); 15 15 int core_alloc_maximum(const char* name, size_t *size, struct buflib_callbacks *ops); 16 16 bool core_shrink(int handle, void* new_start, size_t new_size); 17 + void core_pin(int handle); 18 + void core_unpin(int handle); 19 + unsigned core_pin_count(int handle); 17 20 int core_free(int handle); 18 21 size_t core_available(void); 19 22 size_t core_allocatable(void);