Преглед на файлове

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.
Idan Horowitz преди 3 години
родител
ревизия
ae9c6a9ded
променени са 2 файла, в които са добавени 69 реда и са изтрити 0 реда
  1. 62 0
      Kernel/Arch/x86/i386/Atomics.cpp
  2. 7 0
      Kernel/CMakeLists.txt

+ 62 - 0
Kernel/Arch/x86/i386/Atomics.cpp

@@ -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
+}

+ 7 - 0
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