diff --git a/BAN/Makefile b/BAN/Makefile new file mode 100644 index 00000000..2fe06d79 --- /dev/null +++ b/BAN/Makefile @@ -0,0 +1,86 @@ +DEFAULT_HOST!=../default-host.sh +HOST?=DEFAULT_HOST +HOSTARCH!=../target-triplet-to-arch.sh $(HOST) + +CFLAGS?=-O2 -g +CPPFLAGS?= +LDFLAGS?= +LIBS?= + +DESTDIR?= +PREFIX?=/usr/local +EXEC_PREFIX?=$(PREFIX) +INCLUDEDIR?=$(PREFIX)/include +LIBDIR?=$(EXEC_PREFIX)/lib + +CFLAGS:=$(CFLAGS) -D__is_ban -Iinclude -ffreestanding -Wall -Wextra +CPPFLAGS:=$(CPPFLAGS) +LIBK_CFLAGS:=$(CFLAGS) -D__is_bank +LIBK_CPPFLAGS:=$(CPPFLAGS) + +ARCHDIR=arch/$(HOSTARCH) + +include $(ARCHDIR)/make.config + +CFLAGS:=$(CFLAGS) $(ARCH_CFLAGS) +CPPFLAGS:=$(CPPFLAGS) $(ARCH_CPPFLAGS) +BANK_CFLAGS:=$(BANK_CFLAGS) $(KERNEL_ARCH_CFLAGS) +BANK_CPPFLAGS:=$(BANK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS) + +BUILDDIR=$(abspath build) + +FREEOBJS=\ +$(ARCH_FREEOBJS) \ + +HOSTEDOBJS=\ +$(ARCH_HOSTEDOBJS) \ + +OBJS=\ +$(FREEOBJS) \ +$(HOSTEDOBJS) \ + +BANK_OBJS=$(FREEOBJS:.o=.bank.o) + +BINARIES=bank.a + +.PHONY: all always clean install install-headers install-libs +.SUFFIXES: .o .bank.o .cpp .S + +all: $(BINARIES) + +ban.a: always $(OBJS) + cd $(BUILDDIR) && $(AR) rcs $@ $(OBJS) + +bank.a: always $(LIBK_OBJS) + cd $(BUILDDIR) && $(AR) rcs $@ $(LIBK_OBJS) + +.cpp.o: + $(CXX) -MD -c $< -o $(BUILDDIR)/$@ $(CFLAGS) $(CPPFLAGS) + +.S.o: + $(CXX) -MD -c $< -o $(BUILDDIR)/$@ $(CFLAGS) $(CPPFLAGS) + +.cpp.bank.o: + $(CXX) -MD -c $< -o $(BUILDDIR)/$@ $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) + +.S.bank.o: + $(CXX) -MD -c $< -o $(BUILDDIR)/$@ $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) + +clean: + rm -rf $(BUILDDIR) + +always: + mkdir -p $(BUILDDIR) + +install: install-headers install-libs + +install-headers: + mkdir -p $(DESTDIR)$(INCLUDEDIR) + cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/. + +install-libs: $(BINARIES) + mkdir -p $(DESTDIR)$(LIBDIR) + cp $(BUILDDIR)/$(BINARIES) $(DESTDIR)$(LIBDIR) + +-include $(OBJS:.o=.d) +-include $(LIBK_OBJS:.o=.d) \ No newline at end of file diff --git a/BAN/arch/i386/make.config b/BAN/arch/i386/make.config new file mode 100644 index 00000000..24f8c15e --- /dev/null +++ b/BAN/arch/i386/make.config @@ -0,0 +1,8 @@ +ARCH_CFLAGS= +ARCH_CPPFLAGS= +KERNEL_ARCH_CFLAGS= +KERNEL_ARCH_CPPFLAGS= + +ARCH_FREEOBJS=\ + +ARCH_HOSTEDOBJS=\ diff --git a/BAN/build/bank.a b/BAN/build/bank.a new file mode 100644 index 00000000..8b277f0d --- /dev/null +++ b/BAN/build/bank.a @@ -0,0 +1 @@ +! diff --git a/BAN/include/BAN/Errors.h b/BAN/include/BAN/Errors.h new file mode 100644 index 00000000..9acfdb43 --- /dev/null +++ b/BAN/include/BAN/Errors.h @@ -0,0 +1,78 @@ +#pragma once + +#include + +#if defined(__is_bank) + #include + #define MUST(error) { decltype(error) e = error; if (e.HasError()) { Kernel::panic("{}", e.GetError()); } } +#else + #error "NOT IMPLEMENTED" +#endif + +#define TRY(error) { decltype(error) e = error; if (e.HasError()) return e; } + + +class Error +{ +public: + static Error FromString(const char* message) + { + Error result; + strncpy(result.m_message, message, sizeof(m_message)); + result.m_message[sizeof(result.m_message) - 1] = '\0'; + result.m_error_code = 0xFF; + return result; + } + + uint8_t GetErrorCode() const { return m_error_code; } + const char* GetMessage() const { return m_message; } + +private: + char m_message[128]; + uint8_t m_error_code; +}; + +template +class ErrorOr +{ +public: + ErrorOr(const T& value) : m_has_error(false) { m_data = (void*)new T(value); } + ErrorOr(const Error& error) : m_has_error(true) { m_data = (void*)new Error(error); } + ~ErrorOr() { IsError() ? (delete reinterpret_cast(m_data)) : (delete reinterpret_cast(m_data)); } + + bool IsError() const { return m_has_error; } + const Error& GetError() const { return *reinterpret_cast(m_data); } + T& Value() { return *reinterpret_cast(m_data); } + +private: + bool m_has_error; + void* m_data; +}; + +template<> +class ErrorOr +{ +public: + ErrorOr() : m_error(nullptr) { } + ErrorOr(const Error& error) { m_error = new Error(error); } + ~ErrorOr() { delete m_error; } + + bool IsError() const { return m_error; } + const Error& GetError() const { return *m_error; } + +private: + Error* m_error; +}; + + +namespace BAN::Formatter +{ + template + void print_value(const Error& error, const ValueFormat& format) + { + if (error.GetErrorCode() == 0xFF) + print(error.GetMessage()); + else + print("{} ({})", error.GetMessage(), error.GetErrorCode()); + } +} \ No newline at end of file diff --git a/kernel/include/kernel/Formatter.h b/BAN/include/BAN/Formatter.h similarity index 99% rename from kernel/include/kernel/Formatter.h rename to BAN/include/BAN/Formatter.h index bbbd076b..85e7b40a 100644 --- a/kernel/include/kernel/Formatter.h +++ b/BAN/include/BAN/Formatter.h @@ -3,7 +3,7 @@ #include #include -namespace Formatter +namespace BAN::Formatter { struct ValueFormat; diff --git a/BAN/include/BAN/Queue.h b/BAN/include/BAN/Queue.h new file mode 100644 index 00000000..d35bc84e --- /dev/null +++ b/BAN/include/BAN/Queue.h @@ -0,0 +1,125 @@ +#pragma once + +#include +#include + +#if defined(__is_bank) + #include +#else + #include +#endif + +#include +#include +#include +#include + +namespace BAN +{ + + template + class Queue + { + private: + #if defined(__is_bank) + using allocator = kmalloc; + using deallocator = kfree; + #else + using allocator = malloc; + using deallocator = free; + #endif + + + public: + using size_type = uint32_t; + using value_type = T; + + public: + Queue() = default; + ~Queue(); + + ErrorOr Push(const T& value); + void Pop(); + + bool Empty() const; + size_type Size() const; + + const T& Front() const; + T& Front(); + + private: + ErrorOr VerifyCapacity(size_type size); + + private: + T* m_data = nullptr; + size_type m_capacity = 0; + size_type m_size = 0; + }; + + template + Queue::~Queue() + { + deallocator(m_data); + } + + template + ErrorOr Queue::Push(const T& value) + { + VerifyCapacity(m_size + 1); + m_data[m_size++] = value; + return {}; + } + + template + void Queue::Pop() + { + assert(m_size > 0); + m_data->~T(); + memmove(m_data, m_data + 1, sizeof(T) * (--m_size)); + } + + template + bool Queue::Empty() const + { + return m_size == 0; + } + + template + typename Queue::size_type Queue::Size() const + { + return m_size; + } + + template + const T& Queue::Front() const + { + assert(m_size > 0); + return *m_data; + } + + template + T& Queue::Front() + { + assert(m_size > 0); + return *m_data; + } + + template + ErrorOr Queue::VerifyCapacity(size_type size) + { + if (m_capacity > size) + return {}; + + size_type new_cap = MAX(m_capacity * 1.5f, m_capacity + 1) * sizeof(T); + void* new_data = allocator(new_cap); + if (new_data == nullptr) + return Error { .message = "Queue: out of memory", .error_code = ErrorCode::OutOfMemory }; + + memcpy(new_data, m_data, m_size * sizeof(T)); + deallocator(m_data); + + m_data = (T*)new_data; + m_capacity = new_cap; + } + +} \ No newline at end of file diff --git a/config.sh b/config.sh index cb0675d1..4ae17739 100644 --- a/config.sh +++ b/config.sh @@ -1,5 +1,5 @@ -SYSTEM_HEADER_PROJECTS="libc kernel" -PROJECTS="libc kernel" +SYSTEM_HEADER_PROJECTS="libc BAN kernel" +PROJECTS="libc BAN kernel" export MAKE=${MAKE:-make} export HOST=${HOST:-$(./default-host.sh)} diff --git a/kernel/include/kernel/Serial.h b/kernel/include/kernel/Serial.h index 34bfcf5b..6f4e1c07 100644 --- a/kernel/include/kernel/Serial.h +++ b/kernel/include/kernel/Serial.h @@ -1,9 +1,9 @@ #pragma once -#include +#include -#define dprint Formatter::print -#define dprintln Formatter::println +#define dprint BAN::Formatter::print +#define dprintln BAN::Formatter::println namespace Serial { diff --git a/kernel/include/kernel/kprint.h b/kernel/include/kernel/kprint.h index 2d5fb6ff..4e6fdc23 100644 --- a/kernel/include/kernel/kprint.h +++ b/kernel/include/kernel/kprint.h @@ -1,7 +1,7 @@ #pragma once -#include +#include #include -#define kprint Formatter::print -#define kprintln Formatter::println +#define kprint BAN::Formatter::print +#define kprintln BAN::Formatter::println