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

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


  • To: "minios-devel@xxxxxxxxxxxxx" <minios-devel@xxxxxxxxxxxxx>
  • From: Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
  • Date: Wed, 30 Oct 2019 23:06:39 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=stud.acs.upb.ro; dmarc=pass action=none header.from=stud.acs.upb.ro; dkim=pass header.d=stud.acs.upb.ro; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wBjzDGLsnHriYc9Oa2x6mkllVdGYDtqX96G/QO0QYaE=; b=WNQUQJCRMFlZLUQUxsiW3kjY+OLBvSkXohbadjvjFP4Jm0MN3fjHBsqyhVldsIm6XwESqm9FQ1TApW1P1pFfIuKNKXThyV/V4NwAneL3mSU2bwvwww/Z2Kq3nvQuOmQ+uwN9SktM+jN2wWViXCgLAAvGVlBtOx5mc7FrG0CWmvCBhyana0yhT2jClCMLi/AwK6KmG/WNkGv0hNRLYnJGvScthP6EW12huj2VCK/Gc5ELCPZtFhUSL8gGCkfu0UEYqKKBTcR/AJu6t87zp6sTxjs2Hbz9HmQ9aiys2Y0tE5ik103Wxowzkf+2xSy7mBSug4nsDyh0LIt6PFiXADLRuA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FAF1JgJtlWtmks2DvOvc4cYlfpU3otaeilfkdBrD95c0kESyMLxgVHd8ySMe5WOw2HbrCfxDAMqPrDTf3m7KTDsL7I/hHWMLTXtEBe/LmvR5dyVm2Ru/vU0CWx/SP10kp1HxpMNgdw8vIrWEXAnCRtmA/4oEofcSPOrqaV5jBSiMPw8WnXCJ2Sb97hKtPHMFccWYoWBbSBHFzLZgwhlm3DbtFzjBT3ZwpPO9NLFEiDlu8bnlIke3jik78gwYxJqV9hdf1FEoa7LLExWdGOjzjR6Pd6RSo/DABfBAZ8a6fBDWEkiBDuGmBt1NVpeOzk4UBRJmM7Hbotb6EBucUyI8Zg==
  • Authentication-results: spf=none (sender IP is ) smtp.mailfrom=vlad_andrei.badoiu@xxxxxxxxxxxxxxx;
  • Cc: "felipe.huici@xxxxxxxxx" <felipe.huici@xxxxxxxxx>, Vlad-Andrei BĂDOIU (78692) <vlad_andrei.badoiu@xxxxxxxxxxxxxxx>
  • Delivery-date: Wed, 30 Oct 2019 23:06:47 +0000
  • List-id: Mini-os development list <minios-devel.lists.xenproject.org>
  • Thread-index: AQHVj3avh24B0ECnN0+NjxlIKuShPw==
  • Thread-topic: [UNIKRAFT/COMPILER-RT PATCH 1/1] Enable the libatomic implementation

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®.