Compare commits

..

67 Commits

Author SHA1 Message Date
1de85aa4be
wind: Stop using the removed 'signal' pledge
All checks were successful
continuous-integration/drone/pr Build is passing
2023-08-22 13:37:07 +02:00
58cb1e763f
libui: Install the built library into the system root
All checks were successful
continuous-integration/drone/pr Build is passing
2023-08-22 13:36:47 +02:00
35d8075c4e
wind: Show memory usage in debug output 2023-08-22 13:36:47 +02:00
4462651138
wind: Handle ftruncate() and mmap() errors properly 2023-08-22 13:36:47 +02:00
686db5a1de
wind: Fix client references being out-of-date in windows when disconnecting other clients
Classic "keeping a pointer to an element inside a vector after the vector is updated" bug, ah yes.
2023-08-22 13:36:47 +02:00
550c93318c
taskbar: Wait for terminated child windows 2023-08-22 13:36:47 +02:00
55660511f7
wind: Add debug keybind 2023-08-22 13:36:47 +02:00
76ac39b3b4
wind+libos+libui: Handle interrupted reads properly 2023-08-22 13:36:47 +02:00
97305c0212
base: Actually add the start icon to source control 2023-08-22 13:36:47 +02:00
c54504bd22
libui: Add Buttons 2023-08-22 13:36:47 +02:00
c632112213
libui: Handle other mouse events 2023-08-22 13:36:47 +02:00
db2710099b
libui: Add aligned items using Containers, ImageWidget 2023-08-22 13:36:46 +02:00
042e154271
libui: Add VerticalLayout 2023-08-22 13:36:46 +02:00
2ea0a303b4
wind+libui+taskbar: Add GetScreenRect IPC, non-decorated windows, taskbar 2023-08-22 13:36:46 +02:00
da759d3b96
libui: Actually fill window backgrounds with the correct color 2023-08-22 13:36:46 +02:00
390d55243d
libui: Add basic widget and layout system =D 2023-08-22 13:36:46 +02:00
cac62db038
ui+wind: Send mouse move events through IPC 2023-08-22 13:36:46 +02:00
0e61c7b62d
wind+libui: Add protocol for window close requests 2023-08-22 13:36:46 +02:00
69bf171787
libos+libui+wind: Use uppercase for static struct IDs to avoid confusion with fields 2023-08-22 13:36:46 +02:00
46524ecc1d
libui+gclient: Add basic OOP wrappers around the IPC protocol 2023-08-22 13:36:46 +02:00
87f3922486
wind+gclient: Add SetWindowTitle and support shm buffers 2023-08-22 13:36:46 +02:00
ade6493fe6
gclient: Create two example windows 2023-08-22 13:36:45 +02:00
4a4e193559
wind: Handle CreateWindow IPC messages 2023-08-22 13:36:45 +02:00
7e4f4b91f8
libui: Add CreateWindow IPC message definitions 2023-08-22 13:36:45 +02:00
2bf0881fc1
libos: Add basic IPC message framework 2023-08-22 13:36:45 +02:00
180e9bd5b4
kernel: Fix poll syscall 2023-08-22 13:36:45 +02:00
886c393024
wind: Monitor data on client connections 2023-08-22 13:36:45 +02:00
4de29a09d2
kernel: Add POLLHUP and store it when a polled socket's peer disconnects 2023-08-22 13:36:45 +02:00
e1d7de2f21
libui: Add copyright/author text 2023-08-22 13:36:45 +02:00
7449f1a519
libos: Add copyright/author comments to LocalServer and LocalClient 2023-08-22 13:36:45 +02:00
688bd652dc
wind: Use init --user and pledge() 2023-08-22 13:36:45 +02:00
e679731a18
Update .gitignore 2023-08-22 13:36:44 +02:00
6727dc034a
libos: Remove some shared pointers and change them to owned/live on the stack 2023-08-22 13:36:44 +02:00
f31a90df16
wind: Spawn a new client process after startup
Also, create the socket after dropping privileges.
2023-08-22 13:36:44 +02:00
3686a25a76
apps: Add gclient 2023-08-22 13:36:44 +02:00
0871895cc5
libos: Add os::LocalClient 2023-08-22 13:36:44 +02:00
5085604aab
libui: Change 'into' to 'onto' 2023-08-22 13:36:44 +02:00
aa82c088a0
libui: Document ui::Font 2023-08-22 13:36:44 +02:00
ecd8c4c29c
libui+wind: Move some static variables inside functions 2023-08-22 13:36:44 +02:00
88141727a2
wind: Generate random windows on keypresses 2023-08-22 13:36:44 +02:00
bcf6bc3c97
wind: Make sure windows have a minimum size to fit the titlebar 2023-08-22 13:36:44 +02:00
3e6c9dbaa2
libui: Properly cut off the last drawn character if necessary 2023-08-22 13:36:43 +02:00
b1299aef9e
libui: Add Rect::contains(Rect) 2023-08-22 13:36:43 +02:00
594f42fdd6
libui: Render font characters properly with no spacing, matching the width calculations 2023-08-22 13:36:43 +02:00
45ff38f5e3
wind: Render an actual TGA mouse cursor 2023-08-22 13:36:43 +02:00
8b02bfebdb
wind: Add a close button to windows using a TGA icon 2023-08-22 13:36:43 +02:00
9382ec9eca
libui: Add support for TGA image loading 2023-08-22 13:36:43 +02:00
58f839927c
libui: Add an interface to fill a Canvas with an array of pixels 2023-08-22 13:36:43 +02:00
72704e445a
wind: Add window titlebars using ui::Font 2023-08-22 13:36:43 +02:00
7bc0f36661
libui: Add PSF font loading and rendering 2023-08-22 13:36:43 +02:00
c58f91c48d
libui: Add Color::GRAY 2023-08-22 13:36:43 +02:00
94f297a47f
libui: Rename Rect::absolute to normalized and add a new absolute function 2023-08-22 13:36:43 +02:00
00db974b97
libluna: Add assignment operators to Buffer 2023-08-22 13:36:42 +02:00
dc69f144ad
wind: Reorder drag sequence 2023-08-22 13:36:42 +02:00
714f6a90cc
libui: Add Rect::relative 2023-08-22 13:36:42 +02:00
9d412b7a32
libui: Remove redundant statement 2023-08-22 13:36:42 +02:00
62d56d31a3
libui: Add getters for separate color values 2023-08-22 13:36:42 +02:00
38912dce51
libui: Remove unnecessary stuff 2023-08-22 13:36:42 +02:00
eba2960df3
base: Remove startup items not necessary for GUI startup 2023-08-22 13:36:42 +02:00
54bfcfc8cb
libui+wind: (Draggable) windows 2023-08-22 13:36:42 +02:00
f02bf4bc95
wind: Create a local server object 2023-08-22 13:36:42 +02:00
7d35964c5c
libos: Add a new LocalServer class for local domain sockets 2023-08-22 13:36:42 +02:00
971e69ee8c
kernel: Support listening sockets in poll() 2023-08-22 13:36:41 +02:00
4b04ce1917
base: Start wind on startup instead of the shell 2023-08-22 13:36:41 +02:00
fa6534004a
wind: Add a simple display server skeleton using libui
No client functionality yet, but it's a start.
2023-08-22 13:36:41 +02:00
995aa97a58
libui: Add a GUI and graphics library 2023-08-22 13:36:41 +02:00
b4d9363302
kernel: Fix negative movement in the PS/2 mouse driver 2023-08-22 13:36:41 +02:00
53 changed files with 111 additions and 1471 deletions

1
.gitignore vendored
View File

