]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
trans-decl.c (create_main_function): Move call of _gfortran_caf_init right before...
authorThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 2 Sep 2018 14:22:29 +0000 (14:22 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Sun, 2 Sep 2018 14:22:29 +0000 (14:22 +0000)
2018-09-02  Thomas Koenig  <tkoenig@gcc.gnu.org>
    Nicolas Koenig  <koenigni@gcc.gnu.org>

* trans-decl.c (create_main_function): Move call of
_gfortran_caf_init right before cal to MAIN__().

2018-09-02  Thomas Koenig  <tkoenig@gcc.gnu.org>
    Nicolas Koenig <koenigni@gcc.gnu.org>

* caf/multi.c: Some cleanup.
(image_num): Rename to _gfortrani_caf_this_image.
(sim): New static variable.
(cim): Likewise.
(cond_t): New type.
(init_image): Some reformatting.
(_gfortran_caf_init): Handle arrays of conditions and number for
sync images.
(cond_init): New function.
(cond_wait): New function.
(cond_signal): New function.
(A): Macro to simplify array access.
(_gfortran_caf_sync_images): New function.
* libgfortran.h (caf_num_images): New static variable.
(_gfortrani_caf_this_image): New static variable.
* runtime/compile_options.c (set_options): Return early if
we are in a dependent image.
* runtime/environ.c (static_variable_table): Add
GFORTRAN_CAF_IMAGES with default of 4.
* runtime/main.c (set_args): Return early if we are in a
dependent variable.

Co-Authored-By: Nicolas Koenig <koenigni@gcc.gnu.org>
From-SVN: r264040

gcc/fortran/ChangeLog.dev
gcc/fortran/trans-decl.c
libgfortran/ChangeLog.dev
libgfortran/caf/multi.c
libgfortran/libgfortran.h
libgfortran/runtime/compile_options.c
libgfortran/runtime/environ.c
libgfortran/runtime/main.c

index fec50783f8df6bbf574e5a6b57ccb73d07c04e91..82c9afd40e18e496a54b1642ff8678931e208d19 100644 (file)
@@ -1,3 +1,9 @@
+2018-09-02  Thomas Koenig  <tkoenig@gcc.gnu.org>
+           Nicolas Koenig  <koenigni@gcc.gnu.org>
+
+       * trans-decl.c (create_main_function): Move call of
+       _gfortran_caf_init right before cal to MAIN__().
+
 2018-08-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        * Development log for native coarray fortran.
index eea6b81ebfa855a814109b15876c0872aa1bbfab..64178f0c124918c53ed9b84e4e941f7bf9ace875 100644 (file)
@@ -5969,20 +5969,6 @@ create_main_function (tree fndecl)
 
   /* Call some libgfortran initialization routines, call then MAIN__().  */
 
-  /* Call _gfortran_caf_init (*argc, ***argv).  */
-  if (flag_coarray == GFC_FCOARRAY_LIB)
-    {
-      tree pint_type, pppchar_type;
-      pint_type = build_pointer_type (integer_type_node);
-      pppchar_type
-       = build_pointer_type (build_pointer_type (pchar_type_node));
-
-      tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_init, 2,
-               gfc_build_addr_expr (pint_type, argc),
-               gfc_build_addr_expr (pppchar_type, argv));
-      gfc_add_expr_to_block (&body, tmp);
-    }
-
   /* Call _gfortran_set_args (argc, argv).  */
   TREE_USED (argc) = 1;
   TREE_USED (argv) = 1;
@@ -6088,6 +6074,20 @@ create_main_function (tree fndecl)
       gfc_add_expr_to_block (&body, tmp);
     }
 
+  /* Call _gfortran_caf_init (*argc, ***argv).  */
+  if (flag_coarray == GFC_FCOARRAY_LIB)
+    {
+      tree pint_type, pppchar_type;
+      pint_type = build_pointer_type (integer_type_node);
+      pppchar_type
+       = build_pointer_type (build_pointer_type (pchar_type_node));
+
+      tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_init, 2,
+               gfc_build_addr_expr (pint_type, argc),
+               gfc_build_addr_expr (pppchar_type, argv));
+      gfc_add_expr_to_block (&body, tmp);
+    }
+
   /* Call MAIN__().  */
   tmp = build_call_expr_loc (input_location,
                         fndecl, 0);
