Kernel: Add 8-byte atomics for i686 GCC
Unlike Clang, GCC does not support 8-byte atomics on i686 with the -mno-80387 flag set, so until that is fixed, implement a minimal set of atomics that are currently required.
This commit is contained in:
parent
df4ba7b430
commit
ae9c6a9ded
Notes:
sideshowbarker
2024-07-17 08:07:49 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/ae9c6a9ded Pull-request: https://github.com/SerenityOS/serenity/pull/14923 Reviewed-by: https://github.com/supercomputer7 ✅
2 changed files with 69 additions and 0 deletions
Kernel
62
Kernel/Arch/x86/i386/Atomics.cpp
Normal file
62
Kernel/Arch/x86/i386/Atomics.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue