/* This provides a few of the MPI-uni functions that cannot be implemented with C macros */ #include #if !defined(__MPIUNI_H) #error "Wrong mpi.h included! require mpi.h from MPIUNI" #endif #if !defined(PETSC_STDCALL) #define PETSC_STDCALL #endif #include #if defined(PETSC_HAVE_STDLIB_H) #include #endif #define MPI_SUCCESS 0 #define MPI_FAILURE 1 void *MPIUNI_TMP = 0; int MPIUNI_DATASIZE[10] = {sizeof(int),sizeof(float),sizeof(double),2*sizeof(double),sizeof(char),2*sizeof(int),4*sizeof(double),4,8,2*sizeof(double)}; /* With MPI Uni there are exactly four distinct communicators: MPI_COMM_SELF, MPI_COMM_WORLD, and a MPI_Comm_dup() of each of these (duplicates of duplicates return the same communictor) MPI_COMM_SELF and MPI_COMM_WORLD are MPI_Comm_free() in MPI_Finalize() but in general with PETSc, the other communicators are freed once the last PETSc object is freed (before MPI_Finalize()). */ #define MAX_ATTR 128 typedef struct { void *attribute_val; int active; } MPI_Attr; typedef struct { void *extra_state; MPI_Delete_function *del; } MPI_Attr_keyval; static MPI_Attr_keyval attr_keyval[MAX_ATTR]; static MPI_Attr attr[4][MAX_ATTR]; static int num_attr = 1,mpi_tag_ub = 100000000; #if defined(__cplusplus) extern "C" { #endif /* To avoid problems with prototypes to the system memcpy() it is duplicated here */ int MPIUNI_Memcpy(void *a,const void *b,int n) { int i; char *aa= (char*)a; char *bb= (char*)b; if (b == MPI_IN_PLACE) return 0; for (i=0; i= MAX_ATTR) MPI_Abort(MPI_COMM_WORLD,1); attr_keyval[num_attr].extra_state = extra_state; attr_keyval[num_attr].del = delete_fn; *keyval = num_attr++; return 0; } int MPI_Keyval_free(int *keyval) { attr_keyval[*keyval].extra_state = 0; attr_keyval[*keyval].del = 0; *keyval = 0; return MPI_SUCCESS; } int MPI_Attr_put(MPI_Comm comm,int keyval,void *attribute_val) { if (comm-1 < 0 || comm-1 > 3) return 1; attr[comm-1][keyval].active = 1; attr[comm-1][keyval].attribute_val = attribute_val; return MPI_SUCCESS; } int MPI_Attr_delete(MPI_Comm comm,int keyval) { if (comm-1 < 0 || comm-1 > 3) return 1; if (attr[comm-1][keyval].active && attr_keyval[keyval].del) { void *save_attribute_val = attr[comm-1][keyval].attribute_val; attr[comm-1][keyval].active = 0; attr[comm-1][keyval].attribute_val = 0; (*(attr_keyval[keyval].del))(comm,keyval,save_attribute_val,attr_keyval[keyval].extra_state); } return MPI_SUCCESS; } int MPI_Attr_get(MPI_Comm comm,int keyval,void *attribute_val,int *flag) { if (comm-1 < 0 || comm-1 > 3) return 1; if (!keyval) Keyval_setup(); *flag = attr[comm-1][keyval].active; *(void**)attribute_val = attr[comm-1][keyval].attribute_val; return MPI_SUCCESS; } static int dups[4] = {1,1,1,1}; int MPI_Comm_create(MPI_Comm comm,MPI_Group group,MPI_Comm *newcomm) { if (comm-1 < 0 || comm-1 > 3) return 1; dups[comm-1]++; *newcomm = comm; return MPI_SUCCESS; } int MPI_Comm_dup(MPI_Comm comm,MPI_Comm *out) { if (comm-1 < 0 || comm-1 > 3) return 1; if (comm == MPI_COMM_WORLD || comm == MPI_COMM_SELF) *out = comm + 2; else { *out = comm; dups[comm-1]++; } return 0; } int MPI_Comm_free(MPI_Comm *comm) { int i; if (*comm-1 < 0 || *comm-1 > 3) return 1; if (--dups[*comm-1]) return MPI_SUCCESS; for (i=0; i