Browse Source

- workaround to avoid referencing C constants from Fortran, which has been found unreliable on Darwin
- re-enable Fortran examples build on Darwin

Olivier Aumage 9 years ago
parent
commit
0ff38f93cf
3 changed files with 68 additions and 24 deletions
  1. 0 6
      configure.ac
  2. 44 11
      include/fstarpu_mod.f90
  3. 24 7
      src/util/fstarpu.c

+ 0 - 6
configure.ac

@@ -2115,12 +2115,6 @@ if test "x$FC" != "x"; then
 			enable_build_fortran="no"
 		fi
 	fi
-	if test "x$starpu_darwin" = "xyes" ; then
-		# global constants defined in src/utils/fstarpu.c are not exported
-		# properly on Darwin, causing native Fortran examples to fail
-		AC_MSG_WARN([Fortran examples will not be built on Darwin])
-		enable_build_fortran="no"
-	fi
 	if test "x$enable_build_fortran" = "xyes" ; then
 		AC_DEFINE(STARPU_HAVE_FC, [], [Define this if a Fortran compiler is available])
 	fi

+ 44 - 11
include/fstarpu_mod.f90

@@ -16,18 +16,15 @@
 module fstarpu_mod
         use iso_c_binding
 
-        integer(c_int), bind(C, name="fstarpu_r") :: FSTARPU_R
-        integer(c_int), bind(C, name="fstarpu_w") :: FSTARPU_W
-        integer(c_int), bind(C, name="fstarpu_rw") :: FSTARPU_RW
-        integer(c_int), bind(C, name="fstarpu_scratch") :: FSTARPU_SCRATCH
-        integer(c_int), bind(C, name="fstarpu_redux") :: FSTARPU_REDUX
+        integer(c_int), bind(C) :: FSTARPU_R
+        integer(c_int), bind(C) :: FSTARPU_W
+        integer(c_int), bind(C) :: FSTARPU_RW
+        integer(c_int), bind(C) :: FSTARPU_SCRATCH
+        integer(c_int), bind(C) :: FSTARPU_REDUX
 
-        type(c_ptr), bind(C, name="fstarpu_data") :: FSTARPU_DATA
+        type(c_ptr), bind(C) :: FSTARPU_DATA
 
         interface
-                subroutine fstarpu_init () bind(C)
-                end subroutine fstarpu_init
-
                 subroutine fstarpu_shutdown () bind(C,name="starpu_shutdown")
                 end subroutine fstarpu_shutdown
 
@@ -103,6 +100,42 @@ module fstarpu_mod
 
         end interface
 
-        ! contains
-
+        contains
+
+                subroutine fstarpu_init ()
+
+                        ! Note: Referencing global C constants from Fortran has
+                        ! been found unreliable on some architectures, notably
+                        ! on Darwin. The get_integer/get_pointer_constant
+                        ! scheme is a workaround to that issue.
+
+                        interface
+                                ! These functions are not exported to the end user
+                                function fstarpu_get_integer_constant(s) bind(C)
+                                        use iso_c_binding, only: c_int,c_char
+                                        integer(c_int) :: fstarpu_get_integer_constant
+                                        character(kind=c_char) :: s
+                                end function fstarpu_get_integer_constant
+
+                                function fstarpu_get_pointer_constant(s) bind(C)
+                                        use iso_c_binding, only: c_ptr,c_char
+                                        type(c_ptr) :: fstarpu_get_pointer_constant
+                                        character(kind=c_char) :: s
+                                end function fstarpu_get_pointer_constant
+
+                                subroutine fstarpu_init_internal () bind(C)
+                                end subroutine fstarpu_init_internal
+                        end interface
+
+                        ! Initialize Fortran integer constants from C peers
+                        FSTARPU_R = fstarpu_get_integer_constant(C_CHAR_"FSTARPU_R"//C_NULL_CHAR)
+                        FSTARPU_W = fstarpu_get_integer_constant(C_CHAR_"FSTARPU_W"//C_NULL_CHAR)
+                        FSTARPU_RW = fstarpu_get_integer_constant(C_CHAR_"FSTARPU_RW"//C_NULL_CHAR)
+                        FSTARPU_SCRATCH = fstarpu_get_integer_constant(C_CHAR_"FSTARPU_SCRATCH"//C_NULL_CHAR)
+                        FSTARPU_REDUX = fstarpu_get_integer_constant(C_CHAR_"FSTARPU_REDUX"//C_NULL_CHAR)
+                        ! Initialize Fortran 'pointer' constants from C peers
+                        FSTARPU_DATA = fstarpu_get_pointer_constant(C_CHAR_"FSTARPU_DATA"//C_NULL_CHAR)
+                        ! Initialize StarPU
+                        call fstarpu_init_internal()
+                end subroutine fstarpu_init
 end module fstarpu_mod

+ 24 - 7
src/util/fstarpu.c

@@ -16,20 +16,37 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <starpu.h>
 
 #define _FSTARPU_ERROR(msg) do {fprintf(stderr, "fstarpu error: %s\n", (msg));abort();} while(0)
 
-const int fstarpu_r = STARPU_R;
-const int fstarpu_w = STARPU_W;
-const int fstarpu_rw = STARPU_RW;
-const int fstarpu_scratch = STARPU_SCRATCH;
-const int fstarpu_redux = STARPU_REDUX;
+static const int fstarpu_r	= STARPU_R;
+static const int fstarpu_w	= STARPU_W;
+static const int fstarpu_rw	= STARPU_RW;
+static const int fstarpu_scratch	= STARPU_SCRATCH;
+static const int fstarpu_redux	= STARPU_REDUX;
 
 static const int _fstarpu_data = STARPU_R | STARPU_W | STARPU_SCRATCH | STARPU_REDUX;
-const void * const fstarpu_data = &_fstarpu_data;
+static const void * const fstarpu_data = &_fstarpu_data;
 
-void fstarpu_init(void)
+int fstarpu_get_integer_constant(char *s)
+{
+	if	(!strcmp(s, "FSTARPU_R"))	{ return fstarpu_r; }
+	else if	(!strcmp(s, "FSTARPU_W"))	{ return fstarpu_w; }
+	else if	(!strcmp(s, "FSTARPU_RW"))	{ return fstarpu_rw; }
+	else if	(!strcmp(s, "FSTARPU_SCRATCH"))	{ return fstarpu_scratch; }
+	else if	(!strcmp(s, "FSTARPU_REDUX"))	{ return fstarpu_redux; }
+	else { _FSTARPU_ERROR("unknown integer constant"); }
+}
+
+const void *fstarpu_get_pointer_constant(char *s)
+{
+	if (!strcmp(s, "FSTARPU_DATA")) { return fstarpu_data; }
+	else { _FSTARPU_ERROR("unknown pointer constant"); }
+}
+
+void fstarpu_init_internal(void)
 {
 	int ret = starpu_init(NULL);
 	if (ret != 0)