index 9ae6ef062fcd1bb13421db945b881dc8cd187f99..225637277c71d03740446477895498b07c1bd59e 100644 (file)
@@ -1,5 +1,30 @@
+2018-09-02  Thomas Koenig  <tkoenig@gcc.gnu.org>
+           Nicolas Koenig <koenigni@gcc.gnu.org>
+
+       * caf/multi.c: Some cleanup.
+       (image_num): Rename to _gfortrani_caf_this_image.
+       (sim): New static variable.
+       (cim): Likewise.
+       (cond_t): New type.
+       (init_image): Some reformatting.
+       (_gfortran_caf_init): Handle arrays of conditions and number for
+       sync images.
+       (cond_init): New function.
+       (cond_wait): New function.
+       (cond_signal): New function.
+       (A): Macro to simplify array access.
+       (_gfortran_caf_sync_images): New function.
+       * libgfortran.h (caf_num_images): New static variable.
+       (_gfortrani_caf_this_image): New static variable.
+       * runtime/compile_options.c (set_options): Return early if
+       we are in a dependent image.
+       * runtime/environ.c (static_variable_table): Add
+       GFORTRAN_CAF_IMAGES with default of 4.
+       * runtime/main.c (set_args): Return early if we are in a
+       dependent variable.
+
 2018-08-28  Nicolas Koenig  <koenigni@gcc.gnu.org>
-       
+
        * caf/multi.c: New file
 
 2018-08-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
index b0405c36358461dee332cbdf47c943e240d73c7c..d980436e772d930269389fe7f0b0f1ab8db16988 100644 (file)
@@ -26,17 +26,23 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#include"libcaf.h"
-#include<pthread.h> // gthreads needed here?
-#include<stdlib.h>
-#include<stdio.h>
+#include "libcaf.h"
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
 
-// types
+/* Currently compile programs which call this with
+
+$ gfortran -static-libgfortran -fcoarray=lib foo.f90 -pthread -lcaf_multi
+
+*/
 
 int main(int argc, char **argv);
 
+/* Types.  */
+
 typedef struct {
-  int image_num;
+  int this_image;
   int argc;
   char **argv;
 } init_args;
@@ -45,65 +51,76 @@ typedef struct {
   void **base_array;
 } caf_multi_token_t;
 
-// static vars
+typedef struct cond_t {
+  pthread_cond_t cond;
+  int signalled;
+  pthread_mutex_t mutex;
+} cond_t;
+
+/* Static variables.  */
 
-__thread int image_num = -1;
-int num_images = -1;
+__thread int _gfortrani_caf_this_image = -1;
+int caf_num_images = -1;
 pthread_barrier_t sync_all_barrier;
 pthread_t *tidlist;
 
-// functions
+static int *sim;
+static cond_t *cim;
+
+static int cond_init(cond_t *cond);
 
 static void *
