mirror of
https://github.com/RGBCube/serenity
synced 2025-05-26 01:45:06 +00:00
Kernel: Implement aligned operator new
and use it
The compiler will use these to allocate objects that have alignment requirements greater than that of our normal `operator new` (4/8 byte aligned). This means we can now use smart pointers for over-aligned types. Fixes a FIXME.
This commit is contained in:
parent
c176680443
commit
dd4ed4d22d
4 changed files with 41 additions and 10 deletions
|
@ -301,6 +301,16 @@ size_t kmalloc_good_size(size_t size)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[gnu::malloc, gnu::alloc_size(1), gnu::alloc_align(2)]] static void* kmalloc_aligned_cxx(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
VERIFY(alignment <= 4096);
|
||||||
|
void* ptr = kmalloc(size + alignment + sizeof(ptrdiff_t));
|
||||||
|
size_t max_addr = (size_t)ptr + alignment;
|
||||||
|
void* aligned_ptr = (void*)(max_addr - (max_addr % alignment));
|
||||||
|
((ptrdiff_t*)aligned_ptr)[-1] = (ptrdiff_t)((u8*)aligned_ptr - (u8*)ptr);
|
||||||
|
return aligned_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
void* operator new(size_t size)
|
void* operator new(size_t size)
|
||||||
{
|
{
|
||||||
void* ptr = kmalloc(size);
|
void* ptr = kmalloc(size);
|
||||||
|
@ -313,6 +323,18 @@ void* operator new(size_t size, const std::nothrow_t&) noexcept
|
||||||
return kmalloc(size);
|
return kmalloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* operator new(size_t size, std::align_val_t al)
|
||||||
|
{
|
||||||
|
void* ptr = kmalloc_aligned_cxx(size, (size_t)al);
|
||||||
|
VERIFY(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new(size_t size, std::align_val_t al, const std::nothrow_t&) noexcept
|
||||||
|
{
|
||||||
|
return kmalloc_aligned_cxx(size, (size_t)al);
|
||||||
|
}
|
||||||
|
|
||||||
void* operator new[](size_t size)
|
void* operator new[](size_t size)
|
||||||
{
|
{
|
||||||
void* ptr = kmalloc(size);
|
void* ptr = kmalloc(size);
|
||||||
|
@ -336,6 +358,11 @@ void operator delete(void* ptr, size_t size) noexcept
|
||||||
return kfree_sized(ptr, size);
|
return kfree_sized(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator delete(void* ptr, size_t, std::align_val_t) noexcept
|
||||||
|
{
|
||||||
|
return kfree_aligned(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void operator delete[](void*) noexcept
|
void operator delete[](void*) noexcept
|
||||||
{
|
{
|
||||||
// All deletes in kernel code should have a known size.
|
// All deletes in kernel code should have a known size.
|
||||||
|
|
|
@ -34,6 +34,8 @@ struct nothrow_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const nothrow_t nothrow;
|
extern const nothrow_t nothrow;
|
||||||
|
|
||||||
|
enum class align_val_t : size_t {};
|
||||||
};
|
};
|
||||||
|
|
||||||
void kmalloc_init();
|
void kmalloc_init();
|
||||||
|
@ -59,10 +61,16 @@ inline void* operator new[](size_t, void* p) { return p; }
|
||||||
|
|
||||||
[[nodiscard]] void* operator new(size_t size);
|
[[nodiscard]] void* operator new(size_t size);
|
||||||
[[nodiscard]] void* operator new(size_t size, const std::nothrow_t&) noexcept;
|
[[nodiscard]] void* operator new(size_t size, const std::nothrow_t&) noexcept;
|
||||||
|
[[nodiscard]] void* operator new(size_t size, std::align_val_t);
|
||||||
|
[[nodiscard]] void* operator new(size_t size, std::align_val_t, const std::nothrow_t&) noexcept;
|
||||||
|
|
||||||
void operator delete(void* ptr) noexcept;
|
void operator delete(void* ptr) noexcept;
|
||||||
void operator delete(void* ptr, size_t) noexcept;
|
void operator delete(void* ptr, size_t) noexcept;
|
||||||
|
void operator delete(void* ptr, size_t, std::align_val_t) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] void* operator new[](size_t size);
|
[[nodiscard]] void* operator new[](size_t size);
|
||||||
[[nodiscard]] void* operator new[](size_t size, const std::nothrow_t&) noexcept;
|
[[nodiscard]] void* operator new[](size_t size, const std::nothrow_t&) noexcept;
|
||||||
|
|
||||||
void operator delete[](void* ptrs) noexcept;
|
void operator delete[](void* ptrs) noexcept;
|
||||||
void operator delete[](void* ptr, size_t) noexcept;
|
void operator delete[](void* ptr, size_t) noexcept;
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,9 @@ UNMAP_AFTER_INIT void Thread::initialize()
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<Thread>> Thread::try_create(NonnullRefPtr<Process> process)
|
KResultOr<NonnullRefPtr<Thread>> Thread::try_create(NonnullRefPtr<Process> process)
|
||||||
{
|
{
|
||||||
// FIXME: Once we have aligned + nothrow operator new, we can avoid the manual kfree.
|
auto fpu_state = try_make<FPUState>();
|
||||||
FPUState* fpu_state = (FPUState*)kmalloc_aligned<16>(sizeof(FPUState));
|
|
||||||
if (!fpu_state)
|
if (!fpu_state)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
ArmedScopeGuard fpu_guard([fpu_state]() { kfree_aligned(fpu_state); });
|
|
||||||
|
|
||||||
auto kernel_stack_region = MM.allocate_kernel_region(default_kernel_stack_size, {}, Region::Access::Read | Region::Access::Write, AllocationStrategy::AllocateNow);
|
auto kernel_stack_region = MM.allocate_kernel_region(default_kernel_stack_size, {}, Region::Access::Read | Region::Access::Write, AllocationStrategy::AllocateNow);
|
||||||
if (!kernel_stack_region)
|
if (!kernel_stack_region)
|
||||||
|
@ -53,18 +51,17 @@ KResultOr<NonnullRefPtr<Thread>> Thread::try_create(NonnullRefPtr<Process> proce
|
||||||
if (!block_timer)
|
if (!block_timer)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
auto thread = adopt_ref_if_nonnull(new (nothrow) Thread(move(process), kernel_stack_region.release_nonnull(), block_timer.release_nonnull(), fpu_state));
|
auto thread = adopt_ref_if_nonnull(new (nothrow) Thread(move(process), kernel_stack_region.release_nonnull(), block_timer.release_nonnull(), fpu_state.release_nonnull()));
|
||||||
if (!thread)
|
if (!thread)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
fpu_guard.disarm();
|
|
||||||
|
|
||||||
return thread.release_nonnull();
|
return thread.release_nonnull();
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Region> kernel_stack_region, NonnullRefPtr<Timer> block_timer, FPUState* fpu_state)
|
Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Region> kernel_stack_region, NonnullRefPtr<Timer> block_timer, NonnullOwnPtr<FPUState> fpu_state)
|
||||||
: m_process(move(process))
|
: m_process(move(process))
|
||||||
, m_kernel_stack_region(move(kernel_stack_region))
|
, m_kernel_stack_region(move(kernel_stack_region))
|
||||||
, m_fpu_state(fpu_state)
|
, m_fpu_state(move(fpu_state))
|
||||||
, m_name(m_process->name())
|
, m_name(m_process->name())
|
||||||
, m_block_timer(block_timer)
|
, m_block_timer(block_timer)
|
||||||
, m_global_procfs_inode_index(ProcFSComponentRegistry::the().allocate_inode_index())
|
, m_global_procfs_inode_index(ProcFSComponentRegistry::the().allocate_inode_index())
|
||||||
|
@ -533,7 +530,6 @@ void Thread::finalize()
|
||||||
if (m_dump_backtrace_on_finalization)
|
if (m_dump_backtrace_on_finalization)
|
||||||
dbgln("{}", backtrace());
|
dbgln("{}", backtrace());
|
||||||
|
|
||||||
kfree_aligned(m_fpu_state);
|
|
||||||
drop_thread_count(false);
|
drop_thread_count(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1192,7 +1192,7 @@ public:
|
||||||
String backtrace();
|
String backtrace();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Thread(NonnullRefPtr<Process>, NonnullOwnPtr<Region>, NonnullRefPtr<Timer>, FPUState*);
|
Thread(NonnullRefPtr<Process>, NonnullOwnPtr<Region>, NonnullRefPtr<Timer>, NonnullOwnPtr<FPUState>);
|
||||||
|
|
||||||
IntrusiveListNode<Thread> m_process_thread_list_node;
|
IntrusiveListNode<Thread> m_process_thread_list_node;
|
||||||
int m_runnable_priority { -1 };
|
int m_runnable_priority { -1 };
|
||||||
|
@ -1318,7 +1318,7 @@ private:
|
||||||
unsigned m_ipv4_socket_read_bytes { 0 };
|
unsigned m_ipv4_socket_read_bytes { 0 };
|
||||||
unsigned m_ipv4_socket_write_bytes { 0 };
|
unsigned m_ipv4_socket_write_bytes { 0 };
|
||||||
|
|
||||||
FPUState* m_fpu_state { nullptr };
|
OwnPtr<FPUState> m_fpu_state;
|
||||||
State m_state { Invalid };
|
State m_state { Invalid };
|
||||||
String m_name;
|
String m_name;
|
||||||
u32 m_priority { THREAD_PRIORITY_NORMAL };
|
u32 m_priority { THREAD_PRIORITY_NORMAL };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue