root/ompi/mpi/java/c/mpi_MPI.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bufferConstructor
  2. bufferDestructor
  3. JNI_OnLoad
  4. initFreeList
  5. findClass
  6. findClasses
  7. deleteClasses
  8. Java_mpi_MPI_newInt2
  9. Java_mpi_MPI_newShortInt
  10. Java_mpi_MPI_newLongInt
  11. Java_mpi_MPI_newFloatInt
  12. Java_mpi_MPI_newDoubleInt
  13. Java_mpi_MPI_initVersion
  14. Java_mpi_MPI_Init_1jni
  15. Java_mpi_MPI_InitThread_1jni
  16. Java_mpi_MPI_queryThread_1jni
  17. Java_mpi_MPI_isThreadMain_1jni
  18. Java_mpi_MPI_Finalize_1jni
  19. Java_mpi_MPI_getVersionJNI
  20. Java_mpi_MPI_getLibVersionJNI
  21. Java_mpi_MPI_getProcessorName
  22. Java_mpi_MPI_wtime_1jni
  23. Java_mpi_MPI_wtick_1jni
  24. Java_mpi_MPI_isInitialized
  25. Java_mpi_MPI_isFinalized
  26. Java_mpi_MPI_attachBuffer_1jni
  27. Java_mpi_MPI_detachBuffer_1jni
  28. ompi_java_getArrayCritical
  29. ompi_java_getDirectBufferAddress
  30. getTypeExtent
  31. getArrayRegion
  32. setArrayRegion
  33. getBuffer
  34. releaseBuffer
  35. getCountv
  36. getReadPtr
  37. getReadPtrRank
  38. getReadPtrvRank
  39. getReadPtrvAll
  40. getWritePtr
  41. getWritePtrv
  42. ompi_java_getReadPtr
  43. ompi_java_getReadPtrRank
  44. ompi_java_getReadPtrv
  45. ompi_java_releaseReadPtr
  46. ompi_java_getWritePtr
  47. ompi_java_getWritePtrv
  48. ompi_java_releaseWritePtr
  49. ompi_java_releaseWritePtrv
  50. ompi_java_Integer_valueOf
  51. ompi_java_Long_valueOf
  52. ompi_java_getIntArray
  53. ompi_java_releaseIntArray
  54. ompi_java_forgetIntArray
  55. ompi_java_getDatatypeArray
  56. ompi_java_forgetDatatypeArray
  57. ompi_java_getBooleanArray
  58. ompi_java_releaseBooleanArray
  59. ompi_java_forgetBooleanArray
  60. ompi_java_getPtrArray
  61. ompi_java_releasePtrArray
  62. ompi_java_exceptionCheck
  63. ompi_java_attrSet
  64. ompi_java_attrGet
  65. ompi_java_attrCopy
  66. ompi_java_attrDelete

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2005 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2015-2016 Los Alamos National Security, LLC.  All rights
  14  *                         reserved.
  15  * Copyright (c) 2015-2016 Cisco Systems, Inc.  All rights reserved.
  16  * Copyright (c) 2015      Intel, Inc. All rights reserved.
  17  * Copyright (c) 2015      Research Organization for Information Science
  18  *                         and Technology (RIST). All rights reserved.
  19  * Copyright (c) 2016-2017 IBM Corporation.  All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 /*
  27  * This file is almost a complete re-write for Open MPI compared to the
  28  * original mpiJava package. Its license and copyright are listed below.
  29  * See <path to ompi/mpi/java/README> for more information.
  30  */
  31 /*
  32     Licensed under the Apache License, Version 2.0 (the "License");
  33     you may not use this file except in compliance with the License.
  34     You may obtain a copy of the License at
  35 
  36        http://www.apache.org/licenses/LICENSE-2.0
  37 
  38     Unless required by applicable law or agreed to in writing, software
  39     distributed under the License is distributed on an "AS IS" BASIS,
  40     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  41     See the License for the specific language governing permissions and
  42     limitations under the License.
  43 */
  44 /*
  45  * File         : mpi_MPI.c
  46  * Headerfile   : mpi_MPI.h
  47  * Author       : SungHoon Ko, Xinying Li (contributions from MAEDA Atusi)
  48  * Created      : Thu Apr  9 12:22:15 1998
  49  * Revision     : $Revision: 1.17 $
  50  * Updated      : $Date: 2003/01/17 01:50:37 $
  51  * Copyright: Northeast Parallel Architectures Center
  52  *            at Syracuse University 1998
  53  */
  54 #include "ompi_config.h"
  55 
  56 #include <stdio.h>
  57 #ifdef HAVE_SYS_TYPES_H
  58 #include <sys/types.h>
  59 #endif
  60 #include <stdlib.h>
  61 #include <string.h>
  62 #ifdef HAVE_TARGETCONDITIONALS_H
  63 #include <TargetConditionals.h>
  64 #endif
  65 #ifdef HAVE_SYS_STAT_H
  66 #include <sys/stat.h>
  67 #endif
  68 #ifdef HAVE_DLFCN_H
  69 #include <dlfcn.h>
  70 #endif
  71 #include <poll.h>
  72 #ifdef HAVE_LIBGEN_H
  73 #include <libgen.h>
  74 #endif
  75 
  76 #include "opal/util/output.h"
  77 #include "opal/datatype/opal_convertor.h"
  78 #include "opal/mca/base/mca_base_var.h"
  79 
  80 #include "mpi.h"
  81 #include "ompi/errhandler/errcode.h"
  82 #include "ompi/errhandler/errcode-internal.h"
  83 #include "ompi/datatype/ompi_datatype.h"
  84 #include "mpi_MPI.h"
  85 #include "mpiJava.h"
  86 
  87 ompi_java_globals_t ompi_java = {0};
  88 int ompi_mpi_java_eager = 65536;
  89 opal_free_list_t ompi_java_buffers = {{{0}}};
  90 
  91 static void bufferConstructor(ompi_java_buffer_t *item)
  92 {
  93     item->buffer = malloc(ompi_mpi_java_eager);
  94 }
  95 
  96 static void bufferDestructor(ompi_java_buffer_t *item)
  97 {
  98     free(item->buffer);
  99 }
 100 
 101 OBJ_CLASS_INSTANCE(ompi_java_buffer_t,
 102                    opal_free_list_item_t,
 103                    bufferConstructor,
 104                    bufferDestructor);
 105 
 106 /*
 107  * Class:    mpi_MPI
 108  * Method:   loadGlobalLibraries
 109  *
 110  */
 111 jint JNI_OnLoad(JavaVM *vm, void *reserved)
 112 {
 113     // Ensure that PSM signal hijacking is disabled *before* loading
 114     // the library (see comment in the function for more detail).
 115     opal_init_psm();
 116 
 117     return JNI_VERSION_1_6;
 118 }
 119 
 120 static void initFreeList(void)
 121 {
 122     OBJ_CONSTRUCT(&ompi_java_buffers, opal_free_list_t);
 123 
 124     int r = opal_free_list_init(&ompi_java_buffers,
 125                                 sizeof(ompi_java_buffer_t),
 126                                 opal_cache_line_size,
 127                                 OBJ_CLASS(ompi_java_buffer_t),
 128                                 0, /* payload size */
 129                                 0, /* payload align */
 130                                 2, /* initial elements to alloc */
 131                                 -1, /* max elements */
 132                                 2, /* num elements per alloc */
 133                                 NULL, /* mpool */
 134                                 0, /* mpool reg flags */
 135                                 NULL, /* unused0 */
 136                                 NULL, /* item_init */
 137                                 NULL /* inem_init context */);
 138     if(r != OPAL_SUCCESS)
 139     {
 140         fprintf(stderr, "Unable to initialize ompi_java_buffers.\n");
 141         exit(1);
 142     }
 143 }
 144 
 145 static jclass findClass(JNIEnv *env, const char *className)
 146 {
 147     jclass c = (*env)->FindClass(env, className),
 148            r = (*env)->NewGlobalRef(env, c);
 149 
 150     (*env)->DeleteLocalRef(env, c);
 151     return r;
 152 }
 153 
 154 static void findClasses(JNIEnv *env)
 155 {
 156     ompi_java.CartParmsClass  = findClass(env, "mpi/CartParms");
 157     ompi_java.ShiftParmsClass = findClass(env, "mpi/ShiftParms");
 158     ompi_java.GraphParmsClass = findClass(env, "mpi/GraphParms");
 159 
 160     ompi_java.DistGraphNeighborsClass = findClass(
 161                                         env, "mpi/DistGraphNeighbors");
 162 
 163     ompi_java.StatusClass    = findClass(env, "mpi/Status");
 164     ompi_java.ExceptionClass = findClass(env, "mpi/MPIException");
 165 
 166     ompi_java.ExceptionInit = (*env)->GetMethodID(
 167                               env, ompi_java.ExceptionClass,
 168                               "<init>", "(IILjava/lang/String;)V");
 169 
 170     ompi_java.IntegerClass = findClass(env, "java/lang/Integer");
 171     ompi_java.LongClass    = findClass(env, "java/lang/Long");
 172 
 173     ompi_java.IntegerValueOf = (*env)->GetStaticMethodID(
 174             env, ompi_java.IntegerClass, "valueOf", "(I)Ljava/lang/Integer;");
 175     ompi_java.LongValueOf = (*env)->GetStaticMethodID(
 176             env, ompi_java.LongClass, "valueOf", "(J)Ljava/lang/Long;");
 177 }
 178 
 179 static void deleteClasses(JNIEnv *env)
 180 {
 181     (*env)->DeleteGlobalRef(env, ompi_java.CartParmsClass);
 182     (*env)->DeleteGlobalRef(env, ompi_java.ShiftParmsClass);
 183     (*env)->DeleteGlobalRef(env, ompi_java.VersionClass);
 184     (*env)->DeleteGlobalRef(env, ompi_java.CountClass);
 185     (*env)->DeleteGlobalRef(env, ompi_java.GraphParmsClass);
 186     (*env)->DeleteGlobalRef(env, ompi_java.DistGraphNeighborsClass);
 187     (*env)->DeleteGlobalRef(env, ompi_java.StatusClass);
 188     (*env)->DeleteGlobalRef(env, ompi_java.ExceptionClass);
 189     (*env)->DeleteGlobalRef(env, ompi_java.IntegerClass);
 190     (*env)->DeleteGlobalRef(env, ompi_java.LongClass);
 191 }
 192 
 193 JNIEXPORT jobject JNICALL Java_mpi_MPI_newInt2(JNIEnv *env, jclass clazz)
 194 {
 195     struct { int a; int b; } s;
 196     int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a)));
 197     jclass c = (*env)->FindClass(env, "mpi/Int2");
 198     jmethodID m = (*env)->GetMethodID(env, c, "<init>", "(II)V");
 199     return (*env)->NewObject(env, c, m, iOff, sizeof(int));
 200 }
 201 
 202 JNIEXPORT jobject JNICALL Java_mpi_MPI_newShortInt(JNIEnv *env, jclass clazz)
 203 {
 204     struct { short a; int b; } s;
 205     int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a)));
 206     jclass c = (*env)->FindClass(env, "mpi/ShortInt");
 207     jmethodID m = (*env)->GetMethodID(env, c, "<init>", "(III)V");
 208     return (*env)->NewObject(env, c, m, sizeof(short), iOff, sizeof(int));
 209 }
 210 
 211 JNIEXPORT jobject JNICALL Java_mpi_MPI_newLongInt(JNIEnv *env, jclass clazz)
 212 {
 213     struct { long a; int b; } s;
 214     int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a)));
 215     jclass c = (*env)->FindClass(env, "mpi/LongInt");
 216     jmethodID m = (*env)->GetMethodID(env, c, "<init>", "(III)V");
 217     return (*env)->NewObject(env, c, m, sizeof(long), iOff, sizeof(int));
 218 }
 219 
 220 JNIEXPORT jobject JNICALL Java_mpi_MPI_newFloatInt(JNIEnv *env, jclass clazz)
 221 {
 222     struct { float a; int b; } s;
 223     int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a)));
 224     jclass c = (*env)->FindClass(env, "mpi/FloatInt");
 225     jmethodID m = (*env)->GetMethodID(env, c, "<init>", "(II)V");
 226     return (*env)->NewObject(env, c, m, iOff, sizeof(int));
 227 }
 228 
 229 JNIEXPORT jobject JNICALL Java_mpi_MPI_newDoubleInt(JNIEnv *env, jclass clazz)
 230 {
 231     struct { double a; int b; } s;
 232     int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a)));
 233     jclass c = (*env)->FindClass(env, "mpi/DoubleInt");
 234     jmethodID m = (*env)->GetMethodID(env, c, "<init>", "(II)V");
 235     return (*env)->NewObject(env, c, m, iOff, sizeof(int));
 236 }
 237 
 238 JNIEXPORT void JNICALL Java_mpi_MPI_initVersion(JNIEnv *env, jclass jthis)
 239 {
 240     ompi_java.VersionClass = findClass(env, "mpi/Version");
 241     ompi_java.VersionInit = (*env)->GetMethodID(env, ompi_java.VersionClass, "<init>", "(II)V");
 242 }
 243 
 244 JNIEXPORT jobjectArray JNICALL Java_mpi_MPI_Init_1jni(
 245         JNIEnv *env, jclass clazz, jobjectArray argv)
 246 {
 247     jsize i;
 248     jclass string;
 249     jobject value;
 250 
 251     int len = (*env)->GetArrayLength(env, argv);
 252     char **sargs = (char**)calloc(len+1, sizeof(char*));
 253 
 254     for(i = 0; i < len; i++)
 255     {
 256         jstring jc = (jstring)(*env)->GetObjectArrayElement(env, argv, i);
 257         const char *s = (*env)->GetStringUTFChars(env, jc, NULL);
 258         sargs[i] = strdup(s);
 259         (*env)->ReleaseStringUTFChars(env, jc, s);
 260         (*env)->DeleteLocalRef(env, jc);
 261     }
 262 
 263     int rc = MPI_Init(&len, &sargs);
 264     
 265     if(ompi_java_exceptionCheck(env, rc)) {
 266         for(i = 0; i < len; i++)
 267             free (sargs[i]);
 268         free(sargs);
 269         return NULL;
 270     }
 271 
 272     mca_base_var_register("ompi", "mpi", "java", "eager",
 273                           "Java buffers eager size",
 274                           MCA_BASE_VAR_TYPE_INT, NULL, 0, 0,
 275                           OPAL_INFO_LVL_5,
 276                           MCA_BASE_VAR_SCOPE_READONLY,
 277                           &ompi_mpi_java_eager);
 278 
 279     string = (*env)->FindClass(env, "java/lang/String");
 280     value = (*env)->NewObjectArray(env, len, string, NULL);
 281 
 282     for(i = 0; i < len; i++)
 283     {
 284         jstring jc = (*env)->NewStringUTF(env, sargs[i]);
 285         (*env)->SetObjectArrayElement(env, value, i, jc);
 286         (*env)->DeleteLocalRef(env, jc);
 287         free (sargs[i]);
 288     }
 289 
 290     free (sargs);
 291 
 292     findClasses(env);
 293     initFreeList();
 294     return value;
 295 }
 296 
 297 JNIEXPORT jint JNICALL Java_mpi_MPI_InitThread_1jni(
 298         JNIEnv *env, jclass clazz, jobjectArray argv, jint required)
 299 {
 300     jsize i;
 301     int len = (*env)->GetArrayLength(env,argv);
 302     char **sargs = (char**)calloc(len+1, sizeof(char*));
 303 
 304     for(i = 0; i < len; i++)
 305     {
 306         jstring jc = (jstring)(*env)->GetObjectArrayElement(env, argv, i);
 307         const char *s = (*env)->GetStringUTFChars(env, jc, 0);
 308         sargs[i] = strdup(s);
 309         (*env)->ReleaseStringUTFChars(env, jc, s);
 310         (*env)->DeleteLocalRef(env, jc);
 311     }
 312 
 313     int provided;
 314     int rc = MPI_Init_thread(&len, &sargs, required, &provided);
 315     
 316     if(ompi_java_exceptionCheck(env, rc)) {
 317         for(i = 0; i < len; i++)
 318             free (sargs[i]);
 319         free(sargs);
 320         return -1;
 321     }
 322 
 323     findClasses(env);
 324     initFreeList();
 325     return provided;
 326 }
 327 
 328 JNIEXPORT jint JNICALL Java_mpi_MPI_queryThread_1jni(JNIEnv *env, jclass clazz)
 329 {
 330     int provided;
 331     int rc = MPI_Query_thread(&provided);
 332     ompi_java_exceptionCheck(env, rc);
 333     return provided;
 334 }
 335 
 336 JNIEXPORT jboolean JNICALL Java_mpi_MPI_isThreadMain_1jni(
 337                            JNIEnv *env, jclass clazz)
 338 {
 339     int flag;
 340     int rc = MPI_Is_thread_main(&flag);
 341     ompi_java_exceptionCheck(env, rc);
 342     return flag ? JNI_TRUE : JNI_FALSE;
 343 }
 344 
 345 JNIEXPORT void JNICALL Java_mpi_MPI_Finalize_1jni(JNIEnv *env, jclass obj)
 346 {
 347     OBJ_DESTRUCT(&ompi_java_buffers);
 348     int rc = MPI_Finalize();
 349     ompi_java_exceptionCheck(env, rc);
 350     deleteClasses(env);
 351 }
 352 
 353 JNIEXPORT jobject JNICALL Java_mpi_MPI_getVersionJNI(JNIEnv *env, jclass jthis)
 354 {
 355         int version, subversion;
 356         int rc = MPI_Get_version(&version, &subversion);
 357         ompi_java_exceptionCheck(env, rc);
 358 
 359         return (*env)->NewObject(env, ompi_java.VersionClass,
 360                                      ompi_java.VersionInit, version, subversion);
 361 }
 362 
 363 JNIEXPORT jstring JNICALL Java_mpi_MPI_getLibVersionJNI(JNIEnv *env, jclass jthis)
 364 {
 365         int length;
 366         char version[MPI_MAX_LIBRARY_VERSION_STRING];
 367         int rc = MPI_Get_library_version(version, &length);
 368         ompi_java_exceptionCheck(env, rc);
 369 
 370         return (*env)->NewStringUTF(env, version);
 371 }
 372 
 373 JNIEXPORT jint JNICALL Java_mpi_MPI_getProcessorName(
 374                        JNIEnv *env, jclass obj, jbyteArray buf)
 375 {
 376     int len;
 377     jbyte* bufc = (jbyte*)((*env)->GetByteArrayElements(env, buf, NULL));
 378     int rc = MPI_Get_processor_name((char*)bufc, &len);
 379     ompi_java_exceptionCheck(env, rc);
 380     (*env)->ReleaseByteArrayElements(env, buf, bufc, 0);
 381     return len;
 382 }
 383 
 384 JNIEXPORT jdouble JNICALL Java_mpi_MPI_wtime_1jni(JNIEnv *env, jclass jthis)
 385 {
 386     return MPI_Wtime();
 387 }
 388 
 389 JNIEXPORT jdouble JNICALL Java_mpi_MPI_wtick_1jni(JNIEnv *env, jclass jthis)
 390 {
 391     return MPI_Wtick();
 392 }
 393 
 394 JNIEXPORT jboolean JNICALL Java_mpi_MPI_isInitialized(JNIEnv *env, jclass jthis)
 395 {
 396     int flag;
 397     int rc = MPI_Initialized(&flag);
 398     ompi_java_exceptionCheck(env, rc);
 399     return flag ? JNI_TRUE : JNI_FALSE;
 400 }
 401 
 402 JNIEXPORT jboolean JNICALL Java_mpi_MPI_isFinalized(JNIEnv *env, jclass jthis)
 403 {
 404     int flag;
 405     int rc = MPI_Finalized(&flag);
 406     ompi_java_exceptionCheck(env, rc);
 407     return flag ? JNI_TRUE : JNI_FALSE;
 408 }
 409 
 410 JNIEXPORT void JNICALL Java_mpi_MPI_attachBuffer_1jni(
 411                        JNIEnv *env, jclass jthis, jbyteArray buf)
 412 {
 413     int size=(*env)->GetArrayLength(env,buf);
 414     jbyte* bufptr = (*env)->GetByteArrayElements(env, buf, NULL);
 415     int rc = MPI_Buffer_attach(bufptr,size);
 416     ompi_java_exceptionCheck(env, rc);
 417 }
 418 
 419 JNIEXPORT void JNICALL Java_mpi_MPI_detachBuffer_1jni(
 420                        JNIEnv *env, jclass jthis, jbyteArray buf)
 421 {
 422     int size;
 423     jbyte* bufptr;
 424     int rc = MPI_Buffer_detach(&bufptr, &size);
 425     ompi_java_exceptionCheck(env, rc);
 426 
 427     if(buf != NULL)
 428         (*env)->ReleaseByteArrayElements(env,buf,bufptr,0);
 429 }
 430 
 431 void* ompi_java_getArrayCritical(void** bufBase, JNIEnv *env,
 432                                  jobject buf, int offset)
 433 {
 434     *bufBase = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, buf, NULL);
 435     return ((jbyte*)*bufBase) + offset;
 436 }
 437 
 438 void* ompi_java_getDirectBufferAddress(JNIEnv *env, jobject buf)
 439 {
 440     /* Allow NULL buffers to send/recv 0 items as control messages. */
 441     return buf == NULL ? NULL : (*env)->GetDirectBufferAddress(env, buf);
 442 }
 443 
 444 static int getTypeExtent(JNIEnv *env, MPI_Datatype type)
 445 {
 446     MPI_Aint lb, extent;
 447     int rc = MPI_Type_get_extent(type, &lb, &extent);
 448     ompi_java_exceptionCheck(env, rc);
 449     int value = extent;
 450     assert(((MPI_Aint)value) == extent);
 451     return value;
 452 }
 453 
 454 static void getArrayRegion(JNIEnv *env, jobject buf, int baseType,
 455                            int offset, int length, void *ptr)
 456 {
 457     switch(baseType)
 458     {
 459         case 0:
 460             break;
 461         case 1:
 462             (*env)->GetByteArrayRegion(env, buf, offset, length, ptr);
 463             break;
 464         case 2:
 465             (*env)->GetCharArrayRegion(env, buf, offset / 2, length / 2, ptr);
 466             break;
 467         case 3:
 468             (*env)->GetShortArrayRegion(env, buf, offset / 2, length / 2, ptr);
 469             break;
 470         case 4:
 471             (*env)->GetBooleanArrayRegion(env, buf, offset, length, ptr);
 472             break;
 473         case 5:
 474             (*env)->GetIntArrayRegion(env, buf, offset / 4, length / 4, ptr);
 475             break;
 476         case 6:
 477             (*env)->GetLongArrayRegion(env, buf, offset / 8, length / 8, ptr);
 478             break;
 479         case 7:
 480             (*env)->GetFloatArrayRegion(env, buf, offset / 4, length / 4, ptr);
 481             break;
 482         case 8:
 483             (*env)->GetDoubleArrayRegion(env, buf, offset / 8, length / 8, ptr);
 484             break;
 485         case 9:
 486             (*env)->GetByteArrayRegion(env, buf, offset, length, ptr);
 487             break;
 488         default:
 489             assert(0);
 490     }
 491 }
 492 
 493 static void setArrayRegion(JNIEnv *env, jobject buf, int baseType,
 494                            int offset, int length, void *ptr)
 495 {
 496     switch(baseType)
 497     {
 498         case 0:
 499             break;
 500         case 1:
 501             (*env)->SetByteArrayRegion(env, buf, offset, length, ptr);
 502             break;
 503         case 2:
 504             (*env)->SetCharArrayRegion(env, buf, offset / 2, length / 2, ptr);
 505             break;
 506         case 3:
 507             (*env)->SetShortArrayRegion(env, buf, offset / 2, length / 2, ptr);
 508             break;
 509         case 4:
 510             (*env)->SetBooleanArrayRegion(env, buf, offset, length, ptr);
 511             break;
 512         case 5:
 513             (*env)->SetIntArrayRegion(env, buf, offset / 4, length / 4, ptr);
 514             break;
 515         case 6:
 516             (*env)->SetLongArrayRegion(env, buf, offset / 8, length / 8, ptr);
 517             break;
 518         case 7:
 519             (*env)->SetFloatArrayRegion(env, buf, offset / 4, length / 4, ptr);
 520             break;
 521         case 8:
 522             (*env)->SetDoubleArrayRegion(env, buf, offset / 8, length / 8, ptr);
 523             break;
 524         case 9:
 525             (*env)->SetByteArrayRegion(env, buf, offset, length, ptr);
 526             break;
 527         default:
 528             assert(0);
 529     }
 530 }
 531 
 532 static void* getBuffer(JNIEnv *env, ompi_java_buffer_t **item, int size)
 533 {
 534     if(size > ompi_mpi_java_eager)
 535     {
 536         *item = NULL;
 537         return malloc(size);
 538     }
 539     else
 540     {
 541         opal_free_list_item_t *freeListItem;
 542         freeListItem = opal_free_list_get (&ompi_java_buffers);
 543 
 544         ompi_java_exceptionCheck(env, NULL == freeListItem ? MPI_ERR_NO_MEM :
 545                                  MPI_SUCCESS);
 546         if (NULL == freeListItem) {
 547             return NULL;
 548         }
 549 
 550         *item = (ompi_java_buffer_t*)freeListItem;
 551         return (*item)->buffer;
 552     }
 553 }
 554 
 555 static void releaseBuffer(void *ptr, ompi_java_buffer_t *item)
 556 {
 557     if(item == NULL)
 558     {
 559         free(ptr);
 560     }
 561     else
 562     {
 563         assert(item->buffer == ptr);
 564         opal_free_list_return (&ompi_java_buffers, (opal_free_list_item_t*)item);
 565     }
 566 }
 567 
 568 static int getCountv(int *counts, int *displs, int size)
 569 {
 570     /* Maybe displs is not ordered. */
 571     int i, max = 0;
 572 
 573     for(i = 1; i < size; i++)
 574     {
 575         if(displs[max] < displs[i])
 576             max = i;
 577     }
 578 
 579     return displs[max] * counts[max];
 580 }
 581 
 582 static void* getReadPtr(ompi_java_buffer_t **item, JNIEnv *env, jobject buf,
 583                         int offset, int count, MPI_Datatype type, int baseType)
 584 {
 585     int  length = count * getTypeExtent(env, type);
 586     void *ptr   = getBuffer(env, item, length);
 587 
 588     if(opal_datatype_is_contiguous_memory_layout(&type->super, count))
 589     {
 590         getArrayRegion(env, buf, baseType, offset, length, ptr);
 591     }
 592     else
 593     {
 594         void *inBuf, *inBase;
 595         inBuf = ompi_java_getArrayCritical(&inBase, env, buf, offset);
 596 
 597         int rc = opal_datatype_copy_content_same_ddt(
 598                  &type->super, count, ptr, inBuf);
 599 
 600         ompi_java_exceptionCheck(env,
 601                 rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 602 
 603         (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, JNI_ABORT);
 604     }
 605 
 606     return ptr;
 607 }
 608 
 609 static void* getReadPtrRank(
 610         ompi_java_buffer_t **item, JNIEnv *env, jobject buf, int offset,
 611         int count, int size, int rank, MPI_Datatype type, int baseType)
 612 {
 613     int  extent = getTypeExtent(env, type),
 614          rLen   = extent * count,
 615          length = rLen * size,
 616          rDispl = rLen * rank,
 617          rOff   = offset + rDispl;
 618     void *ptr   = getBuffer(env, item, length);
 619     void *rPtr  = (char*)ptr + rDispl;
 620 
 621     if(opal_datatype_is_contiguous_memory_layout(&type->super, count))
 622     {
 623         getArrayRegion(env, buf, baseType, rOff, rLen, rPtr);
 624     }
 625     else
 626     {
 627         void *bufPtr, *bufBase;
 628         bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, rOff);
 629 
 630         int rc = opal_datatype_copy_content_same_ddt(
 631                  &type->super, count, rPtr, bufPtr);
 632 
 633         ompi_java_exceptionCheck(env,
 634                 rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 635 
 636         (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, JNI_ABORT);
 637     }
 638 
 639     return ptr;
 640 }
 641 
 642 static void* getReadPtrvRank(
 643         ompi_java_buffer_t **item, JNIEnv *env, jobject buf,
 644         int offset, int *counts, int *displs, int size,
 645         int rank, MPI_Datatype type, int baseType)
 646 {
 647     int  extent  = getTypeExtent(env, type),
 648          length  = extent * getCountv(counts, displs, size);
 649     void *ptr    = getBuffer(env, item, length);
 650     int  rootOff = offset + extent * displs[rank];
 651 
 652     if(opal_datatype_is_contiguous_memory_layout(&type->super, counts[rank]))
 653     {
 654         int  rootLength = extent * counts[rank];
 655         void *rootPtr   = (char*)ptr + extent * displs[rank];
 656         getArrayRegion(env, buf, baseType, rootOff, rootLength, rootPtr);
 657     }
 658     else
 659     {
 660         void *inBuf, *inBase;
 661         inBuf = ompi_java_getArrayCritical(&inBase, env, buf, rootOff);
 662 
 663         int rc = opal_datatype_copy_content_same_ddt(
 664                  &type->super, counts[rank], ptr, inBuf);
 665 
 666         ompi_java_exceptionCheck(env,
 667                 rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 668 
 669         (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, JNI_ABORT);
 670     }
 671 
 672     return ptr;
 673 }
 674 
 675 static void* getReadPtrvAll(
 676         ompi_java_buffer_t **item, JNIEnv *env, jobject buf,
 677         int offset, int *counts, int *displs, int size,
 678         MPI_Datatype type, int baseType)
 679 {
 680     int  i,
 681          extent  = getTypeExtent(env, type),
 682          length  = extent * getCountv(counts, displs, size);
 683     void *ptr    = getBuffer(env, item, length);
 684 
 685     if(opal_datatype_is_contiguous_memory_layout(&type->super, 2))
 686     {
 687         for(i = 0; i < size; i++)
 688         {
 689             int   iOff = offset + extent * displs[i],
 690                   iLen = extent * counts[i];
 691             void *iPtr = (char*)ptr + extent * displs[i];
 692             getArrayRegion(env, buf, baseType, iOff, iLen, iPtr);
 693         }
 694     }
 695     else
 696     {
 697         void *bufPtr, *bufBase;
 698         bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offset);
 699 
 700         for(i = 0; i < size; i++)
 701         {
 702             int   iOff = extent * displs[i];
 703             char *iBuf = iOff + (char*)bufPtr,
 704                  *iPtr = iOff + (char*)ptr;
 705 
 706             int rc = opal_datatype_copy_content_same_ddt(
 707                      &type->super, counts[i], iPtr, iBuf);
 708 
 709             ompi_java_exceptionCheck(env,
 710                     rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 711         }
 712 
 713         (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, JNI_ABORT);
 714     }
 715 
 716     return ptr;
 717 }
 718 
 719 static void* getWritePtr(ompi_java_buffer_t **item, JNIEnv *env,
 720                          int count, MPI_Datatype type)
 721 {
 722     int extent = getTypeExtent(env, type),
 723         length = count * extent;
 724 
 725     return getBuffer(env, item, length);
 726 }
 727 
 728 static void* getWritePtrv(ompi_java_buffer_t **item, JNIEnv *env,
 729                           int *counts, int *displs, int size, MPI_Datatype type)
 730 {
 731     int extent = getTypeExtent(env, type),
 732         count  = getCountv(counts, displs, size),
 733         length = extent * count;
 734 
 735     return getBuffer(env, item, length);
 736 }
 737 
 738 void ompi_java_getReadPtr(
 739         void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf,
 740         jboolean db, int offset, int count, MPI_Datatype type, int baseType)
 741 {
 742     if(buf == NULL || baseType == 0)
 743     {
 744         /* Allow NULL buffers to send/recv 0 items as control messages. */
 745         *ptr  = NULL;
 746         *item = NULL;
 747     }
 748     else if(db)
 749     {
 750         assert(offset == 0);
 751         *ptr  = (*env)->GetDirectBufferAddress(env, buf);
 752         *item = NULL;
 753     }
 754     else
 755     {
 756         *ptr = getReadPtr(item, env, buf, offset, count, type, baseType);
 757     }
 758 }
 759 
 760 void ompi_java_getReadPtrRank(
 761         void **ptr, ompi_java_buffer_t **item, JNIEnv *env,
 762         jobject buf, jboolean db, int offset, int count, int size,
 763         int rank, MPI_Datatype type, int baseType)
 764 {
 765     if(buf == NULL || baseType == 0)
 766     {
 767         /* Allow NULL buffers to send/recv 0 items as control messages. */
 768         *ptr  = NULL;
 769         *item = NULL;
 770     }
 771     else if(db)
 772     {
 773         assert(offset == 0);
 774         *ptr  = (*env)->GetDirectBufferAddress(env, buf);
 775         *item = NULL;
 776     }
 777     else
 778     {
 779         *ptr = getReadPtrRank(item, env, buf, offset, count,
 780                               size, rank, type, baseType);
 781     }
 782 }
 783 
 784 void ompi_java_getReadPtrv(
 785         void **ptr, ompi_java_buffer_t **item, JNIEnv *env,
 786         jobject buf, jboolean db, int offset, int *counts, int *displs,
 787         int size, int rank, MPI_Datatype type, int baseType)
 788 {
 789     if(buf == NULL)
 790     {
 791         /* Allow NULL buffers to send/recv 0 items as control messages. */
 792         *ptr  = NULL;
 793         *item = NULL;
 794     }
 795     else if(db)
 796     {
 797         assert(offset == 0);
 798         *ptr  = (*env)->GetDirectBufferAddress(env, buf);
 799         *item = NULL;
 800     }
 801     else if(rank == -1)
 802     {
 803         *ptr = getReadPtrvAll(item, env, buf, offset, counts,
 804                               displs, size, type, baseType);
 805     }
 806     else
 807     {
 808         *ptr = getReadPtrvRank(item, env, buf, offset, counts,
 809                                displs, size, rank, type, baseType);
 810     }
 811 }
 812 
 813 void ompi_java_releaseReadPtr(
 814         void *ptr, ompi_java_buffer_t *item, jobject buf, jboolean db)
 815 {
 816     if(!db && buf && ptr)
 817         releaseBuffer(ptr, item);
 818 }
 819 
 820 void ompi_java_getWritePtr(
 821         void **ptr, ompi_java_buffer_t **item, JNIEnv *env,
 822         jobject buf, jboolean db, int count, MPI_Datatype type)
 823 {
 824     if(buf == NULL)
 825     {
 826         /* Allow NULL buffers to send/recv 0 items as control messages. */
 827         *ptr  = NULL;
 828         *item = NULL;
 829     }
 830     else if(db)
 831     {
 832         *ptr  = (*env)->GetDirectBufferAddress(env, buf);
 833         *item = NULL;
 834     }
 835     else
 836     {
 837         *ptr = getWritePtr(item, env, count, type);
 838     }
 839 }
 840 
 841 void ompi_java_getWritePtrv(
 842         void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf,
 843         jboolean db, int *counts, int *displs, int size, MPI_Datatype type)
 844 {
 845     if(buf == NULL)
 846     {
 847         /* Allow NULL buffers to send/recv 0 items as control messages. */
 848         *ptr  = NULL;
 849         *item = NULL;
 850     }
 851     else if(db)
 852     {
 853         *ptr  = (*env)->GetDirectBufferAddress(env, buf);
 854         *item = NULL;
 855     }
 856     else
 857     {
 858         *ptr = getWritePtrv(item, env, counts, displs, size, type);
 859     }
 860 }
 861 
 862 void ompi_java_releaseWritePtr(
 863         void *ptr, ompi_java_buffer_t *item, JNIEnv *env, jobject buf,
 864         jboolean db, int offset, int count, MPI_Datatype type, int baseType)
 865 {
 866     if(db || !buf || !ptr)
 867         return;
 868 
 869     if(opal_datatype_is_contiguous_memory_layout(&type->super, count))
 870     {
 871         int length = count * getTypeExtent(env, type);
 872         setArrayRegion(env, buf, baseType, offset, length, ptr);
 873     }
 874     else
 875     {
 876         void *inBuf, *inBase;
 877         inBuf = ompi_java_getArrayCritical(&inBase, env, buf, offset);
 878 
 879         int rc = opal_datatype_copy_content_same_ddt(
 880                  &type->super, count, inBuf, ptr);
 881 
 882         ompi_java_exceptionCheck(env,
 883                 rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 884 
 885         (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, 0);
 886     }
 887 
 888     releaseBuffer(ptr, item);
 889 }
 890 
 891 void ompi_java_releaseWritePtrv(
 892         void *ptr, ompi_java_buffer_t *item, JNIEnv *env,
 893         jobject buf, jboolean db, int offset, int *counts, int *displs,
 894         int size, MPI_Datatype type, int baseType)
 895 {
 896     if(db || !buf || !ptr)
 897         return;
 898 
 899     int i;
 900     int extent = getTypeExtent(env, type);
 901 
 902     if(opal_datatype_is_contiguous_memory_layout(&type->super, 2))
 903     {
 904         for(i = 0; i < size; i++)
 905         {
 906             int   iOff = offset + extent * displs[i],
 907                   iLen = extent * counts[i];
 908             void *iPtr = (char*)ptr + extent * displs[i];
 909             setArrayRegion(env, buf, baseType, iOff, iLen, iPtr);
 910         }
 911     }
 912     else
 913     {
 914         void *bufPtr, *bufBase;
 915         bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offset);
 916 
 917         for(i = 0; i < size; i++)
 918         {
 919             int   iOff = extent * displs[i];
 920             char *iBuf = iOff + (char*)bufPtr,
 921                  *iPtr = iOff + (char*)ptr;
 922 
 923             int rc = opal_datatype_copy_content_same_ddt(
 924                      &type->super, counts[i], iBuf, iPtr);
 925 
 926             ompi_java_exceptionCheck(env,
 927                     rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR);
 928         }
 929 
 930         (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, 0);
 931     }
 932 
 933     releaseBuffer(ptr, item);
 934 }
 935 
 936 jobject ompi_java_Integer_valueOf(JNIEnv *env, jint i)
 937 {
 938     return (*env)->CallStaticObjectMethod(env,
 939            ompi_java.IntegerClass, ompi_java.IntegerValueOf, i);
 940 }
 941 
 942 jobject ompi_java_Long_valueOf(JNIEnv *env, jlong i)
 943 {
 944     return (*env)->CallStaticObjectMethod(env,
 945            ompi_java.LongClass, ompi_java.LongValueOf, i);
 946 }
 947 
 948 void ompi_java_getIntArray(JNIEnv *env, jintArray array,
 949                            jint **jptr, int **cptr)
 950 {
 951     jint *jInts = (*env)->GetIntArrayElements(env, array, NULL);
 952     *jptr = jInts;
 953 
 954     if(sizeof(int) == sizeof(jint))
 955     {
 956         *cptr = (int*)jInts;
 957     }
 958     else
 959     {
 960         int i, length = (*env)->GetArrayLength(env, array);
 961         int *cInts = calloc(length, sizeof(int));
 962 
 963         for(i = 0; i < length; i++)
 964             cInts[i] = jInts[i];
 965 
 966         *cptr = cInts;
 967     }
 968 }
 969 
 970 void ompi_java_releaseIntArray(JNIEnv *env, jintArray array,
 971                                jint *jptr, int *cptr)
 972 {
 973     if(jptr != cptr)
 974     {
 975         int i, length = (*env)->GetArrayLength(env, array);
 976 
 977         for(i = 0; i < length; i++)
 978             jptr[i] = cptr[i];
 979 
 980         free(cptr);
 981     }
 982 
 983     (*env)->ReleaseIntArrayElements(env, array, jptr, 0);
 984 }
 985 
 986 void ompi_java_forgetIntArray(JNIEnv *env, jintArray array,
 987                               jint *jptr, int *cptr)
 988 {
 989     if(jptr != cptr)
 990         free(cptr);
 991 
 992     (*env)->ReleaseIntArrayElements(env, array, jptr, JNI_ABORT);
 993 }
 994 
 995 void ompi_java_getDatatypeArray(JNIEnv *env, jlongArray array,
 996                            jlong **jptr, MPI_Datatype **cptr)
 997 {
 998     jlong *jLongs = (*env)->GetLongArrayElements(env, array, NULL);
 999     *jptr = jLongs;
1000 
1001     int i, length = (*env)->GetArrayLength(env, array);
1002     MPI_Datatype *cDatatypes = calloc(length, sizeof(MPI_Datatype));
1003 
1004     for(i = 0; i < length; i++){
1005         cDatatypes[i] = (MPI_Datatype)jLongs[i];
1006     }
1007     *cptr = cDatatypes;
1008 }
1009 
1010 void ompi_java_forgetDatatypeArray(JNIEnv *env, jlongArray array,
1011                               jlong *jptr, MPI_Datatype *cptr)
1012 {
1013     if((long)jptr != (long)cptr)
1014         free(cptr);
1015 
1016     (*env)->ReleaseLongArrayElements(env, array, jptr, JNI_ABORT);
1017 }
1018 
1019 void ompi_java_getBooleanArray(JNIEnv *env, jbooleanArray array,
1020                                jboolean **jptr, int **cptr)
1021 {
1022     int i, length = (*env)->GetArrayLength(env, array);
1023     jboolean *jb = (*env)->GetBooleanArrayElements(env, array, NULL);
1024     int *cb = (int*)calloc(length, sizeof(int));
1025 
1026     for(i = 0; i < length; i++)
1027         cb[i] = jb[i];
1028 
1029     *jptr = jb;
1030     *cptr = cb;
1031 }
1032 
1033 void ompi_java_releaseBooleanArray(JNIEnv *env, jbooleanArray array,
1034                                    jboolean *jptr, int *cptr)
1035 {
1036     int i, length = (*env)->GetArrayLength(env, array);
1037 
1038     for(i = 0; i < length; i++)
1039         jptr[i] = cptr[i] ? JNI_TRUE : JNI_FALSE;
1040 
1041     free(cptr);
1042     (*env)->ReleaseBooleanArrayElements(env, array, jptr, 0);
1043 }
1044 
1045 void ompi_java_forgetBooleanArray(JNIEnv *env, jbooleanArray array,
1046                                   jboolean *jptr, int *cptr)
1047 {
1048     free(cptr);
1049     (*env)->ReleaseBooleanArrayElements(env, array, jptr, JNI_ABORT);
1050 }
1051 
1052 void ompi_java_getPtrArray(JNIEnv *env, jlongArray array,
1053                            jlong **jptr, void ***cptr)
1054 {
1055     jlong *jp = *jptr = (*env)->GetLongArrayElements(env, array, NULL);
1056 
1057     if(sizeof(jlong) == sizeof(void*))
1058     {
1059         *cptr = (void**)jp;
1060     }
1061     else
1062     {
1063         int i, length = (*env)->GetArrayLength(env, array);
1064         void **cp = *cptr = calloc(length, sizeof(void*));
1065 
1066         for(i = 0; i < length; i++)
1067             cp[i] = (void*)jp[i];
1068     }
1069 }
1070 
1071 void ompi_java_releasePtrArray(JNIEnv *env, jlongArray array,
1072                                jlong *jptr, void **cptr)
1073 {
1074     if(jptr != (jlong*)cptr)
1075     {
1076         int i, length = (*env)->GetArrayLength(env, array);
1077 
1078         for(i = 0; i < length; i++)
1079             jptr[i] = (jlong)cptr[i];
1080 
1081         free(cptr);
1082     }
1083 
1084     (*env)->ReleaseLongArrayElements(env, array, jptr, 0);
1085 }
1086 
1087 /* This method checks whether an MPI or JNI exception has occurred.
1088  * If an exception occurs, the C code will continue running.  Once
1089  * code execution returns to Java code, an exception is immediately
1090  * thrown.  Since an exception has occurred somewhere in the C code,
1091  * the object that is returned from C may not be valid.  This is not
1092  * an issue, however, as the assignment opperation will not be
1093  * executed.  The results of this method need not be checked if the
1094  * only following code cleans up memory and then returns to Java.
1095  * If existing objects are changed after a call to this method, the
1096  * results need to be checked and, if an error has occurred, the
1097  * code should instead cleanup any memory and return.
1098  */
1099 jboolean ompi_java_exceptionCheck(JNIEnv *env, int rc)
1100 {
1101     jboolean jni_exception;
1102 
1103     if (rc < 0) {
1104         /* handle ompi error code */
1105         rc = ompi_errcode_get_mpi_code (rc);
1106         /* ompi_mpi_errcode_get_class CAN NOT handle negative error codes.
1107          * all Open MPI MPI error codes should be > 0. */
1108         assert (rc >= 0);
1109     }
1110     jni_exception = (*env)->ExceptionCheck(env);
1111 
1112     if(MPI_SUCCESS == rc && JNI_FALSE == jni_exception)
1113     {
1114         return JNI_FALSE;
1115     }
1116     else if(MPI_SUCCESS != rc)
1117     {
1118         int     errClass = ompi_mpi_errcode_get_class(rc);
1119         char    *message = ompi_mpi_errnum_get_string(rc);
1120         jstring jmessage = (*env)->NewStringUTF(env, (const char*)message);
1121 
1122         jobject mpiex = (*env)->NewObject(env, ompi_java.ExceptionClass,
1123                                           ompi_java.ExceptionInit,
1124                                           rc, errClass, jmessage);
1125         (*env)->Throw(env, mpiex);
1126         (*env)->DeleteLocalRef(env, mpiex);
1127         (*env)->DeleteLocalRef(env, jmessage);
1128         return JNI_TRUE;
1129     }
1130     /* If we get here, a JNI error has occurred. */
1131     return JNI_TRUE;
1132 }
1133 
1134 void* ompi_java_attrSet(JNIEnv *env, jbyteArray jval)
1135 {
1136     int length = (*env)->GetArrayLength(env, jval);
1137     void *cval = malloc(sizeof(int) + length);
1138     *((int*)cval) = length;
1139 
1140     (*env)->GetByteArrayRegion(env, jval,
1141             0, length, (jbyte*)cval + sizeof(int));
1142 
1143     return cval;
1144 }
1145 
1146 jbyteArray ompi_java_attrGet(JNIEnv *env, void *cval)
1147 {
1148     int length = *((int*)cval);
1149     jbyteArray jval = (*env)->NewByteArray(env, length);
1150 
1151     (*env)->SetByteArrayRegion(env, jval,
1152             0, length, (jbyte*)cval + sizeof(int));
1153 
1154     return jval;
1155 }
1156 
1157 int ompi_java_attrCopy(void *attrValIn, void *attrValOut, int *flag)
1158 {
1159     int length = *((int*)attrValIn) + sizeof(int);
1160     *((void**)attrValOut) = malloc(length);
1161     memcpy(*((void**)attrValOut), attrValIn, length);
1162     *flag = 1;
1163     return MPI_SUCCESS;
1164 }
1165 
1166 int ompi_java_attrDelete(void *attrVal)
1167 {
1168     free(attrVal);
1169     return MPI_SUCCESS;
1170 }

/* [<][>][^][v][top][bottom][index][help] */