2020-01-18 11:38:21 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2018-10-16 12:01:38 +03:00
|
|
|
#pragma once
|
|
|
|
|
2019-02-15 14:30:48 +03:00
|
|
|
#include <AK/Types.h>
|
2021-01-25 18:07:10 +03:00
|
|
|
#include <Kernel/Debug.h>
|
2021-06-22 18:16:38 +03:00
|
|
|
#include <LibC/limits.h>
|
2019-02-15 14:30:48 +03:00
|
|
|
|
2020-02-01 12:26:05 +03:00
|
|
|
#define KMALLOC_SCRUB_BYTE 0xbb
|
|
|
|
#define KFREE_SCRUB_BYTE 0xaa
|
|
|
|
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
#define MAKE_ALIGNED_ALLOCATED(type, alignment) \
|
|
|
|
public: \
|
|
|
|
[[nodiscard]] void* operator new(size_t) \
|
|
|
|
{ \
|
2021-12-26 20:08:55 +03:00
|
|
|
void* ptr = kmalloc_aligned(sizeof(type), alignment); \
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
VERIFY(ptr); \
|
|
|
|
return ptr; \
|
|
|
|
} \
|
2022-04-01 20:58:27 +03:00
|
|
|
[[nodiscard]] void* operator new(size_t, std::nothrow_t const&) noexcept { return kmalloc_aligned(sizeof(type), alignment); } \
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
void operator delete(void* ptr) noexcept { kfree_aligned(ptr); } \
|
|
|
|
\
|
2021-03-11 15:11:59 +03:00
|
|
|
private:
|
|
|
|
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
// The C++ standard specifies that the nothrow allocation tag should live in the std namespace.
|
|
|
|
// Otherwise, `new (std::nothrow)` calls wouldn't get resolved.
|
2021-11-06 20:55:32 +03:00
|
|
|
namespace std { // NOLINT(cert-dcl58-cpp) These declarations must be in ::std and we are not using <new>
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
struct nothrow_t {
|
|
|
|
explicit nothrow_t() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const nothrow_t nothrow;
|
2021-07-15 13:08:35 +03:00
|
|
|
|
|
|
|
enum class align_val_t : size_t {};
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
};
|
|
|
|
|
2018-10-16 12:01:38 +03:00
|
|
|
void kmalloc_init();
|
2020-08-30 01:41:30 +03:00
|
|
|
|
2021-07-11 14:19:33 +03:00
|
|
|
void kfree_sized(void*, size_t);
|
2018-10-16 12:01:38 +03:00
|
|
|
|
2020-08-30 01:41:30 +03:00
|
|
|
struct kmalloc_stats {
|
|
|
|
size_t bytes_allocated;
|
|
|
|
size_t bytes_free;
|
|
|
|
size_t kmalloc_call_count;
|
|
|
|
size_t kfree_call_count;
|
|
|
|
};
|
|
|
|
void get_kmalloc_stats(kmalloc_stats&);
|
|
|
|
|
2019-04-16 00:58:48 +03:00
|
|
|
extern bool g_dump_kmalloc_stacks;
|
2018-10-16 12:01:38 +03:00
|
|
|
|
|
|
|
inline void* operator new(size_t, void* p) { return p; }
|
|
|
|
inline void* operator new[](size_t, void* p) { return p; }
|
2019-01-13 01:23:35 +03:00
|
|
|
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
[[nodiscard]] void* operator new(size_t size);
|
2022-04-01 20:58:27 +03:00
|
|
|
[[nodiscard]] void* operator new(size_t size, std::nothrow_t const&) noexcept;
|
2021-07-15 13:08:35 +03:00
|
|
|
[[nodiscard]] void* operator new(size_t size, std::align_val_t);
|
2022-04-01 20:58:27 +03:00
|
|
|
[[nodiscard]] void* operator new(size_t size, std::align_val_t, std::nothrow_t const&) noexcept;
|
2021-07-15 13:08:35 +03:00
|
|
|
|
2021-07-15 14:50:55 +03:00
|
|
|
void operator delete(void* ptr) noexcept DISALLOW("All deletes in the kernel should have a known size.");
|
2021-05-11 11:17:04 +03:00
|
|
|
void operator delete(void* ptr, size_t) noexcept;
|
2021-07-15 14:50:55 +03:00
|
|
|
void operator delete(void* ptr, std::align_val_t) noexcept DISALLOW("All deletes in the kernel should have a known size.");
|
2021-07-15 13:08:35 +03:00
|
|
|
void operator delete(void* ptr, size_t, std::align_val_t) noexcept;
|
|
|
|
|
AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.
To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.
To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.
To perform fallible allocations, the following syntax should be used:
```cpp
auto ptr = new (nothrow) T;
```
As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-20 10:39:20 +03:00
|
|
|
[[nodiscard]] void* operator new[](size_t size);
|
2022-04-01 20:58:27 +03:00
|
|
|
[[nodiscard]] void* operator new[](size_t size, std::nothrow_t const&) noexcept;
|
2021-07-15 13:08:35 +03:00
|
|
|
|
2021-07-15 14:50:55 +03:00
|
|
|
void operator delete[](void* ptrs) noexcept DISALLOW("All deletes in the kernel should have a known size.");
|
2021-05-11 11:17:04 +03:00
|
|
|
void operator delete[](void* ptr, size_t) noexcept;
|
|
|
|
|
2021-08-13 11:32:48 +03:00
|
|
|
[[gnu::malloc, gnu::alloc_size(1)]] void* kmalloc(size_t);
|
2022-03-15 01:59:16 +03:00
|
|
|
[[gnu::malloc, gnu::alloc_size(1, 2)]] void* kcalloc(size_t, size_t);
|
2020-08-25 01:38:20 +03:00
|
|
|
|
2021-12-26 20:08:55 +03:00
|
|
|
[[gnu::malloc, gnu::alloc_size(1), gnu::alloc_align(2)]] void* kmalloc_aligned(size_t size, size_t alignment);
|
2020-08-30 01:41:30 +03:00
|
|
|
|
|
|
|
inline void kfree_aligned(void* ptr)
|
|
|
|
{
|
2021-08-13 13:42:02 +03:00
|
|
|
if (ptr == nullptr)
|
|
|
|
return;
|
2021-12-26 20:08:55 +03:00
|
|
|
kfree_sized((u8*)ptr - ((ptrdiff_t const*)ptr)[-1], ((size_t const*)ptr)[-2]);
|
2020-08-30 01:41:30 +03:00
|
|
|
}
|
|
|
|
|
2021-05-15 11:06:41 +03:00
|
|
|
size_t kmalloc_good_size(size_t);
|
|
|
|
|
2020-08-30 01:41:30 +03:00
|
|
|
void kmalloc_enable_expand();
|