[nostalgia/core/gba] Add test for malloc and unify panic systems

This commit is contained in:
Gary Talent 2020-02-11 21:17:10 -06:00
parent ea14ccac3a
commit fffc66f18b
6 changed files with 141 additions and 67 deletions

View File

@ -1,23 +1,35 @@
add_library(
NostalgiaCore-GBA
core.cpp
gfx.cpp
media.cpp
mem.cpp
panic.cpp
)
target_link_libraries(
NostalgiaCore-GBA PUBLIC
NostalgiaCore
GbaStartup
OxFS
OxStd
)
install(
TARGETS
if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
add_library(
NostalgiaCore-GBA
DESTINATION
include/nostalgia/core
)
core.cpp
gfx.cpp
media.cpp
mem.cpp
panic.cpp
)
target_link_libraries(
NostalgiaCore-GBA PUBLIC
NostalgiaCore
GbaStartup
OxFS
OxStd
)
install(
TARGETS
NostalgiaCore-GBA
DESTINATION
include/nostalgia/core
)
endif()
# tests
if(NOSTALGIA_BUILD_TYPE STREQUAL "Native")
add_executable(NostalgiaCore-GBA_Test
tests.cpp
mem.cpp
)
target_link_libraries(NostalgiaCore-GBA_Test NostalgiaCore)
add_test("NostalgiaCore-GBA\\ Test\\ malloc" NostalgiaCore-GBA_Test malloc)
endif()

View File

@ -14,7 +14,6 @@
#include <nostalgia/core/gfx.hpp>
#include "addresses.hpp"
#include "panic.hpp"
namespace nostalgia::core {
@ -102,7 +101,7 @@ ox::Error shutdownGfx() {
case 3:
return REG_BG3CNT;
default:
panic("Looking up non-existent register");
oxPanic("Looking up non-existent register", OxError(1));
return REG_BG0CNT;
}
}

View File