@ -12,7 +12,6 @@ base/usr/share/pkgdb/**
!base/usr/share/icons/*
base/usr/share/**
base/usr/x86_64-luna/**
base/etc/skel/LICENSE
.fakeroot
kernel/config.cmake
ports/out/

View File

@ -1,8 +1,6 @@
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/FileSystem.h>
#include <os/Prompt.h>
using os::File;
@ -16,20 +14,10 @@ Result<int> luna_main(int argc, char** argv)
parser.add_positional_argument(pathname, "path"_sv, true);
parser.parse(argc, argv);
if (os::FileSystem::exists(pathname))
{
String prompt = TRY(String::format("File %s already exists. Overwrite?"_sv, pathname.chars()));
bool overwrite = os::conditional_prompt(prompt.chars(), os::DefaultNo);
if (!overwrite) return 0;
}
auto file = TRY(File::open_or_create(pathname, File::WriteOnly));
auto input = File::standard_input();
os::println("- Editing %s. Press Enter to start a new line, or Ctrl+D at the start of a line to save and exit. -",
pathname.chars());
while (1)
{
String line = TRY(input->read_line());

View File

@ -3,7 +3,6 @@
#include <luna/PathParser.h>
#include <luna/Sort.h>
#include <luna/String.h>
#include <luna/Utf8.h>
#include <luna/Vector.h>
#include <os/ArgumentParser.h>
#include <os/Directory.h>
@ -25,6 +24,18 @@ static bool g_is_system = false;
FILE* g_init_log = nullptr;
// Request a successful exit from the system (for tests)
void sigterm_handler(int)
{
_exit(0);
}
// Request a failure exit from the system (for tests)
void sigquit_handler(int)
{
_exit(1);
}
struct Service
{
String name;
@ -52,20 +63,6 @@ static void do_log(const char* format, ...)
va_end(ap);
}
// Request a successful exit from the system (for tests)
void sigterm_handler(int)
{
do_log("[init] successful exit requested, complying\n");
exit(0);
}
// Request a failure exit from the system (for tests)
void sigquit_handler(int)
{
do_log("[init] failure exit requested, complying\n");
exit(1);
}
static Result<void> service_child(const Service& service, SharedPtr<os::File> output, SharedPtr<os::File> error,
SharedPtr<os::File> input)
{
@ -303,19 +300,6 @@ static Result<void> set_hostname()
auto hostname = TRY(file->read_line());
hostname.trim("\n");
if (hostname.is_empty())
{
do_log("[init] /etc/hostname is empty or invalid, keeping the default hostname\n");
return {};
}
Utf8StringDecoder decoder(hostname.chars());
if (decoder.code_points().has_error())
{
do_log("[init] /etc/hostname is not valid UTF-8, keeping the default hostname\n");
return {};
}
if (sethostname(hostname.chars(), hostname.length()) < 0) return {};
do_log("[init] successfully set system hostname to '%s'\n", hostname.chars());
@ -339,7 +323,7 @@ static void mount_shmfs()
if (chmod("/dev/shm", 01777) < 0) exit(255);
}
Result<int> sysinit(StringView path)
Result<int> sysinit()
{
if (getpid() != 1)
{
@ -374,8 +358,7 @@ Result<int> sysinit(StringView path)
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec id", nullptr));
if (path.is_empty()) path = "/etc/init";
start_services(path);
start_services("/etc/init");
while (1)
{
@ -411,7 +394,7 @@ Result<int> sysinit(StringView path)
}
}
Result<int> user_init(StringView path)
Result<int> user_init()
{
setpgid(0, 0);
@ -422,8 +405,7 @@ Result<int> user_init(StringView path)
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr));
if (path.is_empty()) path = "/etc/user";
start_services(path);
start_services("/etc/user");
TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr));
@ -464,16 +446,13 @@ Result<int> user_init(StringView path)
Result<int> luna_main(int argc, char** argv)
{
bool user;
StringView service_path;
os::ArgumentParser parser;
parser.add_description("The init system for Luna.");
parser.add_system_program_info("init"_sv);
parser.add_switch_argument(user, 'u', "user"_sv, "initialize a user session instead of the system");
parser.add_value_argument(service_path, 's', "service-path"_sv,
"change the default service path (/etc/init or /etc/user)");
parser.parse(argc, argv);
if (user) return user_init(service_path);
return sysinit(service_path);
if (user) return user_init();
return sysinit();
}

View File

@ -1,4 +1,4 @@
#include <moon/Syscall.h>
#include <luna/Syscall.h>
#include <os/ArgumentParser.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,14 +0,0 @@
Welcome to the Luna operating system!
You are running on the default user account, selene.
If you are familiar with Unix-style operating systems (like Linux or *BSD), you should be able to use the Luna terminal without much problems.
Following the traditional Unix filesystem structure, programs are installed in /usr/bin (/bin is a symlink to /usr/bin). The command `ls /bin` will show all commands available on your current Luna installation.
Currently, because of driver limitations, the root file system is mounted read-only. Your home folder is writable, but volatile; it is created and populated on boot, and its contents will vanish after a reboot.
The system is booted using the 'init' program. You can read its configuration files in the /etc/init directory to learn more about the boot process.
Luna is free software, released under the BSD-2-Clause license. The license is included in the LICENSE file in your home directory.
View the source code and read more about Luna at https://git.cloudapio.eu/apio/Luna.

View File

@ -1,6 +1,3 @@
#!/bin/sh
# Create and populate a volatile home directory.
mount -t tmpfs tmpfs /home/selene
chown selene:selene /home/selene
cp /etc/skel/welcome /home/selene/
cp /etc/skel/LICENSE /home/selene/

View File

@ -24,16 +24,13 @@ Result<void> check_pledge(Thread* thread, Promise promise)
// Thread::process_pending_signals().
thread->signal_handlers[SIGABRT - 1].sa_handler = SIG_DFL;
// Unblock SIGABRT.
thread->signal_mask.set(SIGABRT - 1, false);
// If there are any other pending signals, they might be processed before SIGABRT. Avoid that by resetting the
// thread's pending signals.
thread->pending_signals.clear();
thread->pending_signals = 0;
thread->send_signal(SIGABRT);
// This should never arrive to userspace, unless we're init and have ignored SIGABRT.
// This should never arrive to userspace.
return err(ENOSYS);
}

View File

@ -124,7 +124,7 @@ bool Thread::deliver_signal(int signo, Registers* current_regs)
if (push_mem_on_stack((u8*)&handler.__sa_sigreturn, sizeof(void*)).has_error()) return false;
signal_mask = handler.sa_mask;
if ((handler.sa_flags & SA_NODEFER) == 0) signal_mask.set(signo - 1, true);
if ((handler.sa_flags & SA_NODEFER) == 0) signal_mask |= (1 << (signo - 1));
rsp = regs.rsp;

View File

@ -36,7 +36,7 @@ Result<void> ConsoleDevice::handle_background_process_group(bool can_succeed, in
auto* current = Scheduler::current();
if (current->pgid == foreground_pgrp) return {};
if ((current->signal_mask.get(signo - 1)) || (current->signal_handlers[signo - 1].sa_handler == SIG_IGN))
if ((current->signal_mask & (1 << (signo - 1))) || (current->signal_handlers[signo - 1].sa_handler == SIG_IGN))
{
if (can_succeed) return {};
return err(EIO);

View File

@ -1,7 +1,7 @@
#pragma once
#include "api/Syscall.h"
#include "arch/CPU.h"
#include <luna/Result.h>
#include <luna/Syscall.h>
typedef u64 SyscallArgs[6];

View File

@ -13,7 +13,7 @@ Result<u64> sys_poll(Registers*, SyscallArgs args)
nfds_t nfds = (nfds_t)args[1];
int timeout = (int)args[2];
struct pollfd* kfds = (struct pollfd*)TRY(malloc_impl(nfds * sizeof(pollfd), false, false));
struct pollfd* kfds = (struct pollfd*)TRY(malloc_impl(nfds * sizeof(pollfd)));
auto guard = make_scope_guard([kfds] { free_impl(kfds); });
if (!MemoryManager::copy_from_user(fds, kfds, nfds * sizeof(pollfd))) return err(EFAULT);

View File

@ -79,8 +79,7 @@ Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
if (oldset)
{
sigset_t mask = current->signal_mask.value();
if (!MemoryManager::copy_to_user_typed(oldset, &mask)) return err(EFAULT);
if (!MemoryManager::copy_to_user_typed(oldset, &current->signal_mask)) return err(EFAULT);
}
if (set)
@ -90,8 +89,8 @@ Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
switch (how)
{
case SIG_BLOCK: current->signal_mask = current->signal_mask.value() | kset; break;
case SIG_UNBLOCK: current->signal_mask = current->signal_mask.value() & ~kset; break;
case SIG_BLOCK: current->signal_mask |= kset; break;
case SIG_UNBLOCK: current->signal_mask &= ~kset; break;
case SIG_SETMASK: current->signal_mask = kset; break;
default: return err(EINVAL);
}

View File

@ -148,10 +148,10 @@ void Thread::process_pending_signals(Registers* current_regs)
for (int i = 0; i < NSIG; i++)
{
int signo = i + 1;
if (signo != SIGKILL && signo != SIGSTOP && signal_mask.get(i)) continue;
if (pending_signals.get(i))
if (signo != SIGKILL && signo != SIGSTOP && signal_mask & (1 << i)) continue;
if (pending_signals & (1 << i))
{
pending_signals.set(i, false);
pending_signals &= ~(1 << i);
kinfoln("signal: executing signal %d for thread %d", signo, id);
auto handler = signal_handlers[i];
if (signo != SIGKILL && signo != SIGSTOP && handler.sa_handler == SIG_IGN)
@ -190,11 +190,11 @@ bool Thread::will_ignore_pending_signal()
{
for (int i = 0; i < NSIG; i++)
{
if (pending_signals.get(i))
if (pending_signals & (1 << i))
{
int signo = i + 1;
if (signo == SIGKILL || signo == SIGSTOP) return false;
if (signal_mask.get(i)) continue;
if (signal_mask & (1 << i)) continue;
auto handler = signal_handlers[i];
if (handler.sa_handler == SIG_IGN) return true;
if (handler.sa_handler == SIG_DFL && default_actions[i] == DefaultSignalAction::Ignore) return true;
@ -206,10 +206,8 @@ bool Thread::will_ignore_pending_signal()
void Thread::send_signal(int signo)
{
if (is_kernel) return;
check(signo > 0 && signo <= NSIG);
pending_signals.set(signo - 1, true);
pending_signals |= 1 << (signo - 1);
if (state == ThreadState::Waiting || state == ThreadState::Sleeping)
{

View File

@ -4,7 +4,6 @@
#include "fs/VFS.h"
#include "memory/AddressSpace.h"
#include <bits/signal.h>
#include <luna/Bitset.h>
#include <luna/LinkedList.h>
#include <luna/OwnedPtr.h>
#include <luna/Result.h>
@ -106,8 +105,8 @@ struct Thread : public LinkedListNode<Thread>
SharedPtr<VFS::Inode>* parent_inode = nullptr);
struct sigaction signal_handlers[NSIG];
Bitset<sigset_t> signal_mask { 0 };
Bitset<sigset_t> pending_signals { 0 };
sigset_t signal_mask { 0 };
sigset_t pending_signals { 0 };
bool interrupted { false };
bool unrestricted_task { false };

View File

@ -3,8 +3,8 @@
#ifndef _SYS_SYSCALL_H
#define _SYS_SYSCALL_H
/* This header just forwards to the kernel API header Syscall.h. */
#include <moon/Syscall.h>
/* This header just forwards to luna/Syscall.h, which is used in the kernel as well. */
#include <luna/Syscall.h>
#undef enumerate_syscalls
#endif

