[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT/COMPILER-RT PATCH 1/1] Enable the libatomic implementation



Hi Vlad, looks good, thanks.

Reviewed-by: Felipe Huici <felipe.huici@xxxxxxxxx>

On 31.10.19, 00:06, "Vlad-Andrei BĂDOIU (78692)" 
<vlad_andrei.badoiu@xxxxxxxxxxxxxxx> wrote:

    compiler-rt contains an implementation of an atomics library. We provide
    a config option for to enable this implementation.
    
    Signed-off-by: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
    ---
     Config.uk                                     |   7 +
     Makefile.uk                                   |   3 +
     exportsyms.uk                                 |  11 +-
     ...01-Modify-atomic.c-to-build-with-GCC.patch | 297 ++++++++++++++++++
     4 files changed, 317 insertions(+), 1 deletion(-)
     create mode 100644 patches/0001-Modify-atomic.c-to-build-with-GCC.patch
    
    diff --git a/Config.uk b/Config.uk
    index 5965cf8..7b0cfc7 100644
    --- a/Config.uk
    +++ b/Config.uk
    @@ -1,3 +1,10 @@
     menuconfig LIBCOMPILER_RT
         bool " compiler-rt - runtime support"
         default n
    +
    +if LIBCOMPILER_RT
    +    config LIBCOMPILER_RT_ATOMIC
    +    bool "Implementation of an atomics library"
    +    select CXX_THREADS
    +    default N
    +endif
    diff --git a/Makefile.uk b/Makefile.uk
    index 1d8e0dc..ac25df4 100644
    --- a/Makefile.uk
    +++ b/Makefile.uk
    @@ -236,3 +236,6 @@ LIBCOMPILER_RT_SRCS-y += 
$(LIBCOMPILER_RT_SRC)/lib/builtins/fixsfdi.c
     LIBCOMPILER_RT_SRCS-y += $(LIBCOMPILER_RT_SRC)/lib/builtins/fixdfti.c
     LIBCOMPILER_RT_SRCS-y += $(LIBCOMPILER_RT_SRC)/lib/builtins/floatdidf.c
     LIBCOMPILER_RT_SRCS-y += $(LIBCOMPILER_RT_SRC)/lib/builtins/extendsfdf2.c
    +ifdef CONFIG_LIBCOMPILER_RT_ATOMIC
    +LIBCOMPILER_RT_SRCS-y += $(LIBCOMPILER_RT_SRC)/lib/builtins/atomic.c
    +endif
    diff --git a/exportsyms.uk b/exportsyms.uk
    index 013ce79..16da31d 100644
    --- a/exportsyms.uk
    +++ b/exportsyms.uk
    @@ -4,4 +4,13 @@ __muldc3
     __udivti3
     __popcountdi2
     __mulsc3
    -
    +__atomic_load_16
    +__atomic_store_16
    +__atomic_load_8
    +__atomic_store_8
    +__atomic_load_4
    +__atomic_store_4
    +__atomic_load_2
    +__atomic_store_2
    +__atomic_load_1
    +__atomic_store_1
    diff --git a/patches/0001-Modify-atomic.c-to-build-with-GCC.patch 
