summaryrefslogtreecommitdiff
path: root/src/boot/libu64/stackcheck.c
diff options
context:
space:
mode:
authorDragorn421 <Dragorn421@users.noreply.github.com>2024-11-08 02:27:19 +0100
committerGitHub <noreply@github.com>2024-11-07 17:27:19 -0800
commitfcc5cf828ded5d362b2e63a8868374a50df405ed (patch)
tree530d7d6d8690599593f6588b04d10441e364b5c7 /src/boot/libu64/stackcheck.c
parent9cd9099a0431b369be39f111bf57051f544bead3 (diff)
libu64 (#1705)
* libu64 * libu64 -O2 * Add libu64.md
Diffstat (limited to 'src/boot/libu64/stackcheck.c')
-rw-r--r--src/boot/libu64/stackcheck.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/boot/libu64/stackcheck.c b/src/boot/libu64/stackcheck.c
new file mode 100644
index 000000000..de321bddd
--- /dev/null
+++ b/src/boot/libu64/stackcheck.c
@@ -0,0 +1,122 @@
+#include "libu64/stackcheck.h"
+#include "stdbool.h"
+#include "stdint.h"
+
+StackEntry* sStackInfoListStart = NULL;
+StackEntry* sStackInfoListEnd = NULL;
+
+void StackCheck_Init(StackEntry* entry, void* stackBottom, void* stackTop, u32 initValue, s32 minSpace,
+ const char* name) {
+ if (entry == NULL) {
+ sStackInfoListStart = NULL;
+ } else {
+ StackEntry* iter;
+
+ entry->head = stackBottom;
+ entry->tail = stackTop;
+ entry->initValue = initValue;
+ entry->minSpace = minSpace;
+ entry->name = name;
+ iter = sStackInfoListStart;
+ while (iter) {
+ if (iter == entry) {
+ return;
+ }
+ iter = iter->next;
+ }
+
+ entry->prev = sStackInfoListEnd;
+ entry->next = NULL;
+
+ if (sStackInfoListEnd) {
+ sStackInfoListEnd->next = entry;
+ }
+
+ sStackInfoListEnd = entry;
+ if (sStackInfoListStart == NULL) {
+ sStackInfoListStart = entry;
+ }
+
+ if (entry->minSpace != -1) {
+ u32* addr = entry->head;
+
+ while (addr < (u32*)entry->tail) {
+ *addr++ = entry->initValue;
+ }
+ }
+ }
+}
+
+void StackCheck_Cleanup(StackEntry* entry) {
+ u32 inconsistency = false;
+
+ if (entry->prev == NULL) {
+ if (entry == sStackInfoListStart) {
+ sStackInfoListStart = entry->next;
+ } else {
+ inconsistency = true;
+ }
+ } else {
+ entry->prev->next = entry->next;
+ }
+
+ if (!entry->next) {
+ if (entry == sStackInfoListEnd) {
+ sStackInfoListEnd = entry->prev;
+ } else {
+ inconsistency = true;
+ }
+ }
+
+ if (inconsistency) {}
+}
+
+StackStatus StackCheck_GetState(StackEntry* entry) {
+ u32* last;
+ size_t used;
+ size_t free;
+ StackStatus status;
+
+ for (last = entry->head; last < (u32*)entry->tail; last++) {
+ if (entry->initValue != *last) {
+ break;
+ }
+ }
+
+ used = (uintptr_t)entry->tail - (uintptr_t)last;
+ free = (uintptr_t)last - (uintptr_t)entry->head;
+
+ if (free == 0) {
+ status = STACK_STATUS_OVERFLOW;
+ } else if ((free < (size_t)entry->minSpace) && (entry->minSpace != -1)) {
+ status = STACK_STATUS_WARNING;
+ } else {
+ status = STACK_STATUS_OK;
+ }
+
+ return status;
+}
+
+u32 StackCheck_CheckAll(void) {
+ u32 ret = 0;
+ StackEntry* iter = sStackInfoListStart;
+
+ while (iter != NULL) {
+ StackStatus state = StackCheck_GetState(iter);
+
+ if (state != STACK_STATUS_OK) {
+ ret = 1;
+ }
+ iter = iter->next;
+ }
+
+ return ret;
+}
+
+u32 StackCheck_Check(StackEntry* entry) {
+ if (entry == NULL) {
+ return StackCheck_CheckAll();
+ } else {
+ return StackCheck_GetState(entry);
+ }
+}