Skip to content

Commit

Permalink
Memory management improvements (#638)
Browse files Browse the repository at this point in the history
* Improved memory full reporting to include other areas

* Simplified MemoryRegion and added more error checking, might even solve a double use bug with allocatedSize

* Made GMA API much more intentional wich different alloc functions and removed unused/dead parameters

* Fixed check for proper spacing

* Fixed memory region and tests

* Minor fixes

* Changes as done in meeting

* Removed allocStealableMaxSpeed

* alloc powers of 2 and minimum size

* alignment, padding, sorting

* update tests

* update tests and fix merge issues

* dbt format

* Move allocations into the most reasonable memory locations

* Renamed external to stealable, and nonaudio to external and made sure external allocations don't go into stealable region

* Moved params back to internal memory

* Removed v7_dma_flush_range for now

---------

Co-authored-by: m-m-adams <[email protected]>
  • Loading branch information
PaulFreund and m-m-adams authored Oct 24, 2023
1 parent c3f1d36 commit c8516f0
Show file tree
Hide file tree
Showing 56 changed files with 458 additions and 358 deletions.
14 changes: 7 additions & 7 deletions contrib/debug/heap_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,9 @@ def parse_memory_region(inferior, offset, mem_region_idx):
)

MEM_REGION_NAMES = [
"EXTERNAL",
"STEALABLE",
"INTERNAL",
"NONAUDIO",
"EXTERNAL",
]
mem_region_name = MEM_REGION_NAMES[mem_region_idx]

Expand Down Expand Up @@ -425,18 +425,18 @@ def parse_gma(inferior=gdb.inferiors()[0]):
if HEAP_START is not None:
EXTERNAL_MEMORY_START = 0x0C000000
EXTERNAL_MEMORY_END = 0x10000000
RESERVED_NONAUDIO_ALLOCATOR = 0x00100000
RESERVED_EXTERNAL_ALLOCATOR = 0x00100000

print("** External heap blocks:")
print("** Stealable heap blocks:")
parse_heap(
inferior,
EXTERNAL_MEMORY_START,
EXTERNAL_MEMORY_END - RESERVED_NONAUDIO_ALLOCATOR,
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR,
)
print("** Nonaudio heap blocks:")
print("** External heap blocks:")
parse_heap(
inferior,
EXTERNAL_MEMORY_END - RESERVED_NONAUDIO_ALLOCATOR,
EXTERNAL_MEMORY_END - RESERVED_EXTERNAL_ALLOCATOR,
EXTERNAL_MEMORY_END,
)
print("** Internal Heap blocks:")
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/deluge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ void setUIForLoadedSong(Song* song) {
}

void setupBlankSong() {
void* songMemory = GeneralMemoryAllocator::get().alloc(sizeof(Song), NULL, false, true); // TODO: error checking
void* songMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(Song)); // TODO: error checking
preLoadedSong = new (songMemory) Song();

