diff --git a/Kernel/Arch/x86/i386/Atomics.cpp b/Kernel/Arch/x86/i386/Atomics.cpp new file mode 100644 index 0000000000..19dbab31bc --- /dev/null +++ b/Kernel/Arch/x86/i386/Atomics.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, Idan Horowitz + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +extern "C" { + +#if defined(__GNUC__) && !defined(__clang__) // FIXME: Remove this file once GCC supports 8-byte atomics on i686 + +u64 kernel__atomic_compare_exchange_8(u64 volatile*, u64*, u64, int, int); +# pragma redefine_extname kernel__atomic_compare_exchange_8 __atomic_compare_exchange_8 + +u64 kernel__atomic_compare_exchange_8(u64 volatile* memory, u64* expected, u64 desired, int, int) +{ + u64 previous; + asm volatile("lock; cmpxchg8b %1" + : "=A"(previous), "+m"(*memory) + : "b"((u32)desired), "c"((u32)(desired >> 32)), "0"(*expected)); + return previous; +} + +u64 kernel__atomic_load_8(u64 volatile*, int); +# pragma redefine_extname kernel__atomic_load_8 __atomic_load_8 + +u64 kernel__atomic_load_8(u64 volatile* memory, int) +{ + u64 previous; + asm volatile("movl %%ebx, %%eax\n" + "movl %%ecx, %%edx\n" + "lock; cmpxchg8b %1" + : "=A"(previous), "+m"(*memory)); + return previous; +} + +void kernel__atomic_store_8(u64 volatile*, u64, int); +# pragma redefine_extname kernel__atomic_store_8 __atomic_store_8 + +void kernel__atomic_store_8(u64 volatile* memory, u64 value, int) +{ + u64 expected = *memory; + asm volatile("1: lock; cmpxchg8b %0\n" + " jne 1b" + : "=m"(*memory) + : "b"((u32)value), "c"((u32)(value >> 32)), "A"(expected)); +} + +u64 kernel__atomic_fetch_add_8(u64 volatile*, u64, int); +# pragma redefine_extname kernel__atomic_fetch_add_8 __atomic_fetch_add_8 + +u64 kernel__atomic_fetch_add_8(u64 volatile* memory, u64 value, int memory_order) +{ + u64 previous = *memory; + while (kernel__atomic_compare_exchange_8(memory, &previous, previous + value, memory_order, memory_order) != previous) + ; + return previous; +} + +#endif +} diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 4c3faa537c..475e0992d5 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -362,6 +362,13 @@ if ("${SERENITY_ARCH}" STREQUAL "i686" OR "${SERENITY_ARCH}" STREQUAL "x86_64") ${CMAKE_CURRENT_SOURCE_DIR}/Arch/x86/${KERNEL_ARCH}/SyscallEntry.cpp ) endif() + + if ("${SERENITY_ARCH}" STREQUAL "i686") + set(KERNEL_SOURCES + ${KERNEL_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/Arch/x86/${KERNEL_ARCH}/Atomics.cpp + ) + endif() endif() set(AK_SOURCES