fix: Add framebuffer release/realloc and improved lazy indexing (#2563)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#include "BuildScratch.h"
|
||||
|
||||
#include <Logging.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace buildscratch {
|
||||
namespace {
|
||||
uint8_t* block = nullptr;
|
||||
size_t blockLen = 0;
|
||||
// atomic exchange so an opportunistic claim from another task can never
|
||||
// double-hand-out the block (single core, but FreeRTOS preempts).
|
||||
std::atomic<bool> claimed{false};
|
||||
} // namespace
|
||||
|
||||
void lend(uint8_t* buf, const size_t len) {
|
||||
if (block) {
|
||||
LOG_ERR("SCR", "Build scratch lent twice; ignoring second lend");
|
||||
return;
|
||||
}
|
||||
block = buf;
|
||||
blockLen = len;
|
||||
claimed.store(false);
|
||||
}
|
||||
|
||||
void reclaim() {
|
||||
if (claimed.load()) {
|
||||
// A consumer still holds the block. The storage stays valid (it is the
|
||||
// framebuffer allocation, never freed) but its contents are about to be
|
||||
// clobbered; the consumer's output will be garbage. Loud log so a
|
||||
// lifetime bug is visible instead of a silent corrupt decode.
|
||||
LOG_ERR("SCR", "Build scratch reclaimed while still claimed");
|
||||
}
|
||||
block = nullptr;
|
||||
blockLen = 0;
|
||||
claimed.store(false);
|
||||
}
|
||||
|
||||
uint8_t* claim(const size_t minLen, size_t* lenOut) {
|
||||
if (!block || blockLen < minLen) return nullptr;
|
||||
bool expected = false;
|
||||
if (!claimed.compare_exchange_strong(expected, true)) return nullptr;
|
||||
if (lenOut) *lenOut = blockLen;
|
||||
return block;
|
||||
}
|
||||
|
||||
void release(const uint8_t* p) {
|
||||
if (p && p == block) claimed.store(false);
|
||||
}
|
||||
|
||||
} // namespace buildscratch
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
// Registry for the framebuffer bytes lent out during a build phase
|
||||
// (GfxRenderer::FrameBufferLoan). The lender (GfxRenderer) deposits the block
|
||||
// with lend()/reclaim(); a memory-hungry consumer (e.g. InflateStream's ~43KB
|
||||
// tinfl state + window) may claim() it instead of allocating from the heap.
|
||||
//
|
||||
// Exactly one claimant at a time; claim() returns nullptr when the block is
|
||||
// absent or already claimed, and consumers must fall back to the heap. The
|
||||
// underlying storage is the framebuffer allocation itself, which is never
|
||||
// freed -- so even the pathological case (reclaim() while still claimed, which
|
||||
// logs an error) reads garbage, never freed memory.
|
||||
namespace buildscratch {
|
||||
|
||||
// Lender side (GfxRenderer only).
|
||||
void lend(uint8_t* buf, size_t len);
|
||||
void reclaim();
|
||||
|
||||
// Consumer side: exclusive claim of the whole block if it is at least minLen
|
||||
// bytes; nullptr means "use the heap". Release with the same pointer.
|
||||
uint8_t* claim(size_t minLen, size_t* lenOut = nullptr);
|
||||
void release(const uint8_t* p);
|
||||
|
||||
} // namespace buildscratch
|
||||
Reference in New Issue
Block a user