1 /* Single-image implementation of GNU Fortran Coarray Library
2 Copyright (C) 2011-2014 Free Software Foundation, Inc.
3 Contributed by Tobias Burnus <burnus@net-b.de>
5 This file is part of the GNU Fortran Coarray Runtime Library (libcaf).
7 Libcaf is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Libcaf is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
27 #include <stdio.h> /* For fputs and fprintf. */
28 #include <stdlib.h> /* For exit and malloc. */
29 #include <string.h> /* For memcpy and memset. */
30 #include <stdarg.h> /* For variadic arguments. */
33 /* Define GFC_CAF_CHECK to enable run-time checking. */
34 /* #define GFC_CAF_CHECK 1 */
36 typedef void* single_token_t
;
37 #define TOKEN(X) ((single_token_t) (X))
39 /* Single-image implementation of the CAF library.
40 Note: For performance reasons -fcoarry=single should be used
41 rather than this library. */
43 /* Global variables. */
44 caf_static_t
*caf_static_list
= NULL
;
47 /* Keep in sync with mpi.c. */
49 caf_runtime_error (const char *message
, ...)
52 fprintf (stderr
, "Fortran runtime error: ");
53 va_start (ap
, message
);
54 vfprintf (stderr
, message
, ap
);
56 fprintf (stderr
, "\n");
58 /* FIXME: Shutdown the Fortran RTL to flush the buffer. PR 43849. */
63 _gfortran_caf_init (int *argc
__attribute__ ((unused
)),
64 char ***argv
__attribute__ ((unused
)))
70 _gfortran_caf_finalize (void)
72 while (caf_static_list
!= NULL
)
74 caf_static_t
*tmp
= caf_static_list
->prev
;
75 free (caf_static_list
->token
);
76 free (caf_static_list
);
77 caf_static_list
= tmp
;
83 _gfortran_caf_this_image (int distance
__attribute__ ((unused
)))
90 _gfortran_caf_num_images (int distance
__attribute__ ((unused
)),
91 int failed
__attribute__ ((unused
)))
98 _gfortran_caf_register (size_t size
, caf_register_t type
, caf_token_t
*token
,
99 int *stat
, char *errmsg
, int errmsg_len
)
103 local
= malloc (size
);
104 *token
= malloc (sizeof (single_token_t
));
106 if (unlikely (local
== NULL
|| token
== NULL
))
108 const char msg
[] = "Failed to allocate coarray";
114 int len
= ((int) sizeof (msg
) > errmsg_len
) ? errmsg_len
115 : (int) sizeof (msg
);
116 memcpy (errmsg
, msg
, len
);
117 if (errmsg_len
> len
)
118 memset (&errmsg
[len
], ' ', errmsg_len
-len
);
123 caf_runtime_error (msg
);
131 if (type
== CAF_REGTYPE_COARRAY_STATIC
)
133 caf_static_t
*tmp
= malloc (sizeof (caf_static_t
));
134 tmp
->prev
= caf_static_list
;
136 caf_static_list
= tmp
;
143 _gfortran_caf_deregister (caf_token_t
*token
, int *stat
,
144 char *errmsg
__attribute__ ((unused
)),
145 int errmsg_len
__attribute__ ((unused
)))
147 free (TOKEN(*token
));
155 _gfortran_caf_sync_all (int *stat
,
156 char *errmsg
__attribute__ ((unused
)),
157 int errmsg_len
__attribute__ ((unused
)))
165 _gfortran_caf_sync_images (int count
__attribute__ ((unused
)),
166 int images
[] __attribute__ ((unused
)),
168 char *errmsg
__attribute__ ((unused
)),
169 int errmsg_len
__attribute__ ((unused
)))
174 for (i
= 0; i
< count
; i
++)
177 fprintf (stderr
, "COARRAY ERROR: Invalid image index %d to SYNC "
178 "IMAGES", images
[i
]);
189 _gfortran_caf_error_stop_str (const char *string
, int32_t len
)
191 fputs ("ERROR STOP ", stderr
);
193 fputc (*(string
++), stderr
);
194 fputs ("\n", stderr
);
201 _gfortran_caf_error_stop (int32_t error
)
203 fprintf (stderr
, "ERROR STOP %d\n", error
);
209 _gfortran_caf_co_sum (gfc_descriptor_t
*a
__attribute__ ((unused
)),
210 int result_image
__attribute__ ((unused
)),
211 int *stat
, char *errmsg
__attribute__ ((unused
)),
212 int errmsg_len
__attribute__ ((unused
)))
219 _gfortran_caf_co_min (gfc_descriptor_t
*a
__attribute__ ((unused
)),
220 int result_image
__attribute__ ((unused
)),
221 int *stat
, char *errmsg
__attribute__ ((unused
)),
222 int src_len
__attribute__ ((unused
)),
223 int errmsg_len
__attribute__ ((unused
)))
230 _gfortran_caf_co_max (gfc_descriptor_t
*a
__attribute__ ((unused
)),
231 int result_image
__attribute__ ((unused
)),
232 int *stat
, char *errmsg
__attribute__ ((unused
)),
233 int src_len
__attribute__ ((unused
)),
234 int errmsg_len
__attribute__ ((unused
)))
242 assign_char4_from_char1 (size_t dst_size
, size_t src_size
, uint32_t *dst
,
246 n
= dst_size
/4 > src_size
? src_size
: dst_size
/4;
247 for (i
= 0; i
< n
; ++i
)
248 dst
[i
] = (int32_t) src
[i
];
249 for (; i
< dst_size
/4; ++i
)
250 dst
[i
] = (int32_t) ' ';
255 assign_char1_from_char4 (size_t dst_size
, size_t src_size
, unsigned char *dst
,
259 n
= dst_size
> src_size
/4 ? src_size
/4 : dst_size
;
260 for (i
= 0; i
< n
; ++i
)
261 dst
[i
] = src
[i
] > UINT8_MAX
? (unsigned char) '?' : (unsigned char) src
[i
];
263 memset(&dst
[n
], ' ', dst_size
- n
);
268 convert_type (void *dst
, int dst_type
, int dst_kind
, void *src
, int src_type
,
271 #ifdef HAVE_GFC_INTEGER_16
272 typedef __int128 int128t
;
274 typedef int64_t int128t
;
277 #if defined(GFC_REAL_16_IS_LONG_DOUBLE)
278 typedef long double real128t
;
279 typedef _Complex
long double complex128t
;
280 #elif defined(HAVE_GFC_REAL_16)
281 typedef _Complex
float __attribute__((mode(TC
))) __complex128
;
282 typedef __float128 real128t
;
283 typedef __complex128 complex128t
;
284 #elif defined(HAVE_GFC_REAL_10)
285 typedef long double real128t
;
286 typedef long double complex128t
;
288 typedef double real128t
;
289 typedef _Complex
double complex128t
;
293 real128t real_val
= 0;
294 complex128t cmpx_val
= 0;
300 int_val
= *(int8_t*) src
;
301 else if (src_kind
== 2)
302 int_val
= *(int16_t*) src
;
303 else if (src_kind
== 4)
304 int_val
= *(int32_t*) src
;
305 else if (src_kind
== 8)
306 int_val
= *(int64_t*) src
;
307 #ifdef HAVE_GFC_INTEGER_16
308 else if (src_kind
== 16)
309 int_val
= *(int128t
*) src
;
316 real_val
= *(float*) src
;
317 else if (src_kind
== 8)
318 real_val
= *(double*) src
;
319 #ifdef HAVE_GFC_REAL_10
320 else if (src_kind
== 10)
321 real_val
= *(long double*) src
;
323 #ifdef HAVE_GFC_REAL_16
324 else if (src_kind
== 16)
325 real_val
= *(real128t
*) src
;
332 cmpx_val
= *(_Complex
float*) src
;
333 else if (src_kind
== 8)
334 cmpx_val
= *(_Complex
double*) src
;
335 #ifdef HAVE_GFC_REAL_10
336 else if (src_kind
== 10)
337 cmpx_val
= *(_Complex
long double*) src
;
339 #ifdef HAVE_GFC_REAL_16
340 else if (src_kind
== 16)
341 cmpx_val
= *(complex128t
*) src
;
353 if (src_type
== BT_INTEGER
)
356 *(int8_t*) dst
= (int8_t) int_val
;
357 else if (dst_kind
== 2)
358 *(int16_t*) dst
= (int16_t) int_val
;
359 else if (dst_kind
== 4)
360 *(int32_t*) dst
= (int32_t) int_val
;
361 else if (dst_kind
== 8)
362 *(int64_t*) dst
= (int64_t) int_val
;
363 #ifdef HAVE_GFC_INTEGER_16
364 else if (dst_kind
== 16)
365 *(int128t
*) dst
= (int128t
) int_val
;
370 else if (src_type
== BT_REAL
)
373 *(int8_t*) dst
= (int8_t) real_val
;
374 else if (dst_kind
== 2)
375 *(int16_t*) dst
= (int16_t) real_val
;
376 else if (dst_kind
== 4)
377 *(int32_t*) dst
= (int32_t) real_val
;
378 else if (dst_kind
== 8)
379 *(int64_t*) dst
= (int64_t) real_val
;
380 #ifdef HAVE_GFC_INTEGER_16
381 else if (dst_kind
== 16)
382 *(int128t
*) dst
= (int128t
) real_val
;
387 else if (src_type
== BT_COMPLEX
)
390 *(int8_t*) dst
= (int8_t) cmpx_val
;
391 else if (dst_kind
== 2)
392 *(int16_t*) dst
= (int16_t) cmpx_val
;
393 else if (dst_kind
== 4)
394 *(int32_t*) dst
= (int32_t) cmpx_val
;
395 else if (dst_kind
== 8)
396 *(int64_t*) dst
= (int64_t) cmpx_val
;
397 #ifdef HAVE_GFC_INTEGER_16
398 else if (dst_kind
== 16)
399 *(int128t
*) dst
= (int128t
) cmpx_val
;
408 if (src_type
== BT_INTEGER
)
411 *(float*) dst
= (float) int_val
;
412 else if (dst_kind
== 8)
413 *(double*) dst
= (double) int_val
;
414 #ifdef HAVE_GFC_REAL_10
415 else if (dst_kind
== 10)
416 *(long double*) dst
= (long double) int_val
;
418 #ifdef HAVE_GFC_REAL_16
419 else if (dst_kind
== 16)
420 *(real128t
*) dst
= (real128t
) int_val
;
425 else if (src_type
== BT_REAL
)
428 *(float*) dst
= (float) real_val
;
429 else if (dst_kind
== 8)
430 *(double*) dst
= (double) real_val
;
431 #ifdef HAVE_GFC_REAL_10
432 else if (dst_kind
== 10)
433 *(long double*) dst
= (long double) real_val
;
435 #ifdef HAVE_GFC_REAL_16
436 else if (dst_kind
== 16)
437 *(real128t
*) dst
= (real128t
) real_val
;
442 else if (src_type
== BT_COMPLEX
)
445 *(float*) dst
= (float) cmpx_val
;
446 else if (dst_kind
== 8)
447 *(double*) dst
= (double) cmpx_val
;
448 #ifdef HAVE_GFC_REAL_10
449 else if (dst_kind
== 10)
450 *(long double*) dst
= (long double) cmpx_val
;
452 #ifdef HAVE_GFC_REAL_16
453 else if (dst_kind
== 16)
454 *(real128t
*) dst
= (real128t
) cmpx_val
;
461 if (src_type
== BT_INTEGER
)
464 *(_Complex
float*) dst
= (_Complex
float) int_val
;
465 else if (dst_kind
== 8)
466 *(_Complex
double*) dst
= (_Complex
double) int_val
;
467 #ifdef HAVE_GFC_REAL_10
468 else if (dst_kind
== 10)
469 *(_Complex
long double*) dst
= (_Complex
long double) int_val
;
471 #ifdef HAVE_GFC_REAL_16
472 else if (dst_kind
== 16)
473 *(complex128t
*) dst
= (complex128t
) int_val
;
478 else if (src_type
== BT_REAL
)
481 *(_Complex
float*) dst
= (_Complex
float) real_val
;
482 else if (dst_kind
== 8)
483 *(_Complex
double*) dst
= (_Complex
double) real_val
;
484 #ifdef HAVE_GFC_REAL_10
485 else if (dst_kind
== 10)
486 *(_Complex
long double*) dst
= (_Complex
long double) real_val
;
488 #ifdef HAVE_GFC_REAL_16
489 else if (dst_kind
== 16)
490 *(complex128t
*) dst
= (complex128t
) real_val
;
495 else if (src_type
== BT_COMPLEX
)
498 *(_Complex
float*) dst
= (_Complex
float) cmpx_val
;
499 else if (dst_kind
== 8)
500 *(_Complex
double*) dst
= (_Complex
double) cmpx_val
;
501 #ifdef HAVE_GFC_REAL_10
502 else if (dst_kind
== 10)
503 *(_Complex
long double*) dst
= (_Complex
long double) cmpx_val
;
505 #ifdef HAVE_GFC_REAL_16
506 else if (dst_kind
== 16)
507 *(complex128t
*) dst
= (complex128t
) cmpx_val
;
520 fprintf (stderr
, "libcaf_single RUNTIME ERROR: Cannot convert type %d kind "
521 "%d to type %d kind %d\n", src_type
, src_kind
, dst_type
, dst_kind
);
527 _gfortran_caf_get (caf_token_t token
, size_t offset
,
528 int image_index
__attribute__ ((unused
)),
529 gfc_descriptor_t
*src
,
530 caf_vector_t
*src_vector
__attribute__ ((unused
)),
531 gfc_descriptor_t
*dest
, int src_kind
, int dst_kind
)
533 /* FIXME: Handle vector subscripts. */
536 int rank
= GFC_DESCRIPTOR_RANK (dest
);
537 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
538 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
542 void *sr
= (void *) ((char *) TOKEN (token
) + offset
);
543 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
544 && dst_kind
== src_kind
)
546 memmove (GFC_DESCRIPTOR_DATA (dest
), sr
,
547 dst_size
> src_size
? src_size
: dst_size
);
548 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
551 memset ((void*)(char*) GFC_DESCRIPTOR_DATA (dest
) + src_size
,
552 ' ', dst_size
- src_size
);
553 else /* dst_kind == 4. */
554 for (i
= src_size
/4; i
< dst_size
/4; i
++)
555 ((int32_t*) GFC_DESCRIPTOR_DATA (dest
))[i
] = (int32_t) ' ';
558 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
559 assign_char1_from_char4 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
561 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
562 assign_char4_from_char1 (dst_size
, src_size
, GFC_DESCRIPTOR_DATA (dest
),
565 convert_type (GFC_DESCRIPTOR_DATA (dest
), GFC_DESCRIPTOR_TYPE (dest
),
566 dst_kind
, sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
);
571 for (j
= 0; j
< rank
; j
++)
573 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
582 for (i
= 0; i
< size
; i
++)
584 ptrdiff_t array_offset_dst
= 0;
585 ptrdiff_t stride
= 1;
586 ptrdiff_t extent
= 1;
587 for (j
= 0; j
< rank
-1; j
++)
589 array_offset_dst
+= ((i
/ (extent
*stride
))
590 % (dest
->dim
[j
]._ubound
591 - dest
->dim
[j
].lower_bound
+ 1))
592 * dest
->dim
[j
]._stride
;
593 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
594 stride
= dest
->dim
[j
]._stride
;
596 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
597 void *dst
= dest
->base_addr
+ array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
);
599 ptrdiff_t array_offset_sr
= 0;
602 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
604 array_offset_sr
+= ((i
/ (extent
*stride
))
605 % (src
->dim
[j
]._ubound
606 - src
->dim
[j
].lower_bound
+ 1))
607 * src
->dim
[j
]._stride
;
608 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
609 stride
= src
->dim
[j
]._stride
;
611 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
612 void *sr
= (void *)((char *) TOKEN (token
) + offset
613 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
615 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
616 && dst_kind
== src_kind
)
618 memmove (dst
, sr
, dst_size
> src_size
? src_size
: dst_size
);
619 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
622 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
623 else /* dst_kind == 4. */
624 for (k
= src_size
/4; k
< dst_size
/4; k
++)
625 ((int32_t*) dst
)[k
] = (int32_t) ' ';
628 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
629 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
630 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
631 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
633 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
634 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
);
640 _gfortran_caf_send (caf_token_t token
, size_t offset
,
641 int image_index
__attribute__ ((unused
)),
642 gfc_descriptor_t
*dest
,
643 caf_vector_t
*dst_vector
__attribute__ ((unused
)),
644 gfc_descriptor_t
*src
, int dst_kind
, int src_kind
)
646 /* FIXME: Handle vector subscripts. */
649 int rank
= GFC_DESCRIPTOR_RANK (dest
);
650 size_t src_size
= GFC_DESCRIPTOR_SIZE (src
);
651 size_t dst_size
= GFC_DESCRIPTOR_SIZE (dest
);
655 void *dst
= (void *) ((char *) TOKEN (token
) + offset
);
656 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
657 && dst_kind
== src_kind
)
659 memmove (dst
, GFC_DESCRIPTOR_DATA (src
),
660 dst_size
> src_size
? src_size
: dst_size
);
661 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
664 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
665 else /* dst_kind == 4. */
666 for (i
= src_size
/4; i
< dst_size
/4; i
++)
667 ((int32_t*) dst
)[i
] = (int32_t) ' ';
670 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
671 assign_char1_from_char4 (dst_size
, src_size
, dst
,
672 GFC_DESCRIPTOR_DATA (src
));
673 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
674 assign_char4_from_char1 (dst_size
, src_size
, dst
,
675 GFC_DESCRIPTOR_DATA (src
));
677 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
678 GFC_DESCRIPTOR_DATA (src
), GFC_DESCRIPTOR_TYPE (src
),
684 for (j
= 0; j
< rank
; j
++)
686 ptrdiff_t dimextent
= dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1;
695 for (i
= 0; i
< size
; i
++)
697 ptrdiff_t array_offset_dst
= 0;
698 ptrdiff_t stride
= 1;
699 ptrdiff_t extent
= 1;
700 for (j
= 0; j
< rank
-1; j
++)
702 array_offset_dst
+= ((i
/ (extent
*stride
))
703 % (dest
->dim
[j
]._ubound
704 - dest
->dim
[j
].lower_bound
+ 1))
705 * dest
->dim
[j
]._stride
;
706 extent
= (dest
->dim
[j
]._ubound
- dest
->dim
[j
].lower_bound
+ 1);
707 stride
= dest
->dim
[j
]._stride
;
709 array_offset_dst
+= (i
/ extent
) * dest
->dim
[rank
-1]._stride
;
710 void *dst
= (void *)((char *) TOKEN (token
) + offset
711 + array_offset_dst
*GFC_DESCRIPTOR_SIZE (dest
));
713 if (GFC_DESCRIPTOR_RANK (src
) != 0)
715 ptrdiff_t array_offset_sr
= 0;
718 for (j
= 0; j
< GFC_DESCRIPTOR_RANK (src
)-1; j
++)
720 array_offset_sr
+= ((i
/ (extent
*stride
))
721 % (src
->dim
[j
]._ubound
722 - src
->dim
[j
].lower_bound
+ 1))
723 * src
->dim
[j
]._stride
;
724 extent
= (src
->dim
[j
]._ubound
- src
->dim
[j
].lower_bound
+ 1);
725 stride
= src
->dim
[j
]._stride
;
727 array_offset_sr
+= (i
/ extent
) * src
->dim
[rank
-1]._stride
;
728 sr
= (void *)((char *) src
->base_addr
729 + array_offset_sr
*GFC_DESCRIPTOR_SIZE (src
));
734 if (GFC_DESCRIPTOR_TYPE (dest
) == GFC_DESCRIPTOR_TYPE (src
)
735 && dst_kind
== src_kind
)
738 dst_size
> src_size
? src_size
: dst_size
);
739 if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_size
> src_size
)
742 memset ((void*)(char*) dst
+ src_size
, ' ', dst_size
-src_size
);
743 else /* dst_kind == 4. */
744 for (k
= src_size
/4; k
< dst_size
/4; k
++)
745 ((int32_t*) dst
)[k
] = (int32_t) ' ';
748 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
&& dst_kind
== 1)
749 assign_char1_from_char4 (dst_size
, src_size
, dst
, sr
);
750 else if (GFC_DESCRIPTOR_TYPE (dest
) == BT_CHARACTER
)
751 assign_char4_from_char1 (dst_size
, src_size
, dst
, sr
);
753 convert_type (dst
, GFC_DESCRIPTOR_TYPE (dest
), dst_kind
,
754 sr
, GFC_DESCRIPTOR_TYPE (src
), src_kind
);
760 _gfortran_caf_sendget (caf_token_t dst_token
, size_t dst_offset
,
761 int dst_image_index
, gfc_descriptor_t
*dest
,
762 caf_vector_t
*dst_vector
, caf_token_t src_token
,
764 int src_image_index
__attribute__ ((unused
)),
765 gfc_descriptor_t
*src
,
766 caf_vector_t
*src_vector
__attribute__ ((unused
)),
767 int dst_len
, int src_len
)
769 /* FIXME: Handle vector subscript of 'src_vector'. */
770 /* For a single image, src->base_addr should be the same as src_token + offset
771 but to play save, we do it properly. */
772 void *src_base
= GFC_DESCRIPTOR_DATA (src
);
773 GFC_DESCRIPTOR_DATA (src
) = (void *) ((char *) TOKEN (src_token
) + src_offset
);
774 _gfortran_caf_send (dst_token
, dst_offset
, dst_image_index
, dest
, dst_vector
,
775 src
, dst_len
, src_len
);
776 GFC_DESCRIPTOR_DATA (src
) = src_base
;
781 _gfortran_caf_atomic_define (caf_token_t token
, size_t offset
,
782 int image_index
__attribute__ ((unused
)),
783 void *value
, int *stat
,
784 int type
__attribute__ ((unused
)), int kind
)
788 uint32_t *atom
= (uint32_t *) ((char *) TOKEN (token
) + offset
);
790 __atomic_store (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
797 _gfortran_caf_atomic_ref (caf_token_t token
, size_t offset
,
798 int image_index
__attribute__ ((unused
)),
799 void *value
, int *stat
,
800 int type
__attribute__ ((unused
)), int kind
)
804 uint32_t *atom
= (uint32_t *) ((char *) TOKEN (token
) + offset
);
806 __atomic_load (atom
, (uint32_t *) value
, __ATOMIC_RELAXED
);
814 _gfortran_caf_atomic_cas (caf_token_t token
, size_t offset
,
815 int image_index
__attribute__ ((unused
)),
816 void *old
, void *compare
, void *new_val
, int *stat
,
817 int type
__attribute__ ((unused
)), int kind
)
821 uint32_t *atom
= (uint32_t *) ((char *) TOKEN (token
) + offset
);
823 *(uint32_t *) old
= *(uint32_t *) compare
;
824 (void) __atomic_compare_exchange_n (atom
, (uint32_t *) old
,
825 *(uint32_t *) new_val
, false,
826 __ATOMIC_RELAXED
, __ATOMIC_RELAXED
);
833 _gfortran_caf_atomic_op (int op
, caf_token_t token
, size_t offset
,
834 int image_index
__attribute__ ((unused
)),
835 void *value
, void *old
, int *stat
,
836 int type
__attribute__ ((unused
)), int kind
)
841 uint32_t *atom
= (uint32_t *) ((char *) TOKEN (token
) + offset
);
845 case GFC_CAF_ATOMIC_ADD
:
846 res
= __atomic_fetch_add (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
848 case GFC_CAF_ATOMIC_AND
:
849 res
= __atomic_fetch_and (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
851 case GFC_CAF_ATOMIC_OR
:
852 res
= __atomic_fetch_or (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
854 case GFC_CAF_ATOMIC_XOR
:
855 res
= __atomic_fetch_xor (atom
, *(uint32_t *) value
, __ATOMIC_RELAXED
);
858 __builtin_unreachable();
862 *(uint32_t *) old
= res
;