b/patches/0001-Modify-atomic.c-to-build-with-GCC.patch
    new file mode 100644
    index 0000000..e9210b0
    --- /dev/null
    +++ b/patches/0001-Modify-atomic.c-to-build-with-GCC.patch
    @@ -0,0 +1,297 @@
    +From 0a15b98d110b348ebf8d7e02db8b75786e61ffad Mon Sep 17 00:00:00 2001
    +From: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
    +Date: Thu, 31 Oct 2019 00:07:16 +0200
    +Subject: [PATCH 1/1] Modify atomic.c to build with GCC
    +
    +Signed-off-by: Vlad-Andrei Badoiu <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
    +---
    + lib/builtins/atomic.c | 148 +++++++++++++++++++++++++++++++++++++++++-
    + 1 file changed, 146 insertions(+), 2 deletions(-)
    +
    +diff --git a/lib/builtins/atomic.c b/lib/builtins/atomic.c
    +index ee35e34..1a78ed0 100644
    +--- a/lib/builtins/atomic.c
    ++++ b/lib/builtins/atomic.c
    +@@ -64,8 +64,13 @@ __inline static void unlock(Lock *l) {
    + }
    + __inline static void lock(Lock *l) {
    +   uint32_t old = 1;
    ++#ifdef __GNUC__
    ++  while (!_atomic_compare_exchange_n((_Atomic(uint32_t)*)&l->_count, &old,
    ++#endif
    ++#ifdef __clang__
    +   while 
(!__c11_atomic_compare_exchange_weak((_Atomic(uint32_t)*)&l->_count, &old,
    +-        0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
    ++#endif
    ++        1, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
    +     _umtx_op(l, UMTX_OP_SEM_WAIT, 0, 0, 0);
    +     old = 1;
    +   }
    +@@ -90,13 +95,24 @@ static Lock locks[SPINLOCK_COUNT]; // initialized to 
OS_SPINLOCK_INIT which is 0
    + typedef _Atomic(uintptr_t) Lock;
    + /// Unlock a lock.  This is a release operation.
    + __inline static void unlock(Lock *l) {
    ++#ifdef __GNUC__
    ++  __atomic_store_n(l, 0, __ATOMIC_RELEASE);
    ++#endif
    ++#ifdef __clang__
    +   __c11_atomic_store(l, 0, __ATOMIC_RELEASE);
    ++#endif
    + }
    + /// Locks a lock.  In the current implementation, this is potentially
    + /// unbounded in the contended case.
    + __inline static void lock(Lock *l) {
    +   uintptr_t old = 0;
    ++#ifdef __GNUC__
    ++  while (!__atomic_compare_exchange_n(l, &old, 1, 1, __ATOMIC_ACQUIRE,
    ++#endif
    ++
    ++#ifdef __clang__
    +   while (!__c11_atomic_compare_exchange_weak(l, &old, 1, __ATOMIC_ACQUIRE,
    ++#endif
    +         __ATOMIC_RELAXED))
    +     old = 0;
    + }
    +@@ -125,12 +141,21 @@ static __inline Lock *lock_for_pointer(void *ptr) {
    + /// Macros for determining whether a size is lock free.  Clang can not yet
    + /// codegen __atomic_is_lock_free(16), so for now we assume 16-byte 
values are
    + /// not lock free.
    ++#ifdef __GNUC__
    ++#define IS_LOCK_FREE_1 __atomic_is_lock_free(1, 0)
    ++#define IS_LOCK_FREE_2 __atomic_is_lock_free(2, 0)
    ++#define IS_LOCK_FREE_4 __atomic_is_lock_free(4, 0)
    ++#define IS_LOCK_FREE_8 __atomic_is_lock_free(8, 0)
    ++#define IS_LOCK_FREE_16 0
    ++#endif
    ++
    ++#ifdef __clang__
    + #define IS_LOCK_FREE_1 __c11_atomic_is_lock_free(1)
    + #define IS_LOCK_FREE_2 __c11_atomic_is_lock_free(2)
    + #define IS_LOCK_FREE_4 __c11_atomic_is_lock_free(4)
    + #define IS_LOCK_FREE_8 __c11_atomic_is_lock_free(8)
    + #define IS_LOCK_FREE_16 0
    +-
    ++#endif
    + /// Macro that calls the compiler-generated lock-free versions of 
functions
    + /// when they exist.
    + #define LOCK_FREE_CASES() \
    +@@ -160,9 +185,17 @@ static __inline Lock *lock_for_pointer(void *ptr) {
    + /// An atomic load operation.  This is atomic with respect to the source
    + /// pointer only.
    + void __atomic_load_c(int size, void *src, void *dest, int model) {
    ++#ifdef __GNUC__
    ++#define LOCK_FREE_ACTION(type) \
    ++    *((type*)dest) = __atomic_load_n((_Atomic(type)*)src, model);\
    ++    return;
    ++#endif
    ++
    ++#ifdef __clang__
    + #define LOCK_FREE_ACTION(type) \
    +     *((type*)dest) = __c11_atomic_load((_Atomic(type)*)src, model);\
    +     return;
    ++#endif
    +   LOCK_FREE_CASES();
    + #undef LOCK_FREE_ACTION
    +   Lock *l = lock_for_pointer(src);
    +@@ -174,9 +207,17 @@ void __atomic_load_c(int size, void *src, void *dest, 
int model) {
    + /// An atomic store operation.  This is atomic with respect to the 
destination
    + /// pointer only.
    + void __atomic_store_c(int size, void *dest, void *src, int model) {
    ++#ifdef __GNUC__
    ++#define LOCK_FREE_ACTION(type) \
    ++    __atomic_store_n((_Atomic(type)*)dest, *(type*)dest, model);\
    ++    return;
    ++#endif
    ++
    ++#ifdef __clang__
    + #define LOCK_FREE_ACTION(type) \
    +     __c11_atomic_store((_Atomic(type)*)dest, *(type*)dest, model);\
    +     return;
    ++#endif
    +   LOCK_FREE_CASES();
    + #undef LOCK_FREE_ACTION
    +   Lock *l = lock_for_pointer(dest);
    +@@ -192,9 +233,17 @@ void __atomic_store_c(int size, void *dest, void 
*src, int model) {
    + /// This function returns 1 if the exchange takes place or 0 if it fails. 
    + int __atomic_compare_exchange_c(int size, void *ptr, void *expected,
    +     void *desired, int success, int failure) {
    ++#ifdef __GNUC__
    ++#define LOCK_FREE_ACTION(type) \
    ++  return __atomic_compare_exchange_n((_Atomic(type)*)ptr, 
(type*)expected,\
    ++      *(type*)desired, 0, success, failure)
    ++#endif
    ++
    ++#ifdef __clang__
    + #define LOCK_FREE_ACTION(type) \
    +   return __c11_atomic_compare_exchange_strong((_Atomic(type)*)ptr, 
(type*)expected,\
    +       *(type*)desired, success, failure)
    ++#endif
    +   LOCK_FREE_CASES();
    + #undef LOCK_FREE_ACTION
    +   Lock *l = lock_for_pointer(ptr);
    +@@ -212,10 +261,19 @@ int __atomic_compare_exchange_c(int size, void *ptr, 
void *expected,
    + /// Performs an atomic exchange operation between two pointers.  This is 
atomic
    + /// with respect to the target address.
    + void __atomic_exchange_c(int size, void *ptr, void *val, void *old, int 
model) {
    ++#ifdef __GNUC__
    ++#define LOCK_FREE_ACTION(type) \
    ++    *(type*)old = __atomic_exchange_n((_Atomic(type)*)ptr, *(type*)val,\
    ++        model);\
    ++    return;
    ++#endif
    ++
    ++#ifdef __clang__
    + #define LOCK_FREE_ACTION(type) \
    +     *(type*)old = __c11_atomic_exchange((_Atomic(type)*)ptr, *(type*)val,\
    +         model);\
    +     return;
    ++#endif
    +   LOCK_FREE_CASES();
    + #undef LOCK_FREE_ACTION
    +   Lock *l = lock_for_pointer(ptr);
    +@@ -244,6 +302,20 @@ void __atomic_exchange_c(int size, void *ptr, void 
*val, void *old, int model) {
    +   OPTIMISED_CASE(8, IS_LOCK_FREE_8, uint64_t)
    + #endif
    + 
    ++#ifdef __GNUC__
    ++#define OPTIMISED_CASE(n, lockfree, type)\
    ++type __atomic_load_##n(type *src, int model) {\
    ++  if (lockfree)\
    ++    return __atomic_load_n((_Atomic(type)*)src, model);\
    ++  Lock *l = lock_for_pointer(src);\
    ++  lock(l);\
    ++  type val = *src;\
    ++  unlock(l);\
    ++  return val;\
    ++}
    ++#endif
    ++
    ++#ifdef __clang__
    + #define OPTIMISED_CASE(n, lockfree, type)\
    + type __atomic_load_##n(type *src, int model) {\
    +   if (lockfree)\
    +@@ -254,9 +326,26 @@ type __atomic_load_##n(type *src, int model) {\
    +   unlock(l);\
    +   return val;\
    + }
    ++#endif
    + OPTIMISED_CASES
    + #undef OPTIMISED_CASE
    + 
    ++#ifdef __GNUC__
    ++#define OPTIMISED_CASE(n, lockfree, type)\
    ++void  __atomic_store_##n(type *dest, type val, int model) {\
    ++  if (lockfree) {\
    ++    __atomic_store_n((_Atomic(type)*)dest, val, model);\
    ++    return;\
    ++  }\
    ++  Lock *l = lock_for_pointer(dest);\
    ++  lock(l);\
    ++  *dest = val;\
    ++  unlock(l);\
    ++  return;\
    ++}
    ++#endif
    ++
    ++#ifdef __clang__
    + #define OPTIMISED_CASE(n, lockfree, type)\
    + void  __atomic_store_##n(type *dest, type val, int model) {\
    +   if (lockfree) {\
    +@@ -269,9 +358,25 @@ void  __atomic_store_##n(type *dest, type val, int 
model) {\
    +   unlock(l);\
    +   return;\
    + }
    ++#endif
    + OPTIMISED_CASES
    + #undef OPTIMISED_CASE
    + 
    ++#ifdef __GNUC__
    ++#define OPTIMISED_CASE(n, lockfree, type)\
    ++type __atomic_exchange_##n(type *dest, type val, int model) {\
    ++  if (lockfree)\
    ++    return __atomic_exchange_n((_Atomic(type)*)dest, val, model);\
    ++  Lock *l = lock_for_pointer(dest);\
    ++  lock(l);\
    ++  type tmp = *dest;\
    ++  *dest = val;\
    ++  unlock(l);\
    ++  return tmp;\
    ++}
    ++#endif
    ++
    ++#ifdef __clang__
    + #define OPTIMISED_CASE(n, lockfree, type)\
    + type __atomic_exchange_##n(type *dest, type val, int model) {\
    +   if (lockfree)\
    +@@ -283,9 +388,31 @@ type __atomic_exchange_##n(type *dest, type val, int 
model) {\
    +   unlock(l);\
    +   return tmp;\
    + }
    ++#endif
    + OPTIMISED_CASES
    + #undef OPTIMISED_CASE
    + 
    ++#ifdef __GNUC__
    ++#define OPTIMISED_CASE(n, lockfree, type)\
    ++int __atomic_compare_exchange_##n(type *ptr, type *expected, type 
desired,\
    ++    int success, int failure) {\
    ++  if (lockfree)\
    ++    return __atomic_compare_exchange_n((_Atomic(type)*)ptr, expected, 
desired,\
    ++        0, success, failure);\
    ++  Lock *l = lock_for_pointer(ptr);\
    ++  lock(l);\
    ++  if (*ptr == *expected) {\
    ++    *ptr = desired;\
    ++    unlock(l);\
    ++    return 1;\
    ++  }\
    ++  *expected = *ptr;\
    ++  unlock(l);\
    ++  return 0;\
    ++}
    ++#endif 
    ++
    ++#ifdef __clang__
    + #define OPTIMISED_CASE(n, lockfree, type)\
    + int __atomic_compare_exchange_##n(type *ptr, type *expected, type 
desired,\
    +     int success, int failure) {\
    +@@ -303,12 +430,28 @@ int __atomic_compare_exchange_##n(type *ptr, type 
*expected, type desired,\
    +   unlock(l);\
    +   return 0;\
    + }
    ++#endif
    + OPTIMISED_CASES
    + #undef OPTIMISED_CASE
    + 
    + 
////////////////////////////////////////////////////////////////////////////////
    + // Atomic read-modify-write operations for integers of various sizes.
    + 
////////////////////////////////////////////////////////////////////////////////
    ++#ifdef __GNUC__
    ++#define ATOMIC_RMW(n, lockfree, type, opname, op) \
    ++type __atomic_fetch_##opname##_##n(type *ptr, type val, int model) {\
    ++  if (lockfree) \
    ++    return __atomic_fetch_##opname((_Atomic(type)*)ptr, val, model);\
    ++  Lock *l = lock_for_pointer(ptr);\
    ++  lock(l);\
    ++  type tmp = *ptr;\
    ++  *ptr = tmp op val;\
    ++  unlock(l);\
    ++  return tmp;\
    ++}
    ++#endif
    ++
    ++#ifdef __clang__
    + #define ATOMIC_RMW(n, lockfree, type, opname, op) \
    + type __atomic_fetch_##opname##_##n(type *ptr, type val, int model) {\
    +   if (lockfree) \
    +@@ -320,6 +463,7 @@ type __atomic_fetch_##opname##_##n(type *ptr, type 
val, int model) {\
    +   unlock(l);\
    +   return tmp;\
    + }
    ++#endif
    + 
    + #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, 
add, +)
    + OPTIMISED_CASES
    +-- 
    +2.20.1
    +
    -- 
    2.20.1
    
    

_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.