preLoadedSong->paramManager.setupUnpatched(); // TODO: error checking
Expand Down
3 changes: 2 additions & 1 deletion src/deluge/drivers/uart/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ int32_t uartFlush(int32_t item) {
DMACn(txDmaChannels[item]).N0TB_n = num;
uint32_t dataAddress = (uint32_t)&txBuffers[item][prevReadPos];
DMACn(txDmaChannels[item]).N0SA_n = dataAddress;
v7_dma_flush_range(dataAddress, dataAddress + num);
// Paul: Removed from now as this was not present before and I am unsure if it helps with anything
// v7_dma_flush_range(dataAddress, dataAddress + num);

return 1;
}
Expand Down
3 changes: 1 addition & 2 deletions src/deluge/dsp/delay/delay_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ uint8_t DelayBuffer::init(uint32_t newRate, uint32_t failIfThisSize, bool includ
sizeIncludingExtra = size + (includeExtraSpace ? delaySpaceBetweenReadAndWrite : 0);
AudioEngine::logAction("DelayBuffer::init before");

bufferStart = (StereoSample*)GeneralMemoryAllocator::get().alloc(sizeIncludingExtra * sizeof(StereoSample), NULL,
false, true);
bufferStart = (StereoSample*)GeneralMemoryAllocator::get().allocLowSpeed(sizeIncludingExtra * sizeof(StereoSample));
AudioEngine::logAction("DelayBuffer::init after");
if (bufferStart == 0) {
return ERROR_INSUFFICIENT_RAM;
Expand Down
4 changes: 2 additions & 2 deletions src/deluge/dsp/timestretch/time_stretcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,8 +1049,8 @@ void TimeStretcher::reassessWhetherToBeFillingBuffer(int32_t phaseIncrement, int
#endif

bool TimeStretcher::allocateBuffer(int32_t numChannels) {
buffer = (int32_t*)GeneralMemoryAllocator::get().alloc(TimeStretch::kBufferSize * sizeof(int32_t) * numChannels,
NULL, false, true);
buffer =
(int32_t*)GeneralMemoryAllocator::get().allocMaxSpeed(TimeStretch::kBufferSize * sizeof(int32_t) * numChannels);
return (buffer != NULL);
}

Expand Down
2 changes: 1 addition & 1 deletion src/deluge/gui/context_menu/clear_song.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ bool ClearSong::acceptCurrentOption() {
AudioEngine::songSwapAboutToHappen();
}

void* songMemory = GeneralMemoryAllocator::get().alloc(sizeof(Song), NULL, false, true); // TODO: error checking
void* songMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(Song)); // TODO: error checking
preLoadedSong = new (songMemory) Song();
preLoadedSong->paramManager.setupUnpatched(); // TODO: error checking
GlobalEffectable::initParams(&preLoadedSong->paramManager);
Expand Down
5 changes: 2 additions & 3 deletions src/deluge/gui/ui/browser/sample_browser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,8 +1317,7 @@ bool SampleBrowser::loadAllSamplesInFolder(bool detectPitch, int32_t* getNumSamp
// If all samples were tagged with the same MIDI note, we get suspicious and delete them.
bool discardingMIDINoteFromFile = (numSamples > 1 && commonMIDINote >= 0);

Sample** sortArea =
(Sample**)GeneralMemoryAllocator::get().alloc(numSamples * sizeof(Sample*) * 2, NULL, false, true);
Sample** sortArea = (Sample**)GeneralMemoryAllocator::get().allocMaxSpeed(numSamples * sizeof(Sample*) * 2);
if (!sortArea) {
error = ERROR_INSUFFICIENT_RAM;
goto removeReasonsFromSamplesAndGetOut;
Expand Down Expand Up @@ -1919,7 +1918,7 @@ bool SampleBrowser::importFolderAsKit() {
goto getOut;
}

void* drumMemory = GeneralMemoryAllocator::get().alloc(sizeof(SoundDrum), NULL, false, true);
void* drumMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(SoundDrum));
if (!drumMemory) {
goto getOut;
}
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/gui/ui/load/load_song_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ void LoadSongUI::performLoad() {
playbackHandler.songSwapShouldPreserveTempo = Buttons::isButtonPressed(deluge::hid::button::TEMPO_ENC);
}

void* songMemory = GeneralMemoryAllocator::get().alloc(sizeof(Song), NULL, false, true);
void* songMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(Song));
if (!songMemory) {
ramError:
error = ERROR_INSUFFICIENT_RAM;
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/gui/ui/slicer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ void Slicer::doSlice() {
goto getOut;
}

void* drumMemory = GeneralMemoryAllocator::get().alloc(sizeof(SoundDrum), NULL, false, true);
void* drumMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(SoundDrum));
if (!drumMemory) {
ramError:
error = ERROR_INSUFFICIENT_RAM;
Expand Down
4 changes: 2 additions & 2 deletions src/deluge/gui/views/arranger_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@ void ArrangerView::editPadAction(int32_t x, int32_t y, bool on) {
int32_t size = (output->type == InstrumentType::AUDIO) ? sizeof(AudioClip)
: sizeof(InstrumentClip);

void* memory = GeneralMemoryAllocator::get().alloc(size, NULL, false, true);
void* memory = GeneralMemoryAllocator::get().allocMaxSpeed(size);
if (!memory) {
display->displayError(ERROR_INSUFFICIENT_RAM);
goto justGetOut;
Expand Down Expand Up @@ -2630,7 +2630,7 @@ ActionResult ArrangerView::horizontalEncoderAction(int32_t offset) {

if (offset >= 0) {
void* consMemory =
GeneralMemoryAllocator::get().alloc(sizeof(ConsequenceArrangerParamsTimeInserted));
GeneralMemoryAllocator::get().allocLowSpeed(sizeof(ConsequenceArrangerParamsTimeInserted));
if (consMemory) {
ConsequenceArrangerParamsTimeInserted* consequence = new (consMemory)
ConsequenceArrangerParamsTimeInserted(currentSong->xScroll[NAVIGATION_ARRANGEMENT],
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/gui/views/clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ ActionResult ClipView::horizontalEncoderAction(int32_t offset) {
action = actionLogger.getNewAction(ACTION_CLIP_HORIZONTAL_SHIFT, ACTION_ADDITION_NOT_ALLOWED);
if (action) {
addConsequenceToAction:
void* consMemory = GeneralMemoryAllocator::get().alloc(sizeof(ConsequenceClipHorizontalShift));
void* consMemory = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(ConsequenceClipHorizontalShift));

if (consMemory) {
ConsequenceClipHorizontalShift* newConsequence =
Expand Down
17 changes: 9 additions & 8 deletions src/deluge/gui/views/instrument_clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,8 +931,8 @@ void InstrumentClipView::copyNotes() {
int32_t numNotes = endI - startI;

if (numNotes > 0) {

void* copiedNoteRowMemory = GeneralMemoryAllocator::get().alloc(sizeof(CopiedNoteRow), NULL, true);
// Paul: Might make sense to put these into Internal?
void* copiedNoteRowMemory = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(CopiedNoteRow));
if (!copiedNoteRowMemory) {
ramError:
deleteCopiedNoteRows();
Expand All @@ -948,8 +948,8 @@ void InstrumentClipView::copyNotes() {
prevPointer = &newCopiedNoteRow->next;

// Allocate some memory for the notes
newCopiedNoteRow->notes =
(Note*)GeneralMemoryAllocator::get().alloc(sizeof(Note) * numNotes, NULL, true);
// Paul: Might make sense to put these into Internal?
newCopiedNoteRow->notes = (Note*)GeneralMemoryAllocator::get().allocLowSpeed(sizeof(Note) * numNotes);

if (!newCopiedNoteRow->notes) {
goto ramError;
Expand Down Expand Up @@ -1152,7 +1152,7 @@ void InstrumentClipView::doubleClipLengthAction() {
// Add the ConsequenceClipMultiply to the Action. This must happen before calling doubleClipLength(), which may add note changes and deletions,
// because when redoing, those have to happen after (and they'll have no effect at all, but who cares)
if (action) {
void* consMemory = GeneralMemoryAllocator::get().alloc(sizeof(ConsequenceInstrumentClipMultiply));
void* consMemory = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(ConsequenceInstrumentClipMultiply));

if (consMemory) {
ConsequenceInstrumentClipMultiply* newConsequence = new (consMemory) ConsequenceInstrumentClipMultiply();
Expand Down Expand Up @@ -3397,7 +3397,7 @@ void InstrumentClipView::enterDrumCreator(ModelStackWithNoteRow* modelStack, boo
return;
}

void* memory = GeneralMemoryAllocator::get().alloc(sizeof(SoundDrum), NULL, false, true);
void* memory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(SoundDrum));
if (!memory) {
error = ERROR_INSUFFICIENT_RAM;
goto doDisplayError;
Expand Down Expand Up @@ -5416,7 +5416,8 @@ void InstrumentClipView::rotateNoteRowHorizontally(ModelStackWithNoteRow* modelS
action = actionLogger.getNewAction(ACTION_NOTEROW_HORIZONTAL_SHIFT, ACTION_ADDITION_NOT_ALLOWED);
if (action) {
addConsequenceToAction:
void* consMemory = GeneralMemoryAllocator::get().alloc(sizeof(ConsequenceNoteRowHorizontalShift));
void* consMemory =
GeneralMemoryAllocator::get().allocLowSpeed(sizeof(ConsequenceNoteRowHorizontalShift));

if (consMemory) {
ConsequenceNoteRowHorizontalShift* newConsequence =
Expand Down Expand Up @@ -5532,7 +5533,7 @@ void InstrumentClipView::editNoteRowLength(ModelStackWithNoteRow* modelStack, in
return;
}

void* consMemory = GeneralMemoryAllocator::get().alloc(sizeof(ConsequenceNoteRowLength));
void* consMemory = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(ConsequenceNoteRowLength));
if (!consMemory) {
goto ramError;
}
Expand Down
6 changes: 3 additions & 3 deletions src/deluge/gui/views/session_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,7 @@ static float lastColour = 192 - colourStep + 1;
Clip* SessionView::createNewInstrumentClip(int32_t yDisplay) {
actionLogger.deleteAllLogs();

void* memory = GeneralMemoryAllocator::get().alloc(sizeof(InstrumentClip), NULL, false, true);
void* memory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(InstrumentClip));
if (memory == nullptr) {
display->displayError(ERROR_INSUFFICIENT_RAM);
return nullptr;
Expand Down Expand Up @@ -1621,7 +1621,7 @@ void SessionView::replaceAudioClipWithInstrumentClip(Clip* clip, InstrumentType
}

// Allocate memory for InstrumentClip
void* clipMemory = GeneralMemoryAllocator::get().alloc(sizeof(InstrumentClip), NULL, false, true);
void* clipMemory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(InstrumentClip));
if (!clipMemory) {
ramError:
display->displayError(ERROR_INSUFFICIENT_RAM);
Expand Down Expand Up @@ -3234,7 +3234,7 @@ bool SessionView::gridCreateNewTrackForClip(InstrumentType type, InstrumentClip*

InstrumentClip* SessionView::gridCreateClipWithNewTrack(InstrumentType type) {
// Allocate new clip
void* memory = GeneralMemoryAllocator::get().alloc(sizeof(InstrumentClip), NULL, false, true);
void* memory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(InstrumentClip));
if (!memory) {
display->displayError(ERROR_INSUFFICIENT_RAM);
return nullptr;
Expand Down
12 changes: 8 additions & 4 deletions src/deluge/hid/display/seven_segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ void SevenSegment::removeTopLayer() {
void SevenSegment::setText(std::string_view newText, bool alignRight, uint8_t drawDot, bool doBlink,
uint8_t* newBlinkMask, bool blinkImmediately, bool shouldBlinkFast, int32_t scrollPos,
uint8_t* encodedAddition, bool justReplaceBottomLayer) {
void* layerSpace = GeneralMemoryAllocator::get().alloc(sizeof(NumericLayerBasicText));
// Paul: Render time could be lower putting this into internal
void* layerSpace = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(NumericLayerBasicText));
if (!layerSpace) {
return;
}
Expand Down Expand Up @@ -147,7 +148,8 @@ void SevenSegment::setText(std::string_view newText, bool alignRight, uint8_t dr

NumericLayerScrollingText* SevenSegment::setScrollingText(char const* newText, int32_t startAtTextPos,
int32_t initialDelay) {
void* layerSpace = GeneralMemoryAllocator::get().alloc(sizeof(NumericLayerScrollingText));
// Paul: Render time could be lower putting this into internal
void* layerSpace = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(NumericLayerScrollingText));
if (!layerSpace) {
return NULL;
}
Expand Down Expand Up @@ -195,7 +197,8 @@ void SevenSegment::transitionToNewLayer(NumericLayer* newLayer) {
// If transition...
if (!popupActive && nextTransitionDirection != 0 && topLayer != NULL) {

void* layerSpace = GeneralMemoryAllocator::get().alloc(sizeof(NumericLayerScrollTransition));
// Paul: Render time could be lower putting this into internal
void* layerSpace = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(NumericLayerScrollTransition));

if (layerSpace) {
scrollTransition = new (layerSpace) NumericLayerScrollTransition();
Expand Down Expand Up @@ -541,7 +544,8 @@ void SevenSegment::render() {

// Call this to make the loading animation happen
void SevenSegment::displayLoadingAnimation(bool delayed, bool transparent) {
void* layerSpace = GeneralMemoryAllocator::get().alloc(sizeof(NumericLayerLoadingAnimation));
// Paul: Render time could be lower putting this into internal
void* layerSpace = GeneralMemoryAllocator::get().allocLowSpeed(sizeof(NumericLayerLoadingAnimation));
if (!layerSpace) {
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/deluge/hid/hid_sysex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ void HIDSysex::requestOLEDDisplay(MIDIDevice* device, uint8_t* data, int32_t len
}

if (oledDeltaImage == nullptr) {
oledDeltaImage = (uint8_t*)GeneralMemoryAllocator::get().alloc(
sizeof(uint8_t[OLED_MAIN_HEIGHT_PIXELS >> 3][OLED_MAIN_WIDTH_PIXELS]), NULL, false, true);
oledDeltaImage = (uint8_t*)GeneralMemoryAllocator::get().allocMaxSpeed(
sizeof(uint8_t[OLED_MAIN_HEIGHT_PIXELS >> 3][OLED_MAIN_WIDTH_PIXELS]));
}
}
sendDisplayIfChanged();
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/io/debug/sysex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static void firstPacket(uint8_t* data, int32_t len) {
}
load_bufsize = load_codesize + (511 - ((load_codesize - 1) & 511));

load_buf = (uint8_t*)GeneralMemoryAllocator::get().alloc(load_bufsize, NULL, false, true);
load_buf = (uint8_t*)GeneralMemoryAllocator::get().allocMaxSpeed(load_bufsize);
if (load_buf == nullptr) {
// fail :(
return;
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/io/midi/midi_device_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ MIDIDeviceUSBHosted* getOrCreateHostedMIDIDeviceFromDetails(String* name, uint16
return NULL;
}

void* memory = GeneralMemoryAllocator::get().alloc(sizeof(MIDIDeviceUSBHosted), NULL, false, true);
void* memory = GeneralMemoryAllocator::get().allocMaxSpeed(sizeof(MIDIDeviceUSBHosted));
if (!memory) {
return NULL;
}
Expand Down
4 changes: 2 additions & 2 deletions src/deluge/memory/fallback_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class fallback_allocator {
if (n == 0) {
return nullptr;
}
return static_cast<T*>(GeneralMemoryAllocator::get().allocNonAudio(n * sizeof(T)));
return static_cast<T*>(GeneralMemoryAllocator::get().allocExternal(n * sizeof(T)));
}

void deallocate(T* p, std::size_t n) { delugeDeallocNonAudio(p); }
void deallocate(T* p, std::size_t n) { delugeDeallocExternal(p); }

template <typename U>
bool operator==(const deluge::memory::fallback_allocator<U>& o) {
Expand Down
Loading

0 comments on commit c8516f0

Please sign in to comment.