View File

@ -117,7 +117,9 @@ extern "C"
raise(SIGABRT);
__builtin_trap();
// There is no way we could end up here, unless there is some sort of race condition or the kernel decided to
// change the default action for SIGABRT because it's a Tuesday.
__builtin_unreachable();
}
__noreturn void _Exit(int status)

View File

@ -1,70 +1,37 @@
/**
* @file Alignment.h
* @author apio (cloudapio.eu)
* @brief Functions to align addresses and sizes to specified boundaries.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/TypeTraits.h>
#include <luna/Types.h>
/**
* @brief Check whether a value is aligned to a specific alignment.
*
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to check.
* @return constexpr bool Whether the value is aligned.
*/
template <usize alignment, typename T> constexpr inline bool is_aligned(T value)
template <usize alignment, typename T> constexpr inline T is_aligned(T value)
{
return (value % alignment == 0);
}
/**
* @brief Find the closest aligned value that is smaller than the value provided.
*
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to use.
* @return constexpr T The aligned value.
*/
static_assert(is_aligned<512>(1024u));
static_assert(!is_aligned<32>(235u));
static_assert(is_aligned<4096>(40960u));
template <usize alignment, typename T> constexpr inline T align_down(T value)
{
return value - value % alignment;
}
/**
* @brief Find the closest aligned value that is bigger than the value provided.
*
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to use.
* @return constexpr T The aligned value.
*/
static_assert(align_down<512>(598ul) == 512ul);
static_assert(align_down<64>(194ul) == 192ul);
static_assert(align_down<32>(64ul) == 64ul);
template <usize alignment, typename T> constexpr inline T align_up(T value)
{
if (is_aligned<alignment>(value)) return value;
return align_down<alignment>(value) + alignment;
}
/**
* @brief Offset a pointer by exactly <offset> bytes, no matter the type.
*
* Generally only useful for pointers to void (or char), because breaking other pointers' alignments is not a good
* idea...
*
* @tparam T The underlying type of the pointer.
* @tparam Offset The type of the offset.
* @param ptr The pointer to offset.
* @param offset The offset to use (depending on the type, this could be negative).
* @return constexpr T* The new pointer.
*/
static_assert(align_up<512>(598ul) == 1024ul);
static_assert(align_up<64>(194ul) == 256ul);
static_assert(align_up<32>(64ul) == 64ul);
// Offset a pointer by exactly <offset> bytes, no matter the type. Useful to avoid the quirks that come from C pointer
// arithmetic.
template <typename T, typename Offset> constexpr inline T* offset_ptr(T* ptr, Offset offset)
{
return (T*)((u8*)ptr + offset);

View File

@ -1,30 +1,16 @@
/**
* @file Alloc.h
* @author apio (cloudapio.eu)
* @brief Fallible version of new.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Heap.h>
#include <luna/PlacementNew.h>
#include <luna/Result.h>
/**
* @brief Allocate a value on the heap and initialize it.
*
* When this value is no longer used, you must call delete to destroy it.
*
* @tparam T The type of the value.
* @tparam Args The types of arguments to pass to the value's constructor.
* @param args The arguments to pass to the value's constructor.
* @return Result<T*> An error, or a pointer to the new value.
*/
template <typename T, class... Args> [[nodiscard]] Result<T*> make(Args... args)
{
T* const result = (T*)TRY(malloc_impl(sizeof(T), false, false));
T* const result = (T*)TRY(malloc_impl(sizeof(T)));
new (result) T(args...);
return result;
}
template <typename T> void destroy(T* item)
{
delete item;
}

View File

@ -1,17 +1,5 @@
/**
* @file Atomic.h
* @author apio (cloudapio.eu)
* @brief Atomic value operations.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
/**
* @brief An enum representing the different C++11 memory orders.
*/
enum class MemoryOrder
{
Relaxed = __ATOMIC_RELAXED,
@ -22,114 +10,48 @@ enum class MemoryOrder
SeqCst = __ATOMIC_SEQ_CST,
};
/**
* @brief An atomic wrapper around a simple integer value.
*
* @tparam T The type of the value.
*/
template <typename T> class Atomic
{
public:
/**
* @brief Construct a new Atomic object.
*/
Atomic() : m_value()
{
}
/**
* @brief Construct a new Atomic object.
*
* @param value The value to use.
*/
Atomic(T value) : m_value(value)
{
}
/**
* @brief Store a new value inside this object.
*
* @param other The value to store.
* @return T The updated value.
*/
T operator=(T other)
{
store(other);
return other;
}
/**
* @brief Perform an atomic load of the stored value.
*
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return T The loaded value.
*/
T load(MemoryOrder order = MemoryOrder::SeqCst) const
{
return __atomic_load_n(&m_value, (int)order);
}
/**
* @brief Return the stored value atomically.
*
* @return T The stored value.
*/
operator T() const
{
return load();
}
/**
* @brief Store a new value atomically.
*
* @param value The value to store.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
*/
void store(T value, MemoryOrder order = MemoryOrder::SeqCst)
{
return __atomic_store_n(&m_value, value, (int)order);
}
/**
* @brief Store a new value atomically, and return the old value.
*
* @param value The value to store.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return T The old value.
*/
T exchange(T value, MemoryOrder order = MemoryOrder::SeqCst)
{
return __atomic_exchange_n(&m_value, value, (int)order);
}
/**
* @brief Compare the current value against an expected value and exchange it with a desired value only if they
* match, all in a single atomic step.
*
* @param expected The expected value. After compare_exchange_strong returns, it will be set to the value that used
* to be held.
* @param desired The value to store if the two values match.
* @param success The memory order to use in case of success.
* @param failure The memory order to use in case of failure.
* @return true The values match and the current value was updated to match desired.
* @return false The values did not match and the current value stays the same.
*/
bool compare_exchange_strong(T& expected, T desired, MemoryOrder success, MemoryOrder failure)
{
return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)success, (int)failure);
}
/**
* @brief Compare the current value against an expected value and exchange it with a desired value only if they
* match, all in a single atomic step.
*
* @param expected The expected value. After compare_exchange_strong returns, it will be set to the value that used
* to be held.
* @param desired The value to store if the two values match.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return true The values match and the current value was updated to match desired.
* @return false The values did not match and the current value stays the same.
*/
bool compare_exchange_strong(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst)
{
MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire
@ -138,40 +60,11 @@ template <typename T> class Atomic
return __atomic_compare_exchange_n(&m_value, &expected, desired, false, (int)order, (int)failure);
}
/**
* @brief Compare the current value against an expected value and exchange it with a desired value only if they
* match, all in a single atomic step.
*
* This variant may be more performant than compare_exchange_strong, but is allowed to sometimes spuriously fail
* (fail even if the two values did match).
*
* @param expected The expected value. After compare_exchange_weak returns, it will be set to the value that used
* to be held.
* @param desired The value to store if the two values match.
* @param success The memory order to use in case of success.
* @param failure The memory order to use in case of failure.
* @return true The values match and the current value was updated to match desired.
* @return false The values did not match (or there was a spurious failure) and the current value stays the same.
*/
bool compare_exchange_weak(T& expected, T desired, MemoryOrder success, MemoryOrder failure)
{
return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)success, (int)failure);
}
/**
* @brief Compare the current value against an expected value and exchange it with a desired value only if they
* match, all in a single atomic step.
*
* This variant may be more performant than compare_exchange_strong, but is allowed to sometimes spuriously fail
* (fail even if the two values did match).
*
* @param expected The expected value. After compare_exchange_weak returns, it will be set to the value that used
* to be held.
* @param desired The value to store if the two values match.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return true The values match and the current value was updated to match desired.
* @return false The values did not match (or there was a spurious failure) and the current value stays the same.
*/
bool compare_exchange_weak(T& expected, T desired, MemoryOrder order = MemoryOrder::SeqCst)
{
MemoryOrder failure = (order == MemoryOrder::AcqRel) ? MemoryOrder::Acquire
@ -180,87 +73,41 @@ template <typename T> class Atomic
return __atomic_compare_exchange_n(&m_value, &expected, desired, true, (int)order, (int)failure);
}
/**
* @brief Atomically add a value to the stored value and return the previous value.
*
* @param other The value to add.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return T The original stored value.
*/
T fetch_add(T other, MemoryOrder order = MemoryOrder::SeqCst)
{
return __atomic_fetch_add(&m_value, other, (int)order);
}
/**
* @brief Atomically subtract a value from the stored value and return the previous value.
*
* @param other The value to add.
* @param order The memory order to use (keep it to the default if you don't know what you're doing).
* @return T The original stored value.
*/
T fetch_sub(T other, MemoryOrder order = MemoryOrder::SeqCst)
{
return __atomic_fetch_sub(&m_value, other, (int)order);
}
/**
* @brief Increment the stored value and return it.
*
* @return T The new value.
*/
T operator++()
{
return fetch_add(1) + 1;
}
/**
* @brief Fetch the stored value, increment it and return the original value.
*
* @return T The original value.
*/
T operator++(int)
{
return fetch_add(1);
}
/**
* @brief Decrement the stored value and return it.
*
* @return T The new value.
*/
T operator--()
{
return fetch_sub(1) - 1;
}
/**
* @brief Fetch the stored value, decrement it and return the original value.
*
* @return T The original value.
*/
T operator--(int)
{
return fetch_sub(1);
}
/**
* @brief Add a value to the stored value and return the result.
*
* @param other The value to add.
* @return T The resulting value.
*/
T operator+=(const T& other)
{
return fetch_add(other) + other;
}
/**
* @brief Subtract a value from the stored value and return the result.
*
* @param other The value to subtract.
* @return T The resulting value.
*/
T operator-=(const T& other)
{
return fetch_sub(other) - other;

View File

@ -1,12 +1,3 @@
/**
* @file Attributes.h
* @author apio (cloudapio.eu)
* @brief Macro wrappers around GCC attributes.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#define _weak __attribute__((weak))

View File

@ -1,33 +1,8 @@
/**
* @file Badge.h
* @author apio (cloudapio.eu)
* @brief A simple way to control who can call functions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
/**
* @brief A struct that can only be constructed by one type, used to control access to functions/methods.
*
* Example: There is a private method FooClass::foo() that you want to be callable by BarClass without making it a
* friend.
*
* So, make FooClass::foo() public and make it take a Badge<BarClass> which will only be constructible by BarClass, thus
* limiting the method even though it is public.
*
* @tparam T The type that can construct this badge.
*/
template <class T> struct Badge
{
private:
/**
* @brief Construct a new Badge.
*
* This can only be done by the type T.
*/
constexpr Badge() = default;
Badge(const Badge<T>&) = delete;

View File

@ -1,61 +1,13 @@
/**
* @file Base64.h
* @author apio (cloudapio.eu)
* @brief Base64 encoding and decoding.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Buffer.h>
#include <luna/String.h>
namespace Base64
{
/**
* @brief Encode a string into Base64.
*
* @param data The string to encode.
* @return Result<String> An error, or the resulting Base64 string.
*/
Result<String> encode(StringView data);
/**
* @brief Encode a slice of data into Base64.
*
* @param data The data to encode.
* @return Result<String> An error, or the resulting Base64 string.
*/
Result<String> encode(Slice<const u8> data);
/**
* @brief Encode a buffer into Base64.
*
* @param data The buffer to encode.
* @return Result<String> An error, or the resulting Base64 string.
*/
Result<String> encode(const Buffer& data);
/**
* @brief Decode a Base64 string.
*
* @param data The string to decode.
* @param allow_garbage_chars Whether to skip non-Base64 characters instead of returning an error.
* @return Result<Buffer> An error, or the raw decoded data.
*/
Result<Buffer> decode(StringView data, bool allow_garbage_chars = false);
/**
* @brief Decode a Base64 string, returning a string instead of raw data.
*
* Note that decoded Base64 may be anything; invalid UTF-8, null characters in the middle of data, etc...
* For this reason it is not recommended to use this function unless you're sure that what is decoded will be a
* valid string (so, don't use this with untrusted user input).
*
* @param data The string to decode.
* @param allow_garbage_chars Whether to skip non-Base64 characters instead of returning an error.
* @return Result<String> An error, or the decoded string.
*/
Result<String> decode_string(StringView data, bool allow_garbage_chars = false);
}

View File

@ -1,195 +1,58 @@
/**
* @file Bitmap.h
* @author apio (cloudapio.eu)
* @brief An interface to an array of bits.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Result.h>
#include <luna/Types.h>
/**
* @brief A class providing an interface to an array of bits.
*/
class Bitmap
{
public:
/**
* @brief Construct a new empty Bitmap object.
*
* This object is invalid until initialize() is called on it.
*/
Bitmap();
/**
* @brief Construct a new Bitmap object.
*
* @param location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you must
* free it after it is no longer used by the bitmap.
* @param size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the memory used.
*/
Bitmap(void* location, usize size_in_bytes);
/**
* @brief Initialize a Bitmap object.
*
* If the object was previously initialized, you should call move() instead.
*
* @param location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you must
* free it after it is no longer used by the bitmap.
* @param size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the memory used.
*/
// Naive initialization functions.
void initialize(void* location, usize size_in_bytes);
/**
* @brief Initialize a previously initialized Bitmap object and return the memory location it was previously using.
*
* If the object was not previously initialized, you should call initialize() instead.
*
* @param new_location The memory to use. This memory is not managed by Bitmap; if it is dynamically allocated, you
* must free it after it is no longer used by the bitmap.
* @param new_location_size_in_bytes The size (in bytes, the number of bits available will be 8 times more) of the
* memory used.
* @return void* The old memory location previously used by the bitmap.
*/
void* move(void* new_location, usize new_location_size_in_bytes);
/**
* @brief Change the value of the bit at a specific index.
*
* @param index The index of the bit to change.
* @param value The value to set.
*/
void set(usize index, bool value);
// Dynamic memory initialization functions.
Result<void> allocate(usize size_in_bytes);
Result<void*> resize(usize new_size_in_bytes);
Result<void> deallocate();
/**
* @brief Read the value of the bit at a specific index.
*
* @param index The index of the bit to read.
* @return bool The value of the specified bit.
*/
void set(usize index, bool value);
bool get(usize index) const;
/**
* @brief Return the size in bits of the bitmap.
*
* @return usize The size in bits.
*/
// size() returns size in bits! If you want the size in bytes, call size_in_bytes().
usize size() const
{
return m_size_in_bytes * 8;
}
/**
* @brief Return the size in bytes of the bitmap.
*
* @return usize The size in bytes.
*/
usize size_in_bytes() const
{
return m_size_in_bytes;
}
/**
* @brief Return the memory location used by the bitmap.
*
* @return void* The memory location used. If it is NULL, the bitmap was not initialized.
*/
void* location() const
{
return (void*)m_location;
}
/**
* @brief Check whether the bitmap has been initialized.
*
* @return true The bitmap was initialized by a constructor or initialize().
* @return false The bitmap was not initialized and you should not call other methods on it until initialize() is
* called.
*/
bool initialized() const
{
return m_location;
}
/**
* @brief Find the first bit with a specific value.
*
* @param value The value to look for.
* @param begin If different from 0, the bit index to start looking at.
* @return Option<usize> If a matching bit was found, the index of said bit, otherwise an empty Option.
*/
Option<usize> find(bool value, usize begin = 0) const;
/**
* @brief Find the first bit with a specific value and toggle it.
*
* @param value The value to look for.
* @param begin If different from 0, the bit index to start looking at.
* @return Option<usize> If a matching bit was found, the index of said bit, otherwise an empty Option.
*/
Option<usize> find_and_toggle(bool value, usize begin = 0);
/**
* @brief Find the first region of bits all with a specific value.
*
* @param value The value to look for.
* @param count The number of consecutive bits that should all match the value.
* @param begin If different from 0, the bit index to start looking at.
* @return Option<usize> If a matching region was found, the index of the first bit in said region, otherwise an
* empty Option.
*/
Option<usize> find_region(bool value, usize count, usize begin = 0) const;
/**
* @brief Find the first region of bits all with a specific value, and toggle them all.
*
* @param value The value to look for.
* @param count The number of consecutive bits that should all match the value.
* @param begin If different from 0, the bit index to start looking at.
* @return Option<usize> If a matching region was found, the index of the first bit in said region, otherwise an
* empty Option.
*/
Option<usize> find_and_toggle_region(bool value, usize count, usize begin = 0);
/**
* @brief Check whether a region of bits all match a value.
*
* @param start The bit index of the first bit in the region.
* @param bits The number of bits in the region.
* @param value The value to check against.
* @return bool Whether the region matches.
*/
bool match_region(usize start, usize bits, bool value);
/**
* @brief Check whether a region of bits all match a value, returning an error if the region is outside of the
* Bitmap's bounds (instead of crashing).
*
* @param start The bit index of the first bit in the region.
* @param bits The number of bits in the region.
* @param value The value to check against.
* @return Result<bool> An error if the region is out of bounds, or whether the region matches.
*/
Result<bool> try_match_region(usize start, usize bits, bool value);
/**
* @brief Set the entire bitmap to a value.
*
* @param value The value to use.
*/
void clear(bool value);
/**
* @brief Set a region of bits to a value.
*
* @param start The bit index of the first bit in the region.
* @param bits The number of bits in the region.
* @param value The value to set.
*/
void clear_region(usize start, usize bits, bool value);
private:

View File

@ -1,119 +0,0 @@
/**
* @file Bitset.h
* @author apio (cloudapio.eu)
* @brief A wrapper class to modify/inspect specific bits of an integer type.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Check.h>
/**
* @brief A wrapper class to modify/inspect specific bits of an integer type, to avoid manual error-prone bit shifting.
*
* @tparam T The integer type to use.
*/
template <typename T> class Bitset
{
public:
/**
* @brief Construct a new empty Bitset object.
*/
Bitset() : m_value(0)
{
}
/**
* @brief Construct a new Bitset object with a value.
*
* @param value The value to use.
*/
Bitset(T value) : m_value(value)
{
}
/**
* @brief Construct a copy of another Bitset object.
*
* @param other The original object.
*/
Bitset(const Bitset<T>& other) : m_value(other.m_value)
{
}
/**
* @brief Update the internal value of this bitset.
*
* @param value The new value.
* @return Bitset<T>& A reference to this itset.
*/
Bitset<T>& operator=(T value)
{
m_value = value;
return *this;
}
/**
* @brief Set this bitset to the same value as another bitset.
*
* @param other The pther bitset.
* @return Bitset<T>& A reference to this bitset.
*/
Bitset<T>& operator=(const Bitset<T>& other)
{
if (&other == this) return *this;
m_value = other.m_value;
return *this;
}
/**
* @brief Return the value contained in this bitset.
*
* @return T The contained value.
*/
T value() const
{
return m_value;
}
/**
* @brief Modify one of the individual bits in this bitset.
*
* @param index The index of the bit (this will set/unset 1 << index). It must be less than the bit width of the
* underlying type.
* @param b The value to set the bit to.
*/
void set(int index, bool b)
{
check((usize)index < (sizeof(T) * 8));
if (b) m_value |= (((T)1) << index);
else
m_value &= ~(((T)1) << index);
}
/**
* @brief Get the value of one of the individual bits in this bitset.
*
* @param index The index of the bit (this will read 1 << index). It must be less than the bit width of the
* underlying type.
* @return bool The value of the requested bit.
*/
bool get(int index)
{
check((usize)index < (sizeof(T) * 8));
return m_value & (((T)1) << index);
}
/**
* @brief Clear all the bits in this bitset.
*/
void clear()
{
m_value = 0;
}
private:
T m_value;
};

View File

@ -1,19 +1,7 @@
/**
* @file Buffer.h
* @author apio (cloudapio.eu)
* @brief A managed wrapper around a resizable buffer of arbitrary memory.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Result.h>
#include <luna/Types.h>
/**
* @brief A managed wrapper around a resizable buffer of arbitrary memory.
*/
class Buffer
{
public:
@ -26,135 +14,45 @@ class Buffer
Buffer& operator=(Buffer&&);
Buffer& operator=(const Buffer&) = delete;
/**
* @brief Create a Buffer object, allocating a specific amount of memory for it.
*
* @param size The number of bytes to allocate.
* @return Result<Buffer> An error, or the newly created buffer.
*/
static Result<Buffer> create_sized(usize size);
/**
* @brief Resize the buffer.
*
* The existing data is kept, unless the new size is smaller than the old size, in which case only the first
* new_size bytes are kept.
*
* @param new_size The new size of the buffer, in bytes.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> try_resize(usize new_size);
/**
* @brief Expand the buffer and return a pointer to the beginning of this new expanded area.
*
* @param size The amount of bytes to expand the buffer by.
* @return Result<u8*> An error, or a pointer to the new area of the buffer.
*/
Result<u8*> slice_at_end(usize size);
/**
* @brief Return a pointer to an area of the buffer, expanding it if necessary.
*
* @param offset The offset inside the buffer to start at.
* @param size The amount of bytes to reserve.
* @return Result<u8*> An error, or a pointer to the requested area.
*/
Result<u8*> slice(usize offset, usize size);
/**
* @brief Add data to the end of the buffer.
*
* @param data A pointer to the data to add.
* @param size The amount of bytes to add.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> append_data(const u8* data, usize size);
/**
* @brief Remove data from the beginning of the buffer and return it.
*
* @param data A pointer to store the removed data in.
* @param size The amount of bytes to remove.
* @return usize The amount of bytes actually removed (may be less if the buffer was smaller than the requested
* size).
*/
usize dequeue_data(u8* data, usize size);
/**
* @brief Return a pointer to the data contained in the buffer.
*
* This pointer may be invalid after the buffer is resized.
*
* @return u8* The contained data.
*/
u8* data()
{
return m_data;
}
/**
* @brief Return a pointer to the data contained in the buffer.
*
* This pointer may be invalid after the buffer is resized.
*
* @return const u8* The contained data.
*/
const u8* data() const
{
return m_data;
}
/**
* @brief Return a pointer to the data contained in the buffer, moving the data out of the buffer.
*
* This call will empty the buffer, making it the caller's responsibility to manage the data, including freeing it
* when no longer used.
*
* @return u8* The released data.
*/
u8* release_data();
/**
* @brief Return a pointer to the end of the data contained in the buffer.
*
* This pointer points past the data; as such, dereferencing it directly is undefined behavior.
*
* @return u8* The end of the data.
*/
u8* end()
{
return m_data + m_size;
}
/**
* @brief Return a pointer to the end of the data contained in the buffer.
*
* This pointer points past the data; as such, dereferencing it directly is undefined behavior.
*
* @return const u8* The end of the data.
*/
const u8* end() const
{
return m_data + m_size;
}
/**
* @brief Return the size of the buffer in bytes.
*
* @return usize The buffer's size.
*/
usize size() const
{
return m_size;
}
/**
* @brief Check whether the buffer is empty.
*
* @return true The buffer is empty.
* @return false The buffer is not empty.
*/
bool is_empty() const
{
return m_size == 0;

View File

@ -1,29 +1,7 @@
/**
* @file CPath.h
* @author apio (cloudapio.eu)
* @brief Basic operations on paths using C-style strings.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
extern "C"
{
/**
* @brief Get the base name of a path.
*
* @param path The path to use. This will be modified.
* @return char* A pointer to the base name (usually points inside path).
*/
char* basename(char* path);
/**
* @brief Get the parent directory of a path.
*
* @param path The path to use. This will be modified.
* @return char* A pointer to the directory (usually points inside path).
*/
char* dirname(char* path);
char* basename(char*);
char* dirname(char*);
}

View File

@ -1,34 +1,11 @@
/**
* @file CRC32.h
* @author apio (cloudapio.eu)
* @brief CRC32 checksum calculation.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Types.h>
/**
* @brief A class to calculate a CRC32 checksum.
*/
class CRC32
{
public:
/**
* @brief Add data to the checksum.
*
* @param data The data to add.
* @param size The amount of bytes to add.
*/
void append(const u8* data, usize size);
/**
* @brief Calculate the final checksum.
*
* @return u32 The calculated checksum.
*/
u32 digest();
private:

View File

@ -1,12 +1,3 @@
/**
* @file CString.h
* @author apio (cloudapio.eu)
* @brief Implementations of C-string and memory manipulation functions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Types.h>

View File

@ -1,13 +1,3 @@
/**
* @file CType.h
* @author apio (cloudapio.eu)
* @brief Implementations of C-like character classification functions, prefixed with an underscore to avoid conflicting
* with libc.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
inline constexpr int _isascii(int c)

View File

@ -1,26 +1,6 @@
/**
* @file Check.h
* @author apio (cloudapio.eu)
* @brief Always-enabled assertions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#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);
#ifndef STRINGIZE_VALUE_OF
@ -28,63 +8,32 @@
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
#endif
/**
* @brief Verify an expression is true, or crash at runtime with a custom error message.
*/
// Like check(), but with a custom error message.
#define expect(expr, message) \
do { \
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), message); } \
} 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) \
do { \
if (!(expr)) [[unlikely]] { __check_failed(location, message); } \
} while (0)
/**
* @brief Crash at runtime with a custom error message.
*/
// Fail with an error message and location.
#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)
/**
* @brief Verify an expression is true, or crash at runtime.
*/
// Like assert(), but always enabled.
#define check(expr) \
do { \
if (!(expr)) [[unlikely]] { __check_failed(SourceLocation::current(), #expr); } \
} 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) \
do { \
if (!(expr)) [[unlikely]] { __check_failed(location, #expr); } \
} 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")
/**
* @brief Mark a code section as unimplemented, which will crash if reached.
*/
#define todo() __check_failed(SourceLocation::current(), "Reached a TODO!")

View File

@ -1,24 +1,9 @@
/**
* @file CircularQueue.h
* @author apio (cloudapio.eu)
* @brief Lock-free FIFO data structures.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Atomic.h>
#include <luna/Heap.h>
#include <luna/Result.h>
#include <luna/Types.h>
/**
* @brief An atomic lock-free circular FIFO queue.
*
* @tparam T The type of data to store in this queue.
* @tparam Size The amount of elements to make space for.
*/
template <typename T, usize Size> class CircularQueue
{
enum
@ -31,24 +16,11 @@ template <typename T, usize Size> class CircularQueue
{
}
/**
* @brief Return whether the queue is empty.
*
* @return true The queue is empty.
* @return false The queue is not empty.
*/
bool is_empty() const
{
return m_tail.load() == m_head.load();
}
/**
* @brief Push a value onto the queue.
*
* @param value The value to push.
* @return true The operation succeeded.
* @return false The queue was full or someone else was trying to push a value at the same time.
*/
bool try_push(const T& value)
{
usize current_tail = m_tail.load(MemoryOrder::Relaxed);
@ -67,13 +39,6 @@ template <typename T, usize Size> class CircularQueue
return true;
}
/**
* @brief Pop a value from the queue.
*
* @param value The variable to store the value into.
* @return true The operation succeeded.
* @return false The queue was empty or someone else was trying to pop a value at the same time.
*/
bool try_pop(T& value)
{
usize current_head = m_head.load(MemoryOrder::Relaxed);
@ -98,13 +63,6 @@ template <typename T, usize Size> class CircularQueue
Atomic<usize> m_tail = 0;
};
/**
* @brief An atomic lock-free circular FIFO queue.
*
* In this variant the size is set at runtime.
*
* @tparam T The type of data to store in this queue.
*/
template <typename T> class DynamicCircularQueue
{
@ -118,41 +76,18 @@ template <typename T> class DynamicCircularQueue
if (m_data) free_impl(m_data);
}
/**
* @brief Return whether the queue is empty.
*
* @return true The queue is empty.
* @return false The queue is not empty.
*/
bool is_empty() const
{
return m_tail.load() == m_head.load();
}
/**
* @brief Set the size of the queue and allocate memory for it.
*
* This should not be used to grow the queue, as all existing data is lost. In most cases, this function will only
* be called once to set the initial size of the queue and that's it.
*
* @param size The amount of elements to make space for.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> set_size(usize size)
{
if (m_data) free_impl(m_data);
m_data = (T*)TRY(calloc_impl(size + 1, sizeof(T), false));
m_capacity = size + 1;
return {};
}
/**
* @brief Push a value onto the queue.
*
* @param value The value to push.
* @return true The operation succeeded.
* @return false The queue was full or someone else was trying to push a value at the same time.
*/
bool try_push(const T& value)
{
check(m_capacity);
@ -172,13 +107,6 @@ template <typename T> class DynamicCircularQueue
return true;
}
/**
* @brief Pop a value from the queue.
*
* @param value The variable to store the value into.
* @return true The operation succeeded.
* @return false The queue was empty or someone else was trying to pop a value at the same time.
*/
bool try_pop(T& value)
{
check(m_capacity);

View File

@ -1,33 +1,7 @@
/**
* @file DebugLog.h
* @author apio (cloudapio.eu)
* @brief Debug logging for platform-agnostic functions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Attributes.h>
#include <stdarg.h>
/**
* @brief The actual debug log implementation. This must be provided by the platform or user.
*
* In the kernel, the implementation is located in src/Log.cpp.
* For POSIX systems, libluna provides an implementation in src/ImplPOSIX.cpp.
*
* The printed message must be followed by an implicit newline.
*
* @param format The format string (in the style of printf).
* @param ap The variadic argument list.
*/
extern void debug_log_impl(const char* format, va_list ap);
/**
* @brief Log a formatted message.
*
* @param format The format string (in the style of printf).
* @param ... The format arguments.
*/
void dbgln(const char* format, ...) _format(1, 2);

View File

@ -1,65 +1,16 @@
/**
* @file Format.h
* @author apio (cloudapio.eu)
* @brief C-style string formatting.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once
#include <luna/Attributes.h>
#include <luna/Result.h>
#include <stdarg.h>
/**
* @brief The callback type for cstyle_format.
*
* The first parameter is the resulting character, and the second one is the arbitrary argument passed to cstyle_format.
* Functions of this callback type can return errors, which will be propagated by cstyle_format.
*/
typedef Result<void> (*FormatCallback)(char, void*);
typedef Result<void> (*callback_t)(char, void*);
/**
* @brief Create a formatted string.
*
* Since this function uses a callback, it is very flexible; it can format output to a buffer, file, or whatever else is
* needed by the caller.
*
* This function lacks floating-point support, and wide character support, but otherwise, it has almost all C printf
* features: width, precision, alignment, size modifiers, and many more...
*
* This function is used to implemented all printf-related functions in Luna's libc and is the most tested component in
* libluna (see TestFormat.cpp, which tests it through String::format).
*
* @param format The C-style format string.
* @param callback The function to be called for every character in the resulting string.
* @param arg An arbitrary argument to pass to the callback function.
* @param ap The variadic argument list.
* @return Result<usize> An error, or the number of characters in the resulting string.
*/
Result<usize> cstyle_format(const char* format, FormatCallback callback, void* arg, va_list ap);
// Format output according to a format string and a list of variadic arguments. callback is called with arg for every
// character in the resulting string.
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap);
/**
* @brief Format a string into a fixed-size buffer.
*
* @param buf The buffer to store the resulting string into.
* @param max The maximum number of bytes to store in the buffer.
* @param format The format string.
* @param ap The variadic argument list.
* @return usize The number of characters in the formatted string. If it is more than or equal to max, the string was
* truncated.
*/
// Convenience function which outputs into a fixed-size buffer (not unlike vsnprintf)
usize vstring_format(char* buf, usize max, const char* format, va_list ap);
/**
* @brief Format a string into a fixed-size buffer.
*
* @param buf The buffer to store the resulting string into.
* @param max The maximum number of bytes to store in the buffer.
* @param format The format string.
* @param ... The format arguments.
* @return usize The number of characters in the formatted string. If it is more than or equal to max, the string was
* truncated.
*/
// Convenience function which outputs into a fixed-size buffer (not unlike snprintf)
usize string_format(char* buf, usize max, const char* format, ...) _format(3, 4);

View File

@ -1,61 +1,16 @@
/**
* @file Hash.h
* @author apio (cloudapio.eu)
* @brief Common hash functions for use in hash tables.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/CString.h>
#include <luna/Types.h>
/**
* @brief Calculate the hash of an area of memory.
*
* @param mem A pointer to the memory to hash.
* @param size The amount of bytes to use.
* @param salt A randomly generated salt to vary the output and avoid hash table attacks.
* @return u64 The calculated hash.
*/
u64 hash_memory(const void* mem, usize size, u64 salt);
/**
* @brief Calculate the hash of a value.
*
* The default implementation simply hashes the raw memory representation of the value. This may not be suitable for
* some types, so those can define a template specialization of this function to do their own hashing.
*
* @tparam T The type of the value to hash.
* @param value The value to hash.
* @param salt A randomly generated salt to vary the output and avoid hash table attacks.
* @return u64 The calculated hash.
*/
template <typename T> u64 hash(const T& value, u64 salt)
{
return hash_memory(&value, sizeof(value), salt);
}
/**
* @brief Template specialization of hash() for C-strings.
*
* This function hashes the actual string instead of the pointer value.
*
* @param value The C-string to hash.
* @param salt A randomly generated salt to vary the output and avoid hash table attacks.
* @return u64 The calculated hash.
*/
template <> u64 hash(const char* const& value, u64 salt);
/**
* @brief Swap two values of the same type.
*
* FIXME: This function should be moved to a more appropriate header.
*
* @tparam T The type of the values to swap.
* @param a The first value to swap.
* @param b The second value to swap.
*/
template <typename T> static void swap(T* a, T* b)
{
char* x = (char*)a;

View File

@ -1,94 +1,35 @@
/**
* @file HashMap.h
* @author apio (cloudapio.eu)
* @brief Map between keys and values with best-case constant time lookup.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/HashTable.h>
/**
* @brief Internal representation of a key-value pair in a HashMap.
*
* @tparam K The key type.
* @tparam V The value type.
*/
template <typename K, typename V> struct HashPair
{
K key;
Option<V> value;
/**
* @brief Compare two HashPair objects's keys.
*
* @param other The HashPair to compare against.
* @return true The keys match.
* @return false The keys do not match.
*/
bool operator==(const HashPair<K, V>& other) const
{
return key == other.key;
}
};
/**
* @brief Template specialization of hash() for HashPair objects.
*
* This function hashes only the key, ignoring the value.
*
* @tparam K The key type.
* @tparam V The value type.
* @param value The HashPair to hash.
* @param salt A randomly generated salt to vary the output and avoid hash table attacks.
* @return u64 The calculated hash.
*/
template <typename K, typename V> u64 hash(const HashPair<K, V>& value, u64 salt)
{
return hash(value.key, salt);
}
/**
* @brief A map between keys and values with best-case constant time lookup.
*
* @tparam K The key type.
* @tparam V The value type.
*/
template <typename K, typename V> struct HashMap
{
public:
/**
* @brief Try to insert a key-value pair into the HashMap.
*
* @param key The key to use.
* @param value The value to use.
* @return Result<bool> An error, true if the insertion succeeded, or false if the key already existed.
*/
Result<bool> try_set(const K& key, V&& value)
{
return m_table.try_set(HashPair<K, V> { key, move(value) });
}
/**
* @brief Try to insert a key-value pair into the HashMap.
*
* @param key The key to use.
* @param value The value to use.
* @return Result<bool> An error, true if the insertion succeeded, or false if the key already existed.
*/
Result<bool> try_set(const K& key, const V& value)
{
return m_table.try_set(HashPair<K, V> { key, value });
}
/**
* @brief Get the associated value for a key.
*
* @param key The key to use.
* @return Option<V> The associated value, or an empty option if the key did not exist.
*/
Option<V> try_get(const K& key)
{
auto* p = m_table.try_find(HashPair<K, V> { key, {} });
@ -96,14 +37,6 @@ template <typename K, typename V> struct HashMap
return p->value;
}
/**
* @brief Get a pointer to the associated value for a key inside the HashMap.
*
* This pointer should always be checked before usage.
*
* @param key The key to use.
* @return V* A pointer to the associated value, or nullptr if the key did not exist.
*/
V* try_get_ref(const K& key)
{
auto* p = m_table.try_find(HashPair<K, V> { key, {} });
@ -111,44 +44,21 @@ template <typename K, typename V> struct HashMap
return p->value.value_ptr();
}
/**
* @brief Remove a key-value pair from this HashMap.
*
* @param key The key to use.
* @return true The pair was successfully removed.
* @return false The key did not exist.
*/
bool try_remove(const K& key)
{
return m_table.try_remove(HashPair<K, V> { key, {} });
}
/**
* @brief Return the number of key-value pairs that can currently fit in the HashMap.
*
* The number of actual entries will always be smaller than this (unless it is 0), since the HashMap grows before
* the number of entries reaches the capacity.
*
* @return usize The current capacity.
*/
usize capacity() const
{
return m_table.capacity();
}
/**
* @brief Return the number of key-value pairs currently contained in this HashMap.
*
* @return usize The number of pairs contained.
*/
usize size() const
{
return m_table.size();
}
/**
* @brief Clear the HashMap.
*/
void clear()
{
m_table.clear();

View File

@ -1,50 +1,23 @@
/**
* @file HashTable.h
* @author apio (cloudapio.eu)
* @brief Table of values with best-case constant time lookup.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Hash.h>
#include <luna/Heap.h>
#include <luna/Option.h>
/**
* @brief A table of values with best-case constant time lookup.
*
* @tparam T The type of values to store.
*/
template <typename T> class HashTable
{
static constexpr usize GROW_RATE = 2;
static constexpr usize GROW_FACTOR = 2;
static constexpr usize INITIAL_CAPACITY = 32;
static constexpr usize GROW_FACTOR = 16;
public:
/**
* @brief Try to insert a value into the table.
*
* @param value The value to insert.
* @return Result<bool> An error, true if the insertion succeeded, or false if the value already existed.
*/
Result<bool> try_set(const T& value)
{
T copy { value };
return try_set(move(copy));
}
/**
* @brief Try to insert a value into the table.
*
* @param value The value to insert.
* @return Result<bool> An error, true if the insertion succeeded, or false if the value already existed.
*/
Result<bool> try_set(T&& value)
{
if (should_grow()) TRY(rehash(m_capacity ? m_capacity * GROW_FACTOR : INITIAL_CAPACITY));
if (should_grow()) TRY(rehash(m_capacity + GROW_FACTOR));
u64 index = hash(value, m_salt) % m_capacity;
@ -72,12 +45,6 @@ template <typename T> class HashTable
return true;
}
/**
* @brief Find a value inside the table, returning a pointer to it if found.
*
* @param value The value to compare against.
* @return T* A pointer to the value inside the table if found, or nullptr if it was not found.
*/
T* try_find(const T& value)
{
if (!m_size) return nullptr;
@ -102,13 +69,6 @@ template <typename T> class HashTable
return nullptr;
}
/**
* @brief Remove a value from this table.
*
* @param value The value to remove.
* @return true The value was successfully removed.
* @return false The value did not exist.
*/
bool try_remove(const T& value)
{
if (!m_size) return false;
@ -139,9 +99,6 @@ template <typename T> class HashTable
return false;
}
/**
* @brief Clear the table.
*/
void clear()
{
if (m_capacity)
@ -153,24 +110,11 @@ template <typename T> class HashTable
}
}
/**
* @brief Return the number of values that can currently fit in the table.
*
* The number of actual entries will always be smaller than this (unless it is 0), since the table grows before
* the number of entries reaches the capacity.
*
* @return usize The current capacity.
*/
usize capacity() const
{
return m_capacity;
}
/**
* @brief Return the number of values currently contained in the table.
*
* @return usize The number of values contained.
*/
usize size() const
{
return m_size;

View File

@ -1,19 +1,6 @@
/**
* @file Heap.h
* @author apio (cloudapio.eu)
* @brief libluna implementations of malloc-family functions.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <luna/Result.h>
/**
* @brief Freestanding definitions of std::nothrow and std::align_val_t.
*
*/
namespace std
{
struct nothrow_t
@ -28,100 +15,16 @@ 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;
/**
* @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;
/**
* @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;
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @brief libluna's free implementation.
*
* @param ptr The memory to free.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> free_impl(void* ptr);
/**
* @brief Dump heap usage stats to debug output.
*/
void dump_heap_usage();

View File

@ -1,29 +1,5 @@
/**
* @file Ignore.h
* @author apio (cloudapio.eu)
* @brief Do nothing.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
/**
* @brief Do nothing.
*
* Calling
* ignore(a, b, c);
* is a more compact equivalent of doing:
* (void)a;
* (void)b;
* (void)c;
*
* This function is used to discard unused variables avoiding compiler warnings, if you know they'll be used in the
* future.
*
* @tparam Args The list of ignored variable types.
*/
template <class... Args> constexpr void ignore(Args...)
{
}

View File

@ -1,12 +1,3 @@
/**
* @file Base64.cpp
* @author apio (cloudapio.eu)
* @brief Base64 encoding and decoding.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/Base64.h>
#include <luna/CType.h>
#include <luna/DebugLog.h>
@ -161,6 +152,6 @@ namespace Base64
u8 nul_byte = '\0';
TRY(buf.append_data(&nul_byte, 1));
return String { (char*)buf.release_data(), buf.size() - 1 };
return String { (char*)buf.release_data() };
}
}

View File

@ -1,12 +1,3 @@
/**
* @file Bitmap.cpp
* @author apio (cloudapio.eu)
* @brief An interface to an array of bits.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#include <luna/Bitmap.h>
#include <luna/CString.h>
#include <luna/Check.h>
@ -26,6 +17,24 @@ void Bitmap::initialize(void* location, usize size_in_bytes)
m_size_in_bytes = size_in_bytes;
}
Result<void> Bitmap::allocate(usize size_in_bytes)
{
initialize(TRY(malloc_impl(size_in_bytes)), size_in_bytes);
return {};
}
Result<void*> Bitmap::resize(usize new_size_in_bytes)
{
m_location = (u8*)TRY(realloc_impl(m_location, new_size_in_bytes));
m_size_in_bytes = new_size_in_bytes;
return (void*)m_location;
}
Result<void> Bitmap::deallocate()
{
return free_impl(m_location);
}
void* Bitmap::move(void* new_location, usize new_location_size_in_bytes)
{
if (new_location_size_in_bytes > m_size_in_bytes) memcpy(new_location, m_location, m_size_in_bytes);

View File

@ -1,12 +1,3 @@
/**
* @file Buffer.cpp
* @author apio (cloudapio.eu)
* @brief A managed wrapper around a resizable buffer of arbitrary memory.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/Buffer.h>
#include <luna/CString.h>
#include <luna/Heap.h>

View File

@ -1,12 +1,3 @@
/**
* @file CPath.cpp
* @author apio (cloudapio.eu)
* @brief Basic operations on paths using C-style strings.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/CPath.h>
#include <luna/CString.h>

View File

@ -1,13 +1,5 @@
/**
* @file CRC32.cpp
* @author apio (cloudapio.eu)
* @brief CRC32 checksum calculation.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/CRC32.h>
#include <luna/DebugLog.h>
static const u32 crc_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,

View File

@ -1,15 +1,6 @@
/**
* @file CString.cpp
* @author apio (cloudapio.eu)
* @brief Implementations of C-string and memory manipulation functions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#include <luna/Alloc.h>
#include <luna/CString.h>
#include <luna/CType.h>
#include <luna/Heap.h>
extern "C"
{

View File

@ -1,12 +1,3 @@
/**
* @file CppABI.cpp
* @author apio (cloudapio.eu)
* @brief Implementation of some C++ ABI internal functions, mainly __cxa_atexit.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
typedef void* (*cxa_atexit_func_t)(void*);
struct cxa_atexit_entry

View File

@ -1,12 +1,3 @@
/**
* @file DebugLog.cpp
* @author apio (cloudapio.eu)
* @brief Debug logging for platform-agnostic functions.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#include <luna/DebugLog.h>
void dbgln(const char* format, ...)

View File

@ -1,12 +1,3 @@
/**
* @file Format.cpp
* @author apio (cloudapio.eu)
* @brief C-style string formatting.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#include <luna/CType.h>
#include <luna/Format.h>
#include <luna/NumberParsing.h>
@ -31,7 +22,7 @@ typedef int flags_t;
struct format_state
{
usize count;
FormatCallback callback;
callback_t callback;
void* arg;
};
@ -394,7 +385,7 @@ static Result<void> va_output_integer(char specifier, conv_state& vstate, format
}
}
Result<usize> cstyle_format(const char* format, FormatCallback callback, void* arg, va_list ap)
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap)
{
format_state state;
state.callback = callback;

View File

@ -1,13 +1,3 @@
/**
* @file Hash.cpp
* @author apio (cloudapio.eu)
* @brief Common hash functions for use in hash tables.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#include <luna/CString.h>
#include <luna/Hash.h>
u64 hash_memory(const void* mem, usize size, u64 salt)

View File

@ -1,12 +1,3 @@
/**
* @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/Alloc.h>
#include <luna/CString.h>
@ -434,12 +425,12 @@ void dump_heap_usage()
#ifdef USE_FREESTANDING
void* operator new(usize size, const std::nothrow_t&) noexcept
{
return malloc_impl(size, false, false).value_or(nullptr);
return malloc_impl(size).value_or(nullptr);
}
void* operator new[](usize size, const std::nothrow_t&) noexcept
{
return malloc_impl(size, false, false).value_or(nullptr);
return malloc_impl(size).value_or(nullptr);
}
void operator delete(void* p) noexcept

View File

@ -1,11 +1,4 @@
/**
* @file ImplPOSIX.cpp
* @author apio (cloudapio.eu)
* @brief POSIX userspace implementation of libluna hooks.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
/* POSIX userspace implementation of libluna hooks. */
#include <luna/Attributes.h>
#include <luna/Result.h>

View File

@ -41,7 +41,7 @@ namespace os
* _exit(2). If NULL, the promises are not changed.
* @param execpromises The promises to apply on the next call to execve(2), separated by spaces. If empty, the
* process may only call _exit(2). If NULL, the execpromises are not changed.
* @return Result<void> Whether the operation succeeded.
* @return Result<void> Whether the operation succeded.
*/
Result<void> pledge(const char* promises, const char* execpromises);
}

View File

@ -31,5 +31,3 @@ mkdir -p base/tmp
rm -f base/bin
ln -s usr/bin base/bin
cp $LUNA_ROOT/LICENSE base/etc/skel/LICENSE