Compare commits
2 Commits
419604a4d2
...
64f9e9dcde
Author | SHA1 | Date | |
---|---|---|---|
64f9e9dcde | |||
9c912ddc51 |
@ -1,6 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file Check.h
|
||||||
|
* @author apio (cloudapio.eu)
|
||||||
|
* @brief Always-enabled assertions.
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2022-2023, the Luna authors.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/SourceLocation.h>
|
#include <luna/SourceLocation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when a libluna assertion fails. Some targets already have implementations of this function, but
|
||||||
|
* otherwise it must be implemented by the user.
|
||||||
|
*
|
||||||
|
* In the kernel, the implementation is in src/Log.cpp.
|
||||||
|
* For POSIX systems, libluna provides an implementation in src/ImplPOSIX.cpp.
|
||||||
|
*
|
||||||
|
* @param location The source location at which the assertion failure occurred.
|
||||||
|
* @param expr The expression or custom error message to display.
|
||||||
|
* @return bool Unused, since the function never returns.
|
||||||
|
*/
|
||||||
[[noreturn]] extern bool __check_failed(SourceLocation location, const char* expr);
|
[[noreturn]] extern bool __check_failed(SourceLocation location, const char* expr);
|
||||||
|
|
||||||
#ifndef STRINGIZE_VALUE_OF
|
#ifndef STRINGIZE_VALUE_OF
|
||||||
@ -8,32 +28,63 @@
|
|||||||
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
|
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Like check(), but with a custom error message.
|
/**
|
||||||
|
* @brief Verify an expression is true, or crash at runtime with a custom error message.
|
||||||
|
*/
|
||||||
#define expect(expr, message) \
|
#define expect(expr, message) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), message); } \
|
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), message); } \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify an expression is true, or crash at runtime with a custom error message, indicating a different source
|
||||||
|
* location (useful for reporting caller errors, see Result::release_value() for an example).
|
||||||
|
*/
|
||||||
#define expect_at(expr, location, message) \
|
#define expect_at(expr, location, message) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) [[unlikely]] { __check_failed(location, message); } \
|
if (!(expr)) [[unlikely]] { __check_failed(location, message); } \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Fail with an error message and location.
|
/**
|
||||||
|
* @brief Crash at runtime with a custom error message.
|
||||||
|
*/
|
||||||
#define fail(message) __check_failed(SourceLocation::current(), message)
|
#define fail(message) __check_failed(SourceLocation::current(), message)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crash at runtime with a custom error message, indicating a different source location (useful for
|
||||||
|
* reporting caller errors, see Result::release_value() for an example).
|
||||||
|
*/
|
||||||
#define fail_at(location, message) __check_failed(location, message)
|
#define fail_at(location, message) __check_failed(location, message)
|
||||||
|
|
||||||
// Like assert(), but always enabled.
|
/**
|
||||||
|
* @brief Verify an expression is true, or crash at runtime.
|
||||||
|
*/
|
||||||
#define check(expr) \
|
#define check(expr) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), #expr); } \
|
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), #expr); } \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verify an expression is true, or crash at runtime, indicating a different source location (useful for
|
||||||
|
* reporting caller errors, see Result::release_value() for an example).
|
||||||
|
*/
|
||||||
#define check_at(expr, location) \
|
#define check_at(expr, location) \
|
||||||
do { \
|
do { \
|
||||||
if (!(expr)) [[unlikely]] { __check_failed(location, #expr); } \
|
if (!(expr)) [[unlikely]] { __check_failed(location, #expr); } \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mark a code section as unreachable, which will crash if reached.
|
||||||
|
*
|
||||||
|
* Often it may be more performant to use the compiler's __builtin_unreachable() for this purpose (when the code is
|
||||||
|
* clearly unreachable but the compiler cannot figure it out on its own, see the implementation of _exit() in libc), if
|
||||||
|
* there is just no possible way for execution flow to reach this code segment, but the compiler builtin results in
|
||||||
|
* undefined behavior if reached. Therefore, if a bug may cause this unreachable code to be reached, you may prefer to
|
||||||
|
* use this macro as it has well-defined behavior (crashes at runtime).
|
||||||
|
*/
|
||||||
#define unreachable() __check_failed(SourceLocation::current(), "Reached unreachable code")
|
#define unreachable() __check_failed(SourceLocation::current(), "Reached unreachable code")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mark a code section as unimplemented, which will crash if reached.
|
||||||
|
*/
|
||||||
#define todo() __check_failed(SourceLocation::current(), "Reached a TODO!")
|
#define todo() __check_failed(SourceLocation::current(), "Reached a TODO!")
|
||||||
|
@ -1,6 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @file Heap.h
|
||||||
|
* @author apio (cloudapio.eu)
|
||||||
|
* @brief libluna implementations of malloc-family functions.
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Freestanding definitions of std::nothrow and std::align_val_t.
|
||||||
|
*
|
||||||
|
*/
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
struct nothrow_t
|
struct nothrow_t
|
||||||
@ -15,16 +28,100 @@ namespace std
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Freestanding implementation of new (std::nothrow).
|
||||||
|
*
|
||||||
|
* @param size The amount of memory to allocate.
|
||||||
|
* @return void* A pointer to allocated memory, or nullptr on failure.
|
||||||
|
*/
|
||||||
void* operator new(usize size, const std::nothrow_t&) noexcept;
|
void* operator new(usize size, const std::nothrow_t&) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Freestanding implementation of new (std::nothrow) [].
|
||||||
|
*
|
||||||
|
* @param size The amount of memory to allocate.
|
||||||
|
* @return void* A pointer to allocated memory, or nullptr on failure.
|
||||||
|
*/
|
||||||
void* operator new[](usize size, const std::nothrow_t&) noexcept;
|
void* operator new[](usize size, const std::nothrow_t&) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Freestanding implementation of aligned delete.
|
||||||
|
*
|
||||||
|
* @param ptr The memory to delete.
|
||||||
|
* @param size The amount of memory to deallocate.
|
||||||
|
* @param alignment The alignment of the memory to delete.
|
||||||
|
*/
|
||||||
void operator delete(void* ptr, usize size, std::align_val_t alignment) noexcept;
|
void operator delete(void* ptr, usize size, std::align_val_t alignment) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called to allocate pages of memory. Some targets already have implementations of this function, but
|
||||||
|
* otherwise it must be implemented by the user.
|
||||||
|
*
|
||||||
|
* In the kernel, the implementation is in src/memory/Heap.cpp.
|
||||||
|
* For POSIX systems, libluna provides an implementation in src/ImplPOSIX.cpp.
|
||||||
|
*
|
||||||
|
* @param count The number of memory pages to allocate.
|
||||||
|
* @return Result<void*> An error, or a pointer to the beginning of the first allocated page.
|
||||||
|
*/
|
||||||
extern Result<void*> allocate_pages_impl(usize count);
|
extern Result<void*> allocate_pages_impl(usize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called to free pages of memory. Some targets already have implementations of this function, but
|
||||||
|
* otherwise it must be implemented by the user.
|
||||||
|
*
|
||||||
|
* In the kernel, the implementation is in src/memory/Heap.cpp.
|
||||||
|
* For POSIX systems, libluna provides an implementation in src/ImplPOSIX.cpp.
|
||||||
|
*
|
||||||
|
* @param address The address of the first allocated page.
|
||||||
|
* @param count The number of memory pages to free.
|
||||||
|
* @return Result<void> Whether the operation succeeded.
|
||||||
|
*/
|
||||||
extern Result<void> release_pages_impl(void* address, usize count);
|
extern Result<void> release_pages_impl(void* address, usize count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief libluna's malloc implementation.
|
||||||
|
*
|
||||||
|
* @param size The amount of bytes to allocate.
|
||||||
|
* @param may_realloc Specifies whether the program may call realloc() on the returned memory in the future. Enables
|
||||||
|
* some optimizations if false.
|
||||||
|
* @param should_scrub Specifies whether the memory should be scrubbed with a uniform pattern, helpful for debugging
|
||||||
|
* purposes.
|
||||||
|
* @return Result<void*> An error, or the allocated memory.
|
||||||
|
*/
|
||||||
Result<void*> malloc_impl(usize size, bool may_realloc = true, bool should_scrub = true);
|
Result<void*> malloc_impl(usize size, bool may_realloc = true, bool should_scrub = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief libluna's calloc implementation.
|
||||||
|
*
|
||||||
|
* @param nmemb The number of elements to allocate.
|
||||||
|
* @param size The size in bytes of each element.
|
||||||
|
* @param may_realloc Specifies whether the program may call realloc() on the returned memory in the future. Enables
|
||||||
|
* some optimizations if false.
|
||||||
|
* @return Result<void*> An error, or the allocated memory.
|
||||||
|
*/
|
||||||
Result<void*> calloc_impl(usize nmemb, usize size, bool may_realloc = true);
|
Result<void*> calloc_impl(usize nmemb, usize size, bool may_realloc = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief libluna's realloc implementation.
|
||||||
|
*
|
||||||
|
* @param ptr The memory to resize.
|
||||||
|
* @param size The new size in bytes.
|
||||||
|
* @param may_realloc_again Specifies whether the program may call realloc() again on the returned memory in the future.
|
||||||
|
* Enables some optimizations if false.
|
||||||
|
* @return Result<void*> An error, or the resized memory (may not be the same pointer, the caller should use this
|
||||||
|
* instead of ptr from now on).
|
||||||
|
*/
|
||||||
Result<void*> realloc_impl(void* ptr, usize size, bool may_realloc_again = true);
|
Result<void*> realloc_impl(void* ptr, usize size, bool may_realloc_again = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief libluna's free implementation.
|
||||||
|
*
|
||||||
|
* @param ptr The memory to free.
|
||||||
|
* @return Result<void> Whether the operation succeeded.
|
||||||
|
*/
|
||||||
Result<void> free_impl(void* ptr);
|
Result<void> free_impl(void* ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump heap usage stats to debug output.
|
||||||
|
*/
|
||||||
void dump_heap_usage();
|
void dump_heap_usage();
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @file Heap.cpp
|
||||||
|
* @author apio (cloudapio.eu)
|
||||||
|
* @brief libluna implementations of malloc-family functions.
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#include <luna/Alignment.h>
|
#include <luna/Alignment.h>
|
||||||
#include <luna/Alloc.h>
|
#include <luna/Alloc.h>
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user