2020-01-18 08:38:21 +00:00
|
|
|
/*
|
2021-08-07 20:32:45 +00:00
|
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
2021-06-29 20:57:27 +00:00
|
|
|
* Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev>
|
2020-01-18 08:38:21 +00:00
|
|
|
*
|
2021-04-22 08:24:48 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 08:38:21 +00:00
|
|
|
*/
|
|
|
|
|
2018-10-10 09:53:07 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-08-07 20:32:45 +00:00
|
|
|
#include <AK/Checked.h>
|
2022-10-09 21:23:23 +00:00
|
|
|
#include <AK/Platform.h>
|
2021-08-07 20:32:45 +00:00
|
|
|
|
2021-06-29 20:57:27 +00:00
|
|
|
#if defined(KERNEL)
|
|
|
|
# include <Kernel/Heap/kmalloc.h>
|
|
|
|
#else
|
2020-02-25 14:58:24 +00:00
|
|
|
# include <new>
|
2021-06-29 20:57:27 +00:00
|
|
|
# include <stdlib.h>
|
|
|
|
|
2022-03-14 22:59:16 +00:00
|
|
|
# define kcalloc calloc
|
2021-06-29 20:57:27 +00:00
|
|
|
# define kmalloc malloc
|
|
|
|
# define kmalloc_good_size malloc_good_size
|
2021-07-11 11:21:38 +00:00
|
|
|
|
|
|
|
inline void kfree_sized(void* ptr, size_t)
|
|
|
|
{
|
2022-01-12 03:27:21 +00:00
|
|
|
free(ptr);
|
2021-07-11 11:21:38 +00:00
|
|
|
}
|
2021-06-29 20:57:27 +00:00
|
|
|
#endif
|
|
|
|
|
2022-10-09 21:23:23 +00:00
|
|
|
#ifndef AK_OS_SERENITY
|
2021-06-29 20:57:27 +00:00
|
|
|
# include <AK/Types.h>
|
2021-05-15 08:06:41 +00:00
|
|
|
|
|
|
|
# ifndef AK_OS_MACOS
|
2021-05-30 09:10:39 +00:00
|
|
|
extern "C" {
|
2021-05-15 08:06:41 +00:00
|
|
|
inline size_t malloc_good_size(size_t size) { return size; }
|
2021-05-30 09:10:39 +00:00
|
|
|
}
|
2021-05-15 08:06:41 +00:00
|
|
|
# else
|
|
|
|
# include <malloc/malloc.h>
|
|
|
|
# endif
|
2020-02-25 14:58:24 +00:00
|
|
|
#endif
|
|
|
|
|
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 07:39:20 +00:00
|
|
|
using std::nothrow;
|
2021-08-07 20:32:45 +00:00
|
|
|
|
2022-11-27 15:40:42 +00:00
|
|
|
inline void* kmalloc_array(AK::Checked<size_t> a, AK::Checked<size_t> b)
|
2021-08-07 20:32:45 +00:00
|
|
|
{
|
|
|
|
auto size = a * b;
|
|
|
|
VERIFY(!size.has_overflow());
|
|
|
|
return kmalloc(size.value());
|
|
|
|
}
|
|
|
|
|
2022-11-27 15:40:42 +00:00
|
|
|
inline void* kmalloc_array(AK::Checked<size_t> a, AK::Checked<size_t> b, AK::Checked<size_t> c)
|
2021-08-07 20:32:45 +00:00
|
|
|
{
|
|
|
|
auto size = a * b * c;
|
|
|
|
VERIFY(!size.has_overflow());
|
|
|
|
return kmalloc(size.value());
|
|
|
|
}
|