Compare commits
35 Commits
70bbdbd8f5
...
0ff365c7f0
Author | SHA1 | Date |
---|---|---|
|
0ff365c7f0 | |
|
214e7a5672 | |
|
24b69a6dea | |
|
699235147c | |
|
72ad413a61 | |
|
f11bb082e4 | |
|
2f3fd6867d | |
|
350ae90bb6 | |
|
fb61cab70d | |
|
1d6c08478d | |
|
0dfe0b7023 | |
|
def236b7cd | |
|
247743ef9c | |
|
49122cf729 | |
|
84f579be81 | |
|
3d5f23a1b2 | |
|
8b26b6604d | |
|
f88e55ffa8 | |
|
34bdcb12e5 | |
|
95b353dae5 | |
|
6560f229b1 | |
|
8c9ab2d68c | |
|
8496726ab1 | |
|
32d7f429f8 | |
|
0f52f49188 | |
|
b334259a07 | |
|
74af4e9150 | |
|
8b7790ded2 | |
|
3e97a82af0 | |
|
0066b20413 | |
|
9d6656451a | |
|
32f980e259 | |
|
ca9361abc1 | |
|
36cb3d56fe | |
|
0bece8a54c |
|
@ -34,4 +34,6 @@ signal_trampoline:
|
||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
popf
|
popf
|
||||||
|
|
||||||
|
movl (%esp), %esp
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -59,5 +59,7 @@ signal_trampoline:
|
||||||
addq $16, %rsp
|
addq $16, %rsp
|
||||||
popfq
|
popfq
|
||||||
|
|
||||||
|
movq (%rsp), %rsp
|
||||||
|
|
||||||
// return over red-zone
|
// return over red-zone
|
||||||
ret $128
|
ret $128
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/ByteSpan.h>
|
||||||
|
#include <BAN/Debug.h>
|
||||||
|
#include <BAN/Optional.h>
|
||||||
|
|
||||||
|
namespace Kernel::ACPI
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ResourceData
|
||||||
|
{
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
IRQ,
|
||||||
|
DMA,
|
||||||
|
IOPort,
|
||||||
|
FixedIOPort,
|
||||||
|
FixedDMA,
|
||||||
|
|
||||||
|
// TODO: large stuff the stuff :)
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint16_t irq_mask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t edge_triggered : 1;
|
||||||
|
uint8_t : 2;
|
||||||
|
uint8_t active_low : 1;
|
||||||
|
uint8_t shared : 1;
|
||||||
|
uint8_t wake_capable : 1;
|
||||||
|
uint8_t : 2;
|
||||||
|
};
|
||||||
|
uint8_t raw;
|
||||||
|
};
|
||||||
|
} irq;
|
||||||
|
struct {
|
||||||
|
uint8_t channel_mask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t type : 2; // 0: 8 bit, 1: 8 and 16 bit, 2: 16 bit only
|
||||||
|
uint8_t bus_master : 1;
|
||||||
|
uint8_t : 2;
|
||||||
|
uint8_t channel_speed : 2; // 0: compatibility, 1: type A, 2: type B, 3: type F
|
||||||
|
uint8_t : 1;
|
||||||
|
};
|
||||||
|
uint8_t raw;
|
||||||
|
};
|
||||||
|
} dma;
|
||||||
|
struct {
|
||||||
|
uint16_t range_min_base;
|
||||||
|
uint16_t range_max_base;
|
||||||
|
uint8_t base_alignment;
|
||||||
|
uint8_t range_length;
|
||||||
|
} io_port;
|
||||||
|
struct {
|
||||||
|
uint16_t range_base;
|
||||||
|
uint8_t range_length;
|
||||||
|
} fixed_io_port;
|
||||||
|
struct {
|
||||||
|
uint16_t request_line;
|
||||||
|
uint16_t channel;
|
||||||
|
uint8_t transfer_width; // 0: 8 bit, 1: 16 bit, 2: 32 bit, 3: 64 bit, 4: 128 bit
|
||||||
|
} fixed_dma;
|
||||||
|
} as;
|
||||||
|
Type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourceParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceParser(BAN::ConstByteSpan buffer)
|
||||||
|
: m_buffer(buffer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BAN::Optional<ResourceData> get_next()
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (m_buffer.empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (m_buffer[0] & 0x80)
|
||||||
|
{
|
||||||
|
dprintln("Skipping large resource 0x{2H}", m_buffer[0] & 0x7F);
|
||||||
|
const uint16_t length = (m_buffer[2] << 8) | m_buffer[1];
|
||||||
|
if (m_buffer.size() < static_cast<size_t>(3 + length))
|
||||||
|
return {};
|
||||||
|
m_buffer = m_buffer.slice(3 + length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t length = m_buffer[0] & 0x07;
|
||||||
|
if (m_buffer.size() < static_cast<size_t>(1 + length))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
BAN::Optional<ResourceData> result;
|
||||||
|
switch ((m_buffer[0] >> 3) & 0x0F)
|
||||||
|
{
|
||||||
|
case 0x04:
|
||||||
|
if (length < 2)
|
||||||
|
break;
|
||||||
|
result = ResourceData {
|
||||||
|
.as = { .irq = {
|
||||||
|
.irq_mask = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
||||||
|
.raw = (length >= 3) ? m_buffer[3] : static_cast<uint8_t>(1),
|
||||||
|
}},
|
||||||
|
.type = ResourceData::Type::IRQ,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
if (length < 2)
|
||||||
|
break;
|
||||||
|
result = ResourceData {
|
||||||
|
.as = { .dma = {
|
||||||
|
.channel_mask = m_buffer[1],
|
||||||
|
.raw = m_buffer[2],
|
||||||
|
}},
|
||||||
|
.type = ResourceData::Type::DMA,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
if (length < 7)
|
||||||
|
break;
|
||||||
|
result = ResourceData {
|
||||||
|
.as = { .io_port = {
|
||||||
|
.range_min_base = static_cast<uint16_t>(((m_buffer[3] << 8) | m_buffer[2]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
||||||
|
.range_max_base = static_cast<uint16_t>(((m_buffer[5] << 8) | m_buffer[4]) & ((m_buffer[1] & 1) ? 0xFFFF : 0x03FF)),
|
||||||
|
.base_alignment = m_buffer[6],
|
||||||
|
.range_length = m_buffer[7],
|
||||||
|
}},
|
||||||
|
.type = ResourceData::Type::IOPort,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 0x09:
|
||||||
|
if (length < 3)
|
||||||
|
break;
|
||||||
|
result = ResourceData {
|
||||||
|
.as = { .fixed_io_port = {
|
||||||
|
.range_base = static_cast<uint16_t>(((m_buffer[2] << 8) | m_buffer[1]) & 0x03FF),
|
||||||
|
.range_length = m_buffer[3],
|
||||||
|
}},
|
||||||
|
.type = ResourceData::Type::FixedIOPort,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 0x0A:
|
||||||
|
if (length < 5)
|
||||||
|
break;
|
||||||
|
result = ResourceData {
|
||||||
|
.as = { .fixed_dma = {
|
||||||
|
.request_line = static_cast<uint16_t>((m_buffer[2] << 8) | m_buffer[1]),
|
||||||
|
.channel = static_cast<uint16_t>((m_buffer[4] << 8) | m_buffer[3]),
|
||||||
|
.transfer_width = m_buffer[5],
|
||||||
|
}},
|
||||||
|
.type = ResourceData::Type::FixedDMA,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 0x0F:
|
||||||
|
// End tag
|
||||||
|
return {};
|
||||||
|
case 0x06:
|
||||||
|
case 0x07:
|
||||||
|
case 0x0E:
|
||||||
|
dprintln("Skipping short resource 0x{2H}", (m_buffer[0] >> 3) & 0x0F);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer = m_buffer.slice(1 + length);
|
||||||
|
if (result.has_value())
|
||||||
|
return result.release_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::ConstByteSpan m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -193,6 +193,9 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
BAN::ErrorOr<long> sys_sigaction(int signal, const struct sigaction* act, struct sigaction* oact);
|
||||||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||||
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
||||||
|
BAN::ErrorOr<long> sys_sigsuspend(const sigset_t* set);
|
||||||
|
BAN::ErrorOr<long> sys_sigwait(const sigset_t* set, int* sig);
|
||||||
|
BAN::ErrorOr<long> sys_sigaltstack(const stack_t* ss, stack_t* oss);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
||||||
BAN::ErrorOr<long> sys_yield();
|
BAN::ErrorOr<long> sys_yield();
|
||||||
|
@ -347,14 +350,6 @@ namespace Kernel
|
||||||
BAN::UniqPtr<PageTable> m_page_table;
|
BAN::UniqPtr<PageTable> m_page_table;
|
||||||
BAN::RefPtr<TTY> m_controlling_terminal;
|
BAN::RefPtr<TTY> m_controlling_terminal;
|
||||||
|
|
||||||
struct futex_t
|
|
||||||
{
|
|
||||||
ThreadBlocker blocker;
|
|
||||||
uint32_t waiters { 0 };
|
|
||||||
uint32_t to_wakeup { 0 };
|
|
||||||
};
|
|
||||||
BAN::HashMap<paddr_t, BAN::UniqPtr<futex_t>> m_futexes;
|
|
||||||
|
|
||||||
friend class Thread;
|
friend class Thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
|
#include <BAN/Optional.h>
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <BAN/UniqPtr.h>
|
#include <BAN/UniqPtr.h>
|
||||||
#include <kernel/InterruptStack.h>
|
#include <kernel/InterruptStack.h>
|
||||||
|
@ -59,7 +60,10 @@ namespace Kernel
|
||||||
bool will_execute_signal() const;
|
bool will_execute_signal() const;
|
||||||
// Returns true if handled signal had SA_RESTART
|
// Returns true if handled signal had SA_RESTART
|
||||||
bool handle_signal(int signal = 0);
|
bool handle_signal(int signal = 0);
|
||||||
bool add_signal(int signal);
|
void add_signal(int signal);
|
||||||
|
void set_suspend_signal_mask(uint64_t sigmask);
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> sigaltstack(const stack_t* ss, stack_t* oss);
|
||||||
|
|
||||||
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout
|
||||||
// if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
|
// if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
|
||||||
|
@ -138,6 +142,8 @@ namespace Kernel
|
||||||
static void on_exit_trampoline(Thread*);
|
static void on_exit_trampoline(Thread*);
|
||||||
void on_exit();
|
void on_exit();
|
||||||
|
|
||||||
|
bool currently_on_alternate_stack() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// NOTE: this is the first member to force it being last destructed
|
// NOTE: this is the first member to force it being last destructed
|
||||||
// {kernel,userspace}_stack has to be destroyed before page table
|
// {kernel,userspace}_stack has to be destroyed before page table
|
||||||
|
@ -160,7 +166,9 @@ namespace Kernel
|
||||||
|
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
uint64_t m_signal_block_mask { 0 };
|
uint64_t m_signal_block_mask { 0 };
|
||||||
|
BAN::Optional<uint64_t> m_signal_suspend_mask;
|
||||||
SpinLock m_signal_lock;
|
SpinLock m_signal_lock;
|
||||||
|
stack_t m_signal_alt_stack { nullptr, 0, SS_DISABLE };
|
||||||
static_assert(_SIGMAX < 64);
|
static_assert(_SIGMAX < 64);
|
||||||
|
|
||||||
mutable SpinLock m_cpu_time_lock;
|
mutable SpinLock m_cpu_time_lock;
|
||||||
|
|
|
@ -438,7 +438,7 @@ namespace Kernel::ACPI::AML
|
||||||
{
|
{
|
||||||
dprintln_if(AML_DUMP_FUNCTION_CALLS, "find_named_object('{}', '{}')", scope, name_string);
|
dprintln_if(AML_DUMP_FUNCTION_CALLS, "find_named_object('{}', '{}')", scope, name_string);
|
||||||
|
|
||||||
if (force_absolute || name_string.base != 0)
|
if (force_absolute || name_string.base != 0 || name_string.parts.size() > 1)
|
||||||
{
|
{
|
||||||
// Absolute path
|
// Absolute path
|
||||||
|
|
||||||
|
@ -460,23 +460,15 @@ namespace Kernel::ACPI::AML
|
||||||
// Relative path
|
// Relative path
|
||||||
|
|
||||||
Scope path_guess;
|
Scope path_guess;
|
||||||
TRY(path_guess.parts.reserve(scope.parts.size() + name_string.parts.size()));
|
TRY(path_guess.parts.reserve(scope.parts.size() + 1));
|
||||||
|
const uint32_t name_seg = name_string.parts.front();
|
||||||
|
|
||||||
for (const auto& part : scope.parts)
|
for (const auto& part : scope.parts)
|
||||||
TRY(path_guess.parts.push_back(part));
|
TRY(path_guess.parts.push_back(part));
|
||||||
for (const auto& part : name_string.parts)
|
TRY(path_guess.parts.push_back(name_seg));
|
||||||
TRY(path_guess.parts.push_back(part));
|
|
||||||
|
|
||||||
auto it = m_named_objects.find(path_guess);
|
for (;;)
|
||||||
if (it != m_named_objects.end()) {
|
|
||||||
return FindResult {
|
|
||||||
.path = BAN::move(path_guess),
|
|
||||||
.node = it->value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < scope.parts.size(); i++)
|
|
||||||
{
|
{
|
||||||
path_guess.parts.remove(scope.parts.size() - i - 1);
|
|
||||||
auto it = m_named_objects.find(path_guess);
|
auto it = m_named_objects.find(path_guess);
|
||||||
if (it != m_named_objects.end()) {
|
if (it != m_named_objects.end()) {
|
||||||
return FindResult {
|
return FindResult {
|
||||||
|
@ -484,14 +476,19 @@ namespace Kernel::ACPI::AML
|
||||||
.node = it->value,
|
.node = it->value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (path_guess.parts.size() == 1) {
|
||||||
return FindResult {
|
return FindResult {
|
||||||
.path = {},
|
.path = {},
|
||||||
.node = nullptr,
|
.node = nullptr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path_guess.parts.pop_back();
|
||||||
|
path_guess.parts.back() = name_seg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<Scope> Namespace::find_reference_scope(const Reference* reference)
|
BAN::ErrorOr<Scope> Namespace::find_reference_scope(const Reference* reference)
|
||||||
{
|
{
|
||||||
for (const auto& [obj_path, obj_ref] : m_named_objects)
|
for (const auto& [obj_path, obj_ref] : m_named_objects)
|
||||||
|
|
|
@ -30,19 +30,19 @@ namespace Kernel
|
||||||
|
|
||||||
timespec FATInode::atime() const
|
timespec FATInode::atime() const
|
||||||
{
|
{
|
||||||
uint64_t epoch = fat_date_to_epoch(m_entry.last_access_date, {});
|
const time_t epoch = fat_date_to_epoch(m_entry.last_access_date, {});
|
||||||
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec FATInode::mtime() const
|
timespec FATInode::mtime() const
|
||||||
{
|
{
|
||||||
uint64_t epoch = fat_date_to_epoch(m_entry.write_date, m_entry.write_time);
|
const time_t epoch = fat_date_to_epoch(m_entry.write_date, m_entry.write_time);
|
||||||
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec FATInode::ctime() const
|
timespec FATInode::ctime() const
|
||||||
{
|
{
|
||||||
uint64_t epoch = fat_date_to_epoch(m_entry.creation_date, m_entry.creation_time);
|
const time_t epoch = fat_date_to_epoch(m_entry.creation_date, m_entry.creation_time);
|
||||||
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,22 +318,22 @@ namespace Kernel::Input
|
||||||
m_scancode_to_keycode_normal[0x58] = keycode_normal(4, 5);
|
m_scancode_to_keycode_normal[0x58] = keycode_normal(4, 5);
|
||||||
|
|
||||||
m_scancode_to_keycode_normal[0x76] = keycode_numpad(0, 0);
|
m_scancode_to_keycode_normal[0x76] = keycode_numpad(0, 0);
|
||||||
//m_scancode_to_keycode_normal[0x] = keycode_numpad(0, 1);
|
m_scancode_to_keycode_normal[0x4A] = keycode_numpad(0, 1);
|
||||||
m_scancode_to_keycode_normal[0x7E] = keycode_numpad(0, 2);
|
m_scancode_to_keycode_normal[0x7E] = keycode_numpad(0, 2);
|
||||||
//m_scancode_to_keycode_normal[0x] = keycode_numpad(0, 3);
|
m_scancode_to_keycode_normal[0x4E] = keycode_numpad(0, 3);
|
||||||
m_scancode_to_keycode_normal[0x6C] = keycode_numpad(1, 1);
|
m_scancode_to_keycode_normal[0x6C] = keycode_numpad(1, 0);
|
||||||
m_scancode_to_keycode_normal[0x75] = keycode_numpad(1, 2);
|
m_scancode_to_keycode_normal[0x75] = keycode_numpad(1, 1);
|
||||||
m_scancode_to_keycode_normal[0x7D] = keycode_numpad(1, 3);
|
m_scancode_to_keycode_normal[0x7D] = keycode_numpad(1, 2);
|
||||||
m_scancode_to_keycode_normal[0x7C] = keycode_numpad(1, 4);
|
m_scancode_to_keycode_normal[0x7C] = keycode_numpad(1, 3);
|
||||||
m_scancode_to_keycode_normal[0x6B] = keycode_numpad(2, 1);
|
m_scancode_to_keycode_normal[0x6B] = keycode_numpad(2, 0);
|
||||||
m_scancode_to_keycode_normal[0x73] = keycode_numpad(2, 2);
|
m_scancode_to_keycode_normal[0x73] = keycode_numpad(2, 1);
|
||||||
m_scancode_to_keycode_normal[0x74] = keycode_numpad(2, 3);
|
m_scancode_to_keycode_normal[0x74] = keycode_numpad(2, 2);
|
||||||
m_scancode_to_keycode_normal[0x69] = keycode_numpad(3, 1);
|
m_scancode_to_keycode_normal[0x69] = keycode_numpad(3, 0);
|
||||||
m_scancode_to_keycode_normal[0x72] = keycode_numpad(3, 2);
|
m_scancode_to_keycode_normal[0x72] = keycode_numpad(3, 1);
|
||||||
m_scancode_to_keycode_normal[0x7A] = keycode_numpad(3, 3);
|
m_scancode_to_keycode_normal[0x7A] = keycode_numpad(3, 2);
|
||||||
m_scancode_to_keycode_normal[0x79] = keycode_numpad(3, 4);
|
m_scancode_to_keycode_normal[0x79] = keycode_numpad(3, 3);
|
||||||
m_scancode_to_keycode_normal[0x70] = keycode_numpad(4, 1);
|
m_scancode_to_keycode_normal[0x70] = keycode_numpad(4, 0);
|
||||||
m_scancode_to_keycode_normal[0x71] = keycode_numpad(4, 2);
|
m_scancode_to_keycode_normal[0x71] = keycode_numpad(4, 1);
|
||||||
|
|
||||||
m_scancode_to_keycode_normal[0x08] = keycode_function(0);
|
m_scancode_to_keycode_normal[0x08] = keycode_function(0);
|
||||||
m_scancode_to_keycode_normal[0x07] = keycode_function(1);
|
m_scancode_to_keycode_normal[0x07] = keycode_function(1);
|
||||||
|
|
|
@ -289,10 +289,10 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> UnixDomainSocket::add_packet(BAN::ConstByteSpan packet)
|
BAN::ErrorOr<void> UnixDomainSocket::add_packet(BAN::ConstByteSpan packet)
|
||||||
{
|
{
|
||||||
auto state = m_packet_lock.lock();
|
SpinLockGuard guard(m_packet_lock);
|
||||||
while (m_packet_sizes.full() || m_packet_size_total + packet.size() > s_packet_buffer_size)
|
while (m_packet_sizes.full() || m_packet_size_total + packet.size() > s_packet_buffer_size)
|
||||||
{
|
{
|
||||||
SpinLockAsMutex smutex(m_packet_lock, state);
|
SpinLockGuardAsMutex smutex(guard);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,6 @@ namespace Kernel
|
||||||
m_packet_sizes.push(packet.size());
|
m_packet_sizes.push(packet.size());
|
||||||
|
|
||||||
m_packet_thread_blocker.unblock();
|
m_packet_thread_blocker.unblock();
|
||||||
m_packet_lock.unlock(state);
|
|
||||||
|
|
||||||
epoll_notify(EPOLLIN);
|
epoll_notify(EPOLLIN);
|
||||||
|
|
||||||
|
@ -414,7 +413,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> UnixDomainSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr*, socklen_t*)
|
BAN::ErrorOr<size_t> UnixDomainSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr*, socklen_t*)
|
||||||
{
|
{
|
||||||
auto state = m_packet_lock.lock();
|
SpinLockGuard guard(m_packet_lock);
|
||||||
while (m_packet_size_total == 0)
|
while (m_packet_size_total == 0)
|
||||||
{
|
{
|
||||||
if (m_info.has<ConnectionInfo>())
|
if (m_info.has<ConnectionInfo>())
|
||||||
|
@ -422,18 +421,12 @@ namespace Kernel
|
||||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||||
bool expected = true;
|
bool expected = true;
|
||||||
if (connection_info.target_closed.compare_exchange(expected, false))
|
if (connection_info.target_closed.compare_exchange(expected, false))
|
||||||
{
|
|
||||||
m_packet_lock.unlock(state);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (!connection_info.connection)
|
if (!connection_info.connection)
|
||||||
{
|
|
||||||
m_packet_lock.unlock(state);
|
|
||||||
return BAN::Error::from_errno(ENOTCONN);
|
return BAN::Error::from_errno(ENOTCONN);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SpinLockAsMutex smutex(m_packet_lock, state);
|
SpinLockGuardAsMutex smutex(guard);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_packet_thread_blocker, &smutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +446,6 @@ namespace Kernel
|
||||||
m_packet_size_total -= nread;
|
m_packet_size_total -= nread;
|
||||||
|
|
||||||
m_packet_thread_blocker.unblock();
|
m_packet_thread_blocker.unblock();
|
||||||
m_packet_lock.unlock(state);
|
|
||||||
|
|
||||||
epoll_notify(EPOLLOUT);
|
epoll_notify(EPOLLOUT);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,15 @@ namespace Kernel
|
||||||
static BAN::Vector<Process*> s_processes;
|
static BAN::Vector<Process*> s_processes;
|
||||||
static RecursiveSpinLock s_process_lock;
|
static RecursiveSpinLock s_process_lock;
|
||||||
|
|
||||||
|
struct futex_t
|
||||||
|
{
|
||||||
|
ThreadBlocker blocker;
|
||||||
|
uint32_t waiters { 0 };
|
||||||
|
uint32_t to_wakeup { 0 };
|
||||||
|
};
|
||||||
|
static BAN::HashMap<paddr_t, BAN::UniqPtr<futex_t>> s_futexes;
|
||||||
|
static Mutex s_futex_lock;
|
||||||
|
|
||||||
static void for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback)
|
static void for_each_process(const BAN::Function<BAN::Iteration(Process&)>& callback)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(s_process_lock);
|
SpinLockGuard _(s_process_lock);
|
||||||
|
@ -309,7 +318,7 @@ namespace Kernel
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
for (auto* thread : m_threads)
|
for (auto* thread : m_threads)
|
||||||
if (thread != &Thread::current())
|
if (thread != &Thread::current())
|
||||||
ASSERT(thread->add_signal(SIGKILL));
|
thread->add_signal(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_threads.size() > 1)
|
while (m_threads.size() > 1)
|
||||||
|
@ -1158,7 +1167,9 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
|
BAN::ErrorOr<long> Process::sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path1 != nullptr)
|
||||||
TRY(validate_string_access(path1));
|
TRY(validate_string_access(path1));
|
||||||
|
if (path2 != nullptr)
|
||||||
TRY(validate_string_access(path2));
|
TRY(validate_string_access(path2));
|
||||||
|
|
||||||
auto inode = TRY(find_file(fd1, path1, flag)).inode;
|
auto inode = TRY(find_file(fd1, path1, flag)).inode;
|
||||||
|
@ -1180,6 +1191,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_WRONLY));
|
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_WRONLY));
|
||||||
|
@ -1195,6 +1207,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
TRY(validate_pointer_access(buffer, bufsize, true));
|
TRY(validate_pointer_access(buffer, bufsize, true));
|
||||||
|
|
||||||
|
@ -1262,6 +1275,7 @@ namespace Kernel
|
||||||
flag = O_NOFOLLOW;
|
flag = O_NOFOLLOW;
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||||
|
@ -1285,6 +1299,7 @@ namespace Kernel
|
||||||
flag = O_NOFOLLOW;
|
flag = O_NOFOLLOW;
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||||
|
@ -1971,6 +1986,8 @@ namespace Kernel
|
||||||
flag = O_NOFOLLOW;
|
flag = O_NOFOLLOW;
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
|
TRY(validate_string_access(path));
|
||||||
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
||||||
|
|
||||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||||
|
@ -1994,6 +2011,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_fstatvfsat(int fd, const char* path, struct statvfs* buf)
|
BAN::ErrorOr<long> Process::sys_fstatvfsat(int fd, const char* path, struct statvfs* buf)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
if (path != nullptr)
|
||||||
|
TRY(validate_string_access(path));
|
||||||
TRY(validate_pointer_access(buf, sizeof(struct statvfs), true));
|
TRY(validate_pointer_access(buf, sizeof(struct statvfs), true));
|
||||||
|
|
||||||
auto inode = TRY(find_file(fd, path, 0)).inode;
|
auto inode = TRY(find_file(fd, path, 0)).inode;
|
||||||
|
@ -2158,6 +2177,17 @@ namespace Kernel
|
||||||
vaddr_t base_addr = reinterpret_cast<vaddr_t>(args.addr);
|
vaddr_t base_addr = reinterpret_cast<vaddr_t>(args.addr);
|
||||||
address_range.start = BAN::Math::div_round_up<vaddr_t>(base_addr, PAGE_SIZE) * PAGE_SIZE;
|
address_range.start = BAN::Math::div_round_up<vaddr_t>(base_addr, PAGE_SIZE) * PAGE_SIZE;
|
||||||
address_range.end = BAN::Math::div_round_up<vaddr_t>(base_addr + args.len, PAGE_SIZE) * PAGE_SIZE;
|
address_range.end = BAN::Math::div_round_up<vaddr_t>(base_addr + args.len, PAGE_SIZE) * PAGE_SIZE;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_mapped_regions.size(); i++)
|
||||||
|
{
|
||||||
|
if (!m_mapped_regions[i]->overlaps(base_addr, args.len))
|
||||||
|
continue;
|
||||||
|
if (!m_mapped_regions[i]->contains_fully(base_addr, args.len))
|
||||||
|
derrorln("VERY BROKEN MAP_FIXED UNMAP");
|
||||||
|
m_mapped_regions[i]->wait_not_pinned();
|
||||||
|
m_mapped_regions.remove(i--);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.flags & MAP_ANONYMOUS)
|
if (args.flags & MAP_ANONYMOUS)
|
||||||
|
@ -2641,23 +2671,81 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_sigsuspend(const sigset_t* set)
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
TRY(validate_pointer_access(set, sizeof(sigset_t), false));
|
||||||
|
|
||||||
|
auto& thread = Thread::current();
|
||||||
|
thread.set_suspend_signal_mask(*set & ~(SIGKILL | SIGSTOP));
|
||||||
|
|
||||||
|
while (!thread.is_interrupted_by_signal())
|
||||||
|
Processor::scheduler().block_current_thread(nullptr, -1, &m_process_lock);
|
||||||
|
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_sigwait(const sigset_t* set, int* sig)
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
auto& thread = Thread::current();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
TRY(validate_pointer_access(set, sizeof(sigset_t), false));
|
||||||
|
TRY(validate_pointer_access(sig, sizeof(int), true));
|
||||||
|
|
||||||
|
{
|
||||||
|
SpinLockGuard _1(thread.m_signal_lock);
|
||||||
|
SpinLockGuard _2(m_signal_lock);
|
||||||
|
|
||||||
|
const uint64_t pending = thread.m_signal_pending_mask | this->m_signal_pending_mask;
|
||||||
|
if (const auto wait_mask = pending & *set)
|
||||||
|
{
|
||||||
|
for (size_t i = _SIGMIN; i <= _SIGMAX; i++)
|
||||||
|
{
|
||||||
|
const auto mask = 1ull << i;
|
||||||
|
if (!(wait_mask & mask))
|
||||||
|
continue;
|
||||||
|
thread.m_signal_pending_mask &= ~mask;
|
||||||
|
this->m_signal_pending_mask &= ~mask;
|
||||||
|
*sig = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Processor::scheduler().block_current_thread(nullptr, -1, &m_process_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_sigaltstack(const stack_t* ss, stack_t* oss)
|
||||||
|
{
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
if (ss != nullptr)
|
||||||
|
TRY(validate_pointer_access(ss, sizeof(stack_t), false));
|
||||||
|
if (oss != nullptr)
|
||||||
|
TRY(validate_pointer_access(oss, sizeof(stack_t), true));
|
||||||
|
|
||||||
|
TRY(Thread::current().sigaltstack(ss, oss));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime)
|
BAN::ErrorOr<long> Process::sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime)
|
||||||
{
|
{
|
||||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||||
if (vaddr % 4)
|
if (vaddr % 4)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
const bool is_private = (op & FUTEX_PRIVATE);
|
|
||||||
const bool is_realtime = (op & FUTEX_REALTIME);
|
const bool is_realtime = (op & FUTEX_REALTIME);
|
||||||
op &= ~(FUTEX_PRIVATE | FUTEX_REALTIME);
|
op &= ~(FUTEX_PRIVATE | FUTEX_REALTIME);
|
||||||
|
|
||||||
if (!is_private)
|
// TODO: possibly optimize private futexes?
|
||||||
{
|
|
||||||
dwarnln("TODO: shared futex");
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(s_futex_lock);
|
||||||
|
|
||||||
auto* buffer_region = TRY(validate_and_pin_pointer_access(addr, sizeof(uint32_t), false));
|
auto* buffer_region = TRY(validate_and_pin_pointer_access(addr, sizeof(uint32_t), false));
|
||||||
BAN::ScopeGuard pin_guard([&] { if (buffer_region) buffer_region->unpin(); });
|
BAN::ScopeGuard pin_guard([&] { if (buffer_region) buffer_region->unpin(); });
|
||||||
|
@ -2688,20 +2776,20 @@ namespace Kernel
|
||||||
return SystemTimer::get().ns_since_boot() + (abs_ns - real_ns);
|
return SystemTimer::get().ns_since_boot() + (abs_ns - real_ns);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
auto it = m_futexes.find(paddr);
|
auto it = s_futexes.find(paddr);
|
||||||
if (it == m_futexes.end())
|
if (it == s_futexes.end())
|
||||||
it = TRY(m_futexes.emplace(paddr, TRY(BAN::UniqPtr<futex_t>::create())));
|
it = TRY(s_futexes.emplace(paddr, TRY(BAN::UniqPtr<futex_t>::create())));
|
||||||
futex_t* const futex = it->value.ptr();
|
futex_t* const futex = it->value.ptr();
|
||||||
|
|
||||||
futex->waiters++;
|
futex->waiters++;
|
||||||
BAN::ScopeGuard _([futex, paddr, this] {
|
BAN::ScopeGuard _([futex, paddr] {
|
||||||
if (--futex->waiters == 0)
|
if (--futex->waiters == 0)
|
||||||
m_futexes.remove(paddr);
|
s_futexes.remove(paddr);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
TRY(Thread::current().block_or_eintr_or_waketime_ns(futex->blocker, wake_time_ns, true, &m_process_lock));
|
TRY(Thread::current().block_or_eintr_or_waketime_ns(futex->blocker, wake_time_ns, true, &s_futex_lock));
|
||||||
if (BAN::atomic_load(*addr) == val || futex->to_wakeup == 0)
|
if (BAN::atomic_load(*addr) == val || futex->to_wakeup == 0)
|
||||||
continue;
|
continue;
|
||||||
futex->to_wakeup--;
|
futex->to_wakeup--;
|
||||||
|
@ -2710,8 +2798,8 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
case FUTEX_WAKE:
|
case FUTEX_WAKE:
|
||||||
{
|
{
|
||||||
auto it = m_futexes.find(paddr);
|
auto it = s_futexes.find(paddr);
|
||||||
if (it == m_futexes.end())
|
if (it == s_futexes.end())
|
||||||
return 0;
|
return 0;
|
||||||
futex_t* const futex = it->value.ptr();
|
futex_t* const futex = it->value.ptr();
|
||||||
|
|
||||||
|
@ -3211,8 +3299,10 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_getgroups(gid_t groups[], size_t count)
|
BAN::ErrorOr<long> Process::sys_getgroups(gid_t groups[], size_t count)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
const auto current = m_credentials.groups();
|
||||||
|
if (count == 0)
|
||||||
|
return current.size();
|
||||||
TRY(validate_pointer_access(groups, count * sizeof(gid_t), true));
|
TRY(validate_pointer_access(groups, count * sizeof(gid_t), true));
|
||||||
auto current = m_credentials.groups();
|
|
||||||
if (current.size() > count)
|
if (current.size() > count)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
for (size_t i = 0; i < current.size(); i++)
|
for (size_t i = 0; i < current.size(); i++)
|
||||||
|
@ -3295,6 +3385,9 @@ unauthorized_access:
|
||||||
{
|
{
|
||||||
// TODO: This seems very slow as we loop over the range twice
|
// TODO: This seems very slow as we loop over the range twice
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
TRY(validate_pointer_access_check(ptr, size, needs_write));
|
TRY(validate_pointer_access_check(ptr, size, needs_write));
|
||||||
|
|
||||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||||
|
|
|
@ -92,14 +92,14 @@ namespace Kernel
|
||||||
if (ret.is_error() && ret.error().is_kernel_error())
|
if (ret.is_error() && ret.error().is_kernel_error())
|
||||||
Kernel::panic("Kernel error while returning to userspace {}", ret.error());
|
Kernel::panic("Kernel error while returning to userspace {}", ret.error());
|
||||||
|
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
auto& current_thread = Thread::current();
|
auto& current_thread = Thread::current();
|
||||||
if (current_thread.can_add_signal_to_execute())
|
if (current_thread.can_add_signal_to_execute())
|
||||||
if (current_thread.handle_signal())
|
if (current_thread.handle_signal())
|
||||||
if (ret.is_error() && ret.error().get_error_code() == EINTR && is_restartable_syscall(syscall))
|
if (ret.is_error() && ret.error().get_error_code() == EINTR && is_restartable_syscall(syscall))
|
||||||
ret = BAN::Error::from_errno(ERESTART);
|
ret = BAN::Error::from_errno(ERESTART);
|
||||||
|
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
|
||||||
|
|
||||||
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
||||||
|
|
||||||
if (ret.is_error())
|
if (ret.is_error())
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace Kernel
|
||||||
|
|
||||||
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
|
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
|
||||||
: TTY({
|
: TTY({
|
||||||
.c_iflag = 0,
|
.c_iflag = ICRNL,
|
||||||
.c_oflag = 0,
|
.c_oflag = 0,
|
||||||
.c_cflag = CS8,
|
.c_cflag = CS8,
|
||||||
.c_lflag = ECHO | ECHOE | ECHOK | ICANON | ISIG,
|
.c_lflag = ECHO | ECHOE | ECHOK | ICANON | ISIG,
|
||||||
|
|
|
@ -243,19 +243,14 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
if (m_termios.c_lflag & ICANON)
|
|
||||||
{
|
|
||||||
if ((m_termios.c_iflag & ISTRIP))
|
if ((m_termios.c_iflag & ISTRIP))
|
||||||
ch &= 0x7F;
|
ch &= 0x7F;
|
||||||
if ((m_termios.c_iflag & IGNCR) && ch == CR)
|
if ((m_termios.c_iflag & IGNCR) && ch == CR)
|
||||||
return;
|
return;
|
||||||
uint8_t conv = ch;
|
|
||||||
if ((m_termios.c_iflag & ICRNL) && ch == CR)
|
if ((m_termios.c_iflag & ICRNL) && ch == CR)
|
||||||
conv = NL;
|
ch = NL;
|
||||||
if ((m_termios.c_iflag & INLCR) && ch == NL)
|
else if ((m_termios.c_iflag & INLCR) && ch == NL)
|
||||||
conv = CR;
|
ch = CR;
|
||||||
ch = conv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_termios.c_lflag & ISIG)
|
if (m_termios.c_lflag & ISIG)
|
||||||
{
|
{
|
||||||
|
@ -298,11 +293,10 @@ namespace Kernel
|
||||||
should_flush = true;
|
should_flush = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == NL || ch == m_termios.c_cc[VEOL])
|
if (ch == NL || ch == CR || ch == m_termios.c_cc[VEOL])
|
||||||
{
|
{
|
||||||
should_flush = true;
|
should_flush = true;
|
||||||
force_echo = !!(m_termios.c_lflag & ECHONL);
|
force_echo = !!(m_termios.c_lflag & ECHONL);
|
||||||
ch = NL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Kernel
|
||||||
|
|
||||||
VirtualTTY::VirtualTTY(BAN::RefPtr<TerminalDriver> driver)
|
VirtualTTY::VirtualTTY(BAN::RefPtr<TerminalDriver> driver)
|
||||||
: TTY({
|
: TTY({
|
||||||
.c_iflag = 0,
|
.c_iflag = ICRNL,
|
||||||
.c_oflag = 0,
|
.c_oflag = 0,
|
||||||
.c_cflag = CS8,
|
.c_cflag = CS8,
|
||||||
.c_lflag = ECHO | ECHOE | ECHOK | ICANON | ISIG,
|
.c_lflag = ECHO | ECHOE | ECHOK | ICANON | ISIG,
|
||||||
|
|
|
@ -69,6 +69,20 @@ namespace Kernel
|
||||||
s_default_sse_storage_initialized = true;
|
s_default_sse_storage_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_default_ignored_signal(int signal)
|
||||||
|
{
|
||||||
|
switch (signal)
|
||||||
|
{
|
||||||
|
case SIGCHLD:
|
||||||
|
case SIGURG:
|
||||||
|
case SIGWINCH:
|
||||||
|
case SIGCANCEL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<Thread*> Thread::create_kernel(entry_t entry, void* data)
|
BAN::ErrorOr<Thread*> Thread::create_kernel(entry_t entry, void* data)
|
||||||
{
|
{
|
||||||
// Create the thread object
|
// Create the thread object
|
||||||
|
@ -467,7 +481,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
if (signal_handler == (vaddr_t)SIG_IGN)
|
||||||
continue;
|
continue;
|
||||||
if (signal_handler == (vaddr_t)SIG_DFL && (i == SIGCHLD || i == SIGURG))
|
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(i))
|
||||||
continue;
|
continue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -493,6 +507,7 @@ namespace Kernel
|
||||||
ASSERT(is_userspace());
|
ASSERT(is_userspace());
|
||||||
|
|
||||||
auto state = m_signal_lock.lock();
|
auto state = m_signal_lock.lock();
|
||||||
|
ASSERT(state == InterruptState::Disabled);
|
||||||
|
|
||||||
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
|
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(kernel_stack_top() - sizeof(InterruptStack));
|
||||||
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
||||||
|
@ -516,6 +531,7 @@ namespace Kernel
|
||||||
|
|
||||||
vaddr_t signal_handler;
|
vaddr_t signal_handler;
|
||||||
bool has_sa_restart;
|
bool has_sa_restart;
|
||||||
|
vaddr_t signal_stack_top = 0;
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_process->m_signal_lock);
|
SpinLockGuard _(m_process->m_signal_lock);
|
||||||
|
|
||||||
|
@ -528,11 +544,23 @@ namespace Kernel
|
||||||
handler.sa_handler = SIG_DFL;
|
handler.sa_handler = SIG_DFL;
|
||||||
|
|
||||||
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
||||||
|
|
||||||
|
const auto& alt_stack = m_signal_alt_stack;
|
||||||
|
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
|
||||||
|
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_signal_pending_mask &= ~(1ull << signal);
|
m_signal_pending_mask &= ~(1ull << signal);
|
||||||
process().remove_pending_signal(signal);
|
process().remove_pending_signal(signal);
|
||||||
|
|
||||||
|
if (m_signal_suspend_mask.has_value())
|
||||||
|
{
|
||||||
|
m_signal_block_mask = m_signal_suspend_mask.value();
|
||||||
|
m_signal_suspend_mask.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_signal_lock.unlock(state);
|
||||||
|
|
||||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
if (signal_handler == (vaddr_t)SIG_IGN)
|
||||||
;
|
;
|
||||||
else if (signal_handler != (vaddr_t)SIG_DFL)
|
else if (signal_handler != (vaddr_t)SIG_DFL)
|
||||||
|
@ -541,7 +569,32 @@ namespace Kernel
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
interrupt_stack.sp -= 128; // skip possible red-zone
|
interrupt_stack.sp -= 128; // skip possible red-zone
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
// Make sure stack is allocated
|
||||||
|
|
||||||
|
const vaddr_t pages[3] {
|
||||||
|
(interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK,
|
||||||
|
(signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK,
|
||||||
|
(signal_stack_top - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (m_process->page_table().get_page_flags(pages[i]) & PageTable::Flags::Present)
|
||||||
|
continue;
|
||||||
|
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||||
|
if (auto ret = m_process->allocate_page_for_demand_paging(pages[i], true, false); ret.is_error() || !ret.value())
|
||||||
|
m_process->exit(128 + SIGSEGV, SIGSEGV);
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
write_to_stack(interrupt_stack.sp, interrupt_stack.ip);
|
write_to_stack(interrupt_stack.sp, interrupt_stack.ip);
|
||||||
|
const vaddr_t old_stack = interrupt_stack.sp;
|
||||||
|
if (signal_stack_top)
|
||||||
|
interrupt_stack.sp = signal_stack_top;
|
||||||
|
write_to_stack(interrupt_stack.sp, old_stack);
|
||||||
write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
|
write_to_stack(interrupt_stack.sp, interrupt_stack.flags);
|
||||||
write_to_stack(interrupt_stack.sp, signal);
|
write_to_stack(interrupt_stack.sp, signal);
|
||||||
write_to_stack(interrupt_stack.sp, signal_handler);
|
write_to_stack(interrupt_stack.sp, signal_handler);
|
||||||
|
@ -562,7 +615,6 @@ namespace Kernel
|
||||||
case SIGTRAP:
|
case SIGTRAP:
|
||||||
case SIGXCPU:
|
case SIGXCPU:
|
||||||
case SIGXFSZ:
|
case SIGXFSZ:
|
||||||
m_signal_lock.unlock(state);
|
|
||||||
process().exit(128 + signal, signal | 0x80);
|
process().exit(128 + signal, signal | 0x80);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
|
@ -578,18 +630,11 @@ namespace Kernel
|
||||||
case SIGPOLL:
|
case SIGPOLL:
|
||||||
case SIGPROF:
|
case SIGPROF:
|
||||||
case SIGVTALRM:
|
case SIGVTALRM:
|
||||||
m_signal_lock.unlock(state);
|
|
||||||
process().exit(128 + signal, signal);
|
process().exit(128 + signal, signal);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
// Ignore the signal
|
|
||||||
case SIGCHLD:
|
|
||||||
case SIGURG:
|
|
||||||
case SIGWINCH:
|
|
||||||
case SIGCANCEL:
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Stop the process:
|
// Stop the process:
|
||||||
|
case SIGSTOP:
|
||||||
case SIGTSTP:
|
case SIGTSTP:
|
||||||
case SIGTTIN:
|
case SIGTTIN:
|
||||||
case SIGTTOU:
|
case SIGTTOU:
|
||||||
|
@ -598,15 +643,18 @@ namespace Kernel
|
||||||
// Continue the process, if it is stopped; otherwise, ignore the signal.
|
// Continue the process, if it is stopped; otherwise, ignore the signal.
|
||||||
case SIGCONT:
|
case SIGCONT:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_signal_lock.unlock(state);
|
default:
|
||||||
|
if (is_default_ignored_signal(signal))
|
||||||
|
break;
|
||||||
|
panic("Executing unhandled signal {}", signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return has_sa_restart;
|
return has_sa_restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::add_signal(int signal)
|
void Thread::add_signal(int signal)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_signal_lock);
|
SpinLockGuard _(m_signal_lock);
|
||||||
if (m_process)
|
if (m_process)
|
||||||
|
@ -618,19 +666,64 @@ namespace Kernel
|
||||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
||||||
}
|
}
|
||||||
if (signal_handler == (vaddr_t)SIG_IGN)
|
if (signal_handler == (vaddr_t)SIG_IGN)
|
||||||
return false;
|
return;
|
||||||
if (signal_handler == (vaddr_t)SIG_DFL && (signal == SIGCHLD || signal == SIGURG))
|
if (signal_handler == (vaddr_t)SIG_DFL && is_default_ignored_signal(signal))
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
uint64_t mask = 1ull << signal;
|
|
||||||
if (!(m_signal_block_mask & mask))
|
const uint64_t mask = 1ull << signal;
|
||||||
{
|
|
||||||
m_signal_pending_mask |= mask;
|
m_signal_pending_mask |= mask;
|
||||||
|
|
||||||
if (this != &Thread::current())
|
if (this != &Thread::current())
|
||||||
Processor::scheduler().unblock_thread(this);
|
Processor::scheduler().unblock_thread(this);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::set_suspend_signal_mask(uint64_t sigmask)
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_signal_lock);
|
||||||
|
ASSERT(!m_signal_suspend_mask.has_value());
|
||||||
|
m_signal_suspend_mask = m_signal_block_mask;
|
||||||
|
m_signal_block_mask = sigmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thread::currently_on_alternate_stack() const
|
||||||
|
{
|
||||||
|
ASSERT(m_signal_lock.current_processor_has_lock());
|
||||||
|
|
||||||
|
if (m_signal_alt_stack.ss_flags == SS_ONSTACK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const vaddr_t stack_bottom = reinterpret_cast<vaddr_t>(m_signal_alt_stack.ss_sp);
|
||||||
|
const vaddr_t stack_top = stack_bottom + m_signal_alt_stack.ss_size;
|
||||||
|
const vaddr_t sp = m_interrupt_stack.sp;
|
||||||
|
return stack_bottom <= sp && sp <= stack_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Thread::sigaltstack(const stack_t* ss, stack_t* oss)
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_signal_lock);
|
||||||
|
|
||||||
|
const bool on_alt_stack = currently_on_alternate_stack();
|
||||||
|
|
||||||
|
if (oss)
|
||||||
|
{
|
||||||
|
*oss = m_signal_alt_stack;
|
||||||
|
if (on_alt_stack)
|
||||||
|
oss->ss_flags = SS_ONSTACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ss)
|
||||||
|
{
|
||||||
|
if (on_alt_stack)
|
||||||
|
return BAN::Error::from_errno(EPERM);
|
||||||
|
if (ss->ss_flags && ss->ss_flags != SS_DISABLE)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (ss->ss_size < MINSIGSTKSZ)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
m_signal_alt_stack = *ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns)
|
BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns)
|
||||||
|
|
|
@ -299,7 +299,7 @@ namespace Kernel
|
||||||
long ns_this_second = ticks_this_second * regs.counter_clk_period / FS_PER_NS;
|
long ns_this_second = ticks_this_second * regs.counter_clk_period / FS_PER_NS;
|
||||||
|
|
||||||
return timespec {
|
return timespec {
|
||||||
.tv_sec = seconds,
|
.tv_sec = static_cast<time_t>(seconds),
|
||||||
.tv_nsec = ns_this_second
|
.tv_nsec = ns_this_second
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,8 +487,8 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-
|
||||||
+/* vi: set ts=4 sw=4 expandtab: */
|
+/* vi: set ts=4 sw=4 expandtab: */
|
||||||
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
|
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
|
||||||
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-06 02:01:21.086666679 +0300
|
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-21 02:32:59.649175565 +0300
|
||||||
@@ -0,0 +1,718 @@
|
@@ -0,0 +1,724 @@
|
||||||
+/*
|
+/*
|
||||||
+ Simple DirectMedia Layer
|
+ Simple DirectMedia Layer
|
||||||
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
@ -894,6 +894,12 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
|
||||||
+ }
|
+ }
|
||||||
+ );
|
+ );
|
||||||
+
|
+
|
||||||
|
+ ban_window->window->set_window_focus_event_callback(
|
||||||
|
+ [window](LibGUI::EventPacket::WindowFocusEvent::event_t event) {
|
||||||
|
+ SDL_SetKeyboardFocus(event.focused ? window : nullptr);
|
||||||
|
+ }
|
||||||
|
+ );
|
||||||
|
+
|
||||||
+ ban_window->window->set_close_window_event_callback(
|
+ ban_window->window->set_close_window_event_callback(
|
||||||
+ [window]() {
|
+ [window]() {
|
||||||
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
||||||
|
|
|
@ -3,15 +3,16 @@
|
||||||
NAME='SDL2_mixer'
|
NAME='SDL2_mixer'
|
||||||
VERSION='2.8.1'
|
VERSION='2.8.1'
|
||||||
DOWNLOAD_URL="https://github.com/libsdl-org/SDL_mixer/releases/download/release-$VERSION/SDL2_mixer-$VERSION.tar.gz#cb760211b056bfe44f4a1e180cc7cb201137e4d1572f2002cc1be728efd22660"
|
DOWNLOAD_URL="https://github.com/libsdl-org/SDL_mixer/releases/download/release-$VERSION/SDL2_mixer-$VERSION.tar.gz#cb760211b056bfe44f4a1e180cc7cb201137e4d1572f2002cc1be728efd22660"
|
||||||
DEPENDENCIES=('SDL2')
|
DEPENDENCIES=('SDL2' 'timidity')
|
||||||
|
|
||||||
configure() {
|
configure() {
|
||||||
$BANAN_CMAKE --fresh -S . -B build -G Ninja \
|
$BANAN_CMAKE --fresh -S . -B build -G Ninja \
|
||||||
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||||
-DCMAKE_INSTALL_PREFIX='/usr' \
|
-DCMAKE_INSTALL_PREFIX='/usr' \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DSDL2MIXER_DEPS_SHARED=OFF \
|
||||||
|
-DSDL2MIXER_MIDI_FLUIDSYNTH=OFF \
|
||||||
-DSDL2MIXER_WAVPACK=OFF \
|
-DSDL2MIXER_WAVPACK=OFF \
|
||||||
-DSDL2MIXER_MIDI=OFF \
|
|
||||||
-DSDL2MIXER_OPUS=OFF \
|
-DSDL2MIXER_OPUS=OFF \
|
||||||
-DSDL2MIXER_MOD=OFF \
|
-DSDL2MIXER_MOD=OFF \
|
||||||
|| exit 1
|
|| exit 1
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='glib'
|
||||||
|
VERSION='2.85.2'
|
||||||
|
DOWNLOAD_URL="https://download.gnome.org/sources/glib/${VERSION%.*}/glib-$VERSION.tar.xz#833b97c0f0a1bfdba1d0fbfc36cd368b855c5afd9f02b8ffb24129114ad051b2"
|
||||||
|
DEPENDENCIES=('pcre2' 'libffi' 'zlib' 'libiconv')
|
||||||
|
CONFIGURE_OPTIONS=(
|
||||||
|
'-Dprefix=/usr'
|
||||||
|
'-Dxattr=false'
|
||||||
|
)
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
meson setup \
|
||||||
|
--reconfigure \
|
||||||
|
--cross-file "$MESON_CROSS_FILE" \
|
||||||
|
"${CONFIGURE_OPTIONS[@]}" \
|
||||||
|
build || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
meson compile -C build || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
diff -ruN glib-2.85.2/gio/gnetworking.h.in glib-2.85.2-banan_os/gio/gnetworking.h.in
|
||||||
|
--- glib-2.85.2/gio/gnetworking.h.in 2025-07-21 20:47:53.000000000 +0300
|
||||||
|
+++ glib-2.85.2-banan_os/gio/gnetworking.h.in 2025-08-19 18:21:06.038296386 +0300
|
||||||
|
@@ -40,13 +40,17 @@
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
+#ifndef __banan_os__
|
||||||
|
#include <resolv.h>
|
||||||
|
+#endif
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
+#ifndef __banan_os__
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
+#endif
|
||||||
|
@NAMESER_COMPAT_INCLUDE@
|
||||||
|
|
||||||
|
#ifndef __GI_SCANNER__
|
||||||
|
diff -ruN glib-2.85.2/gio/gthreadedresolver.c glib-2.85.2-banan_os/gio/gthreadedresolver.c
|
||||||
|
--- glib-2.85.2/gio/gthreadedresolver.c 2025-07-21 20:47:53.000000000 +0300
|
||||||
|
+++ glib-2.85.2-banan_os/gio/gthreadedresolver.c 2025-08-19 18:21:06.052332130 +0300
|
||||||
|
@@ -41,6 +41,10 @@
|
||||||
|
#include "gsocketaddress.h"
|
||||||
|
#include "gsrvtarget.h"
|
||||||
|
|
||||||
|
+#if defined __banan_os__
|
||||||
|
+#include <endian.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#if HAVE_GETIFADDRS
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
|
@@ -692,7 +696,7 @@
|
||||||
|
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
|
||||||
|
-#if defined __BIONIC__ && !defined BIND_4_COMPAT
|
||||||
|
+#if (defined __BIONIC__ && !defined BIND_4_COMPAT) || defined __banan_os__
|
||||||
|
/* Copy from bionic/libc/private/arpa_nameser_compat.h
|
||||||
|
* and bionic/libc/private/arpa_nameser.h */
|
||||||
|
typedef struct {
|
||||||
|
@@ -763,6 +767,14 @@
|
||||||
|
#define dn_skipname __dn_skipname
|
||||||
|
int dn_skipname(const u_char *, const u_char *);
|
||||||
|
|
||||||
|
+#if defined __banan_os__
|
||||||
|
+#warning "TODO: dn_expand"
|
||||||
|
+int dn_expand(const u_char *, const u_char *, const u_char *, char *, int)
|
||||||
|
+{
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* From bionic/libc/private/arpa_nameser_compat.h */
|
||||||
|
#define T_MX ns_t_mx
|
||||||
|
#define T_TXT ns_t_txt
|
||||||
|
@@ -1369,7 +1381,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
-#ifdef __BIONIC__
|
||||||
|
+#if defined __BIONIC__
|
||||||
|
#ifndef C_IN
|
||||||
|
#define C_IN 1
|
||||||
|
#endif
|
||||||
|
@@ -1420,6 +1432,9 @@
|
||||||
|
g_byte_array_set_size (answer, len * 2);
|
||||||
|
#if defined(HAVE_RES_NQUERY)
|
||||||
|
len = res_nquery (&res, rrname, C_IN, rrtype, answer->data, answer->len);
|
||||||
|
+#elif defined __banan_os__
|
||||||
|
+#warning "TODO: res_query"
|
||||||
|
+ len = -1;
|
||||||
|
#else
|
||||||
|
len = res_query (rrname, C_IN, rrtype, answer->data, answer->len);
|
||||||
|
#endif
|
||||||
|
diff -ruN glib-2.85.2/gio/meson.build glib-2.85.2-banan_os/gio/meson.build
|
||||||
|
--- glib-2.85.2/gio/meson.build 2025-07-21 20:47:53.000000000 +0300
|
||||||
|
+++ glib-2.85.2-banan_os/gio/meson.build 2025-08-19 18:21:06.062294634 +0300
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
|
||||||
|
gnetworking_h_nameser_compat_include = ''
|
||||||
|
|
||||||
|
-if host_system not in ['windows', 'android']
|
||||||
|
+if host_system not in ['windows', 'android', 'banan_os']
|
||||||
|
# Don't check for C_IN on Android since it does not define it in public
|
||||||
|
# headers, we define it ourselves wherever necessary
|
||||||
|
if not cc.compiles('''#include <sys/types.h>
|
||||||
|
@@ -40,6 +40,7 @@
|
||||||
|
network_libs = [ ]
|
||||||
|
network_args = [ ]
|
||||||
|
if host_system != 'windows'
|
||||||
|
+ if host_system != 'banan_os'
|
||||||
|
# res_query()
|
||||||
|
res_query_test = '''#include <resolv.h>
|
||||||
|
int main (int argc, char ** argv) {
|
||||||
|
@@ -63,6 +64,7 @@
|
||||||
|
error('Could not find res_query()')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
+ endif
|
||||||
|
|
||||||
|
# socket()
|
||||||
|
socket_test = '''#include <sys/types.h>
|
|
@ -0,0 +1,39 @@
|
||||||
|
diff -ruN glib-2.85.2/gio/gunixmounts.c glib-2.85.2-banan_os/gio/gunixmounts.c
|
||||||
|
--- glib-2.85.2/gio/gunixmounts.c 2025-07-21 20:47:53.000000000 +0300
|
||||||
|
+++ glib-2.85.2-banan_os/gio/gunixmounts.c 2025-08-19 18:21:06.055332112 +0300
|
||||||
|
@@ -1114,7 +1114,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
/* QNX {{{2 */
|
||||||
|
-#elif defined (HAVE_QNX)
|
||||||
|
+#elif defined (HAVE_QNX) || defined (__banan_os__)
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_mtab_monitor_file (void)
|
||||||
|
@@ -1754,6 +1754,26 @@
|
||||||
|
if (time_read_out != NULL)
|
||||||
|
*time_read_out = 0;
|
||||||
|
if (n_points_out != NULL)
|
||||||
|
+ *n_points_out = 0;
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#elif defined (__banan_os__)
|
||||||
|
+
|
||||||
|
+static GList *
|
||||||
|
+_g_get_unix_mount_points (void)
|
||||||
|
+{
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static GUnixMountPoint **
|
||||||
|
+_g_unix_mount_points_get_from_file (const char *table_path,
|
||||||
|
+ uint64_t *time_read_out,
|
||||||
|
+ size_t *n_points_out)
|
||||||
|
+{
|
||||||
|
+ if (time_read_out != NULL)
|
||||||
|
+ *time_read_out = 0;
|
||||||
|
+ if (n_points_out != NULL)
|
||||||
|
*n_points_out = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='libffi'
|
||||||
|
VERSION='3.5.2'
|
||||||
|
DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc"
|
||||||
|
CONFIG_SUB=('config.sub')
|
||||||
|
|
||||||
|
post_install() {
|
||||||
|
# remove libtool file
|
||||||
|
rm -f $BANAN_SYSROOT/usr/lib/libffi.la
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
diff -ruN libffi-3.5.2/configure libffi-3.5.2-banan_os/configure
|
||||||
|
--- libffi-3.5.2/configure 2025-08-02 09:44:34.000000000 +0300
|
||||||
|
+++ libffi-3.5.2-banan_os/configure 2025-08-08 18:24:29.271963294 +0300
|
||||||
|
@@ -7432,6 +7432,10 @@
|
||||||
|
lt_cv_deplibs_check_method=pass_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
+banan_os*)
|
||||||
|
+ lt_cv_deplibs_check_method=pass_all
|
||||||
|
+ ;;
|
||||||
|
+
|
||||||
|
beos*)
|
||||||
|
lt_cv_deplibs_check_method=pass_all
|
||||||
|
;;
|
||||||
|
@@ -12978,6 +12982,16 @@
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
|
+banan_os*)
|
||||||
|
+ version_type=linux # correct to gnu/linux during the next big refactor
|
||||||
|
+ need_lib_prefix=no
|
||||||
|
+ need_version=no
|
||||||
|
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||||
|
+ soname_spec='$libname$release$shared_ext$major'
|
||||||
|
+ dynamic_linker="$host_os DynamicLoader.so"
|
||||||
|
+ shlibpath_var=LD_LIBRARY_PATH
|
||||||
|
+ ;;
|
||||||
|
+
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shared_ext'
|
||||||
|
dynamic_linker="$host_os ld.so"
|
||||||
|
@@ -17612,6 +17626,16 @@
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
|
+banan_os*)
|
||||||
|
+ version_type=linux # correct to gnu/linux during the next big refactor
|
||||||
|
+ need_lib_prefix=no
|
||||||
|
+ need_version=no
|
||||||
|
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||||
|
+ soname_spec='$libname$release$shared_ext$major'
|
||||||
|
+ dynamic_linker="$host_os DynamicLoader.so"
|
||||||
|
+ shlibpath_var=LD_LIBRARY_PATH
|
||||||
|
+ ;;
|
||||||
|
+
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shared_ext'
|
||||||
|
dynamic_linker="$host_os ld.so"
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='nano'
|
||||||
|
VERSION='8.5'
|
||||||
|
DOWNLOAD_URL="https://www.nano-editor.org/dist/v8/nano-$VERSION.tar.xz#000b011d339c141af9646d43288f54325ff5c6e8d39d6e482b787bbc6654c26a"
|
||||||
|
DEPENDENCIES=('ncurses')
|
||||||
|
CONFIG_SUB=('config.sub')
|
||||||
|
CONFIGURE_OPTIONS=(
|
||||||
|
'ac_cv_header_glob_h=no'
|
||||||
|
)
|
||||||
|
|
||||||
|
pre_configure() {
|
||||||
|
echo '#include_next <sys/types.h>' > lib/sys_types.in.h
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
diff -ruN nano-8.5/lib/getprogname.c nano-8.5-banan_os/lib/getprogname.c
|
||||||
|
--- nano-8.5/lib/getprogname.c 2025-06-12 10:29:39.000000000 +0300
|
||||||
|
+++ nano-8.5-banan_os/lib/getprogname.c 2025-08-19 01:25:56.020428849 +0300
|
||||||
|
@@ -50,7 +50,7 @@
|
||||||
|
# include <sys/procfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#if defined __SCO_VERSION__ || defined __sysv5__
|
||||||
|
+#if defined __SCO_VERSION__ || defined __sysv5__ || defined __banan_os__
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
@@ -265,7 +265,7 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
-# elif defined __SCO_VERSION__ || defined __sysv5__ /* SCO OpenServer6/UnixWare */
|
||||||
|
+# elif defined __SCO_VERSION__ || defined __sysv5__ || defined __banan_os__ /* SCO OpenServer6/UnixWare */
|
||||||
|
char buf[80];
|
||||||
|
int fd;
|
||||||
|
sprintf (buf, "/proc/%d/cmdline", getpid());
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='nyancat'
|
||||||
|
VERSION='git'
|
||||||
|
DOWNLOAD_URL="https://github.com/klange/nyancat.git#1.5.2"
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
cp src/nyancat "$BANAN_SYSROOT/usr/bin/"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='pcre2'
|
||||||
|
VERSION='10.45'
|
||||||
|
DOWNLOAD_URL="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$VERSION/pcre2-$VERSION.tar.gz#0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee"
|
||||||
|
CONFIG_SUB=('config.sub')
|
||||||
|
|
||||||
|
post_install() {
|
||||||
|
# remove libtool files
|
||||||
|
rm -f $BANAN_SYSROOT/usr/lib/libpcre2-8.la
|
||||||
|
rm -f $BANAN_SYSROOT/usr/lib/libpcre2-posix.la
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diff -ruN pcre2-10.45/configure pcre2-10.45-banan_os/configure
|
||||||
|
--- pcre2-10.45/configure 2025-02-04 15:48:33.000000000 +0200
|
||||||
|
+++ pcre2-10.45-banan_os/configure 2025-08-08 00:22:52.975889591 +0300
|
||||||
|
@@ -6536,6 +6536,10 @@
|
||||||
|
lt_cv_deplibs_check_method=pass_all
|
||||||
|
;;
|
||||||
|
|
||||||
|
+banan_os*)
|
||||||
|
+ lt_cv_deplibs_check_method=pass_all
|
||||||
|
+ ;;
|
||||||
|
+
|
||||||
|
beos*)
|
||||||
|
lt_cv_deplibs_check_method=pass_all
|
||||||
|
;;
|
||||||
|
@@ -12197,6 +12201,16 @@
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
|
+banan_os*)
|
||||||
|
+ version_type=linux # correct to gnu/linux during the next big refactor
|
||||||
|
+ need_lib_prefix=no
|
||||||
|
+ need_version=no
|
||||||
|
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
|
||||||
|
+ soname_spec='$libname$release$shared_ext$major'
|
||||||
|
+ dynamic_linker="$host_os DynamicLoader.so"
|
||||||
|
+ shlibpath_var=LD_LIBRARY_PATH
|
||||||
|
+ ;;
|
||||||
|
+
|
||||||
|
beos*)
|
||||||
|
library_names_spec='$libname$shared_ext'
|
||||||
|
dynamic_linker="$host_os ld.so"
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='qemu'
|
||||||
|
VERSION='10.0.2'
|
||||||
|
DOWNLOAD_URL="https://download.qemu.org/qemu-$VERSION.tar.xz#ef786f2398cb5184600f69aef4d5d691efd44576a3cff4126d38d4c6fec87759"
|
||||||
|
DEPENDENCIES=('glib' 'SDL2')
|
||||||
|
MAKE_BUILD_TARGETS=('qemu-system-x86_64')
|
||||||
|
CONFIGURE_OPTIONS=(
|
||||||
|
'--cross-prefix='
|
||||||
|
'--target-list=x86_64-softmmu'
|
||||||
|
'--disable-tpm'
|
||||||
|
'--disable-docs'
|
||||||
|
)
|
||||||
|
|
||||||
|
pre_configure() {
|
||||||
|
echo '' > tests/meson.build
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
diff -ruN qemu-10.0.2/configure qemu-10.0.2-banan_os/configure
|
||||||
|
--- qemu-10.0.2/configure 2025-05-29 01:05:46.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-banan_os/configure 2025-05-31 00:03:10.361102831 +0300
|
||||||
|
@@ -360,6 +360,8 @@
|
||||||
|
host_os=netbsd
|
||||||
|
elif check_define __APPLE__; then
|
||||||
|
host_os=darwin
|
||||||
|
+elif check_define __banan_os__; then
|
||||||
|
+ host_os=banan_os
|
||||||
|
else
|
||||||
|
# This is a fatal error, but don't report it yet, because we
|
||||||
|
# might be going to just print the --help text, or it might
|
|
@ -0,0 +1,43 @@
|
||||||
|
diff -ru qemu-10.0.2/util/oslib-posix.c qemu-10.0.2-x86_64/util/oslib-posix.c
|
||||||
|
--- qemu-10.0.2/util/oslib-posix.c 2025-05-29 01:05:47.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-x86_64/util/oslib-posix.c 2025-08-18 02:38:04.839116456 +0300
|
||||||
|
@@ -128,7 +128,39 @@
|
||||||
|
|
||||||
|
int qemu_daemon(int nochdir, int noclose)
|
||||||
|
{
|
||||||
|
+#if defined(__banan_os__)
|
||||||
|
+ const pid_t pid = fork();
|
||||||
|
+ if (pid == -1) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ if (pid > 0) {
|
||||||
|
+ exit(0);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (setsid() == -1) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (nochdir == 0) {
|
||||||
|
+ if (chdir("/") == -1) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (noclose == 0) {
|
||||||
|
+ int fd = open("/dev/null", O_RDWR);
|
||||||
|
+ if (fd == -1) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ dup2(fd, STDIN_FILENO);
|
||||||
|
+ dup2(fd, STDOUT_FILENO);
|
||||||
|
+ dup2(fd, STDERR_FILENO);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+#else
|
||||||
|
return daemon(nochdir, noclose);
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qemu_write_pidfile(const char *path, Error **errp)
|
|
@ -0,0 +1,24 @@
|
||||||
|
diff -ru qemu-10.0.2/util/main-loop.c qemu-10.0.2-x86_64/util/main-loop.c
|
||||||
|
--- qemu-10.0.2/util/main-loop.c 2025-05-29 01:05:47.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-x86_64/util/main-loop.c 2025-08-09 18:35:25.670990547 +0300
|
||||||
|
@@ -95,8 +95,10 @@
|
||||||
|
* not catch it reliably.
|
||||||
|
*/
|
||||||
|
sigemptyset(&set);
|
||||||
|
+#if !defined(__banan_os__)
|
||||||
|
sigaddset(&set, SIG_IPI);
|
||||||
|
sigaddset(&set, SIGIO);
|
||||||
|
+#endif
|
||||||
|
sigaddset(&set, SIGALRM);
|
||||||
|
sigaddset(&set, SIGBUS);
|
||||||
|
/* SIGINT cannot be handled via signalfd, so that ^C can be used
|
||||||
|
@@ -106,7 +108,9 @@
|
||||||
|
*/
|
||||||
|
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||||
|
|
||||||
|
+#if !defined(__banan_os__)
|
||||||
|
sigdelset(&set, SIG_IPI);
|
||||||
|
+#endif
|
||||||
|
sigfd = qemu_signalfd(&set);
|
||||||
|
if (sigfd == -1) {
|
||||||
|
error_setg_errno(errp, errno, "failed to create signalfd");
|
|
@ -0,0 +1,22 @@
|
||||||
|
diff -ru qemu-10.0.2/net/colo.c qemu-10.0.2-x86_64/net/colo.c
|
||||||
|
--- qemu-10.0.2/net/colo.c 2025-05-29 01:05:46.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-x86_64/net/colo.c 2025-08-09 19:24:57.624758915 +0300
|
||||||
|
@@ -123,14 +123,18 @@
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
case IPPROTO_DCCP:
|
||||||
|
+#if !defined(__banan_os__)
|
||||||
|
case IPPROTO_ESP:
|
||||||
|
+#endif
|
||||||
|
case IPPROTO_SCTP:
|
||||||
|
case IPPROTO_UDPLITE:
|
||||||
|
tmp_ports = *(uint32_t *)(pkt->transport_header);
|
||||||
|
break;
|
||||||
|
+#if !defined(__banan_os__)
|
||||||
|
case IPPROTO_AH:
|
||||||
|
tmp_ports = *(uint32_t *)(pkt->transport_header + 4);
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
diff -ru qemu-10.0.2/block/file-posix.c qemu-10.0.2-x86_64/block/file-posix.c
|
||||||
|
--- qemu-10.0.2/block/file-posix.c 2025-05-29 01:05:46.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-x86_64/block/file-posix.c 2025-08-09 19:00:18.062695074 +0300
|
||||||
|
@@ -110,6 +110,10 @@
|
||||||
|
#include <sys/diskslice.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef __banan_os__
|
||||||
|
+#include <sys/ioctl.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* OS X does not have O_DSYNC */
|
||||||
|
#ifndef O_DSYNC
|
||||||
|
#ifdef O_SYNC
|
||||||
|
Only in qemu-10.0.2-x86_64: build
|
||||||
|
Only in qemu-10.0.2-x86_64: .cache
|
||||||
|
diff -ru qemu-10.0.2/chardev/char-pty.c qemu-10.0.2-x86_64/chardev/char-pty.c
|
||||||
|
--- qemu-10.0.2/chardev/char-pty.c 2025-05-29 01:05:46.000000000 +0300
|
||||||
|
+++ qemu-10.0.2-x86_64/chardev/char-pty.c 2025-08-09 19:03:07.909515897 +0300
|
||||||
|
@@ -236,7 +236,11 @@
|
||||||
|
# include <termios.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#ifdef __sun__
|
||||||
|
+#if defined(__banan_os__)
|
||||||
|
+# include <sys/ioctl.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(__sun__) || defined(__banan_os__)
|
||||||
|
|
||||||
|
#if !defined(HAVE_OPENPTY)
|
||||||
|
/* Once illumos has openpty(), this is going to be removed. */
|
|
@ -19,7 +19,6 @@ setjmp:
|
||||||
xorl %eax, %eax
|
xorl %eax, %eax
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.size setjmp, . - setjmp
|
.size setjmp, . - setjmp
|
||||||
|
|
||||||
// void longjmp(jmp_buf env, int val)
|
// void longjmp(jmp_buf env, int val)
|
||||||
|
@ -39,5 +38,27 @@ longjmp:
|
||||||
movl 16(%edx), %edi
|
movl 16(%edx), %edi
|
||||||
movl 20(%edx), %esi
|
movl 20(%edx), %esi
|
||||||
jmp *%ecx
|
jmp *%ecx
|
||||||
|
|
||||||
.size longjmp, . - longjmp
|
.size longjmp, . - longjmp
|
||||||
|
|
||||||
|
// int sigsetjmp(sigjmp_buf env, int savemask)
|
||||||
|
.global sigsetjmp
|
||||||
|
sigsetjmp:
|
||||||
|
movl 4(%esp), %edx
|
||||||
|
movl 8(%esp), %ecx
|
||||||
|
|
||||||
|
movl %ecx, 24(%edx)
|
||||||
|
testl %ecx, %ecx
|
||||||
|
jz setjmp
|
||||||
|
|
||||||
|
leal 24(%edx), %edx
|
||||||
|
xorl %ecx, %ecx
|
||||||
|
|
||||||
|
subl $12, %esp
|
||||||
|
movl %edx, 8(%esp)
|
||||||
|
movl %ecx, 4(%esp)
|
||||||
|
movl %ecx, 0(%esp)
|
||||||
|
call pthread_sigmask
|
||||||
|
addl $12, %esp
|
||||||
|
|
||||||
|
jmp setjmp
|
||||||
|
.size sigsetjmp, . - sigsetjmp
|
||||||
|
|
|
@ -38,3 +38,21 @@ longjmp:
|
||||||
movq 56(%rdi), %r15
|
movq 56(%rdi), %r15
|
||||||
jmp *%rcx
|
jmp *%rcx
|
||||||
.size longjmp, . - longjmp
|
.size longjmp, . - longjmp
|
||||||
|
|
||||||
|
// int sigsetjmp(sigjmp_buf env, int savemask)
|
||||||
|
.global sigsetjmp
|
||||||
|
sigsetjmp:
|
||||||
|
movq %rsi, 64(%rdi)
|
||||||
|
testq %rsi, %rsi
|
||||||
|
jz setjmp
|
||||||
|
|
||||||
|
subq $8, %rsp
|
||||||
|
movq %rdi, (%rsp)
|
||||||
|
leaq 72(%rsi), %rdx
|
||||||
|
xorq %rsi, %rsi
|
||||||
|
call pthread_sigmask
|
||||||
|
movq (%rsp), %rdi
|
||||||
|
addq $8, %rsp
|
||||||
|
|
||||||
|
jmp setjmp
|
||||||
|
.size sigsetjmp, . - sigsetjmp
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
extern "C" int __dladdr(const void*, Dl_info_t*) __attribute__((weak));
|
||||||
|
int dladdr(const void* __restrict addr, Dl_info_t* __restrict dlip)
|
||||||
|
{
|
||||||
|
if (&__dladdr == nullptr) [[unlikely]]
|
||||||
|
return 0;
|
||||||
|
return __dladdr(addr, dlip);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" int __dlclose(void*) __attribute__((weak));
|
extern "C" int __dlclose(void*) __attribute__((weak));
|
||||||
int dlclose(void* handle)
|
int dlclose(void* handle)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,8 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
pthread_t locker;
|
uint32_t futex;
|
||||||
|
uint32_t waiters;
|
||||||
unsigned lock_depth;
|
unsigned lock_depth;
|
||||||
} pthread_mutex_t;
|
} pthread_mutex_t;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,18 @@ __BEGIN_DECLS
|
||||||
#define RTLD_NEXT ((void*)-1)
|
#define RTLD_NEXT ((void*)-1)
|
||||||
#define RTLD_DEFAULT ((void*) 0)
|
#define RTLD_DEFAULT ((void*) 0)
|
||||||
|
|
||||||
|
struct Dl_info
|
||||||
|
{
|
||||||
|
const char* dli_fname; /* Pathname of mapped object file. */
|
||||||
|
void* dli_fbase; /* Base of mapped address range. */
|
||||||
|
const char* dli_sname; /* Sumbol name or null pointer. */
|
||||||
|
void* dli_saddr; /* Symbol address or null pointer. */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Dl_info Dl_info_t; /* POSIX type */
|
||||||
|
typedef struct Dl_info Dl_info; /* Linux type */
|
||||||
|
|
||||||
|
int dladdr(const void* __restrict addr, Dl_info_t* __restrict dlip);
|
||||||
int dlclose(void* handle);
|
int dlclose(void* handle);
|
||||||
char* dlerror(void);
|
char* dlerror(void);
|
||||||
void* dlopen(const char* file, int mode);
|
void* dlopen(const char* file, int mode);
|
||||||
|
|
|
@ -79,7 +79,7 @@ struct uthread
|
||||||
|
|
||||||
#define PTHREAD_SPIN_INITIALIZER (pthread_spinlock_t)0
|
#define PTHREAD_SPIN_INITIALIZER (pthread_spinlock_t)0
|
||||||
#define PTHREAD_COND_INITIALIZER (pthread_cond_t){ { CLOCK_REALTIME, 0 }, PTHREAD_SPIN_INITIALIZER, NULL }
|
#define PTHREAD_COND_INITIALIZER (pthread_cond_t){ { CLOCK_REALTIME, 0 }, PTHREAD_SPIN_INITIALIZER, NULL }
|
||||||
#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t){ { PTHREAD_MUTEX_DEFAULT, 0 }, 0, 0 }
|
#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t){ { PTHREAD_MUTEX_DEFAULT, 0 }, 0, 0, 0 }
|
||||||
#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t){ { 0 }, 0, 0 }
|
#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t){ { 0 }, 0, 0 }
|
||||||
|
|
||||||
#define _PTHREAD_ATFORK_PREPARE 0
|
#define _PTHREAD_ATFORK_PREPARE 0
|
||||||
|
|
|
@ -132,8 +132,9 @@ struct sigevent
|
||||||
#define SA_SIGINFO 0x010
|
#define SA_SIGINFO 0x010
|
||||||
#define SA_NOCLDWAIT 0x020
|
#define SA_NOCLDWAIT 0x020
|
||||||
#define SA_NODEFER 0x040
|
#define SA_NODEFER 0x040
|
||||||
#define SS_ONSTACK 0x080
|
|
||||||
#define SS_DISABLE 0x100
|
#define SS_ONSTACK 1
|
||||||
|
#define SS_DISABLE 2
|
||||||
|
|
||||||
#define MINSIGSTKSZ 4096
|
#define MINSIGSTKSZ 4096
|
||||||
#define SIGSTKSZ 4096
|
#define SIGSTKSZ 4096
|
||||||
|
|
|
@ -90,6 +90,9 @@ __BEGIN_DECLS
|
||||||
O(SYS_SIGACTION, sigaction) \
|
O(SYS_SIGACTION, sigaction) \
|
||||||
O(SYS_SIGPENDING, sigpending) \
|
O(SYS_SIGPENDING, sigpending) \
|
||||||
O(SYS_SIGPROCMASK, sigprocmask) \
|
O(SYS_SIGPROCMASK, sigprocmask) \
|
||||||
|
O(SYS_SIGSUSPEND, sigsuspend) \
|
||||||
|
O(SYS_SIGWAIT, sigwait) \
|
||||||
|
O(SYS_SIGALTSTACK, sigaltstack) \
|
||||||
O(SYS_SETITIMER, setitimer) \
|
O(SYS_SETITIMER, setitimer) \
|
||||||
O(SYS_POSIX_OPENPT, posix_openpt) \
|
O(SYS_POSIX_OPENPT, posix_openpt) \
|
||||||
O(SYS_PTSNAME, ptsname) \
|
O(SYS_PTSNAME, ptsname) \
|
||||||
|
|
|
@ -146,7 +146,7 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#if !defined(__time_t_defined) && (defined(__need_all_types) || defined(__need_time_t))
|
#if !defined(__time_t_defined) && (defined(__need_all_types) || defined(__need_time_t))
|
||||||
#define __time_t_defined 1
|
#define __time_t_defined 1
|
||||||
typedef unsigned long long time_t;
|
typedef long long time_t;
|
||||||
#endif
|
#endif
|
||||||
#undef __need_time_t
|
#undef __need_time_t
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#include <bits/types/locale_t.h>
|
#include <bits/types/locale_t.h>
|
||||||
|
|
||||||
typedef struct {} mbstate_t;
|
typedef int mbstate_t;
|
||||||
|
|
||||||
typedef int wctype_t;
|
typedef int wctype_t;
|
||||||
|
|
||||||
|
|
|
@ -736,34 +736,6 @@ int pthread_spin_unlock(pthread_spinlock_t* lock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static int _pthread_timedlock(T* __restrict lock, const struct timespec* __restrict abstime, int (*trylock)(T*))
|
|
||||||
{
|
|
||||||
if (trylock(lock) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
constexpr auto has_timed_out =
|
|
||||||
[](const struct timespec* abstime) -> bool
|
|
||||||
{
|
|
||||||
struct timespec curtime;
|
|
||||||
clock_gettime(CLOCK_REALTIME, &curtime);
|
|
||||||
if (curtime.tv_sec < abstime->tv_sec)
|
|
||||||
return false;
|
|
||||||
if (curtime.tv_sec > abstime->tv_sec)
|
|
||||||
return true;
|
|
||||||
return curtime.tv_nsec >= abstime->tv_nsec;
|
|
||||||
};
|
|
||||||
|
|
||||||
while (!has_timed_out(abstime))
|
|
||||||
{
|
|
||||||
if (trylock(lock) == 0)
|
|
||||||
return 0;
|
|
||||||
sched_yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ETIMEDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr)
|
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr)
|
||||||
{
|
{
|
||||||
(void)attr;
|
(void)attr;
|
||||||
|
@ -835,7 +807,8 @@ int pthread_mutex_init(pthread_mutex_t* __restrict mutex, const pthread_mutexatt
|
||||||
attr = &default_attr;
|
attr = &default_attr;
|
||||||
*mutex = {
|
*mutex = {
|
||||||
.attr = *attr,
|
.attr = *attr,
|
||||||
.locker = 0,
|
.futex = 0,
|
||||||
|
.waiters = 0,
|
||||||
.lock_depth = 0,
|
.lock_depth = 0,
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -843,55 +816,28 @@ int pthread_mutex_init(pthread_mutex_t* __restrict mutex, const pthread_mutexatt
|
||||||
|
|
||||||
int pthread_mutex_lock(pthread_mutex_t* mutex)
|
int pthread_mutex_lock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
// NOTE: current yielding implementation supports shared
|
return pthread_mutex_timedlock(mutex, nullptr);
|
||||||
|
|
||||||
const auto tid = pthread_self();
|
|
||||||
|
|
||||||
switch (mutex->attr.type)
|
|
||||||
{
|
|
||||||
case PTHREAD_MUTEX_RECURSIVE:
|
|
||||||
if (mutex->locker != tid)
|
|
||||||
break;
|
|
||||||
mutex->lock_depth++;
|
|
||||||
return 0;
|
|
||||||
case PTHREAD_MUTEX_ERRORCHECK:
|
|
||||||
if (mutex->locker != tid)
|
|
||||||
break;
|
|
||||||
return EDEADLK;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_t expected = 0;
|
|
||||||
while (!BAN::atomic_compare_exchange(mutex->locker, expected, tid, BAN::MemoryOrder::memory_order_acquire))
|
|
||||||
{
|
|
||||||
sched_yield();
|
|
||||||
expected = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex->lock_depth = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_mutex_trylock(pthread_mutex_t* mutex)
|
int pthread_mutex_trylock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
// NOTE: current yielding implementation supports shared
|
const uint32_t tid = pthread_self();
|
||||||
|
|
||||||
const auto tid = pthread_self();
|
|
||||||
|
|
||||||
switch (mutex->attr.type)
|
switch (mutex->attr.type)
|
||||||
{
|
{
|
||||||
case PTHREAD_MUTEX_RECURSIVE:
|
case PTHREAD_MUTEX_RECURSIVE:
|
||||||
if (mutex->locker != tid)
|
if (mutex->futex != tid)
|
||||||
break;
|
break;
|
||||||
mutex->lock_depth++;
|
mutex->lock_depth++;
|
||||||
return 0;
|
return 0;
|
||||||
case PTHREAD_MUTEX_ERRORCHECK:
|
case PTHREAD_MUTEX_ERRORCHECK:
|
||||||
if (mutex->locker != tid)
|
if (mutex->futex != tid)
|
||||||
break;
|
break;
|
||||||
return EDEADLK;
|
return EDEADLK;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_t expected = 0;
|
uint32_t expected = 0;
|
||||||
if (!BAN::atomic_compare_exchange(mutex->locker, expected, tid, BAN::MemoryOrder::memory_order_acquire))
|
if (!BAN::atomic_compare_exchange(mutex->futex, expected, tid, BAN::MemoryOrder::memory_order_acquire))
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
|
|
||||||
mutex->lock_depth = 1;
|
mutex->lock_depth = 1;
|
||||||
|
@ -900,18 +846,42 @@ int pthread_mutex_trylock(pthread_mutex_t* mutex)
|
||||||
|
|
||||||
int pthread_mutex_timedlock(pthread_mutex_t* __restrict mutex, const struct timespec* __restrict abstime)
|
int pthread_mutex_timedlock(pthread_mutex_t* __restrict mutex, const struct timespec* __restrict abstime)
|
||||||
{
|
{
|
||||||
return _pthread_timedlock(mutex, abstime, &pthread_mutex_trylock);
|
// recursive/errorcheck handled in trylock to remove code duplication
|
||||||
|
if (const int ret = pthread_mutex_trylock(mutex); ret != EBUSY)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
const uint32_t tid = pthread_self();
|
||||||
|
|
||||||
|
uint32_t expected = 0;
|
||||||
|
while (!BAN::atomic_compare_exchange(mutex->futex, expected, tid, BAN::memory_order_acquire))
|
||||||
|
{
|
||||||
|
const int op = FUTEX_WAIT | (mutex->attr.shared ? 0 : FUTEX_PRIVATE) | FUTEX_REALTIME;
|
||||||
|
|
||||||
|
BAN::atomic_add_fetch(mutex->waiters, 1);
|
||||||
|
const auto ret = futex(op, &mutex->futex, expected, abstime);
|
||||||
|
BAN::atomic_sub_fetch(mutex->waiters, 1);
|
||||||
|
|
||||||
|
if (ret == -1 && errno == ETIMEDOUT)
|
||||||
|
return ETIMEDOUT;
|
||||||
|
|
||||||
|
expected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex->lock_depth = 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_mutex_unlock(pthread_mutex_t* mutex)
|
int pthread_mutex_unlock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
// NOTE: current yielding implementation supports shared
|
ASSERT(mutex->futex == static_cast<uint32_t>(pthread_self()));
|
||||||
|
|
||||||
ASSERT(mutex->locker == pthread_self());
|
|
||||||
|
|
||||||
mutex->lock_depth--;
|
mutex->lock_depth--;
|
||||||
if (mutex->lock_depth == 0)
|
if (mutex->lock_depth == 0)
|
||||||
BAN::atomic_store(mutex->locker, 0, BAN::MemoryOrder::memory_order_release);
|
{
|
||||||
|
BAN::atomic_store(mutex->futex, 0, BAN::memory_order_release);
|
||||||
|
if (BAN::atomic_load(mutex->waiters))
|
||||||
|
futex(FUTEX_WAKE, &mutex->futex, 1, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -971,6 +941,36 @@ int pthread_rwlock_init(pthread_rwlock_t* __restrict rwlock, const pthread_rwloc
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: rewrite rwlock with futexes
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static int pthread_rwlock_timedlock(T* __restrict lock, const struct timespec* __restrict abstime, int (*trylock)(T*))
|
||||||
|
{
|
||||||
|
if (trylock(lock) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
constexpr auto has_timed_out =
|
||||||
|
[](const struct timespec* abstime) -> bool
|
||||||
|
{
|
||||||
|
struct timespec curtime;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &curtime);
|
||||||
|
if (curtime.tv_sec < abstime->tv_sec)
|
||||||
|
return false;
|
||||||
|
if (curtime.tv_sec > abstime->tv_sec)
|
||||||
|
return true;
|
||||||
|
return curtime.tv_nsec >= abstime->tv_nsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (!has_timed_out(abstime))
|
||||||
|
{
|
||||||
|
if (trylock(lock) == 0)
|
||||||
|
return 0;
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock)
|
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock)
|
||||||
{
|
{
|
||||||
unsigned expected = BAN::atomic_load(rwlock->lockers);
|
unsigned expected = BAN::atomic_load(rwlock->lockers);
|
||||||
|
@ -995,7 +995,7 @@ int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock)
|
||||||
|
|
||||||
int pthread_rwlock_timedrdlock(pthread_rwlock_t* __restrict rwlock, const struct timespec* __restrict abstime)
|
int pthread_rwlock_timedrdlock(pthread_rwlock_t* __restrict rwlock, const struct timespec* __restrict abstime)
|
||||||
{
|
{
|
||||||
return _pthread_timedlock(rwlock, abstime, &pthread_rwlock_tryrdlock);
|
return pthread_rwlock_timedlock(rwlock, abstime, &pthread_rwlock_tryrdlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock)
|
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock)
|
||||||
|
@ -1021,7 +1021,7 @@ int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock)
|
||||||
|
|
||||||
int pthread_rwlock_timedwrlock(pthread_rwlock_t* __restrict rwlock, const struct timespec* __restrict abstime)
|
int pthread_rwlock_timedwrlock(pthread_rwlock_t* __restrict rwlock, const struct timespec* __restrict abstime)
|
||||||
{
|
{
|
||||||
return _pthread_timedlock(rwlock, abstime, &pthread_rwlock_trywrlock);
|
return pthread_rwlock_timedlock(rwlock, abstime, &pthread_rwlock_trywrlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock)
|
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock)
|
||||||
|
|
|
@ -7,13 +7,5 @@ void siglongjmp(sigjmp_buf env, int val)
|
||||||
{
|
{
|
||||||
if (env[_JMP_BUF_REGS])
|
if (env[_JMP_BUF_REGS])
|
||||||
pthread_sigmask(SIG_SETMASK, reinterpret_cast<sigset_t*>(&env[_JMP_BUF_REGS + 1]), nullptr);
|
pthread_sigmask(SIG_SETMASK, reinterpret_cast<sigset_t*>(&env[_JMP_BUF_REGS + 1]), nullptr);
|
||||||
return longjmp(env, val);
|
longjmp(env, val);
|
||||||
}
|
|
||||||
|
|
||||||
int sigsetjmp(sigjmp_buf env, int savemask)
|
|
||||||
{
|
|
||||||
env[_JMP_BUF_REGS] = savemask;
|
|
||||||
if (savemask)
|
|
||||||
pthread_sigmask(0, nullptr, reinterpret_cast<sigset_t*>(&env[_JMP_BUF_REGS + 1]));
|
|
||||||
return setjmp(env);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,3 +164,22 @@ int sigrelse(int sig)
|
||||||
(void)sigaddset(&set, sig);
|
(void)sigaddset(&set, sig);
|
||||||
return sigprocmask(SIG_UNBLOCK, &set, nullptr);
|
return sigprocmask(SIG_UNBLOCK, &set, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigsuspend(const sigset_t* sigmask)
|
||||||
|
{
|
||||||
|
return syscall(SYS_SIGSUSPEND, sigmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sigwait(const sigset_t* __restrict set, int* __restrict sig)
|
||||||
|
{
|
||||||
|
if (syscall(SYS_SIGWAIT, set, sig) == -1)
|
||||||
|
return errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sigaltstack(const stack_t* __restrict ss, stack_t* __restrict oss)
|
||||||
|
{
|
||||||
|
if (syscall(SYS_SIGALTSTACK, ss, oss) == -1)
|
||||||
|
return errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -606,6 +606,7 @@ int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n)
|
||||||
|
|
||||||
return wch ? length : 0;
|
return wch ? length : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,6 +646,31 @@ size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wctomb(char* s, wchar_t wchar)
|
||||||
|
{
|
||||||
|
// no state-dependent encodings
|
||||||
|
if (s == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (__getlocale(LC_CTYPE))
|
||||||
|
{
|
||||||
|
case locale_t::LOCALE_INVALID:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
case locale_t::LOCALE_POSIX:
|
||||||
|
*s = wchar;
|
||||||
|
return wchar ? 1 : 0;
|
||||||
|
case locale_t::LOCALE_UTF8:
|
||||||
|
char buffer[5];
|
||||||
|
if (!BAN::UTF8::from_codepoints(&wchar, 1, buffer))
|
||||||
|
return -1;
|
||||||
|
const size_t length = strlen(buffer);
|
||||||
|
memcpy(s, buffer, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
|
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n)
|
||||||
{
|
{
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <BAN/Assert.h>
|
||||||
#include <BAN/Debug.h>
|
#include <BAN/Debug.h>
|
||||||
#include <BAN/Math.h>
|
#include <BAN/Math.h>
|
||||||
|
|
||||||
|
@ -167,15 +168,18 @@ time_t mktime(struct tm* tm)
|
||||||
|
|
||||||
struct tm* gmtime_r(const time_t* timer, struct tm* __restrict result)
|
struct tm* gmtime_r(const time_t* timer, struct tm* __restrict result)
|
||||||
{
|
{
|
||||||
|
// FIXME: allow negative times :)
|
||||||
|
ASSERT(*timer >= 0);
|
||||||
|
|
||||||
constexpr uint64_t month_days[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
|
constexpr uint64_t month_days[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
|
||||||
|
|
||||||
time_t time = *timer;
|
unsigned long long time = *timer;
|
||||||
|
|
||||||
result->tm_sec = time % 60; time /= 60;
|
result->tm_sec = time % 60; time /= 60;
|
||||||
result->tm_min = time % 60; time /= 60;
|
result->tm_min = time % 60; time /= 60;
|
||||||
result->tm_hour = time % 24; time /= 24;
|
result->tm_hour = time % 24; time /= 24;
|
||||||
|
|
||||||
time_t total_days = time;
|
unsigned long long total_days = time;
|
||||||
result->tm_wday = (total_days + 4) % 7;
|
result->tm_wday = (total_days + 4) % 7;
|
||||||
result->tm_year = 1970;
|
result->tm_year = 1970;
|
||||||
while (total_days >= 365U + is_leap_year(result->tm_year))
|
while (total_days >= 365U + is_leap_year(result->tm_year))
|
||||||
|
|
|
@ -335,6 +335,10 @@ namespace LibGUI
|
||||||
if (m_window_shown_event_callback)
|
if (m_window_shown_event_callback)
|
||||||
m_window_shown_event_callback(TRY_OR_BREAK(EventPacket::WindowShownEvent::deserialize(packet_data.span())).event);
|
m_window_shown_event_callback(TRY_OR_BREAK(EventPacket::WindowShownEvent::deserialize(packet_data.span())).event);
|
||||||
break;
|
break;
|
||||||
|
case PacketType::WindowFocusEvent:
|
||||||
|
if (m_window_focus_event_callback)
|
||||||
|
m_window_focus_event_callback(TRY_OR_BREAK(EventPacket::WindowFocusEvent::deserialize(packet_data.span())).event);
|
||||||
|
break;
|
||||||
case PacketType::KeyEvent:
|
case PacketType::KeyEvent:
|
||||||
if (m_key_event_callback)
|
if (m_key_event_callback)
|
||||||
m_key_event_callback(TRY_OR_BREAK(EventPacket::KeyEvent::deserialize(packet_data.span())).event);
|
m_key_event_callback(TRY_OR_BREAK(EventPacket::KeyEvent::deserialize(packet_data.span())).event);
|
||||||
|
|
|
@ -217,6 +217,7 @@ namespace LibGUI
|
||||||
CloseWindowEvent,
|
CloseWindowEvent,
|
||||||
ResizeWindowEvent,
|
ResizeWindowEvent,
|
||||||
WindowShownEvent,
|
WindowShownEvent,
|
||||||
|
WindowFocusEvent,
|
||||||
KeyEvent,
|
KeyEvent,
|
||||||
MouseButtonEvent,
|
MouseButtonEvent,
|
||||||
MouseMoveEvent,
|
MouseMoveEvent,
|
||||||
|
@ -333,6 +334,14 @@ namespace LibGUI
|
||||||
event_t, event
|
event_t, event
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DEFINE_PACKET_EXTRA(
|
||||||
|
WindowFocusEvent,
|
||||||
|
struct event_t {
|
||||||
|
bool focused;
|
||||||
|
},
|
||||||
|
event_t, event
|
||||||
|
);
|
||||||
|
|
||||||
DEFINE_PACKET_EXTRA(
|
DEFINE_PACKET_EXTRA(
|
||||||
KeyEvent,
|
KeyEvent,
|
||||||
using event_t = LibInput::KeyEvent,
|
using event_t = LibInput::KeyEvent,
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace LibGUI
|
||||||
void set_mouse_move_event_callback(BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> callback) { m_mouse_move_event_callback = callback; }
|
void set_mouse_move_event_callback(BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> callback) { m_mouse_move_event_callback = callback; }
|
||||||
void set_mouse_scroll_event_callback(BAN::Function<void(EventPacket::MouseScrollEvent::event_t)> callback) { m_mouse_scroll_event_callback = callback; }
|
void set_mouse_scroll_event_callback(BAN::Function<void(EventPacket::MouseScrollEvent::event_t)> callback) { m_mouse_scroll_event_callback = callback; }
|
||||||
void set_window_shown_event_callback(BAN::Function<void(EventPacket::WindowShownEvent::event_t)> callback) { m_window_shown_event_callback = callback; }
|
void set_window_shown_event_callback(BAN::Function<void(EventPacket::WindowShownEvent::event_t)> callback) { m_window_shown_event_callback = callback; }
|
||||||
|
void set_window_focus_event_callback(BAN::Function<void(EventPacket::WindowFocusEvent::event_t)> callback) { m_window_focus_event_callback = callback; }
|
||||||
|
|
||||||
int server_fd() const { return m_server_fd; }
|
int server_fd() const { return m_server_fd; }
|
||||||
|
|
||||||
|
@ -108,6 +109,7 @@ namespace LibGUI
|
||||||
BAN::Function<void()> m_close_window_event_callback;
|
BAN::Function<void()> m_close_window_event_callback;
|
||||||
BAN::Function<void()> m_resize_window_event_callback;
|
BAN::Function<void()> m_resize_window_event_callback;
|
||||||
BAN::Function<void(EventPacket::WindowShownEvent::event_t)> m_window_shown_event_callback;
|
BAN::Function<void(EventPacket::WindowShownEvent::event_t)> m_window_shown_event_callback;
|
||||||
|
BAN::Function<void(EventPacket::WindowFocusEvent::event_t)> m_window_focus_event_callback;
|
||||||
BAN::Function<void(EventPacket::KeyEvent::event_t)> m_key_event_callback;
|
BAN::Function<void(EventPacket::KeyEvent::event_t)> m_key_event_callback;
|
||||||
BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> m_mouse_button_event_callback;
|
BAN::Function<void(EventPacket::MouseButtonEvent::event_t)> m_mouse_button_event_callback;
|
||||||
BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> m_mouse_move_event_callback;
|
BAN::Function<void(EventPacket::MouseMoveEvent::event_t)> m_mouse_move_event_callback;
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace LibInput
|
||||||
"å", "ä", "ö",
|
"å", "ä", "ö",
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||||
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\n", " ",
|
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\r", " ",
|
||||||
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
||||||
"(", ")", "[", "]", "{", "}",
|
"(", ")", "[", "]", "{", "}",
|
||||||
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
||||||
|
@ -77,7 +77,7 @@ namespace LibInput
|
||||||
"Å", "Ä", "Ö",
|
"Å", "Ä", "Ö",
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||||
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\n", " ",
|
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\r", " ",
|
||||||
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
||||||
"(", ")", "[", "]", "{", "}",
|
"(", ")", "[", "]", "{", "}",
|
||||||
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
||||||
|
@ -96,7 +96,7 @@ namespace LibInput
|
||||||
"Å", "Ä", "Ö",
|
"Å", "Ä", "Ö",
|
||||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||||
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\n", " ",
|
/*"Insert", "PrintScreen", "Delete", "Home", "End", "PageUp", "PageDown",*/ nullptr, nullptr, "\x7F", nullptr, nullptr, nullptr, nullptr, "\r", " ",
|
||||||
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
"!", "\"", "#", "¤", "%", "&", "/", "§", "½",
|
||||||
"(", ")", "[", "]", "{", "}",
|
"(", ")", "[", "]", "{", "}",
|
||||||
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
"=", "?", "+", "\\", "´", "`", "¨", "¸", "\b", "@", "£", "$", "€",
|
||||||
|
|
|
@ -22,15 +22,15 @@ namespace LibInput
|
||||||
consteval uint8_t keycode_normal(uint8_t row, uint8_t col)
|
consteval uint8_t keycode_normal(uint8_t row, uint8_t col)
|
||||||
{
|
{
|
||||||
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
|
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
|
||||||
BANAN_CONSTEVAL_STATIC_ASSERT(col < 0b11111 - 8);
|
BANAN_CONSTEVAL_STATIC_ASSERT(col <= 0b11111 - 8);
|
||||||
return ((row + 1) << 5) | col;
|
return ((row + 1) << 5) | col;
|
||||||
}
|
}
|
||||||
|
|
||||||
consteval uint8_t keycode_numpad(uint8_t row, uint8_t col)
|
consteval uint8_t keycode_numpad(uint8_t row, uint8_t col)
|
||||||
{
|
{
|
||||||
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
|
BANAN_CONSTEVAL_STATIC_ASSERT(row <= 0b111 - 1);
|
||||||
BANAN_CONSTEVAL_STATIC_ASSERT(col <= 8);
|
BANAN_CONSTEVAL_STATIC_ASSERT(col < 8);
|
||||||
return ((row + 1) << 5) | (col + 0b11111 - 8);
|
return ((row + 1) << 5) | (col + 0b11111 - 8 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Key
|
enum class Key
|
||||||
|
|
|
@ -116,11 +116,14 @@ uint64_t AudioServer::update()
|
||||||
if (!anyone_playing)
|
if (!anyone_playing)
|
||||||
return 60'000;
|
return 60'000;
|
||||||
|
|
||||||
// FIXME: this works but if any client stops producing audio samples
|
const uint32_t sample_frames_per_10ms = m_sample_rate / 100;
|
||||||
// the whole audio server halts
|
if (max_sample_frames_to_queue < sample_frames_per_10ms)
|
||||||
const uint32_t samples_per_10ms = m_sample_rate / 100;
|
{
|
||||||
if (max_sample_frames_to_queue < samples_per_10ms)
|
const uint32_t sample_frames_sent = m_samples_sent / m_channels;
|
||||||
|
if (sample_frames_sent >= sample_frames_per_10ms)
|
||||||
return 1;
|
return 1;
|
||||||
|
max_sample_frames_to_queue = sample_frames_per_10ms;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& [_, buffer] : m_audio_buffers)
|
for (auto& [_, buffer] : m_audio_buffers)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +138,7 @@ uint64_t AudioServer::update()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames_to_queue, buffer_sample_frames_available);
|
const size_t sample_frames_to_queue = BAN::Math::min<size_t>(max_sample_frames_to_queue, buffer_sample_frames_available);
|
||||||
if (sample_frames_to_queue < samples_per_10ms)
|
if (sample_frames_to_queue < sample_frames_per_10ms)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (m_samples.size() < queued_samples_end + sample_frames_to_queue * m_channels)
|
while (m_samples.size() < queued_samples_end + sample_frames_to_queue * m_channels)
|
||||||
|
|
|
@ -190,6 +190,19 @@ struct LoadedElf
|
||||||
bool is_relocating;
|
bool is_relocating;
|
||||||
|
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
struct LoadedPHDR
|
||||||
|
{
|
||||||
|
uintptr_t base;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
LoadedPHDR loaded_phdrs[16];
|
||||||
|
size_t loaded_phdr_count;
|
||||||
|
|
||||||
|
size_t real_symtab_size;
|
||||||
|
size_t real_symtab_entsize;
|
||||||
|
const uint8_t* real_symtab_addr;
|
||||||
|
const uint8_t* real_strtab_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LoadedElf s_loaded_files[128];
|
static LoadedElf s_loaded_files[128];
|
||||||
|
@ -433,6 +446,7 @@ extern "C" int __dlclose(void* handle);
|
||||||
extern "C" char* __dlerror(void);
|
extern "C" char* __dlerror(void);
|
||||||
extern "C" void* __dlopen(const char* file, int mode);
|
extern "C" void* __dlopen(const char* file, int mode);
|
||||||
extern "C" void* __dlsym(void* __restrict handle, const char* __restrict name);
|
extern "C" void* __dlsym(void* __restrict handle, const char* __restrict name);
|
||||||
|
extern "C" int __dladdr(const void* addr, Dl_info_t* dlip);
|
||||||
|
|
||||||
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
|
template<typename RelocT> requires BAN::is_same_v<RelocT, ElfNativeRelocation> || BAN::is_same_v<RelocT, ElfNativeRelocationA>
|
||||||
static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc, bool resolve_symbols)
|
static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc, bool resolve_symbols)
|
||||||
|
@ -458,6 +472,7 @@ static uintptr_t handle_relocation(const LoadedElf& elf, const RelocT& reloc, bo
|
||||||
CHECK_SYM(__dlerror);
|
CHECK_SYM(__dlerror);
|
||||||
CHECK_SYM(__dlopen);
|
CHECK_SYM(__dlopen);
|
||||||
CHECK_SYM(__dlsym);
|
CHECK_SYM(__dlsym);
|
||||||
|
CHECK_SYM(__dladdr);
|
||||||
#undef CHECK_SYM
|
#undef CHECK_SYM
|
||||||
else if (symbol.st_shndx && ELF_ST_BIND(symbol.st_info) != STB_WEAK)
|
else if (symbol.st_shndx && ELF_ST_BIND(symbol.st_info) != STB_WEAK)
|
||||||
symbol_address = elf.base + symbol.st_value;
|
symbol_address = elf.base + symbol.st_value;
|
||||||
|
@ -947,6 +962,64 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool read_section_header(const LoadedElf& elf, size_t index, ElfNativeSectionHeader& header)
|
||||||
|
{
|
||||||
|
if (index >= elf.file_header.e_shnum)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto& file_header = elf.file_header;
|
||||||
|
if (syscall(SYS_PREAD, elf.fd, &header, sizeof(header), file_header.e_shoff + index * file_header.e_shentsize) != sizeof(header))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t* mmap_section_header_data(const LoadedElf& elf, const ElfNativeSectionHeader& header)
|
||||||
|
{
|
||||||
|
const size_t offset_in_page = header.sh_offset % PAGE_SIZE;
|
||||||
|
const sys_mmap_t mmap_args {
|
||||||
|
.addr = nullptr,
|
||||||
|
.len = header.sh_size + offset_in_page,
|
||||||
|
.prot = PROT_READ,
|
||||||
|
.flags = MAP_SHARED,
|
||||||
|
.fildes = elf.fd,
|
||||||
|
.off = static_cast<off_t>(header.sh_offset - offset_in_page),
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t* mmap_ret = reinterpret_cast<const uint8_t*>(syscall(SYS_MMAP, &mmap_args));
|
||||||
|
if (mmap_ret == MAP_FAILED)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return mmap_ret + offset_in_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool load_symbol_table(LoadedElf& elf)
|
||||||
|
{
|
||||||
|
if (elf.file_header.e_shentsize < sizeof(ElfNativeSectionHeader))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < elf.file_header.e_shnum; i++)
|
||||||
|
{
|
||||||
|
ElfNativeSectionHeader symtab_header;
|
||||||
|
if (!read_section_header(elf, i, symtab_header))
|
||||||
|
return false;
|
||||||
|
if (symtab_header.sh_type != SHT_SYMTAB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ElfNativeSectionHeader strtab_header;
|
||||||
|
if (!read_section_header(elf, symtab_header.sh_link, strtab_header))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
elf.real_symtab_entsize = symtab_header.sh_entsize;
|
||||||
|
elf.real_symtab_size = symtab_header.sh_size;
|
||||||
|
elf.real_symtab_addr = mmap_section_header_data(elf, symtab_header);
|
||||||
|
elf.real_strtab_addr = mmap_section_header_data(elf, strtab_header);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static LoadedElf& load_elf(const char* path, int fd)
|
static LoadedElf& load_elf(const char* path, int fd)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < s_loaded_file_count; i++)
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
@ -1021,8 +1094,13 @@ static LoadedElf& load_elf(const char* path, int fd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfNativeProgramHeader tls_header {};
|
auto& elf = s_loaded_files[s_loaded_file_count++];
|
||||||
tls_header.p_type = PT_NULL;
|
elf.tls_header.p_type = PT_NULL;
|
||||||
|
elf.base = base;
|
||||||
|
elf.fd = fd;
|
||||||
|
elf.dynamics = nullptr;
|
||||||
|
memcpy(&elf.file_header, &file_header, sizeof(file_header));
|
||||||
|
strcpy(elf.path, path);
|
||||||
|
|
||||||
for (size_t i = 0; i < file_header.e_phnum; i++)
|
for (size_t i = 0; i < file_header.e_phnum; i++)
|
||||||
{
|
{
|
||||||
|
@ -1043,10 +1121,20 @@ static LoadedElf& load_elf(const char* path, int fd)
|
||||||
case PT_GNU_RELRO:
|
case PT_GNU_RELRO:
|
||||||
break;
|
break;
|
||||||
case PT_TLS:
|
case PT_TLS:
|
||||||
tls_header = program_header;
|
elf.tls_header = program_header;
|
||||||
break;
|
break;
|
||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
|
if (elf.loaded_phdr_count >= sizeof(elf.loaded_phdrs) / sizeof(*elf.loaded_phdrs))
|
||||||
|
{
|
||||||
|
print(STDERR_FILENO, "file '");
|
||||||
|
print(STDERR_FILENO, elf.path);
|
||||||
|
print_error_and_exit("' has too many PT_LOAD headers", 0);
|
||||||
|
}
|
||||||
program_header.p_vaddr += base;
|
program_header.p_vaddr += base;
|
||||||
|
elf.loaded_phdrs[elf.loaded_phdr_count++] = {
|
||||||
|
.base = program_header.p_vaddr,
|
||||||
|
.size = program_header.p_memsz,
|
||||||
|
};
|
||||||
load_program_header(program_header, fd, needs_writable);
|
load_program_header(program_header, fd, needs_writable);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1056,13 +1144,6 @@ static LoadedElf& load_elf(const char* path, int fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& elf = s_loaded_files[s_loaded_file_count++];
|
|
||||||
elf.tls_header = tls_header;
|
|
||||||
elf.base = base;
|
|
||||||
elf.fd = fd;
|
|
||||||
elf.dynamics = nullptr;
|
|
||||||
memcpy(&elf.file_header, &file_header, sizeof(file_header));
|
|
||||||
strcpy(elf.path, path);
|
|
||||||
|
|
||||||
if (has_dynamic_pheader)
|
if (has_dynamic_pheader)
|
||||||
{
|
{
|
||||||
|
@ -1084,6 +1165,8 @@ static LoadedElf& load_elf(const char* path, int fd)
|
||||||
handle_dynamic(elf);
|
handle_dynamic(elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_symbol_table(elf);
|
||||||
|
|
||||||
return elf;
|
return elf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,6 +1502,88 @@ void* __dlsym(void* __restrict handle, const char* __restrict name)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool elf_contains_address(const LoadedElf& elf, const void* address)
|
||||||
|
{
|
||||||
|
const uintptr_t addr_uptr = reinterpret_cast<uintptr_t>(address);
|
||||||
|
for (size_t i = 0; i < elf.loaded_phdr_count; i++)
|
||||||
|
{
|
||||||
|
const auto& phdr = elf.loaded_phdrs[i];
|
||||||
|
if (phdr.base <= addr_uptr && addr_uptr < phdr.base + phdr.size)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FindSymbolResult
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
void* addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FindSymbolResult find_symbol_containing(const LoadedElf& elf, const void* address)
|
||||||
|
{
|
||||||
|
const uintptr_t addr_uptr = reinterpret_cast<uintptr_t>(address);
|
||||||
|
|
||||||
|
const size_t symbol_count = reinterpret_cast<const uint32_t*>(elf.hash)[1];
|
||||||
|
for (size_t i = 1; i < symbol_count; i++)
|
||||||
|
{
|
||||||
|
const auto& symbol = *reinterpret_cast<const ElfNativeSymbol*>(elf.symtab + i * elf.syment);
|
||||||
|
const uintptr_t symbol_base = elf.base + symbol.st_value;
|
||||||
|
if (!(symbol_base <= addr_uptr && addr_uptr < symbol_base + symbol.st_size))
|
||||||
|
continue;
|
||||||
|
return {
|
||||||
|
.name = reinterpret_cast<const char*>(elf.strtab + symbol.st_name),
|
||||||
|
.addr = reinterpret_cast<void*>(symbol_base),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!elf.real_symtab_addr || !elf.real_strtab_addr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
for (size_t i = 1; i < elf.real_symtab_size / elf.real_symtab_entsize; i++)
|
||||||
|
{
|
||||||
|
const auto& symbol = *reinterpret_cast<const ElfNativeSymbol*>(elf.real_symtab_addr + i * elf.real_symtab_entsize);
|
||||||
|
const uintptr_t symbol_base = elf.base + symbol.st_value;
|
||||||
|
if (!(symbol_base <= addr_uptr && addr_uptr < symbol_base + symbol.st_size))
|
||||||
|
continue;
|
||||||
|
return {
|
||||||
|
.name = reinterpret_cast<const char*>(elf.real_strtab_addr + symbol.st_name),
|
||||||
|
.addr = reinterpret_cast<void*>(symbol_base),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int __dladdr(const void* addr, Dl_info_t* dlip)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
|
{
|
||||||
|
const auto& elf = s_loaded_files[i];
|
||||||
|
if (!elf_contains_address(elf, addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dlip->dli_fname = elf.path;
|
||||||
|
dlip->dli_fbase = reinterpret_cast<void*>(elf.base);
|
||||||
|
|
||||||
|
if (const auto symbol = find_symbol_containing(elf, addr); symbol.addr && symbol.name)
|
||||||
|
{
|
||||||
|
dlip->dli_sname = symbol.name;
|
||||||
|
dlip->dli_saddr = symbol.addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dlip->dli_sname = nullptr;
|
||||||
|
dlip->dli_saddr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_dlerror_string = "address is not contained in any file";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static LibELF::AuxiliaryVector* find_auxv(char** envp)
|
static LibELF::AuxiliaryVector* find_auxv(char** envp)
|
||||||
{
|
{
|
||||||
if (envp == nullptr)
|
if (envp == nullptr)
|
||||||
|
|
|
@ -181,13 +181,6 @@ void Terminal::run()
|
||||||
perror("ioctl");
|
perror("ioctl");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pid_t fgpgrp = tcgetpgrp(m_shell_info.pts_master);
|
|
||||||
if (fgpgrp == -1)
|
|
||||||
{
|
|
||||||
perror("tcgetpgrp");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd());
|
const int max_fd = BAN::Math::max(m_shell_info.pts_master, m_window->server_fd());
|
||||||
|
@ -676,6 +669,14 @@ Rectangle Terminal::putcodepoint(uint32_t codepoint)
|
||||||
auto& texture = m_window->texture();
|
auto& texture = m_window->texture();
|
||||||
switch (codepoint)
|
switch (codepoint)
|
||||||
{
|
{
|
||||||
|
case 0x00: // null
|
||||||
|
case 0x01: // start of heading
|
||||||
|
case 0x02: // start of text
|
||||||
|
case 0x1C: // file separator
|
||||||
|
case 0x1D: // group separator
|
||||||
|
case 0x1E: // record separator
|
||||||
|
case 0x1F: // unit separator
|
||||||
|
break;
|
||||||
case '\a':
|
case '\a':
|
||||||
// TODO: bell
|
// TODO: bell
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -90,7 +90,7 @@ void WindowServer::on_window_create(int fd, const LibGUI::WindowPacket::WindowCr
|
||||||
|
|
||||||
window_popper.disable();
|
window_popper.disable();
|
||||||
|
|
||||||
if (packet.attributes.focusable)
|
if (packet.attributes.shown && packet.attributes.focusable)
|
||||||
set_focused_window(window);
|
set_focused_window(window);
|
||||||
else if (m_client_windows.size() > 1)
|
else if (m_client_windows.size() > 1)
|
||||||
BAN::swap(m_client_windows[m_client_windows.size() - 1], m_client_windows[m_client_windows.size() - 2]);
|
BAN::swap(m_client_windows[m_client_windows.size() - 1], m_client_windows[m_client_windows.size() - 2]);
|
||||||
|
@ -197,6 +197,9 @@ void WindowServer::on_window_set_attributes(int fd, const LibGUI::WindowPacket::
|
||||||
};
|
};
|
||||||
if (auto ret = event_packet.send_serialized(target_window->client_fd()); ret.is_error())
|
if (auto ret = event_packet.send_serialized(target_window->client_fd()); ret.is_error())
|
||||||
dwarnln("could not send window shown event: {}", ret.error());
|
dwarnln("could not send window shown event: {}", ret.error());
|
||||||
|
|
||||||
|
if (packet.attributes.focusable && packet.attributes.shown)
|
||||||
|
set_focused_window(target_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowServer::on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative& packet)
|
void WindowServer::on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative& packet)
|
||||||
|
@ -512,7 +515,9 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::RefPtr<Window> target_window;
|
BAN::RefPtr<Window> target_window;
|
||||||
if (!event.pressed)
|
if (m_state == State::Fullscreen)
|
||||||
|
target_window = m_focused_window;
|
||||||
|
if (!event.pressed && !target_window)
|
||||||
target_window = m_mouse_button_windows[button_idx];
|
target_window = m_mouse_button_windows[button_idx];
|
||||||
for (size_t i = m_client_windows.size(); i > 0 && !target_window; i--)
|
for (size_t i = m_client_windows.size(); i > 0 && !target_window; i--)
|
||||||
if (m_client_windows[i - 1]->full_area().contains(m_cursor) && m_client_windows[i - 1]->get_attributes().shown)
|
if (m_client_windows[i - 1]->full_area().contains(m_cursor) && m_client_windows[i - 1]->get_attributes().shown)
|
||||||
|
@ -556,7 +561,7 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
||||||
if (event.button == LibInput::MouseButton::Left && !event.pressed && target_window->close_button_area().contains(m_cursor))
|
if (event.button == LibInput::MouseButton::Left && !event.pressed && target_window->close_button_area().contains(m_cursor))
|
||||||
{
|
{
|
||||||
LibGUI::EventPacket::CloseWindowEvent packet;
|
LibGUI::EventPacket::CloseWindowEvent packet;
|
||||||
if (auto ret = packet.send_serialized(m_focused_window->client_fd()); ret.is_error())
|
if (auto ret = packet.send_serialized(target_window->client_fd()); ret.is_error())
|
||||||
dwarnln("could not send close window event: {}", ret.error());
|
dwarnln("could not send close window event: {}", ret.error());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -568,9 +573,9 @@ void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
||||||
LibGUI::EventPacket::MouseButtonEvent packet;
|
LibGUI::EventPacket::MouseButtonEvent packet;
|
||||||
packet.event.button = event.button;
|
packet.event.button = event.button;
|
||||||
packet.event.pressed = event.pressed;
|
packet.event.pressed = event.pressed;
|
||||||
packet.event.x = m_cursor.x - m_focused_window->client_x();
|
packet.event.x = m_cursor.x - target_window->client_x();
|
||||||
packet.event.y = m_cursor.y - m_focused_window->client_y();
|
packet.event.y = m_cursor.y - target_window->client_y();
|
||||||
if (auto ret = packet.send_serialized(m_focused_window->client_fd()); ret.is_error())
|
if (auto ret = packet.send_serialized(target_window->client_fd()); ret.is_error())
|
||||||
{
|
{
|
||||||
dwarnln("could not send mouse button event: {}", ret.error());
|
dwarnln("could not send mouse button event: {}", ret.error());
|
||||||
return;
|
return;
|
||||||
|
@ -779,6 +784,17 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
||||||
invalidate(cursor_area());
|
invalidate(cursor_area());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_focused_window)
|
||||||
|
{
|
||||||
|
LibGUI::EventPacket::WindowFocusEvent packet;
|
||||||
|
packet.event.focused = false;
|
||||||
|
if (auto ret = packet.send_serialized(m_focused_window->client_fd()); ret.is_error())
|
||||||
|
{
|
||||||
|
dwarnln("could not send window focus event: {}", ret.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = m_client_windows.size(); i > 0; i--)
|
for (size_t i = m_client_windows.size(); i > 0; i--)
|
||||||
{
|
{
|
||||||
if (m_client_windows[i - 1] == window)
|
if (m_client_windows[i - 1] == window)
|
||||||
|
@ -790,6 +806,17 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_focused_window)
|
||||||
|
{
|
||||||
|
LibGUI::EventPacket::WindowFocusEvent packet;
|
||||||
|
packet.event.focused = true;
|
||||||
|
if (auto ret = packet.send_serialized(m_focused_window->client_fd()); ret.is_error())
|
||||||
|
{
|
||||||
|
dwarnln("could not send window focus event: {}", ret.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t alpha_blend(uint32_t color_a, uint32_t color_b)
|
static uint32_t alpha_blend(uint32_t color_a, uint32_t color_b)
|
||||||
|
@ -1410,6 +1437,10 @@ void WindowServer::remove_client_fd(int fd)
|
||||||
invalidate(m_framebuffer.area());
|
invalidate(m_framebuffer.area());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& window : m_mouse_button_windows)
|
||||||
|
if (window && window->client_fd() == fd)
|
||||||
|
window.clear();
|
||||||
|
|
||||||
for (size_t i = 0; i < m_client_windows.size(); i++)
|
for (size_t i = 0; i < m_client_windows.size(); i++)
|
||||||
{
|
{
|
||||||
auto window = m_client_windows[i];
|
auto window = m_client_windows[i];
|
||||||
|
|
Loading…
Reference in New Issue