-init_image (void *p) {
+init_image (void *p)
+{
   init_args args = *(init_args *) p; 
   free(p);
 
-  image_num = args.image_num;
+  _gfortrani_caf_this_image = args.this_image;
 
-  pthread_barrier_wait(&sync_all_barrier);
+  pthread_barrier_wait (&sync_all_barrier);
+
+ /* XXX: Must be called since there is no other way to set the
+ options for the images since _gfortran_set_option is called after
+ _gfortran_caf_init and options is a local variable in main. It would
+ be better to switch to calling MAIN__ once we have the new
+ interface.  */
 
-  main(args.argc, args.argv); //XXX: Must be called since there is no other
-                             //     way to set the options for the images
-                             //     since _gfortran_set_option is called
-                             //     after _gfortran_caf_init and options
-                             //     is a local variable in main. It would
-                             //     be better to switch to calling MAIN
-                             //     once we have the new interface.
+  main (args.argc, args.argv);
 
   return NULL;
 }
 
 void
-_gfortran_caf_init (int *argcptr, char ***argvptr) {
-  if (image_num > 0) // to ensure the function is only
-    return          // executed once after calling main
-                    // recursively
-
-  int i;
-  int nimages = 4; //XXX
+_gfortran_caf_init (int *argcptr, char ***argvptr)
+{
   init_args *args;
-  pthread_t tid;
   
-  num_images = nimages;
-   
-  pthread_barrier_init(&sync_all_barrier, NULL, nimages);  
+  /* Ensure the function is only executed once after calling main
+     recursively.  */
+  if (_gfortrani_caf_this_image > 0)
+    return; 
+
+  pthread_barrier_init (&sync_all_barrier, NULL, caf_num_images);  
   
-  tidlist = malloc(nimages*sizeof(pthread_t));
+  tidlist = calloc (caf_num_images, sizeof(pthread_t));
+  sim = calloc(caf_num_images * caf_num_images, sizeof(int));
+  cim = calloc(caf_num_images * caf_num_images, sizeof(cond_t));
+
+  for (int i = 0; i < caf_num_images; i++)
+    cond_init(cim + i);
 
-  for(i = 1; i < num_images; i++) {
-    args = malloc(sizeof(init_args)); 
-    args->image_num = i;
+  for (int i = 1; i < caf_num_images; i++) {
+    args = malloc (sizeof (init_args)); 
+    args->this_image = i;
     args->argc = *argcptr;
     args->argv = *argvptr;
-    pthread_create(&tid, NULL, init_image, args);
-    tidlist[i] = tid;
+    pthread_create (tidlist + i, NULL, init_image, args);
   }
   
-  tidlist[0] = pthread_self();
-  image_num = 0;
+  tidlist[0] = pthread_self ();
+  _gfortrani_caf_this_image = 0;
 
-  pthread_barrier_wait(&sync_all_barrier);
+  pthread_barrier_wait (&sync_all_barrier);
 }
 
 /*
@@ -123,7 +140,7 @@ _gfortran_caf_register (size_t size, caf_register_t type, caf_token_t *token,
          *t = malloc(sizeof(caf_multi_token_t)); 
          (*t)->base_array = malloc(get_num_images()*size);
        }
-      data->base_addr = (*t)->base_array+image_num*size;
+      data->base_addr = (*t)->base_array+this_image*size;
       pthread_mutex_unlock(&lock);
     }
   else
@@ -158,15 +175,15 @@ void
 _gfortran_caf_finalize(void) 
 { 
   int i;
-  if (image_num != 0)
+  if (_gfortrani_caf_this_image != 0)
     pthread_exit(NULL);
-  for (i = 1; i<num_images; i++)
+  for (i = 1; i < caf_num_images; i++)
     pthread_join(tidlist[i], NULL);
 }
 
 int
 _gfortran_caf_this_image(int distance) {
-  return image_num+1;
+  return _gfortrani_caf_this_image+1;
 }
 
 
@@ -174,11 +191,95 @@ int
 _gfortran_caf_num_images (int distance __attribute__ ((unused)),
                          int failed __attribute__ ((unused)))
 {
-  return num_images;
+  return caf_num_images;
+}
+
+static int
+cond_init(cond_t *cond)
+{
+  pthread_mutex_init (&cond->mutex, NULL);
+  pthread_cond_init (&cond->cond, NULL);
+  cond->signalled = 0;
+  return 0;
 }
 
-// Probably has a race condition, if a thread reaches the barrier before
-// all have left, but I'm not certain how that works
+static int
+cond_wait (cond_t * cond)
+{
+  while (!cond->signalled)
+    pthread_cond_wait (&cond->cond, &cond->mutex);
+
+  cond->signalled = 0;
+  pthread_mutex_unlock (&cond->mutex);
+  return 0;
+}
+
+static int
+cond_signal (cond_t *cond)
+{
+  cond->signalled = 1;
+  pthread_cond_signal (&cond->cond);
+  pthread_mutex_unlock (&cond->mutex);
+  return 0;
+}
+
+#define A(i,j) (sim[(i) + caf_num_images * (j)])
+
+void
+_gfortran_caf_sync_images (int count __attribute__ ((unused)),
+                          int images[] __attribute__ ((unused)),
+                          int *stat,
+                          char *errmsg __attribute__ ((unused)),
+                          size_t errmsg_len __attribute__ ((unused)))
+{
+  pthread_mutex_t *my_mutex;
+
+  for (int i=0; i < count; i++)
+    {
+      if (images[i] - 1 != _gfortrani_caf_this_image)
+       {
+         cond_t *other_thread = cim + images[i] - 1;
+         pthread_mutex_lock (&other_thread->mutex);
+         A(_gfortrani_caf_this_image, images[i] - 1) ++;
+         cond_signal(other_thread);
+       }
+    }
+
+  while (1)
+    {
+      int x;
+      int do_wait = 0;
+
+      my_mutex =  &(cim[_gfortrani_caf_this_image].mutex);
+      pthread_mutex_lock (my_mutex);
+
+      for (int i = 0; i < count; i++)
+       {
+         if (images[i] - 1 != _gfortrani_caf_this_image)
+           {
+             x = A(images[i] - 1,_gfortrani_caf_this_image)
+               < A(_gfortrani_caf_this_image, images[i] - 1);
+             if (x)
+               {
+                 do_wait = 1;
+                 break;
+               }
+           }
+       }
+
+      if (do_wait)
+         cond_wait(cim + _gfortrani_caf_this_image);
+      else
+       break;
+    }
+  pthread_mutex_unlock (my_mutex);
+}
+
+#undef A
+
+/* Probably has a race condition, if a thread reaches the barrier
+   before all have left, but I'm not certain how that works.  */
+
 void
 _gfortran_caf_sync_all (int *stat,
                        char *errmsg __attribute__ ((unused)),
index b5a742aac88772a2d7d73ee415582056f658e21f..64ae8d7838840dc47487273127594abaa487469a 100644 (file)
@@ -1746,7 +1746,8 @@ void cshift1_16_c16 (gfc_array_c16 * const restrict,
 internal_proto(cshift1_16_c16);
 #endif
 
-/* Define this if we support asynchronous I/O on this platform.  This
-   currently requires weak symbols.  */
+extern int caf_num_images;
+internal_proto(caf_num_images);
+extern __thread int _gfortrani_caf_this_image;
 
 #endif  /* LIBGFOR_H  */
index 1d37e7709dfc8c53062a552c714bdfb541c054e4..ef8777e1505378bd24c286acbd073d2549dd2bd0 100644 (file)
@@ -145,6 +145,12 @@ export_proto(set_options);
 void
 set_options (int num, int options[])
 {
+  /* Do not set options if we're not in the main program
+     of a pthread coarray application.  */
+
+  if (_gfortrani_caf_this_image > 0)
+    return;
+
   if (num >= 1)
     compile_options.warn_std = options[0];
   if (num >= 2)
index 22faad348da660b1645a14877170c3e255a7a5c6..c65754b73ef47cf4cae26cfc0174aae844d5b54e 100644 (file)
@@ -217,6 +217,9 @@ static variable variable_table[] = {
   /* Print out a backtrace if possible on runtime error */
   { "GFORTRAN_ERROR_BACKTRACE", -1, &options.backtrace, init_boolean },
 
+  /* Number of images to start with -fcoarray=pthread.  */
+  { "GFORTRAN_CAF_IMAGES", 4, &caf_num_images, init_integer },
+
   { NULL, 0, NULL, NULL }
 };
 
index f434e5bb9e672fe8fef9bda6b8bc847605ee75b7..81e52f71721c1dd1fa6a635f68bdf5547520b262 100644 (file)
@@ -43,6 +43,9 @@ static char **argv_save;
 void
 set_args (int argc, char **argv)
 {
+  if (_gfortrani_caf_this_image > 0)
+    return;
+
   argc_save = argc;
   argv_save = argv;
 }