@ -7,11 +7,9 @@
*/
#include "addresses.hpp"
#include "ox/std/bit.hpp"
#include "ox/std/types.hpp"
#include "panic.hpp"
#include <ox/std/std.hpp>
#include <ox/std/assert.hpp>
#include <ox/std/bit.hpp>
// this warning is too dumb to realize that it can actually confirm the hard
// coded address aligns with the requirement of HeapSegment, so it must be
@ -25,6 +23,10 @@
namespace nostalgia::core {
static class HeapSegment *volatile g_heapBegin = nullptr;
static class HeapSegment *volatile g_heapEnd = nullptr;
static class HeapSegment *volatile heapIdx = nullptr;
static constexpr std::size_t alignedSize(std::size_t sz) {
return sz + (sz & 7);
}
@ -38,39 +40,35 @@ struct HeapSegment {
std::size_t size;
uint8_t inUse;
void init(std::size_t maxSize = ox::bit_cast<std::size_t>(HEAP_END)) {
this->size = maxSize - reinterpret_cast<std::size_t>(this);
void init(std::size_t maxSize = ox::bit_cast<std::size_t>(g_heapEnd)) {
this->size = maxSize - ox::bit_cast<std::size_t>(this);
this->inUse = false;
}
template<typename T>
T *data() {
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(this) + alignedSize(this));
return ox::bit_cast<T*>(ox::bit_cast<uint8_t*>(this) + alignedSize(this));
}
template<typename T = uint8_t>
T *end() {
const auto size = alignedSize(this) + alignedSize(this->size);
auto e = reinterpret_cast<uintptr_t>(reinterpret_cast<uint8_t*>(this) + size);
return reinterpret_cast<T*>(e);
auto e = ox::bit_cast<uintptr_t>(ox::bit_cast<uint8_t*>(this) + size);
return ox::bit_cast<T*>(e);
}
};
static HeapSegment *volatile heapIdx = nullptr;
void initHeap() {
heapIdx = HEAP_BEGIN;
heapIdx->init();
void initHeap(char *heapBegin, char *heapEnd) {
g_heapBegin = ox::bit_cast<HeapSegment*>(heapBegin);
g_heapEnd = ox::bit_cast<HeapSegment*>(heapEnd);
heapIdx = g_heapBegin;
heapIdx->size = ox::bit_cast<std::size_t>(heapEnd) - ox::bit_cast<std::size_t>(heapIdx);
heapIdx->inUse = false;
}
static HeapSegment *findSegmentFor(std::size_t sz) {
for (auto s = HEAP_BEGIN; s + sz < HEAP_END; s = s->end<HeapSegment>()) {
if (s->size >= sz && !s->inUse) {
return s;
}
}
return nullptr;
void initHeap() {
initHeap(ox::bit_cast<char*>(HEAP_BEGIN), ox::bit_cast<char*>(HEAP_END));
}
struct SegmentPair {
@ -90,6 +88,16 @@ static SegmentPair findSegmentOf(void *ptr) {
return {};
}
static HeapSegment *findSegmentFor(std::size_t sz) {
for (auto s = g_heapBegin; s <= g_heapEnd; s = s->end<HeapSegment>()) {
if (s->size >= sz && !s->inUse) {
return s;
}
}
oxPanic("malloc: could not find segment", OxError(1));
return nullptr;
}
[[nodiscard]] void *malloc(std::size_t allocSize) {
const auto targetSize = alignedSize(sizeof(HeapSegment)) + alignedSize(allocSize);
auto seg = findSegmentFor(targetSize);
@ -99,9 +107,8 @@ static SegmentPair findSegmentOf(void *ptr) {
const auto bytesRemaining = seg->size - targetSize;
seg->size = targetSize;
seg->inUse = true;
auto out = seg->data<void>();
seg->end<HeapSegment>()->init(bytesRemaining);
return out;
return seg->data<void>();
}
void free(void *ptr) {
@ -111,12 +118,14 @@ void free(void *ptr) {
} else if (p.segment) {
p.segment->inUse = false;
} else {
panic("Bad heap free");
oxPanic("Bad heap free", OxError(1));
}
}
}
#ifndef OX_USE_STDLIB
using namespace nostalgia;
void *operator new(std::size_t allocSize) {
@ -142,3 +151,13 @@ void operator delete(void *ptr, unsigned) {
void operator delete[](void *ptr, unsigned) {
core::free(ptr);
}
void operator delete(void *ptr, unsigned long int) {
core::free(ptr);
}
void operator delete[](void *ptr, unsigned long int) {
core::free(ptr);
}
#endif

View File

@ -7,15 +7,21 @@
*/
#include "../core.hpp"
#include "panic.hpp"
#include "../gfx.hpp"
namespace nostalgia::core {
namespace ox {
void panic(const char *msg) {
using namespace nostalgia::core;
void panic(const char*, int, const char *msg, ox::Error err) {
oxIgnoreError(initGfx(nullptr));
oxIgnoreError(initConsole(nullptr));
ox::BString<23> serr = "Error code: ";
serr += err;
puts(nullptr, 32 + 0, 1, "SADNESS...");
puts(nullptr, 32 + 0, 4, "UNEXPECTED STATE:");
puts(nullptr, 32 + 2, 6, msg);
puts(nullptr, 32 + 2, 7, serr.c_str());
puts(nullptr, 32 + 0, 10, "PLEASE RESTART THE SYSTEM");
// TODO: properly end program execution, this wastes power
while (1);

View File

@ -1,16 +0,0 @@
/*
* Copyright 2016 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace nostalgia::core {
void panic(const char *msg);
}

View File

@ -0,0 +1,54 @@
#include <map>
#include <string>
#include <vector>
#include <ox/std/std.hpp>
#include <nostalgia/core/mem.hpp>
namespace nostalgia::core {
[[nodiscard]] void *malloc(std::size_t allocSize);
void free(void *ptr);
void panic(const char *msg) {
oxPanic(msg, OxError(1));
}
void initHeap(char *heapBegin, char *heapEnd);
}
using namespace nostalgia;
int testMalloc(std::string) {
std::vector<char> buff(ox::units::MB);
core::initHeap(&buff.front(), &buff.back());
oxAssert(core::malloc(5) != nullptr, "malloc is broken");
oxAssert(core::malloc(5) != nullptr, "malloc is broken");
return 0;
}
std::map<std::string, int(*)(std::string)> tests = {
{
{ "malloc", testMalloc },
}
};
int main(int argc, const char **args) {
int retval = -1;
if (argc > 1) {
auto testName = args[1];
std::string testArg = "";
if (args[2]) {
testArg = args[2];
}
if (tests.find(testName) != tests.end()) {
retval = tests[testName](testArg);
}
}
return retval;
}