summaryrefslogtreecommitdiff
path: root/libgfortran/caf
diff options
context:
space:
mode:
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2014-07-12 19:02:57 +0000
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2014-07-12 19:02:57 +0000
commit97b9ac347aae20f93be4c1e7b2fcd4ef32d861a3 (patch)
tree9c63676c636ff51b2efc0a019d14caccdf82245e /libgfortran/caf
parent75fe6d70857dd947177f4ae63292a6cf669d0ba4 (diff)
downloadgcc-97b9ac347aae20f93be4c1e7b2fcd4ef32d861a3.tar.gz
2014-07-12 Tobias Burnus <burnus@net-b.de>
gcc/fortran/ * libgfortran.h (libcaf_atomic_codes): Add. * trans-decl.c (gfor_fndecl_caf_atomic_def, gfor_fndecl_caf_atomic_ref, gfor_fndecl_caf_atomic_cas, gfor_fndecl_caf_atomic_op): New variables. (gfc_build_builtin_function_decls): Initialize them. * trans.h (gfor_fndecl_caf_atomic_def, gfor_fndecl_caf_atomic_ref, gfor_fndecl_caf_atomic_cas, gfor_fndecl_caf_atomic_op): New variables. * trans-intrinsic.c (conv_intrinsic_atomic_op, conv_intrinsic_atomic_ref, conv_intrinsic_atomic_cas): Add library calls with -fcoarray=lib. libgfortran/ * caf/libcaf.h (_gfortran_caf_atomic_define, _gfortran_caf_atomic_ref, _gfortran_caf_atomic_op, _gfortran_caf_atomic_cas): New prototypes. * caf/single.c (_gfortran_caf_atomic_define, _gfortran_caf_atomic_ref, _gfortran_caf_atomic_op, _gfortran_caf_atomic_cas): New functions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@212484 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran/caf')
-rw-r--r--libgfortran/caf/libcaf.h9
-rw-r--r--libgfortran/caf/single.c90
2 files changed, 99 insertions, 0 deletions
diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h
index 2c97880f122..0ae7135885f 100644
--- a/libgfortran/caf/libcaf.h
+++ b/libgfortran/caf/libcaf.h
@@ -128,4 +128,13 @@ void _gfortran_caf_send (caf_token_t, size_t, int, gfc_descriptor_t *,
void _gfortran_caf_sendget (caf_token_t, size_t, int, gfc_descriptor_t *,
caf_vector_t *, caf_token_t, size_t, int,
gfc_descriptor_t *, caf_vector_t *, int, int);
+
+void _gfortran_caf_atomic_define (caf_token_t, size_t, int, void *, int *,
+ int, int);
+void _gfortran_caf_atomic_ref (caf_token_t, size_t, int, void *, int *,
+ int, int);
+void _gfortran_caf_atomic_cas (caf_token_t, size_t, int, void *, void *,
+ void *, int *, int, int);
+void _gfortran_caf_atomic_op (int, caf_token_t, size_t, int, void *, void *,
+ int *, int, int);
#endif /* LIBCAF_H */
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index d053c503129..1f5da7293e5 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdlib.h> /* For exit and malloc. */
#include <string.h> /* For memcpy and memset. */
#include <stdarg.h> /* For variadic arguments. */
+#include <assert.h>
/* Define GFC_CAF_CHECK to enable run-time checking. */
/* #define GFC_CAF_CHECK 1 */
@@ -774,3 +775,92 @@ _gfortran_caf_sendget (caf_token_t dst_token, size_t dst_offset,
src, dst_len, src_len);
GFC_DESCRIPTOR_DATA (src) = src_base;
}
+
+
+void
+_gfortran_caf_atomic_define (caf_token_t token, size_t offset,
+ int image_index __attribute__ ((unused)),
+ void *value, int *stat,
+ int type __attribute__ ((unused)), int kind)
+{
+ assert(kind == 4);
+
+ uint32_t *atom = (uint32_t *) ((char *) TOKEN (token) + offset);
+
+ __atomic_store (atom, (uint32_t *) value, __ATOMIC_RELAXED);
+
+ if (stat)
+ *stat = 0;
+}
+
+void
+_gfortran_caf_atomic_ref (caf_token_t token, size_t offset,
+ int image_index __attribute__ ((unused)),
+ void *value, int *stat,
+ int type __attribute__ ((unused)), int kind)
+{
+ assert(kind == 4);
+
+ uint32_t *atom = (uint32_t *) ((char *) TOKEN (token) + offset);
+
+ __atomic_load (atom, (uint32_t *) value, __ATOMIC_RELAXED);
+
+ if (stat)
+ *stat = 0;
+}
+
+
+void
+_gfortran_caf_atomic_cas (caf_token_t token, size_t offset,
+ int image_index __attribute__ ((unused)),
+ void *old, void *compare, void *new_val, int *stat,
+ int type __attribute__ ((unused)), int kind)
+{
+ assert(kind == 4);
+
+ uint32_t *atom = (uint32_t *) ((char *) TOKEN (token) + offset);
+
+ *(uint32_t *) old = *(uint32_t *) compare;
+ (void) __atomic_compare_exchange_n (atom, (uint32_t *) old,
+ *(uint32_t *) new_val, false,
+ __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+ if (stat)
+ *stat = 0;
+}
+
+
+void
+_gfortran_caf_atomic_op (int op, caf_token_t token, size_t offset,
+ int image_index __attribute__ ((unused)),
+ void *value, void *old, int *stat,
+ int type __attribute__ ((unused)), int kind)
+{
+ assert(kind == 4);
+
+ uint32_t res;
+ uint32_t *atom = (uint32_t *) ((char *) TOKEN (token) + offset);
+
+ switch (op)
+ {
+ case GFC_CAF_ATOMIC_ADD:
+ res = __atomic_fetch_add (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
+ break;
+ case GFC_CAF_ATOMIC_AND:
+ res = __atomic_fetch_and (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
+ break;
+ case GFC_CAF_ATOMIC_OR:
+ res = __atomic_fetch_or (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
+ break;
+ case GFC_CAF_ATOMIC_XOR:
+ res = __atomic_fetch_xor (atom, *(uint32_t *) value, __ATOMIC_RELAXED);
+ break;
+ default:
+ __builtin_unreachable();
+ }
+
+ if (old)
+ *(uint32_t *) old = res;
+
+ if (stat)
+ *stat = 0;
+}