/* Copyright (C) 2019-2020 Free Software Foundation, Inc. Contributed by Nicolas Koenig This file is part of the GNU Fortran Native Coarray Library (libnca). Libnca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Libnca is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "libgfortran.h" #include "libcoarraynative.h" #include static void sync_all_init (counter_barrier *b) { master_bind_active_image_barrier (this_image.m, b); } static inline void lock_table (sync_iface *si) { pthread_mutex_lock (&si->cis->table_lock); } static inline void unlock_table (sync_iface *si) { pthread_mutex_unlock (&si->cis->table_lock); } static inline void wait_table_cond (sync_iface *si, pthread_cond_t *cond) { pthread_cond_wait (cond, &si->cis->table_lock); } static int * get_locked_table (sync_iface *si) { lock_table (si); return si->table; } void sync_iface_init (sync_iface *si, alloc_iface *ai, shared_memory *sm) { si->cis = SHMPTR_AS ( sync_iface_shared *, shared_malloc (get_allocator (ai), sizeof (sync_iface_shared)), sm); sync_all_init (&si->cis->sync_all); initialize_shared_mutex (&si->cis->table_lock); si->sm = sm; si->a = get_allocator (ai); si->cis->table = shared_malloc (si->a, sizeof (int) * local->total_num_images * local->total_num_images); si->cis->triggers = shared_malloc (si->a, sizeof (pthread_cond_t) * local->total_num_images); si->table = SHMPTR_AS (int *, si->cis->table, si->sm); si->triggers = SHMPTR_AS (pthread_cond_t *, si->cis->triggers, si->sm); for (int i = 0; i < local->total_num_images; i++) initialize_shared_condition (&si->triggers[i]); } /* TODO: Maybe check whether synchronizing image is still alive. */ void sync_table (sync_iface *si, int *images, int size) { #if defined(DEBUG_NATIVE_COARRAY) && DEBUG_NATIVE_COARRAY dprintf (2, "Image %d waiting for these %ld images: ", this_image.image_num + 1, size); for (int d_i = 0; (size_t)d_i < size; d_i++) dprintf (2, "%d ", images[d_i]); dprintf (2, "\n"); #endif int i; int done; int *table = get_locked_table (si); if (size > 0) { for (i = 0; i < size; i++) { table[images[i] - 1 + local->total_num_images * this_image.image_num]++; pthread_cond_signal (&si->triggers[images[i] - 1]); } for (;;) { done = 1; for (i = 0; i < size; i++) done &= si->table[images[i] - 1 + this_image.image_num * local->total_num_images] == si->table[this_image.image_num + (images[i] - 1) * local->total_num_images]; if (done) break; wait_table_cond (si, &si->triggers[this_image.image_num]); } } else { size = local->total_num_images; for (i = 0; i < size; i++) { table[i + local->total_num_images * this_image.image_num]++; pthread_cond_signal (&si->triggers[i]); } for (;;) { done = 1; for (i = 0; i < size; i++) done &= si->table[i + this_image.image_num * local->total_num_images] == si->table[this_image.image_num + i * local->total_num_images]; if (done) break; wait_table_cond (si, &si->triggers[this_image.image_num]); } } unlock_table (si); } void sync_all (sync_iface *si) { counter_barrier_wait (&si->cis->sync_all); }