In order to reduce our reliance on __builtin_{ffs, clz, ctz, popcount},
this commit removes all calls to these functions and replaces them with
the equivalent functions in AK/BuiltinWrappers.h.
The actual value is unchanged, but the previous `0xffffffff` was an
unsigned value, which lead to clang getting mad at `foowc() == WEOF`.
This commit makes it a signed int on clang, which *should* serve
the same purpose and not lead to clang getting mad at us.
Both `AK/Assertions.h` and `assert.h` would define the macro if `NDEBUG`
is set.
Remove the definition from `assert.h` since it is not an ISO-C
requirement.
This fixes at least half of our LibC includes in the kernel. The source
of truth for errno codes and their description strings now lives in
Kernel/API/POSIX/errno.h as an enumeration, which LibC includes.
This syscall is very much similar to open(2), with the difference of
accepting a string and a length, instead of requiring a null-terminated
string. This way, if the string passed is not null-terminated, we can
still perform the syscall.
This includes a new Thread::Blocker called SignalBlocker which blocks
until a signal of a matching type is pending. The current Blocker
implementation in the Kernel is very complicated, but cleaning it up is
a different yak for a different day.
Also, remove incomplete, superfluous check.
Incomplete, because only the byte at the provided address was checked;
this misses the last bytes of the "jerk page".
Superfluous, because it is already correctly checked by peek_user_data
(which calls copy_from_user).
The caller/tracer should not typically attempt to read non-userspace
addresses, we don't need to "hot-path" it either.
This is not actually implemented at the moment, as we do not support
sending or receiving out-of-band data at all currently, but it is
required for some ports to compile.
POSIX mandates that the macros contained in `stdint.h` be suitable for
use by the C preprocessor.
If we write `((size_t)-1)`, the C preprocessor will just skip the cast
and treat the value as `-1`. This means that we end up taking the wrong
branch in an `#if` directive like `#if SIZE_MAX > UINT32_MAX`.
This fixes building the LLVM port on i686.
x86_64 is an LP64 platform, so its `uint64_t` type is defined to be
`unsigned long`, not `unsigned long long` like on i686. This means that
the `UL` literal suffix should be used instead of `ULL`.
Furthermore, `uintptr_t` is 64 bits wide on x86_64, so defining
`UINTPTR_MAX` to be `UINT32_MAX` is also not correct.
This allows userspace to trigger a full (FIXME) flush of a shared file
mapping to disk. We iterate over all the mapped pages in the VMObject
and write them out to the underlying inode, one by one. This is rather
naive, and there's lots of room for improvement.
Note that shared file mappings are currently not possible since mmap()
returns ENOTSUP for PROT_WRITE+MAP_SHARED. That restriction will be
removed in a subsequent commit. :^)
C++17 introduced aligned versions of `new` and `delete`, which are
automatically called by the compiler when allocating over-aligned
objects. As with the regular allocator functions, these are generally
thin wrappers around LibC.
We did not have support for aligned allocations in LibC, so this was not
possible. While libstdc++ has a fallback implementation, libc++ does
not, so the aligned allocation function was disabled internally. This
made building the LLVM port with Clang impossible.
Note that while the Microsoft docs say that aligned_malloc and
_aligned_free are declared in `malloc.h`, libc++ doesn't #include that
file, but instead relies on the definition coming from `stdlib.h`.
Therefore, I chose to declare it in that file instead of creating a new
LibC header.
I chose not to implement the more Unix-y `memalign`, `posix_memalign`,
or the C11 `aligned_alloc`, because that would require us to
significantly alter the memory allocator's internals. See the comment in
malloc.cpp.
libc++ uses a Pthread condition variable in one of its initialization
functions. This means that Pthread forwarding has to be set up in LibC
before libc++ can be initialized. Also, because LibPthread is written in
C++, (at least some) parts of the C++ standard library have to be linked
against it.
This is a circular dependency, which means that the order in which these
two libraries' initialization functions are called is undefined. In some
cases, libc++ will come first, which will then trigger an assert due to
the missing Pthread forwarding.
This issue isn't necessarily unique to LibPthread, as all libraries that
libc++ depends on exhibit the same circular dependency issue.
The reason why this issue didn't affect the GNU toolchain is that
libstdc++ is always linked statically. If we were to change that, I
believe that we would run into the same issue.
`off_t` is a 64-bit signed integer, so passing it in a register on i686
is not the best idea.
This fix gets us one step closer to making the LLVM port work.
In particular, we track separately whether each AtExitEntry has already
been called, through a separate Bitmap. This has several side-effects:
- We now call malloc() during __cxa_finalize(). I believe this is fine,
and at that point during program execution memory pressure should be
low anyway.
- An attacker could prevent arbitrary entries from executing by writing
to atexit_called_entries. However, this already was possible (by
setting atexit_entry_count to zero), and this path is even more
troublesome (the attacker needs to overwrite atexit_called_entries,
and a region serving as *atexit_called_entries.m_data, and magically
know exactly how many entries already exist.)
- This reduces the size of AtExitEntry from 16 to 12 (on i686). As such,
we can reduce the initial memory allocation from two to one page,
reducing the initial capacity from 512 to 341 entries (or 256 to 170,
on x86_64). It seems that most programs only use 36-47 entries anyway.
For 'true', this shaves off about 69 syscalls, as measured by strace.