diff options
author | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-12 19:02:57 +0000 |
---|---|---|
committer | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-12 19:02:57 +0000 |
commit | 97b9ac347aae20f93be4c1e7b2fcd4ef32d861a3 (patch) | |
tree | 9c63676c636ff51b2efc0a019d14caccdf82245e /libgfortran/caf | |
parent | 75fe6d70857dd947177f4ae63292a6cf669d0ba4 (diff) | |
download | gcc-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.h | 9 | ||||
-rw-r--r-- | libgfortran/caf/single.c | 90 |
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; +} |