Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
general_memory_allocator.h
1/*
2 * Copyright © 2015-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include "memory/memory_region.h"
22
23#define MEMORY_REGION_STEALABLE 0
24#define MEMORY_REGION_INTERNAL 1
25#define MEMORY_REGION_EXTERNAL 2
26#define MEMORY_REGION_EXTERNAL_SMALL 3
27#define MEMORY_REGION_INTERNAL_SMALL 4
28#define NUM_MEMORY_REGIONS 5
29constexpr uint32_t RESERVED_EXTERNAL_ALLOCATOR = 0x00200000; // 2 MiB
30constexpr uint32_t RESERVED_EXTERNAL_SMALL_ALLOCATOR = 0x00020000; // 200k
31constexpr uint32_t RESERVED_INTERNAL_SMALL = 0x00010000; // 200k
32class Stealable;
33
34/*
35 * ======================= MEMORY ALLOCATION ========================
36 *
37 * The Deluge codebase uses a custom memory allocation system, largely necessitated by the fact that
38 * the Deluge’s CPU has 3MB ram, plus the Deluge has an external 64MB SDRAM IC, and both of these
39 * need to have dynamic memory allocation as part of the same system.
40 *
41 * The internal RAM on the CPU is a bit faster, so is allocated first when available.
42 * But huge blocks of data like cached Clusters of audio data from the SD card are always
43 * placed on the external RAM IC because they would overwhelm the internal RAM too quickly,
44 * preventing potentially thousands of small objects which need to be accessed all the time
45 * from being placed in that fast internal RAM.
46 *
47 * Various objects or pieces of data remain loaded (cached) in RAM even when they are no longer necessarily needed.
48 * The main example of this is audio data in Clusters, discussed above. The base class for all such
49 * objects is Stealable, and as the name suggests, their memory may usually be “stolen” when needed.
50 *
51 * Most Stealables store a “numReasonsToBeLoaded”, which counts how many “things” are requiring
52 * that object to be retained in RAM. E.g. a Cluster of audio data would have a “reason” to
53 * remain loaded in RAM if it is currently being played back. If that numReasons goes down to 0,
54 * then that Stealable object is usually free to have its memory stolen.
55 *
56 * Stealables which in fact are eligible to be stolen at a given moment are stored in a queue which
57 * prioritises stealing of the audio data which is less likely to be needed, e.g. if it belongs to a
58 * Song that’s no longer loaded. But, to avoid overcomplication, this queue is not adhered to in the
59 * case where a neighbouring region of memory is chosen for allocation (or itself being stolen) when
60 * the allocation requires that the object in question have its memory stolen too in order to make
61 * up a large enough allocation.
62 */
63
64class GeneralMemoryAllocator {
65public:
66 GeneralMemoryAllocator();
67 [[gnu::always_inline]] void* allocMaxSpeed(uint32_t requiredSize, void* thingNotToStealFrom = nullptr) {
68 return alloc(requiredSize, true, false, thingNotToStealFrom);
69 }
70
71 [[gnu::always_inline]] void* allocLowSpeed(uint32_t requiredSize, void* thingNotToStealFrom = nullptr) {
72 return alloc(requiredSize, false, false, thingNotToStealFrom);
73 }
74
75 [[gnu::always_inline]] void* allocStealable(uint32_t requiredSize, void* thingNotToStealFrom = nullptr) {
76 return alloc(requiredSize, false, true, thingNotToStealFrom);
77 }
78
79 void* alloc(uint32_t requiredSize, bool mayUseOnChipRam, bool makeStealable, void* thingNotToStealFrom);
80 void dealloc(void* address);
81 void* allocExternal(uint32_t requiredSize);
82 void* allocInternal(uint32_t requiredSize);
83 void deallocExternal(void* address);
84 uint32_t shortenRight(void* address, uint32_t newSize);
85 uint32_t shortenLeft(void* address, uint32_t amountToShorten, uint32_t numBytesToMoveRightIfSuccessful = 0);
86 void extend(void* address, uint32_t minAmountToExtend, uint32_t idealAmountToExtend,
87 uint32_t* getAmountExtendedLeft, uint32_t* getAmountExtendedRight, void* thingNotToStealFrom = nullptr);
88 uint32_t extendRightAsMuchAsEasilyPossible(void* address);
89 void test();
90 uint32_t getAllocatedSize(void* address);
91 void checkStack(char const* caller);
92 void testShorten(int32_t i);
93 int32_t getRegion(void* address);
94 void testMemoryDeallocated(void* address);
95
96 void putStealableInQueue(Stealable& stealable, StealableQueue q);
97 void putStealableInAppropriateQueue(Stealable& stealable);
98
99 MemoryRegion regions[NUM_MEMORY_REGIONS];
100 // only used for managing stealables (audio files that we could deallocate and re load from sd later if needed)
101 CacheManager cacheManager;
102 bool lock;
103
104 static GeneralMemoryAllocator& get() {
105 static GeneralMemoryAllocator generalMemoryAllocator;
106 return generalMemoryAllocator;
107 }
108
109private:
110 void checkEverythingOk(char const* errorString);
111};
112
113extern "C" {
114void* delugeAlloc(unsigned int requiredSize, bool mayUseOnChipRam = true);
115void delugeDealloc(void* address);
116}
Definition cache_manager.h:12
Definition memory_region.h:44
Definition stealable.h:25