From 539038a4c8aebfc17dba367b41642c96ae329835 Mon Sep 17 00:00:00 2001 From: Jessie Yang Date: Wed, 14 Jan 2026 11:41:40 -0800 Subject: [PATCH 001/230] coll/tuned: Change the allreduce default collective algorithm selection Include the new allreduce algorithm allgather_reduce in the default algorithm selections. The default algorithm selections were out of date and not performing well. After gathering data using the ompi-collectives-tuning package, new default algorithm decisions are selected for allreduce, which have significant speedup for small node number and message size on inter node communicators. Signed-off-by: Jessie Yang --- ompi/mca/coll/tuned/coll_tuned.h | 1 + .../coll/tuned/coll_tuned_decision_fixed.c | 188 ++++++++++++++++++ ompi/mca/coll/tuned/coll_tuned_module.c | 3 +- 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/ompi/mca/coll/tuned/coll_tuned.h b/ompi/mca/coll/tuned/coll_tuned.h index 47634caec25..53bb8705aa0 100644 --- a/ompi/mca/coll/tuned/coll_tuned.h +++ b/ompi/mca/coll/tuned/coll_tuned.h @@ -113,6 +113,7 @@ int ompi_coll_tuned_allgatherv_intra_check_forced_init(coll_tuned_force_algorith /* All Reduce */ int ompi_coll_tuned_allreduce_intra_dec_fixed(ALLREDUCE_ARGS); +int ompi_coll_tuned_allreduce_intra_disjoint_dec_fixed(ALLREDUCE_ARGS); int ompi_coll_tuned_allreduce_intra_dec_dynamic(ALLREDUCE_ARGS); int ompi_coll_tuned_allreduce_intra_do_this(ALLREDUCE_ARGS, int algorithm, int faninout, int segsize); int ompi_coll_tuned_allreduce_intra_check_forced_init (coll_tuned_force_algorithm_mca_param_indices_t *mca_param_indices); diff --git a/ompi/mca/coll/tuned/coll_tuned_decision_fixed.c b/ompi/mca/coll/tuned/coll_tuned_decision_fixed.c index e97993ffe10..3b0077c9bcc 100644 --- a/ompi/mca/coll/tuned/coll_tuned_decision_fixed.c +++ b/ompi/mca/coll/tuned/coll_tuned_decision_fixed.c @@ -218,6 +218,194 @@ ompi_coll_tuned_allreduce_intra_dec_fixed(const void *sbuf, void *rbuf, size_t c comm, module, alg, 0, 0); } + +/* + * allreduce_intra_disjoint + * + * Function: - selects allreduce algorithm to use for disjoint (inter-node) + * communicators, whose communication patterns differ from intra-node. + * This function implements a decision tree that selects the most + * efficient allreduce algorithm based on communicator size, message + * size, and operation commutativity. + * Accepts: - same as MPI_Allreduce() + * Returns: - MPI_SUCCESS or error code + */ +int +ompi_coll_tuned_allreduce_intra_disjoint_dec_fixed(const void *sbuf, void *rbuf, size_t count, + struct ompi_datatype_t *dtype, + struct ompi_op_t *op, + struct ompi_communicator_t *comm, + mca_coll_base_module_t *module) +{ + + size_t dsize, total_dsize; + int communicator_size, alg; + communicator_size = ompi_comm_size(comm); + OPAL_OUTPUT_VERBOSE((COLL_TUNED_TRACING_VERBOSE, ompi_coll_tuned_stream, + "ompi_coll_tuned_allreduce_intra_disjoint_dec_fixed")); + + ompi_datatype_type_size(dtype, &dsize); + total_dsize = dsize * (ptrdiff_t)count; + + /** Algorithms: + * {1, "basic_linear"}, + * {2, "nonoverlapping"}, + * {3, "recursive_doubling"}, + * {4, "ring"}, + * {5, "segmented_ring"}, + * {6, "rabenseifner"}, + * {7, "allgather_reduce"} + * + * Currently, ring, segmented ring, and rabenseifner do not support + * non-commutative operations. + */ + if( !ompi_op_is_commute(op) ) { + if (communicator_size == 2) { + alg = 3; + } else if (communicator_size < 4) { + alg = 7; + } else if (communicator_size < 8) { + if (total_dsize < 1048576) { + alg = 7; + } else { + alg = 3; + } + } else if (communicator_size < 16) { + if (total_dsize < 262144) { + alg = 7; + } else { + alg = 3; + } + } else if (communicator_size < 32) { + if (total_dsize < 32768) { + alg = 7; + } else if (total_dsize < 131072) { + alg = 2; + } else { + alg = 3; + } + } else if (communicator_size <= 64) { + if (total_dsize < 32768) { + alg = 7; + } else { + alg = 3; + } + } else if (communicator_size < 128) { + alg = 3; + } else if (communicator_size < 256) { + if (total_dsize < 131072) { + alg = 2; + } else if (total_dsize < 524288) { + alg = 3; + } else { + alg = 2; + } + } else if (communicator_size < 512) { + if (total_dsize < 4096) { + alg = 2; + } else if (total_dsize < 524288) { + alg = 3; + } else { + alg = 2; + } + } else { + if (total_dsize < 2048) { + alg = 2; + } else { + alg = 3; + } + } + } else { + if (communicator_size == 2) { + alg = 3; + } else if (communicator_size < 4) { + alg = 7; + } else if (communicator_size < 8) { + if (total_dsize < 1048576) { + alg = 7; + } else { + alg = 3; + } + } else if (communicator_size < 16) { + if (total_dsize < 262144) { + alg = 7; + } else if (total_dsize < 1048576) { + alg = 6; + } else { + alg = 3; + } + } else if (communicator_size < 32) { + if (total_dsize < 32768) { + alg = 7; + } else if (total_dsize < 131072) { + alg = 2; + } else { + alg = 6; + } + } else if (communicator_size <= 64) { + if (total_dsize < 32768) { + alg = 7; + } else if (total_dsize < 131072) { + alg = 3; + } else { + alg = 6; + } + } else if (communicator_size < 128) { + if (total_dsize < 262144) { + alg = 3; + } else { + alg = 6; + } + } else if (communicator_size < 256) { + if (total_dsize < 131072) { + alg = 2; + } else if (total_dsize < 262144) { + alg = 3; + } else { + alg = 6; + } + } else if (communicator_size < 512) { + if (total_dsize < 4096) { + alg = 2; + } else { + alg = 6; + } + } else if (communicator_size < 2048) { + if (total_dsize < 2048) { + alg = 2; + } else if (total_dsize < 16384) { + alg = 3; + } else { + alg = 6; + } + } else if (communicator_size < 4096) { + if (total_dsize < 2048) { + alg = 2; + } else if (total_dsize < 4096) { + alg = 5; + } else if (total_dsize < 16384) { + alg = 3; + } else { + alg = 6; + } + } else { + if (total_dsize < 2048) { + alg = 2; + } else if (total_dsize < 16384) { + alg = 5; + } else if (total_dsize < 32768) { + alg = 3; + } else { + alg = 6; + } + } + } + + return ompi_coll_tuned_allreduce_intra_do_this (sbuf, rbuf, count, dtype, op, + comm, module, alg, 0, 0); +} + + /* * alltoall_intra_dec * diff --git a/ompi/mca/coll/tuned/coll_tuned_module.c b/ompi/mca/coll/tuned/coll_tuned_module.c index 20bb4c4a49b..f82bcf27951 100644 --- a/ompi/mca/coll/tuned/coll_tuned_module.c +++ b/ompi/mca/coll/tuned/coll_tuned_module.c @@ -105,12 +105,13 @@ ompi_coll_tuned_comm_query(struct ompi_communicator_t *comm, int *priority) */ if (OMPI_COMM_IS_DISJOINT_SET(comm) && OMPI_COMM_IS_DISJOINT(comm)) { tuned_module->super.coll_bcast = ompi_coll_tuned_bcast_intra_disjoint_dec_fixed; + tuned_module->super.coll_allreduce = ompi_coll_tuned_allreduce_intra_disjoint_dec_fixed; } else { tuned_module->super.coll_bcast = ompi_coll_tuned_bcast_intra_dec_fixed; + tuned_module->super.coll_allreduce = ompi_coll_tuned_allreduce_intra_dec_fixed; } tuned_module->super.coll_allgather = ompi_coll_tuned_allgather_intra_dec_fixed; tuned_module->super.coll_allgatherv = ompi_coll_tuned_allgatherv_intra_dec_fixed; - tuned_module->super.coll_allreduce = ompi_coll_tuned_allreduce_intra_dec_fixed; tuned_module->super.coll_alltoall = ompi_coll_tuned_alltoall_intra_dec_fixed; tuned_module->super.coll_alltoallv = ompi_coll_tuned_alltoallv_intra_dec_fixed; tuned_module->super.coll_barrier = ompi_coll_tuned_barrier_intra_dec_fixed; From fc7fa114e37ba8fc6ca096621b1a02ea600fa84b Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 16 Mar 2026 16:33:49 -0600 Subject: [PATCH 002/230] Use compiler basename in ltmain_flang_darwin patch Checking $CC directly fails if the compiler is given with a full path (e.g., in a Spack-based build). This change fixes the check of the compiler to use the basename, as is done in a few other places. Signed-off-by: Bill Sacks --- config/ltmain_flang_darwin.diff | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/config/ltmain_flang_darwin.diff b/config/ltmain_flang_darwin.diff index 02dc81d988a..138b5f3ff6a 100644 --- a/config/ltmain_flang_darwin.diff +++ b/config/ltmain_flang_darwin.diff @@ -1,13 +1,14 @@ --- config/ltmain.sh +++ config/ltmain.sh -@@ -9024,7 +9024,14 @@ +@@ -9024,7 +9024,15 @@ compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + case $host in + *-*-darwin*) -+ case $CC in ++ func_cc_basename "$CC" ++ case $func_cc_basename_result in + flang*) compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -Wl,-framework,\1%g'`;; + *) compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`;; + esac;; @@ -16,7 +17,7 @@ fi fi dependency_libs=$newdependency_libs -@@ -9369,7 +9376,7 @@ +@@ -9369,7 +9377,7 @@ # On Darwin other compilers func_cc_basename $CC case $func_cc_basename_result in @@ -25,12 +26,13 @@ verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) -@@ -9869,7 +9876,10 @@ +@@ -9869,7 +9877,11 @@ # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` -+ case $CC in ++ func_cc_basename "$CC" ++ case $func_cc_basename_result in + flang*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -Wl,-framework,\1%g'`;; + *) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`;; + esac From 08acc5f2517e36fed2a3d5a6b3ef46709910c555 Mon Sep 17 00:00:00 2001 From: Matthew Whitlock Date: Fri, 30 Jan 2026 13:15:51 -0600 Subject: [PATCH 003/230] btl/ofi fault tolerance fixes Signed-off-by: Matthew Whitlock --- opal/mca/btl/ofi/btl_ofi_context.c | 10 +++++++++- opal/mca/btl/ofi/btl_ofi_frag.c | 7 +++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/opal/mca/btl/ofi/btl_ofi_context.c b/opal/mca/btl/ofi/btl_ofi_context.c index ea876d548c0..6a492d4382c 100644 --- a/opal/mca/btl/ofi/btl_ofi_context.c +++ b/opal/mca/btl/ofi/btl_ofi_context.c @@ -389,7 +389,15 @@ int mca_btl_ofi_context_progress(mca_btl_ofi_context_t *context) MCA_BTL_OFI_ABORT(); } else if(NULL != cqerr.op_context){ switch(cqerr.err) { - case -FI_EIO: { + case FI_EREMOTEIO: + case FI_EHOSTUNREACH: + case FI_ECONNABORTED: + case FI_ECONNRESET: +#ifdef FI_EHOSTDOWN + // FI_EHOSTDOWN added in libfabric 1.6.0 + case FI_EHOSTDOWN: +#endif + case FI_EIO: { mca_btl_ofi_completion_context_t *c_ctx = (mca_btl_ofi_completion_context_t*) cqerr.op_context; mca_btl_ofi_base_completion_t *comp = diff --git a/opal/mca/btl/ofi/btl_ofi_frag.c b/opal/mca/btl/ofi/btl_ofi_frag.c index e325dd34ccf..cb51da4a74f 100644 --- a/opal/mca/btl/ofi/btl_ofi_frag.c +++ b/opal/mca/btl/ofi/btl_ofi_frag.c @@ -44,6 +44,7 @@ mca_btl_ofi_frag_completion_t *mca_btl_ofi_frag_completion_alloc(mca_btl_base_mo comp = (mca_btl_ofi_frag_completion_t *) opal_free_list_get(&context->frag_comp_list); comp->base.btl = btl; + comp->base.endpoint = frag->endpoint; comp->base.my_context = context; comp->base.my_list = &context->frag_comp_list; comp->base.type = type; @@ -158,8 +159,10 @@ int mca_btl_ofi_recv_frag(mca_btl_ofi_module_t *ofi_btl, mca_btl_base_endpoint_t .tag = frag->hdr.tag, .cbdata = reg->cbdata}; - /* call the callback */ - reg->cbfunc(&ofi_btl->super, &recv_desc); + if (OPAL_LIKELY(OPAL_SUCCESS == rc)) { + /* call the callback */ + reg->cbfunc(&ofi_btl->super, &recv_desc); + } mca_btl_ofi_frag_complete(frag, rc); /* repost the recv */ From 0c86834a68c8691088570925e33b854758e1e400 Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Thu, 19 Mar 2026 13:29:06 -0700 Subject: [PATCH 004/230] request: add acquire/release barriers for sync struct handoff On weakly-ordered architectures (ARM64), the request completion handoff between ompi_request_wait_completion and ompi_request_complete lacks ordering guarantees for the sync struct publication pattern. The waiter initializes a sync struct on the stack (WAIT_SYNC_INIT) and publishes its address into req->req_complete via a relaxed CAS. The completer retrieves this address via a relaxed swap. Without barriers, the completer can dereference the sync pointer before the struct initialization stores are visible, causing wait_sync_update to operate on stale data and the wakeup signal to be lost. Add opal_atomic_wmb() before the CAS in ompi_request_wait_completion to ensure the sync struct initialization is visible before the pointer is published. Add opal_atomic_rmb() after the swap in ompi_request_complete to ensure the completer sees the initialized struct contents before dereferencing. Apply the same wmb fence in ompi_request_default_wait_any, ompi_request_default_wait_all, and ompi_request_default_wait_some, which use the same WAIT_SYNC_INIT + CAS publication pattern. This follows the established OMPI pattern of caller-imposed barriers around relaxed atomic primitives, consistent with the fix in a55e9b2 (btl/smcuda: Add atomic_wmb() before sm_fifo_write). Observed as a deadlock under MPI_THREAD_MULTIPLE on 64-core ARM64 (Graviton) instances: GDB shows req_complete=REQUEST_COMPLETED but sync->count=1, indicating the completer retrieved the sync pointer but the wakeup never reached the waiter. Fixes: #13761 Related to #12011, #11999 Signed-off-by: Brett Kleinschmidt --- ompi/request/req_wait.c | 3 +++ ompi/request/request.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ompi/request/req_wait.c b/ompi/request/req_wait.c index f5b3d43deac..8ac3c9515ac 100644 --- a/ompi/request/req_wait.c +++ b/ompi/request/req_wait.c @@ -103,6 +103,7 @@ int ompi_request_default_wait_any(size_t count, recheck: WAIT_SYNC_INIT(&sync, 1); + opal_atomic_wmb(); /* release: sync struct init must be visible before CAS publishes &sync */ num_requests_null_inactive = 0; for (i = 0; i < count; i++) { @@ -238,6 +239,7 @@ int ompi_request_default_wait_all( size_t count, recheck: WAIT_SYNC_INIT(&sync, count); + opal_atomic_wmb(); /* release: sync struct init must be visible before CAS publishes &sync */ rptr = requests; for (i = 0; i < count; i++) { void *_tmp_ptr = REQUEST_PENDING; @@ -466,6 +468,7 @@ int ompi_request_default_wait_some(size_t count, recheck: WAIT_SYNC_INIT(&sync, 1); + opal_atomic_wmb(); /* release: sync struct init must be visible before CAS publishes &sync */ *outcount = 0; diff --git a/ompi/request/request.h b/ompi/request/request.h index 548c053a7bc..afa4a4a9062 100644 --- a/ompi/request/request.h +++ b/ompi/request/request.h @@ -465,6 +465,7 @@ static inline void ompi_request_wait_completion(ompi_request_t *req) _tmp_ptr = REQUEST_PENDING; WAIT_SYNC_INIT(&sync, 1); + opal_atomic_wmb(); /* release: sync struct init must be visible before CAS publishes &sync */ if (OPAL_ATOMIC_COMPARE_EXCHANGE_STRONG_PTR(&req->req_complete, &_tmp_ptr, &sync)) { SYNC_WAIT(&sync); @@ -533,6 +534,7 @@ static inline int ompi_request_complete(ompi_request_t* request, bool with_signa ompi_wait_sync_t *tmp_sync = (ompi_wait_sync_t *) OPAL_ATOMIC_SWAP_PTR(&request->req_complete, REQUEST_COMPLETED); + opal_atomic_rmb(); /* acquire: pair with wmb before CAS to see sync struct contents */ if( REQUEST_PENDING != tmp_sync ) { wait_sync_update(tmp_sync, 1, request->req_status.MPI_ERROR); } From 910a394363f9c6368727b2d1e5fe57c72161d412 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Tue, 24 Mar 2026 12:28:20 -0400 Subject: [PATCH 005/230] GitHub Actions: add backport workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two workflows to automate backporting merged PRs to release branches: - backport.yaml: cherry-picks PR commits to target branches and opens backport PRs with target:* labels. Triggered automatically via backport:* labels on merge, or manually via workflow_dispatch. - backport-command.yaml: parses /backport ... comments on merged PRs and dispatches backport.yaml, with 👀 acknowledgement reactions. Signed-off-by: Joseph Schuchart Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/backport-command.yaml | 190 ++++++++++++ .github/workflows/backport.yaml | 379 ++++++++++++++++++++++++ 2 files changed, 569 insertions(+) create mode 100644 .github/workflows/backport-command.yaml create mode 100644 .github/workflows/backport.yaml diff --git a/.github/workflows/backport-command.yaml b/.github/workflows/backport-command.yaml new file mode 100644 index 00000000000..c5738b2cd69 --- /dev/null +++ b/.github/workflows/backport-command.yaml @@ -0,0 +1,190 @@ +# Slash-command handler for /backport. +# +# Posting a comment on a merged PR with: +# +# /backport v5.0.x v4.1.x +# +# is equivalent to manually triggering the "Backport" workflow from the +# GitHub Actions UI with those branch names. Multiple branches may be +# supplied as space- or comma-separated values on the same line. +# +# Only users with write, maintain, or admin access to the repository may +# trigger the command. If an unauthorized user attempts /backport, the bot +# replies with an explanatory comment. For valid commands it acknowledges +# with a 👀 reaction; invalid or unrecognised commands get a usage hint. + +name: Backport slash command + +on: + issue_comment: + types: [created] + +permissions: {} + +jobs: + dispatch: + name: Handle /backport comment + runs-on: ubuntu-latest + # Only act on PR comments (issue_comment fires for both issues and PRs). + if: github.event.issue.pull_request != null + permissions: + actions: write # trigger workflow_dispatch + issues: write # post reactions and comments + pull-requests: read # read PR merge status + steps: + - name: Parse command and validate PR + id: parse + uses: actions/github-script@v7 + with: + script: | + const body = context.payload.comment.body; + const commentId = context.payload.comment.id; + const issueNumber = context.payload.issue.number; + const login = context.payload.comment.user.login; + + // Detect a bare /backport with no arguments and reply helpfully. + const bareMatch = /^\/backport\s*$/m.test(body); + // Look for /backport with arguments at the start of any line. + const match = body.match(/^\/backport\s+([^\r\n]+)/m); + + // If the comment doesn't contain any /backport command at all, + // do nothing — no need to check permissions. + if (!bareMatch && !match) { + core.setOutput('triggered', 'false'); + return; + } + + // Check actual repository permission level rather than + // author_association: MEMBER alone does not imply write + // access on org-owned public repos. + let permission = 'none'; + try { + const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, + repo: context.repo.repo, + username: login, + }); + // Use role_name rather than permission: the legacy + // permission field collapses 'maintain' into 'write', + // losing the distinction between the two tiers. + permission = data.role_name; // 'admin' | 'maintain' | 'write' | 'triage' | 'read' + } catch (err) { + if (err.status !== 404) throw err; + // 404 = not a collaborator; permission stays 'none' + } + if (!['admin', 'maintain', 'write'].includes(permission)) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `âš ī¸ @${login} Backports can only be triggered by users with write, maintain, or admin access.`, + }); + core.setOutput('triggered', 'false'); + return; + } + + if (bareMatch && !match) { + core.setOutput('triggered', 'false'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', + }); + return; + } + if (!match) { + core.setOutput('triggered', 'false'); + return; + } + + // Parse branch list (space- or comma-separated). + const branches = match[1].trim().split(/[\s,]+/).filter(Boolean); + if (branches.length === 0) { + // e.g. "/backport ,,," — separators only, no real branch names + core.setOutput('triggered', 'false'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', + }); + return; + } + + // Validate branch names with the same allow-list used in + // backport.yaml so the user gets immediate feedback rather + // than a silent dispatch failure. + const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; + const invalidBranches = branches.filter(b => !validBranchRe.test(b)); + if (invalidBranches.length > 0) { + core.setOutput('triggered', 'false'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`, + }); + return; + } + + // Confirm the PR is actually merged. + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: issueNumber, + }); + + if (!pr.merged) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ Cannot backport: this PR has not been merged yet.', + }); + core.setOutput('triggered', 'false'); + return; + } + + // Acknowledge the command with a 👀 reaction. + // Ignore 422 (reaction already exists) so re-runs don't fail. + try { + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId, + content: 'eyes', + }); + } catch (err) { + if (err.status !== 422) throw err; + } + + core.setOutput('triggered', 'true'); + core.setOutput('pr_number', String(issueNumber)); + core.setOutput('branches', branches.join(',')); + core.notice(`Dispatching backport of PR #${issueNumber} to: ${branches.join(', ')}`); + + - name: Trigger backport workflow + if: steps.parse.outputs.triggered == 'true' + uses: actions/github-script@v7 + env: + PR_NUMBER: ${{ steps.parse.outputs.pr_number }} + BRANCHES: ${{ steps.parse.outputs.branches }} + with: + script: | + // workflow_dispatch requires a ref; use the default branch. + const { data: repo } = await github.rest.repos.get({ + owner: context.repo.owner, + repo: context.repo.repo, + }); + + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'backport.yaml', + ref: repo.default_branch, + inputs: { + pr_number: process.env.PR_NUMBER, + branches: process.env.BRANCHES, + }, + }); diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml new file mode 100644 index 00000000000..ebff4e66ace --- /dev/null +++ b/.github/workflows/backport.yaml @@ -0,0 +1,379 @@ +# Backport merged PRs to release branches. +# +# This workflow supports two modes: +# +# 1. Automatic (label-based): Apply one or more "backport:vX.Y.z" labels to a +# PR before merging. Once the PR is merged, this workflow fires and creates +# a cherry-pick PR for each labelled target branch. +# +# 2. Manual (workflow_dispatch): After a PR has already been merged, trigger +# this workflow manually via the GitHub Actions UI, providing the PR number +# and a comma-separated list of target branches. +# +# For every successful cherry-pick, a new PR is opened against the target +# branch and tagged with a "target:vX.Y.z" label. If the cherry-pick +# produces conflicts, a comment is posted on the original PR instead so a +# developer can handle it manually. + +name: Backport + +on: + pull_request_target: + types: [closed] + workflow_dispatch: + inputs: + pr_number: + description: 'Number of the merged PR to backport' + required: true + type: number + branches: + description: 'Target release branches (comma-separated, e.g. v5.0.x,v4.1.x)' + required: true + type: string + +permissions: {} + +jobs: + # ------------------------------------------------------------------------- + # Determine which branches need a backport and expose them as a matrix. + # ------------------------------------------------------------------------- + prepare: + name: Prepare backport targets + runs-on: ubuntu-latest + # For pull_request_target: only act when the PR was actually merged AND + # carries at least one "backport:" label (avoids a spurious job run on + # every other merge). For workflow_dispatch: always proceed. + if: > + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.merged == true && + contains(toJson(github.event.pull_request.labels.*.name), '"backport:')) + outputs: + matrix: ${{ steps.targets.outputs.matrix }} + has_targets: ${{ steps.targets.outputs.has_targets }} + pr_number: ${{ steps.targets.outputs.pr_number }} + steps: + - name: Determine backport targets + id: targets + uses: actions/github-script@v7 + with: + script: | + let branches = []; + let prNumber; + + if (context.eventName === 'workflow_dispatch') { + prNumber = Number(context.payload.inputs.pr_number); + if (!Number.isFinite(prNumber) || prNumber <= 0 || !Number.isInteger(prNumber)) { + core.setFailed(`Invalid pr_number: "${context.payload.inputs.pr_number}"`); + return; + } + branches = context.payload.inputs.branches + .split(',') + .map(b => b.trim()) + .filter(Boolean); + } else { + prNumber = context.payload.pull_request.number; + const labels = context.payload.pull_request.labels.map(l => l.name); + for (const label of labels) { + const match = label.match(/^backport:(.+)$/); + if (match) { + branches.push(match[1].trim()); + } + } + } + + // Validate branch names with a strict allow-list: must start + // with alphanumeric and contain only alphanumeric, dot, + // hyphen, underscore, or slash. De-duplicate preserving order. + const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; + const invalid = branches.filter(b => !validBranchRe.test(b)); + if (invalid.length > 0) { + core.setFailed(`Invalid branch name(s): ${invalid.join(', ')}`); + return; + } + branches = [...new Set(branches)]; + + core.setOutput('pr_number', String(prNumber)); + core.setOutput('has_targets', branches.length > 0 ? 'true' : 'false'); + core.setOutput('matrix', JSON.stringify({ branch: branches })); + + if (branches.length === 0) { + core.notice('No backport targets found — nothing to do.'); + } else { + core.notice(`Will backport PR #${prNumber} to: ${branches.join(', ')}`); + } + + # ------------------------------------------------------------------------- + # One job per target branch. All branches run in parallel; a failure on + # one branch does not cancel the others. + # ------------------------------------------------------------------------- + backport: + name: Backport to ${{ matrix.branch }} + needs: prepare + if: needs.prepare.outputs.has_targets == 'true' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + strategy: + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} + fail-fast: false + env: + PR_NUMBER: ${{ needs.prepare.outputs.pr_number }} + TARGET_BRANCH: ${{ matrix.branch }} + steps: + - name: Checkout repository (full history) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure git identity + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Retrieve PR metadata (title, body, commit list) via the API. + # Use paginate() so PRs with more than 100 commits are handled correctly. + - name: Fetch PR metadata + id: pr_meta + uses: actions/github-script@v7 + with: + script: | + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: Number(process.env.PR_NUMBER), + }); + core.setOutput('title', pr.data.title); + // Body may be empty/null — default to empty string. + core.setOutput('body', pr.data.body ?? ''); + + // Collect all commit SHAs in merge order, paginating as needed. + const commits = await github.paginate(github.rest.pulls.listCommits, { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: Number(process.env.PR_NUMBER), + per_page: 100, + }); + const shas = commits.map(c => c.sha); + core.setOutput('commits', shas.join(' ')); + + # Verify the target release branch actually exists before doing any + # work. Post a comment and skip if it does not. + - name: Validate target branch exists + id: validate + uses: actions/github-script@v7 + with: + script: | + try { + await github.rest.repos.getBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + branch: process.env.TARGET_BRANCH, + }); + core.setOutput('branch_exists', 'true'); + } catch (err) { + if (err.status !== 404) throw err; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body: `âš ī¸ Cannot backport to \`${process.env.TARGET_BRANCH}\`: branch does not exist in this repository.`, + }); + core.setOutput('branch_exists', 'false'); + } + + # Cherry-pick every commit from the PR onto a new branch based on + # the target release branch. Push the branch on success; set a + # flag on conflict so the next step can report the failure. + - name: Cherry-pick commits onto backport branch + id: cherry_pick + if: steps.validate.outputs.branch_exists == 'true' + env: + COMMITS: ${{ steps.pr_meta.outputs.commits }} + run: | + set -euo pipefail + + # Resolve a unique branch name. The counter handles the common + # case of re-running a backport; the push-retry below handles the + # rare race where two concurrent runs pick the same name. + git fetch --prune origin + # Fetch the PR's original commits so they are available locally + # regardless of how the PR was merged (squash, rebase, merge commit). + git fetch origin "refs/pull/${PR_NUMBER}/head" + BASE_BRANCH="backport/pr-${PR_NUMBER}-to-${TARGET_BRANCH}" + BACKPORT_BRANCH="${BASE_BRANCH}" + counter=1 + while git ls-remote --exit-code --heads origin "${BACKPORT_BRANCH}" > /dev/null 2>&1; do + counter=$((counter + 1)) + BACKPORT_BRANCH="${BASE_BRANCH}-${counter}" + done + echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" + + git fetch origin "${TARGET_BRANCH}" + git checkout -b "${BACKPORT_BRANCH}" "origin/${TARGET_BRANCH}" + + cherry_pick_failed=false + failed_sha="" + for sha in $COMMITS; do + echo "Cherry-picking ${sha} ..." + + # Detect merge commits (more than one parent) and cherry-pick + # relative to the first parent with -m 1. + parent_count=$(git cat-file -p "${sha}" | grep -c '^parent ' || true) + if [ "${parent_count}" -gt 1 ]; then + echo " Merge commit detected, using -m 1" + cherry_flags="-m 1" + else + cherry_flags="" + fi + + # --empty=drop silently skips commits already applied to the + # target branch rather than recording a no-op empty commit. + if ! git cherry-pick --empty=drop -x ${cherry_flags} "${sha}"; then + cherry_pick_failed=true + failed_sha="${sha}" + git cherry-pick --abort 2>/dev/null || true + break + fi + done + + echo "cherry_pick_failed=${cherry_pick_failed}" >> "$GITHUB_OUTPUT" + echo "failed_sha=${failed_sha}" >> "$GITHUB_OUTPUT" + + if [ "${cherry_pick_failed}" = "false" ]; then + # If every commit was already present in the target branch, + # cherry-pick dropped them all and HEAD hasn't moved. + new_commits=$(git rev-list --count "origin/${TARGET_BRANCH}..HEAD") + if [ "${new_commits}" -eq 0 ]; then + echo "nothing_to_backport=true" >> "$GITHUB_OUTPUT" + else + echo "nothing_to_backport=false" >> "$GITHUB_OUTPUT" + # Push; on a naming collision from a concurrent run, fall back + # to a name that includes the unique run ID. + if ! git push origin "${BACKPORT_BRANCH}" 2>/dev/null; then + BACKPORT_BRANCH="${BASE_BRANCH}-${GITHUB_RUN_ID}" + git branch -m "${BACKPORT_BRANCH}" + git push origin "${BACKPORT_BRANCH}" + echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" + fi + fi + fi + + # All commits were already present in the target branch — no PR needed. + - name: Comment when nothing to backport + if: steps.cherry_pick.outputs.nothing_to_backport == 'true' + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body: `â„šī¸ All commits from this PR are already present in \`${process.env.TARGET_BRANCH}\` — no backport needed.`, + }); + core.notice(`Nothing to backport to ${process.env.TARGET_BRANCH} — all commits already present.`); + + # Open a PR against the target branch and attach the target:* label. + - name: Create backport PR + if: >- + steps.cherry_pick.outputs.cherry_pick_failed == 'false' && + steps.cherry_pick.outputs.nothing_to_backport == 'false' + uses: actions/github-script@v7 + env: + ORIGINAL_TITLE: ${{ steps.pr_meta.outputs.title }} + ORIGINAL_BODY: ${{ steps.pr_meta.outputs.body }} + BACKPORT_BRANCH: ${{ steps.cherry_pick.outputs.backport_branch }} + with: + script: | + const prNumber = Number(process.env.PR_NUMBER); + const targetBranch = process.env.TARGET_BRANCH; + const labelName = `target:${targetBranch}`; + + // Ensure the target:* label exists in this repo. + try { + await github.rest.issues.getLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + }); + } catch (err) { + if (err.status === 404) { + try { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + color: '0075ca', + description: `Backport targeting the ${targetBranch} branch`, + }); + } catch (createErr) { + // 422 = another concurrent job created the label first; safe to ignore. + if (createErr.status !== 422) throw createErr; + } + } else { + throw err; + } + } + + const title = `[${targetBranch}] ${process.env.ORIGINAL_TITLE}`; + const body = [ + `Backport of #${prNumber} to \`${targetBranch}\`.`, + '', + '---', + '', + process.env.ORIGINAL_BODY, + ].join('\n'); + + const { data: newPR } = await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + head: process.env.BACKPORT_BRANCH, + base: targetBranch, + }); + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: newPR.number, + labels: [labelName], + }); + + core.notice(`Opened backport PR #${newPR.number}: ${newPR.html_url}`); + + # If cherry-pick failed, leave a comment on the original PR so a + # developer knows to create the backport manually. + - name: Comment on cherry-pick failure + if: steps.cherry_pick.outputs.cherry_pick_failed == 'true' + uses: actions/github-script@v7 + env: + FAILED_SHA: ${{ steps.cherry_pick.outputs.failed_sha }} + with: + script: | + const prNumber = Number(process.env.PR_NUMBER); + const targetBranch = process.env.TARGET_BRANCH; + const failedSha = process.env.FAILED_SHA; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: [ + `âš ī¸ **Automatic backport to \`${targetBranch}\` failed.**`, + '', + `Cherry-pick of commit ${failedSha} produced conflicts.`, + 'Please create the backport manually:', + '', + '```bash', + `git fetch origin ${targetBranch}`, + `git checkout -b backport/pr-${prNumber}-to-${targetBranch} origin/${targetBranch}`, + `git cherry-pick -x `, + `git push origin backport/pr-${prNumber}-to-${targetBranch}`, + '```', + ].join('\n'), + }); + + core.warning(`Cherry-pick to ${targetBranch} failed at ${failedSha} — manual backport required.`); From a312180b43ca352432debd837600b0383526888f Mon Sep 17 00:00:00 2001 From: Mike Wilkins Date: Sun, 15 Mar 2026 18:30:47 -0400 Subject: [PATCH 006/230] accelerator/cuda: defer VMM/mpool checks in check_addr fast path For standard cudaMalloc pointers (DEVICE type with valid context), return early after cuPointerGetAttributes without calling accelerator_cuda_check_vmm or accelerator_cuda_check_mpool. These checks invoke cuMemRetainAllocationHandle and cuPointerGetAttribute(MEMPOOL_HANDLE) respectively, adding unnecessary CUDA driver call overhead for the common case. The VMM and mpool checks are preserved for pointers that require them: host-type memory that may be device-backed via VMM or memory pools, and device memory with a NULL context. Signed-off-by: Mike Wilkins --- opal/mca/accelerator/cuda/accelerator_cuda.c | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/opal/mca/accelerator/cuda/accelerator_cuda.c b/opal/mca/accelerator/cuda/accelerator_cuda.c index 6a88d98df48..43a6f7acbb0 100644 --- a/opal/mca/accelerator/cuda/accelerator_cuda.c +++ b/opal/mca/accelerator/cuda/accelerator_cuda.c @@ -321,9 +321,6 @@ static int accelerator_cuda_check_addr(const void *addr, int *dev_id, uint64_t * *flags = 0; - is_vmm = accelerator_cuda_check_vmm(dbuf, &vmm_mem_type, &vmm_dev_id); - is_mpool_ptr = accelerator_cuda_check_mpool(dbuf, &mpool_mem_type, &mpool_dev_id); - #if OPAL_CUDA_GET_ATTRIBUTES uint32_t is_managed = 0; /* With CUDA 7.0, we can get multiple attributes with a single call */ @@ -352,7 +349,20 @@ static int accelerator_cuda_check_addr(const void *addr, int *dev_id, uint64_t * } else { return OPAL_ERROR; } - } else if (CU_MEMORYTYPE_HOST == mem_type) { + } + + if (CU_MEMORYTYPE_DEVICE == mem_type && NULL != mem_ctx) { + result = cuCtxGetCurrent(&ctx); + if (OPAL_UNLIKELY(NULL == ctx)) { + cuCtxSetCurrent(mem_ctx); + } + return 1; + } + + is_vmm = accelerator_cuda_check_vmm(dbuf, &vmm_mem_type, &vmm_dev_id); + is_mpool_ptr = accelerator_cuda_check_mpool(dbuf, &mpool_mem_type, &mpool_dev_id); + + if (CU_MEMORYTYPE_HOST == mem_type) { if (is_vmm && (vmm_mem_type == CU_MEMORYTYPE_DEVICE)) { mem_type = CU_MEMORYTYPE_DEVICE; *dev_id = vmm_dev_id; @@ -377,6 +387,9 @@ static int accelerator_cuda_check_addr(const void *addr, int *dev_id, uint64_t * } } #else /* OPAL_CUDA_GET_ATTRIBUTES */ + is_vmm = accelerator_cuda_check_vmm(dbuf, &vmm_mem_type, &vmm_dev_id); + is_mpool_ptr = accelerator_cuda_check_mpool(dbuf, &mpool_mem_type, &mpool_dev_id); + result = cuPointerGetAttribute(&mem_type, CU_POINTER_ATTRIBUTE_MEMORY_TYPE, dbuf); if (CUDA_SUCCESS != result) { /* If cuda is not initialized, assume it is a host buffer. */ From 593eef5314f26c2537d16f60fdd73f35cdd33f9f Mon Sep 17 00:00:00 2001 From: geokoko <71934918+geokoko@users.noreply.github.com> Date: Fri, 3 Apr 2026 23:18:00 +0300 Subject: [PATCH 007/230] Replace deprecated inet_ntoa() with inet_ntop() inet_ntoa() is deprecated according to the Linux man pages and is also on Fedora's rpminspect forbidden functions list. Replace all occurrences with inet_ntop(), which writes to a caller-provided buffer. Update the tcp2 endpoint buffers to use INET_ADDRSTRLEN and remove the now-obsolete inet_ntoa valgrind suppressions. Signed-off-by: geokoko <71934918+geokoko@users.noreply.github.com> --- .../btl_tcp2_endpoint.c | 6 +++--- contrib/openmpi-valgrind.supp | 16 ---------------- opal/mca/btl/tcp/btl_tcp_endpoint.c | 12 ++++++++++-- opal/mca/btl/usnic/btl_usnic_module.c | 12 ++++++++---- opal/util/net.c | 6 +++++- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/contrib/build-mca-comps-outside-of-tree/btl_tcp2_endpoint.c b/contrib/build-mca-comps-outside-of-tree/btl_tcp2_endpoint.c index 385f645d062..339db08da89 100644 --- a/contrib/build-mca-comps-outside-of-tree/btl_tcp2_endpoint.c +++ b/contrib/build-mca-comps-outside-of-tree/btl_tcp2_endpoint.c @@ -122,7 +122,7 @@ static void mca_btl_tcp2_endpoint_send_handler(int sd, short flags, void* user); void mca_btl_tcp_endpoint_dump(mca_btl_base_endpoint_t* btl_endpoint, const char* msg) { - char src[64], dst[64], *status; + char src[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN], *status; int sndbuf, rcvbuf, nodelay, flags = -1; #if OPAL_ENABLE_IPV6 struct sockaddr_storage inaddr; @@ -144,7 +144,7 @@ void mca_btl_tcp_endpoint_dump(mca_btl_base_endpoint_t* btl_endpoint, const char } } #else - sprintf(src, "%s", inet_ntoa(inaddr.sin_addr)); + inet_ntop(AF_INET, &inaddr.sin_addr, src, sizeof(src)); #endif getpeername(btl_endpoint->endpoint_sd, (struct sockaddr*)&inaddr, &addrlen); #if OPAL_ENABLE_IPV6 @@ -156,7 +156,7 @@ void mca_btl_tcp_endpoint_dump(mca_btl_base_endpoint_t* btl_endpoint, const char } } #else - sprintf(dst, "%s", inet_ntoa(inaddr.sin_addr)); + inet_ntop(AF_INET, &inaddr.sin_addr, dst, sizeof(dst)); #endif if((flags = fcntl(btl_endpoint->endpoint_sd, F_GETFL, 0)) < 0) { diff --git a/contrib/openmpi-valgrind.supp b/contrib/openmpi-valgrind.supp index 0a3ba945658..ca7826a3bf2 100644 --- a/contrib/openmpi-valgrind.supp +++ b/contrib/openmpi-valgrind.supp @@ -67,22 +67,6 @@ # ############################################################### -# inet_ntoa on linux mallocs a static buffer. We can't free -# it, so we have to live with it -{ - linux_inet_ntoa - Memcheck:Leak - fun:malloc - fun:inet_ntoa -} -{ - linux_inet_ntoa_thread - Memcheck:Leak - fun:calloc - fun:pthread_setspecific - fun:inet_ntoa -} - ############################################################### # diff --git a/opal/mca/btl/tcp/btl_tcp_endpoint.c b/opal/mca/btl/tcp/btl_tcp_endpoint.c index fb2a5212993..7a7ec64f4da 100644 --- a/opal/mca/btl/tcp/btl_tcp_endpoint.c +++ b/opal/mca/btl/tcp/btl_tcp_endpoint.c @@ -168,7 +168,11 @@ void mca_btl_tcp_endpoint_dump(int level, const char *fname, int lineno, const c } } # else - used += snprintf(&outmsg[used], DEBUG_LENGTH - used, "%s -", inet_ntoa(inaddr.sin_addr)); + { + char ep_addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &inaddr.sin_addr, ep_addr, sizeof(ep_addr)); + used += snprintf(&outmsg[used], DEBUG_LENGTH - used, "%s -", ep_addr); + } if (used >= DEBUG_LENGTH) goto out; # endif @@ -184,7 +188,11 @@ void mca_btl_tcp_endpoint_dump(int level, const char *fname, int lineno, const c } } # else - used += snprintf(&outmsg[used], DEBUG_LENGTH - used, " %s", inet_ntoa(inaddr.sin_addr)); + { + char ep_addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &inaddr.sin_addr, ep_addr, sizeof(ep_addr)); + used += snprintf(&outmsg[used], DEBUG_LENGTH - used, " %s", ep_addr); + } if (used >= DEBUG_LENGTH) goto out; # endif diff --git a/opal/mca/btl/usnic/btl_usnic_module.c b/opal/mca/btl/usnic/btl_usnic_module.c index 7ae08e6fb67..63fa1351305 100644 --- a/opal/mca/btl/usnic/btl_usnic_module.c +++ b/opal/mca/btl/usnic/btl_usnic_module.c @@ -1564,10 +1564,14 @@ static int create_ep(opal_btl_usnic_module_t *module, struct opal_btl_usnic_chan } else { str = "UNKNOWN"; } - opal_output_verbose(15, USNIC_OUT, - "btl:usnic:create_ep:%s: new usnic local endpoint channel %s: %s:%d", - module->linux_device_name, str, inet_ntoa(sin->sin_addr), - ntohs(sin->sin_port)); + { + char ep_addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &sin->sin_addr, ep_addr, sizeof(ep_addr)); + opal_output_verbose(15, USNIC_OUT, + "btl:usnic:create_ep:%s: new usnic local endpoint channel %s: %s:%d", + module->linux_device_name, str, ep_addr, + ntohs(sin->sin_port)); + } return OPAL_SUCCESS; } diff --git a/opal/util/net.c b/opal/util/net.c index ec0c372dd99..e53a0ddcf37 100644 --- a/opal/util/net.c +++ b/opal/util/net.c @@ -406,7 +406,11 @@ char *opal_net_get_hostname(const struct sockaddr *addr) } return name; # else - return inet_ntoa(((struct sockaddr_in *) addr)->sin_addr); + { + static char ntop_buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &((struct sockaddr_in *) addr)->sin_addr, ntop_buf, sizeof(ntop_buf)); + return ntop_buf; + } # endif } From 7290eaf63c1214bd506b1f1e6f2b99133bca6bfe Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Wed, 1 Apr 2026 14:41:27 -0600 Subject: [PATCH 008/230] fortran: fix problems with neighbor collectives The calculation of the sizes needed for various arrays, esp. of datatypes for neighbor collectives, was completely wrong. Related to issue #13790 Signed-off-by: Howard Pritchard --- ompi/mpi/bindings/ompi_bindings/fortran.py | 3 +- ompi/mpi/fortran/base/Makefile.am | 6 +- .../base/fortran_base_topo_neighbors.h | 49 +++++++++++++++ ompi/mpi/fortran/base/topo_neighbors.c | 61 +++++++++++++++++++ .../fortran/mpif-h/ineighbor_alltoallv_f.c | 21 ++++--- .../fortran/mpif-h/ineighbor_alltoallw_f.c | 31 +++++++--- .../mpi/fortran/mpif-h/neighbor_alltoallv_f.c | 20 ++++-- .../mpif-h/neighbor_alltoallv_init_f.c | 20 ++++-- .../mpi/fortran/mpif-h/neighbor_alltoallw_f.c | 31 +++++++--- .../mpif-h/neighbor_alltoallw_init_f.c | 32 +++++++--- .../use-mpi-f08/ineighbor_alltoallv_ts.c.in | 20 +++--- .../use-mpi-f08/ineighbor_alltoallw_ts.c.in | 32 ++++++---- .../neighbor_alltoallv_init_ts.c.in | 20 +++--- .../use-mpi-f08/neighbor_alltoallv_ts.c.in | 20 +++--- .../neighbor_alltoallw_init_ts.c.in | 36 +++++++---- .../use-mpi-f08/neighbor_alltoallw_ts.c.in | 31 ++++++---- 16 files changed, 326 insertions(+), 107 deletions(-) create mode 100644 ompi/mpi/fortran/base/fortran_base_topo_neighbors.h create mode 100644 ompi/mpi/fortran/base/topo_neighbors.c diff --git a/ompi/mpi/bindings/ompi_bindings/fortran.py b/ompi/mpi/bindings/ompi_bindings/fortran.py index 5e4256eacab..ea6253ef894 100644 --- a/ompi/mpi/bindings/ompi_bindings/fortran.py +++ b/ompi/mpi/bindings/ompi_bindings/fortran.py @@ -1,4 +1,4 @@ -# Copyright (c) 2024-2025 Triad National Security, LLC. All rights +# Copyright (c) 2024-2026 Triad National Security, LLC. All rights # reserved. # # $COPYRIGHT$ @@ -261,6 +261,7 @@ def print_c_source_header(out): out.dump('#include "ompi/mpi/fortran/mpif-h/status-conversion.h"') out.dump('#include "ompi/mpi/fortran/base/constants.h"') out.dump('#include "ompi/mpi/fortran/base/fint_2_int.h"') + out.dump('#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h"') out.dump('#include "ompi/request/request.h"') out.dump('#include "ompi/communicator/communicator.h"') out.dump('#include "ompi/win/win.h"') diff --git a/ompi/mpi/fortran/base/Makefile.am b/ompi/mpi/fortran/base/Makefile.am index 100fba8991c..a9f5ca147f7 100644 --- a/ompi/mpi/fortran/base/Makefile.am +++ b/ompi/mpi/fortran/base/Makefile.am @@ -13,6 +13,8 @@ # Copyright (c) 2015-2017 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2026 Triad National Security, LLC. All rights +# reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -51,5 +53,7 @@ libmpi_fortran_base_la_SOURCES = \ conversion_fn_null_f.c \ f90_accessors.c \ strings.c \ - test_constants_f.c + test_constants_f.c \ + fortran_base_topo_neighbors.h \ + topo_neighbors.c endif diff --git a/ompi/mpi/fortran/base/fortran_base_topo_neighbors.h b/ompi/mpi/fortran/base/fortran_base_topo_neighbors.h new file mode 100644 index 00000000000..9d170b96193 --- /dev/null +++ b/ompi/mpi/fortran/base/fortran_base_topo_neighbors.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2010-2018 Cisco Systems, Inc. All rights reserved + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#ifndef OMPI_FORTRAN_BASE_TOPO_NEIGHBORS_H +#define OMPI_FORTRAN_BASE_TOPO_NEIGHBORS_H + +#include "mpi.h" +#include "ompi_config.h" + +BEGIN_C_DECLS +/** + * Return number of neighbors given a supplied communicator + * + * @param[in] c_comm MPI communicator (must have an associated topology) + * @param[out] indegree number of neighbors directed in + * @param[out] outdegree number of neighbors directed out + * + * See 8.6 "Neighborhood Collective Communication on Virtual Topologies" of + * the MPI 5 standard for additional info about number of neighbors for + * the three different topology types supported by MPI as of that version + * of the standard. + * + * Note only top-level 'c' MPI interfaces are used here as the intent + * is for this function to work in the case that the OMPI fortran interface + * base is moved to an external package at some point. + */ +OMPI_DECLSPEC int ompi_fortran_neighbor_count(MPI_Comm comm, int *indegree, int *outdegree); + +END_C_DECLS + +#endif /* OMPI_FORTRAN_BASE_TOPO_NEIGHBORS_H */ diff --git a/ompi/mpi/fortran/base/topo_neighbors.c b/ompi/mpi/fortran/base/topo_neighbors.c new file mode 100644 index 00000000000..a5ec35ef836 --- /dev/null +++ b/ompi/mpi/fortran/base/topo_neighbors.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "mpi.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" + +int ompi_fortran_neighbor_count(MPI_Comm comm, int *indegree, int *outdegree) +{ + int ret; + int topo_type, ndims, nneighbors, weighted, my_rank; + + if ((NULL == indegree) || (NULL == outdegree)) { + ret = MPI_ERR_ARG; + goto fn_exit; + } + + ret = PMPI_Topo_test(comm, &topo_type); + if (MPI_SUCCESS != ret) { + goto fn_exit; + } + + switch (topo_type) { + case MPI_CART: + ret = PMPI_Cartdim_get(comm, &ndims); + if (MPI_SUCCESS != ret) { + goto fn_exit; + } + *outdegree = *indegree = 2 * ndims; + break; + case MPI_GRAPH: + ret = PMPI_Comm_rank(comm, &my_rank); + if (MPI_SUCCESS != ret) { + goto fn_exit; + } + ret = PMPI_Graph_neighbors_count(comm, my_rank, &nneighbors); + if (MPI_SUCCESS != ret) { + goto fn_exit; + } + *outdegree = *indegree = nneighbors; + break; + case MPI_DIST_GRAPH: + ret = PMPI_Dist_graph_neighbors_count(comm, indegree, outdegree, &weighted); + if (MPI_SUCCESS != ret) { + goto fn_exit; + } + break; + case MPI_UNDEFINED: + default: + break; + } + +fn_exit: + return ret; +} diff --git a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c index c7b9901cadf..144b2efec08 100644 --- a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c +++ b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c @@ -14,7 +14,8 @@ * Copyright (c) 2013 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +27,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #include "ompi/mca/coll/base/coll_base_util.h" #if OMPI_BUILD_MPI_PROFILING @@ -79,7 +81,7 @@ void ompi_ineighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *s MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -89,11 +91,16 @@ void ompi_ineighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *s c_sendtype = PMPI_Type_f2c(*sendtype); c_recvtype = PMPI_Type_f2c(*recvtype); - PMPI_Comm_size(c_comm, &size); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(sdispls, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); - OMPI_ARRAY_FINT_2_INT(rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } + + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(sdispls, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + OMPI_ARRAY_FINT_2_INT(rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c index 680d6a9d94a..b18597a4ce4 100644 --- a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c +++ b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -27,6 +29,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" #include "ompi/mca/coll/base/coll_base_util.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #if OMPI_BUILD_MPI_PROFILING #if OPAL_HAVE_WEAK_SYMBOLS @@ -80,23 +83,31 @@ void ompi_ineighbor_alltoallw_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Comm c_comm; MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Request c_request; - int size, idx = 0, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(recvcounts); c_comm = PMPI_Comm_f2c(*comm); - PMPI_Comm_size(c_comm, &size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } - c_sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - c_recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } /* Ineighbor_alltoallw does not support MPI_IN_PLACE */ diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_f.c index e9b96425e94..6a2eddae47e 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +28,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #if OMPI_BUILD_MPI_PROFILING #if OPAL_HAVE_WEAK_SYMBOLS @@ -77,7 +80,7 @@ void ompi_neighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sd { MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; - int size, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -87,11 +90,16 @@ void ompi_neighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sd c_sendtype = PMPI_Type_f2c(*sendtype); c_recvtype = PMPI_Type_f2c(*recvtype); - PMPI_Comm_size(c_comm, &size); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(sdispls, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); - OMPI_ARRAY_FINT_2_INT(rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } + + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(sdispls, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + OMPI_ARRAY_FINT_2_INT(rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c index 27ffadbc446..8bfb79dd964 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +28,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #include "ompi/mca/coll/base/coll_base_util.h" #if OMPI_BUILD_MPI_PROFILING @@ -80,7 +83,7 @@ void ompi_neighbor_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fin MPI_Datatype c_sendtype, c_recvtype; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -91,11 +94,16 @@ void ompi_neighbor_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fin c_recvtype = PMPI_Type_f2c(*recvtype); c_info = PMPI_Info_f2c(*info); - PMPI_Comm_size(c_comm, &size); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(sdispls, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); - OMPI_ARRAY_FINT_2_INT(rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } + + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(sdispls, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + OMPI_ARRAY_FINT_2_INT(rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_f.c index f5a34a36e1c..58df8d1ef9b 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +28,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #if OMPI_BUILD_MPI_PROFILING #if OPAL_HAVE_WEAK_SYMBOLS @@ -78,23 +81,31 @@ void ompi_neighbor_alltoallw_f(char *sendbuf, MPI_Fint *sendcounts, { MPI_Comm c_comm; MPI_Datatype *c_sendtypes, *c_recvtypes; - int size, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(recvcounts); c_comm = PMPI_Comm_f2c(*comm); - PMPI_Comm_size(c_comm, &size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } - c_sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - c_recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } /* Alltoallw does not support MPI_IN_PLACE */ diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c index 59910c88e36..30f9f575c89 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +28,7 @@ #include "ompi/mpi/fortran/mpif-h/bindings.h" #include "ompi/mpi/fortran/base/constants.h" +#include "ompi/mpi/fortran/base/fortran_base_topo_neighbors.h" #include "ompi/mca/coll/base/coll_base_util.h" #if OMPI_BUILD_MPI_PROFILING @@ -81,24 +84,33 @@ void ompi_neighbor_alltoallw_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(recvcounts); c_comm = PMPI_Comm_f2c(*comm); c_info = PMPI_Info_f2c(*info); - PMPI_Comm_size(c_comm, &size); - c_sendtypes = (MPI_Datatype *) malloc(2* size * sizeof(MPI_Datatype)); - c_recvtypes = c_sendtypes + size; + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + return; + } + + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); - OMPI_ARRAY_FINT_2_INT(sendcounts, size); - OMPI_ARRAY_FINT_2_INT(recvcounts, size); + OMPI_ARRAY_FINT_2_INT(sendcounts, outdegree); + OMPI_ARRAY_FINT_2_INT(recvcounts, indegree); + + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } /* Neighbor_alltoallw_init does not support MPI_IN_PLACE */ diff --git a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in index 1de86c01d45..d83aacd28c5 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -32,7 +32,7 @@ PROTOTYPE VOID ineighbor_alltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, c_ierr; + int indegree, outdegree, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @DISP_TYPE@ *tmp_sdispls = NULL; @@ -55,11 +55,17 @@ PROTOTYPE VOID ineighbor_alltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP c_sendtype = PMPI_Type_f2c(*sendtype); c_recvtype = PMPI_Type_f2c(*recvtype); - PMPI_Comm_size(c_comm, &size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } + + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in index 4c387b3dcde..05652526d65 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -33,7 +33,7 @@ PROTOTYPE VOID ineighbor_alltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Request c_request; - int size, c_ierr; + int indegree, outdegree, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @COUNT_TYPE@ *tmp_recvcounts = NULL; @@ -50,18 +50,28 @@ PROTOTYPE VOID ineighbor_alltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); return; } - PMPI_Comm_size(c_comm, &size); - c_sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - c_recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } + + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); + + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } /* Ineighbor_alltoallw does not support MPI_IN_PLACE */ diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in index 0a5729ccb03..6d7e08e8570 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024-2025 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -36,7 +36,7 @@ PROTOTYPE VOID neighbor_alltoallv_init(BUFFER x1, COUNT_ARRAY sendcounts, DISP_A MPI_Datatype c_recvtype = PMPI_Type_f2c(*recvtype);; MPI_Info c_info; MPI_Request c_request; - int size, c_ierr, idx = 0; + int indegree, outdegree, c_ierr, idx = 0; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @DISP_TYPE@ *tmp_sdispls = NULL; @@ -58,11 +58,17 @@ PROTOTYPE VOID neighbor_alltoallv_init(BUFFER x1, COUNT_ARRAY sendcounts, DISP_A return; } - PMPI_Comm_size(c_comm, &size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } + + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_ts.c.in index 8610e0221d3..9873104d22e 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024-2025 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -32,7 +32,7 @@ PROTOTYPE VOID neighbor_alltoallv(BUFFER x1, COUNT_ARRAY sendcounts, DISP_ARRAY MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype c_sendtype = PMPI_Type_f2c(*sendtype); MPI_Datatype c_recvtype = PMPI_Type_f2c(*recvtype); - int size, c_ierr; + int indegree, outdegree, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @DISP_TYPE@ *tmp_sdispls = NULL; @@ -52,11 +52,17 @@ PROTOTYPE VOID neighbor_alltoallv(BUFFER x1, COUNT_ARRAY sendcounts, DISP_ARRAY return; } - PMPI_Comm_size(c_comm, &size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, size); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } + + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, indegree); sendbuf = (char *) OMPI_F2C_IN_PLACE(sendbuf); sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in index 8a514759b41..78d136ebf6b 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024-2025 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -36,7 +36,7 @@ PROTOTYPE VOID neighbor_alltoallw_init(BUFFER x1, COUNT_ARRAY sendcounts, MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Request c_request; MPI_Info c_info; - int size, c_ierr, idx = 0; + int indegree, outdegree, c_ierr, idx = 0; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @COUNT_TYPE@ *tmp_recvcounts = NULL; @@ -56,24 +56,34 @@ PROTOTYPE VOID neighbor_alltoallw_init(BUFFER x1, COUNT_ARRAY sendcounts, OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME) return; } - PMPI_Comm_size(c_comm, &size); - c_sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - c_recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, size); + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); + + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sdispls, tmp_sdispls, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(rdispls, tmp_rdispls, indegree); /* Alltoallw does not support MPI_IN_PLACE */ sendbuf = (char *) OMPI_F2C_BOTTOM(sendbuf); recvbuf = (char *) OMPI_F2C_BOTTOM(recvbuf); - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } + + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } c_ierr = @INNER_CALL@(sendbuf, diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_ts.c.in index e4dc0181dc7..c6a141360fb 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -32,7 +32,7 @@ PROTOTYPE VOID neighbor_alltoallw(BUFFER x1, COUNT_ARRAY sendcounts, { MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype *c_sendtypes, *c_recvtypes; - int size, c_ierr; + int indegree, outdegree, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @COUNT_TYPE@ *tmp_recvcounts = NULL; @@ -49,18 +49,27 @@ PROTOTYPE VOID neighbor_alltoallw(BUFFER x1, COUNT_ARRAY sendcounts, OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME) return; } - PMPI_Comm_size(c_comm, &size); - c_sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - c_recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + c_ierr = ompi_fortran_neighbor_count(c_comm, &indegree, &outdegree); + if (MPI_SUCCESS != c_ierr) { + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); + OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); + return; + } + + c_sendtypes = (MPI_Datatype *) malloc(outdegree * sizeof(MPI_Datatype)); + c_recvtypes = (MPI_Datatype *) malloc(indegree * sizeof(MPI_Datatype)); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, size); - OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, size); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(sendcounts, tmp_sendcounts, outdegree); + OMPI_FORTRAN_BIGCOUNT_ARRAY_SET(recvcounts, tmp_recvcounts, indegree); - while (size > 0) { - c_sendtypes[size - 1] = PMPI_Type_f2c(sendtypes[size - 1]); - c_recvtypes[size - 1] = PMPI_Type_f2c(recvtypes[size - 1]); - --size; + while (outdegree > 0) { + c_sendtypes[outdegree - 1] = PMPI_Type_f2c(sendtypes[outdegree - 1]); + --outdegree; + } + while (indegree > 0) { + c_recvtypes[indegree - 1] = PMPI_Type_f2c(recvtypes[indegree - 1]); + --indegree; } /* Alltoallw does not support MPI_IN_PLACE */ From 2bd4b9ac0d739448b4c9ccee8f8a2171b952f245 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Mon, 6 Apr 2026 11:11:42 -0600 Subject: [PATCH 009/230] openpmix: advance sha to 61bd9252 Signed-off-by: Howard Pritchard --- 3rd-party/openpmix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd-party/openpmix b/3rd-party/openpmix index 53fce423d5d..61bd925224e 160000 --- a/3rd-party/openpmix +++ b/3rd-party/openpmix @@ -1 +1 @@ -Subproject commit 53fce423d5d6b25798ed1f32837671dc55d0230d +Subproject commit 61bd925224ee512041dea591eacc0d675cfea22e From 09c86a72bb085338093c500c042af4753e6b3137 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Mon, 23 Mar 2026 13:05:17 -0700 Subject: [PATCH 010/230] perf(han): Add freelist infrastructure and MCA params for persist-buffer optimization Add opal_free_list-based buffer pools (fragment_item_t, large_fragment_item_t) with configurable sizes via han_fragment_size and han_large_fragment_size MCA parameters. Freelist init/destroy gated on han_use_persist_buffers (default off). This infrastructure eliminates malloc/free cycles that invalidate EFA NIC memory registration caches, enabling stable buffer addresses across collective calls. New MCA parameters: coll_han_use_persist_buffers (bool, default false) coll_han_fragment_size (size_t, default 0) coll_han_large_fragment_size (size_t, default 0) Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 46 ++++++++++ ompi/mca/coll/han/coll_han_component.c | 27 ++++++ ompi/mca/coll/han/coll_han_module.c | 117 +++++++++++++++++++++++++ 3 files changed, 190 insertions(+) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index 2af2ae7a2c4..6fedce9b5dd 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -43,6 +43,7 @@ #include "ompi/mca/mca.h" #include "opal/util/output.h" #include "opal/mca/smsc/smsc.h" +#include "opal/class/opal_free_list.h" #include "ompi/mca/coll/base/coll_base_functions.h" #include "coll_han_trigger.h" #include "ompi/mca/coll/han/coll_han_dynamic.h" @@ -57,6 +58,34 @@ #define COLL_HAN_LOW_MODULES 3 #define COLL_HAN_UP_MODULES 2 +/** + * Fragment item for freelist-based buffer pool + * Used to provide stable buffer addresses across collective calls + */ +typedef struct fragment_item_s { + opal_free_list_item_t super; + void *buffer; /* Fixed-size buffer (han_fragment_size bytes) */ +} fragment_item_t; +OBJ_CLASS_DECLARATION(fragment_item_t); + +/** + * Large fragment item for freelist-based buffer pool. + * Size controlled by han_large_fragment_size MCA parameter (0 = disabled). + */ +typedef struct large_fragment_item_s { + opal_free_list_item_t super; + void *buffer; +} large_fragment_item_t; +OBJ_CLASS_DECLARATION(large_fragment_item_t); + +/** Source tag for tiered allocation (used by alloc/free helpers). */ +enum { + HAN_ALLOC_MALLOC = 0, + HAN_ALLOC_LARGE = 1, + HAN_ALLOC_SMALL = 2 +}; + + struct mca_coll_han_bcast_args_s { mca_coll_task_t *cur_task; ompi_communicator_t *up_comm; @@ -296,6 +325,13 @@ typedef struct mca_coll_han_component_t { opal_free_list_t pack_buffers; int64_t han_packbuf_max_count; int64_t han_packbuf_bytes; + + /* Persist-buffer optimization (0 = disabled, use malloc/free) */ + bool han_use_persist_buffers; + + /* Fragment size for buffer reuse optimization (0 = disabled) */ + size_t han_fragment_size; + size_t han_large_fragment_size; } mca_coll_han_component_t; /* @@ -384,8 +420,18 @@ typedef struct mca_coll_han_module_t { */ int dynamic_errors; + /* Persistent bounce buffer for alltoall — grows to high-water mark + via realloc so the NIC rcache registration stays valid. */ + char *alltoall_bounce; + size_t alltoall_bounce_size; + /* Sub-communicator */ struct ompi_communicator_t *sub_comm[NB_TOPO_LVL]; + + /* Fragment pool for buffer reuse (64KB items) */ + opal_free_list_t fragment_freelist; + /* Large fragment pool for pipeline reorder buffers (1MB items) */ + opal_free_list_t large_fragment_freelist; } mca_coll_han_module_t; OBJ_CLASS_DECLARATION(mca_coll_han_module_t); diff --git a/ompi/mca/coll/han/coll_han_component.c b/ompi/mca/coll/han/coll_han_component.c index 7ae17b9e4f8..c9c7fca2a17 100644 --- a/ompi/mca/coll/han/coll_han_component.c +++ b/ompi/mca/coll/han/coll_han_component.c @@ -640,5 +640,32 @@ static int han_register(void) &(cs->max_dynamic_errors)); + cs->han_use_persist_buffers = false; + (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, + "use_persist_buffers", + "Use persistent/freelist buffers to avoid malloc/free in collectives (0 = disabled)", + MCA_BASE_VAR_TYPE_BOOL, NULL, 0, MCA_BASE_VAR_FLAG_SETTABLE, + OPAL_INFO_LVL_6, + MCA_BASE_VAR_SCOPE_ALL, + &(cs->han_use_persist_buffers)); + + cs->han_fragment_size = 0; + (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, + "fragment_size", + "Size of freelist fragment buffers for collective operations (currently used by allgather, 0 = disabled)", + MCA_BASE_VAR_TYPE_UNSIGNED_LONG, NULL, 0, MCA_BASE_VAR_FLAG_SETTABLE, + OPAL_INFO_LVL_6, + MCA_BASE_VAR_SCOPE_ALL, + &(cs->han_fragment_size)); + + cs->han_large_fragment_size = 0; + (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, + "large_fragment_size", + "Size of large freelist buffers for pipeline reorder (0 = use small fragments or malloc)", + MCA_BASE_VAR_TYPE_UNSIGNED_LONG, NULL, 0, MCA_BASE_VAR_FLAG_SETTABLE, + OPAL_INFO_LVL_6, + MCA_BASE_VAR_SCOPE_ALL, + &(cs->han_large_fragment_size)); + return OMPI_SUCCESS; } diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index 28338439e39..0de7c987870 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -22,6 +22,113 @@ #include "coll_han.h" #include "coll_han_dynamic.h" +/* + * Fragment item class for freelist-based buffer pool (64KB) + */ +static void fragment_item_constructor(fragment_item_t *item) +{ + item->buffer = NULL; + if (mca_coll_han_component.han_fragment_size > 0) { + if (posix_memalign(&item->buffer, 4096, mca_coll_han_component.han_fragment_size) != 0) { + item->buffer = NULL; + } + } +} + +static void fragment_item_destructor(fragment_item_t *item) +{ + if (item->buffer) { + free(item->buffer); + item->buffer = NULL; + } +} + +OBJ_CLASS_INSTANCE(fragment_item_t, + opal_free_list_item_t, + fragment_item_constructor, + fragment_item_destructor); + +/* + * Large fragment item class for freelist-based buffer pool (1MB) + */ +static void large_fragment_item_constructor(large_fragment_item_t *item) +{ + item->buffer = NULL; + if (mca_coll_han_component.han_large_fragment_size > 0) { + if (posix_memalign(&item->buffer, 4096, mca_coll_han_component.han_large_fragment_size) != 0) { + item->buffer = NULL; + } + } +} + +static void large_fragment_item_destructor(large_fragment_item_t *item) +{ + if (item->buffer) { + free(item->buffer); + item->buffer = NULL; + } +} + +OBJ_CLASS_INSTANCE(large_fragment_item_t, + opal_free_list_item_t, + large_fragment_item_constructor, + large_fragment_item_destructor); + +/** + * Initialize fragment freelists on a HAN module. + */ +#define HAN_FRAG_INITIAL_COUNT 32 +#define HAN_FRAG_MAX_COUNT (-1) /* unlimited */ +#define HAN_FRAG_GROWTH_BATCH 64 +#define HAN_LARGE_FRAG_INITIAL 4 +#define HAN_LARGE_FRAG_MAX 20 +#define HAN_LARGE_FRAG_GROWTH 4 + +static void han_init_freelists(mca_coll_han_module_t *han_module) +{ + if (!mca_coll_han_component.han_use_persist_buffers) { + return; + } + if (mca_coll_han_component.han_fragment_size > 0) { + OBJ_CONSTRUCT(&han_module->fragment_freelist, opal_free_list_t); + opal_free_list_init(&han_module->fragment_freelist, + sizeof(fragment_item_t), + opal_cache_line_size, + OBJ_CLASS(fragment_item_t), + 0, opal_cache_line_size, + HAN_FRAG_INITIAL_COUNT, + HAN_FRAG_MAX_COUNT, + HAN_FRAG_GROWTH_BATCH, + NULL, 0, NULL, NULL, NULL); + } + OBJ_CONSTRUCT(&han_module->large_fragment_freelist, opal_free_list_t); + if (mca_coll_han_component.han_large_fragment_size > 0) { + opal_free_list_init(&han_module->large_fragment_freelist, + sizeof(large_fragment_item_t), + opal_cache_line_size, + OBJ_CLASS(large_fragment_item_t), + 0, opal_cache_line_size, + HAN_LARGE_FRAG_INITIAL, + HAN_LARGE_FRAG_MAX, + HAN_LARGE_FRAG_GROWTH, + NULL, 0, NULL, NULL, NULL); + } +} + +/** + * Destroy fragment freelists on a HAN module. + */ +static void han_destroy_freelists(mca_coll_han_module_t *han_module) +{ + if (!mca_coll_han_component.han_use_persist_buffers) { + return; + } + if (mca_coll_han_component.han_fragment_size > 0) { + OBJ_DESTRUCT(&han_module->fragment_freelist); + } + OBJ_DESTRUCT(&han_module->large_fragment_freelist); +} + /* *@file @@ -90,6 +197,8 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) } module->dynamic_errors = 0; + module->alltoall_bounce = NULL; + module->alltoall_bounce_size = 0; han_module_clear(module); @@ -144,6 +253,10 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) } } + free(module->alltoall_bounce); + module->alltoall_bounce = NULL; + module->alltoall_bounce_size = 0; + han_module_clear(module); } @@ -300,6 +413,8 @@ mca_coll_han_module_enable(mca_coll_base_module_t * module, { mca_coll_han_module_t * han_module = (mca_coll_han_module_t*) module; + han_init_freelists(han_module); + HAN_INSTALL_COLL_API(comm, han_module, alltoall); HAN_INSTALL_COLL_API(comm, han_module, alltoallv); HAN_INSTALL_COLL_API(comm, han_module, allgather); @@ -329,6 +444,8 @@ mca_coll_han_module_disable(mca_coll_base_module_t * module, { mca_coll_han_module_t * han_module = (mca_coll_han_module_t *) module; + han_destroy_freelists(han_module); + HAN_UNINSTALL_COLL_API(comm, han_module, alltoall); HAN_UNINSTALL_COLL_API(comm, han_module, alltoallv); HAN_UNINSTALL_COLL_API(comm, han_module, allgather); From ba87effdf1b19e63552d7570e2e7a043bc2440ab Mon Sep 17 00:00:00 2001 From: Yin Li Date: Mon, 23 Mar 2026 13:06:03 -0700 Subject: [PATCH 011/230] perf(han/allgather): Use freelist buffers and pipelined igather+ibcast Replace malloc/free on inter-node buffers with freelist allocation. Add pipeline path that overlaps igather+ibcast across fragments when message is large enough (>= HAN_MIN_PIPELINE_FRAGS fragments). Refactored into helper functions: han_reorder_frag() - reorder one fragment for non-mapbycore han_allgather_mapbycore() - fast path (no reorder needed) han_allgather_single_frag() - single-fragment path han_allgather_pipeline() - multi-fragment pipeline path OSU allgather latency improvement: Graviton c7g 32ppn: up to 3x at 256KB-1MB p5en 32ppn: up to 2x at 256KB-1MB Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 5 + ompi/mca/coll/han/coll_han_allgather.c | 629 +++++++++++++++++++++---- 2 files changed, 549 insertions(+), 85 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index 6fedce9b5dd..83721fabe50 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -144,6 +144,9 @@ struct mca_coll_han_allreduce_args_s { }; typedef struct mca_coll_han_allreduce_args_s mca_coll_han_allreduce_args_t; +/* Forward declaration needed by scatter and gather arg structs */ +typedef struct mca_coll_han_module_t mca_coll_han_module_t; + struct mca_coll_han_scatter_args_s { mca_coll_task_t *cur_task; ompi_communicator_t *up_comm; @@ -203,6 +206,8 @@ struct mca_coll_han_allgather_s { bool noop; bool is_mapbycore; int *topo; + mca_coll_han_module_t *han_module; + opal_free_list_item_t *inter_frag; /* Fragment for inter-node buffer */ }; typedef struct mca_coll_han_allgather_s mca_coll_han_allgather_t; diff --git a/ompi/mca/coll/han/coll_han_allgather.c b/ompi/mca/coll/han/coll_han_allgather.c index 9d3a0825f83..ce8c851247d 100644 --- a/ompi/mca/coll/han/coll_han_allgather.c +++ b/ompi/mca/coll/han/coll_han_allgather.c @@ -24,10 +24,95 @@ #include "ompi/mca/pml/pml.h" #include "coll_han_trigger.h" +/* Minimum number of fragments before the pipeline path is used. + * Below this threshold the simple path avoids pipeline setup overhead. */ +#define HAN_MIN_PIPELINE_FRAGS 4 + static int mca_coll_han_allgather_lb_task(void *task_args); static int mca_coll_han_allgather_lg_task(void *task_args); static int mca_coll_han_allgather_uag_task(void *task_args); +/** + * Allocate a buffer from the small fragment freelist, falling back to malloc. + * On return, *item is non-NULL if the buffer came from the freelist. + */ +static char *han_alloc_frag(opal_free_list_t *fl, size_t frag_size, + size_t needed, opal_free_list_item_t **item) +{ + *item = NULL; + if (mca_coll_han_component.han_use_persist_buffers + && frag_size > 0 && needed <= frag_size) { + fragment_item_t *fi = (fragment_item_t *)opal_free_list_get(fl); + if (fi != NULL) { + *item = (opal_free_list_item_t *)fi; + return (char *)fi->buffer; + } + } + return (char *)malloc(needed); +} + +/** + * Free a buffer: return to freelist if item is non-NULL, else free(). + */ +static void han_free_frag(opal_free_list_t *fl, opal_free_list_item_t *item, + char *buf) +{ + if (item != NULL) { + opal_free_list_return(fl, item); + } else { + free(buf); + } +} + +/** + * Tiered allocation: try large freelist, then small freelist, then malloc. + * Sets *item and *src (1=large, 2=small, 0=malloc) for han_free_tiered(). + */ +static char *han_alloc_tiered(opal_free_list_t *large_fl, size_t large_size, + opal_free_list_t *small_fl, size_t small_size, + size_t needed, opal_free_list_item_t **item, + int *src) +{ + *item = NULL; + *src = HAN_ALLOC_MALLOC; + if (!mca_coll_han_component.han_use_persist_buffers) { + return (char *)malloc(needed); + } + if (large_size > 0 && needed <= large_size) { + large_fragment_item_t *lfi = (large_fragment_item_t *)opal_free_list_get(large_fl); + if (lfi != NULL) { + *item = (opal_free_list_item_t *)lfi; + *src = HAN_ALLOC_LARGE; + return (char *)lfi->buffer; + } + } + if (small_size > 0 && needed <= small_size) { + fragment_item_t *fi = (fragment_item_t *)opal_free_list_get(small_fl); + if (fi != NULL) { + *item = (opal_free_list_item_t *)fi; + *src = HAN_ALLOC_SMALL; + return (char *)fi->buffer; + } + } + return (char *)malloc(needed); +} + +/** + * Free a tiered allocation based on src tag. + */ +static void han_free_tiered(opal_free_list_t *large_fl, + opal_free_list_t *small_fl, + opal_free_list_item_t *item, char *buf, int src) +{ + if (src == HAN_ALLOC_LARGE) { + opal_free_list_return(large_fl, item); + } else if (src == HAN_ALLOC_SMALL) { + opal_free_list_return(small_fl, item); + } else { + free(buf); + } +} + static inline void mca_coll_han_set_allgather_args(mca_coll_han_allgather_t * args, mca_coll_task_t * cur_task, @@ -45,7 +130,8 @@ mca_coll_han_set_allgather_args(mca_coll_han_allgather_t * args, bool noop, bool is_mapbycore, int *topo, - ompi_request_t * req) + ompi_request_t * req, + mca_coll_han_module_t *han_module) { args->cur_task = cur_task; args->sbuf = sbuf; @@ -63,6 +149,8 @@ mca_coll_han_set_allgather_args(mca_coll_han_allgather_t * args, args->is_mapbycore = is_mapbycore; args->topo = topo; args->req = req; + args->han_module = han_module; + args->inter_frag = NULL; } @@ -120,7 +208,7 @@ mca_coll_han_allgather_intra(const void *sbuf, size_t scount, mca_coll_han_set_allgather_args(lg_args, lg, (char *) sbuf, NULL, scount, sdtype, rbuf, rcount, rdtype, root_low_rank, up_comm, low_comm, w_rank, low_rank != root_low_rank, han_module->is_mapbycore, topo, - temp_request); + temp_request, han_module); /* Init and issue lg task */ init_task(lg, mca_coll_han_allgather_lg_task, (void *) (lg_args)); issue_task(lg); @@ -140,19 +228,29 @@ int mca_coll_han_allgather_lg_task(void *task_args) OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] HAN Allgather: lg\n", t->w_rank)); - /* If the process is one of the node leader */ ptrdiff_t rlb, rext; ompi_datatype_get_extent (t->rdtype, &rlb, &rext); if (MPI_IN_PLACE == t->sbuf) { t->sdtype = t->rdtype; t->scount = t->rcount; } + + /* If the process is one of the node leaders, allocate receive buffer */ if (!t->noop) { int low_size = ompi_comm_size(t->low_comm); ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size, &rgap); - tmp_buf = (char *) malloc(rsize); + + t->inter_frag = NULL; + if (mca_coll_han_component.han_fragment_size == 0 || t->han_module == NULL) { + tmp_buf = (char *) malloc(rsize); + } else { + tmp_buf = han_alloc_frag(&t->han_module->fragment_freelist, + mca_coll_han_component.han_fragment_size, + (size_t)rsize, &t->inter_frag); + } tmp_rbuf = tmp_buf - rgap; + if (MPI_IN_PLACE == t->sbuf) { tmp_send = ((char*)t->rbuf) + (ptrdiff_t)t->w_rank * (ptrdiff_t)t->rcount * rext; ompi_datatype_copy_content_same_ddt(t->rdtype, t->rcount, tmp_rbuf, tmp_send); @@ -223,7 +321,9 @@ int mca_coll_han_allgather_uag_task(void *task_args) t->up_comm, t->up_comm->c_coll->coll_allgather_module); if (t->sbuf_inter_free != NULL) { - free(t->sbuf_inter_free); + han_free_frag(&t->han_module->fragment_freelist, + t->inter_frag, t->sbuf_inter_free); + t->inter_frag = NULL; t->sbuf_inter_free = NULL; } @@ -288,6 +388,309 @@ int mca_coll_han_allgather_lb_task(void *task_args) } +/** + * Reorder a fragment from gathered layout into rbuf at the correct offset. + * Used by the pipeline and single-fragment paths. + */ +static inline void +han_reorder_frag(char *rbuf, const char *src_buf, + struct ompi_datatype_t *rdtype, ptrdiff_t rextent, + size_t frag_count, size_t frag_offset, size_t rcount, + int up_size, int low_size, const int *topo) +{ + for (int i = 0; i < up_size; i++) { + for (int j = 0; j < low_size; j++) { + int global_idx = i * low_size + j; + int dest_rank = topo[global_idx * 2 + 1]; + ompi_datatype_copy_content_same_ddt(rdtype, + (ptrdiff_t)frag_count, + rbuf + rextent * ((ptrdiff_t)dest_rank * (ptrdiff_t)rcount + + (ptrdiff_t)frag_offset), + (char *)src_buf + rextent * (ptrdiff_t)global_idx + * (ptrdiff_t)frag_count); + } + } +} + +/** + * Mapbycore fast path: gather directly into rbuf, in-place allgather, + * single bcast. No temporary buffers needed. + */ +static int +han_allgather_mapbycore(const void *sbuf, size_t scount, + struct ompi_datatype_t *sdtype, + void *rbuf, size_t rcount, + struct ompi_datatype_t *rdtype, + struct ompi_communicator_t *up_comm, + struct ompi_communicator_t *low_comm, + int w_rank, int low_rank, int up_rank, + int low_size, int up_size, int root_low_rank) +{ + ptrdiff_t rlb, rext; + ompi_datatype_get_extent(rdtype, &rlb, &rext); + size_t total_count = rcount * low_size; + char *my_slot = (char *)rbuf + (ptrdiff_t)up_rank * (ptrdiff_t)total_count * rext; + + if (MPI_IN_PLACE == sbuf) { + if (low_rank == root_low_rank) { + low_comm->c_coll->coll_gather(MPI_IN_PLACE, scount, sdtype, + my_slot, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } else { + char *my_data = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; + low_comm->c_coll->coll_gather(my_data, rcount, rdtype, + NULL, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + } else { + low_comm->c_coll->coll_gather((char *)sbuf, scount, sdtype, + my_slot, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + + if (low_rank == root_low_rank) { + up_comm->c_coll->coll_allgather(MPI_IN_PLACE, total_count, rdtype, + rbuf, total_count, rdtype, + up_comm, up_comm->c_coll->coll_allgather_module); + } + + low_comm->c_coll->coll_bcast(rbuf, rcount*low_size*up_size, rdtype, + root_low_rank, low_comm, + low_comm->c_coll->coll_bcast_module); + return OMPI_SUCCESS; +} + +/** + * Single-fragment freelist path: gather into reorder_buf, in-place + * allgather, reorder into rbuf, bcast. + */ +static int +han_allgather_single_frag(const void *sbuf, size_t scount, + struct ompi_datatype_t *sdtype, + void *rbuf, size_t rcount, + struct ompi_datatype_t *rdtype, + mca_coll_han_module_t *han_module, + struct ompi_communicator_t *up_comm, + struct ompi_communicator_t *low_comm, + struct ompi_communicator_t *comm, + int w_rank, int low_rank, int up_rank, + int low_size, int up_size, int root_low_rank, + size_t frag_size, const int *topo) +{ + ptrdiff_t rlb, rext, rextent; + ompi_datatype_get_extent(rdtype, &rlb, &rext); + ompi_datatype_type_extent(rdtype, &rextent); + size_t total_count = rcount * low_size; + char *reorder_buf = NULL; + char *reorder_buf_start = NULL; + char *my_slot = NULL; + opal_free_list_item_t *fl_item = NULL; + + if (low_rank == root_low_rank) { + ptrdiff_t rsize, rgap = 0; + rsize = opal_datatype_span(&rdtype->super, + (int64_t)rcount * low_size * up_size, &rgap); + + reorder_buf = han_alloc_frag(&han_module->fragment_freelist, + frag_size, (size_t)rsize, &fl_item); + reorder_buf_start = reorder_buf - rgap; + my_slot = reorder_buf_start + + rextent * (ptrdiff_t)up_rank * (ptrdiff_t)total_count; + if (MPI_IN_PLACE == sbuf) { + char *my_data = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; + ompi_datatype_copy_content_same_ddt(rdtype, rcount, my_slot, my_data); + } + } + + if (MPI_IN_PLACE == sbuf) { + if (low_rank == root_low_rank) { + low_comm->c_coll->coll_gather(MPI_IN_PLACE, scount, sdtype, + my_slot, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } else { + char *my_data = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; + low_comm->c_coll->coll_gather(my_data, rcount, rdtype, + NULL, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + } else { + low_comm->c_coll->coll_gather((char *)sbuf, scount, sdtype, + my_slot, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + + if (low_rank == root_low_rank) { + up_comm->c_coll->coll_allgather(MPI_IN_PLACE, total_count, rdtype, + reorder_buf_start, total_count, rdtype, + up_comm, up_comm->c_coll->coll_allgather_module); + + ompi_coll_han_reorder_gather(reorder_buf_start, rbuf, rcount, rdtype, comm, topo); + han_free_frag(&han_module->fragment_freelist, fl_item, reorder_buf); + } + + low_comm->c_coll->coll_bcast(rbuf, rcount * low_size * up_size, rdtype, + root_low_rank, low_comm, low_comm->c_coll->coll_bcast_module); + return OMPI_SUCCESS; +} + +/** + * Pipeline path: double-buffered igather+ibcast with blocking low_comm + * gather as the sync point. + */ +static int +han_allgather_pipeline(const void *sbuf, size_t scount, + struct ompi_datatype_t *sdtype, + void *rbuf, size_t rcount, + struct ompi_datatype_t *rdtype, + mca_coll_han_module_t *han_module, + struct ompi_communicator_t *up_comm, + struct ompi_communicator_t *low_comm, + int w_rank, int low_rank, + int low_size, int up_size, int root_low_rank, + size_t frag_size, size_t frag_count, size_t num_frags, + const int *topo) +{ + ptrdiff_t rlb, rext, rextent; + int root_up_rank = 0; + ompi_datatype_get_extent(rdtype, &rlb, &rext); + ompi_datatype_type_extent(rdtype, &rextent); + + /* Allocate double-buffered reorder buffers */ + char *frag_reorder[2] = {NULL, NULL}; + opal_free_list_item_t *frag_reorder_item[2] = {NULL, NULL}; + int frag_reorder_src[2] = {HAN_ALLOC_MALLOC, HAN_ALLOC_MALLOC}; + if (low_rank == root_low_rank) { + size_t frag_reorder_size = (size_t)frag_count * low_size * up_size * rextent; + size_t large_frag_size = mca_coll_han_component.han_large_fragment_size; + for (int b = 0; b < 2; b++) { + frag_reorder[b] = han_alloc_tiered( + &han_module->large_fragment_freelist, large_frag_size, + &han_module->fragment_freelist, frag_size, + frag_reorder_size, &frag_reorder_item[b], + &frag_reorder_src[b]); + } + } + + opal_free_list_item_t *inter_frag_item = NULL; + char *gather_buf = NULL; + ompi_request_t *igather_req = NULL; + ompi_request_t *ibcast_req = NULL; + size_t prev_frag_count = 0; + size_t prev_frag_offset = 0; + int cur_buf = 0; + + for (size_t frag = 0; frag < num_frags; frag++) { + size_t frag_offset = frag * frag_count; + size_t this_count = frag_count; + if (frag_offset + this_count > rcount) + this_count = rcount - frag_offset; + + int prev_buf = 1 - cur_buf; + + if (frag > 0 && low_rank == root_low_rank) { + ompi_request_wait(&igather_req, MPI_STATUS_IGNORE); + igather_req = NULL; + + han_free_frag(&han_module->fragment_freelist, + inter_frag_item, gather_buf); + inter_frag_item = NULL; + gather_buf = NULL; + + size_t prev_ag = prev_frag_count * low_size * up_size; + up_comm->c_coll->coll_ibcast(frag_reorder[prev_buf], prev_ag, rdtype, + root_up_rank, up_comm, &ibcast_req, + up_comm->c_coll->coll_ibcast_module); + } + + if (low_rank == root_low_rank) { + gather_buf = han_alloc_frag(&han_module->fragment_freelist, + frag_size, + (size_t)this_count * low_size * rextent, + &inter_frag_item); + if (MPI_IN_PLACE == sbuf) { + char *my_data = ((char*)rbuf) + + ((ptrdiff_t)w_rank * (ptrdiff_t)rcount + (ptrdiff_t)frag_offset) * rext; + ompi_datatype_copy_content_same_ddt(rdtype, this_count, + gather_buf, my_data); + } + } + + /* ALL ranks: blocking low_comm gather — SYNC POINT */ + if (MPI_IN_PLACE == sbuf) { + if (low_rank == root_low_rank) { + low_comm->c_coll->coll_gather(MPI_IN_PLACE, this_count, rdtype, + gather_buf, this_count, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } else { + char *my_data = ((char*)rbuf) + + ((ptrdiff_t)w_rank * (ptrdiff_t)rcount + (ptrdiff_t)frag_offset) * rext; + low_comm->c_coll->coll_gather(my_data, this_count, rdtype, + NULL, this_count, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + } else { + low_comm->c_coll->coll_gather( + (char *)sbuf + (ptrdiff_t)frag_offset * rext, this_count, sdtype, + gather_buf, this_count, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + + if (low_rank == root_low_rank) { + size_t ag_count = this_count * low_size; + up_comm->c_coll->coll_igather(gather_buf, ag_count, rdtype, + frag_reorder[cur_buf], ag_count, rdtype, root_up_rank, + up_comm, &igather_req, up_comm->c_coll->coll_igather_module); + } + + if (frag > 0 && low_rank == root_low_rank) { + ompi_request_wait(&ibcast_req, MPI_STATUS_IGNORE); + ibcast_req = NULL; + + han_reorder_frag(rbuf, frag_reorder[prev_buf], rdtype, rextent, + prev_frag_count, prev_frag_offset, rcount, + up_size, low_size, topo); + } + + prev_frag_count = this_count; + prev_frag_offset = frag_offset; + cur_buf = 1 - cur_buf; + } + + /* Epilogue: last frag */ + if (low_rank == root_low_rank) { + int last_buf = 1 - cur_buf; + + if (igather_req != NULL) { + ompi_request_wait(&igather_req, MPI_STATUS_IGNORE); + } + + han_free_frag(&han_module->fragment_freelist, + inter_frag_item, gather_buf); + + size_t last_ag = prev_frag_count * low_size * up_size; + up_comm->c_coll->coll_ibcast(frag_reorder[last_buf], last_ag, rdtype, + root_up_rank, up_comm, &ibcast_req, + up_comm->c_coll->coll_ibcast_module); + ompi_request_wait(&ibcast_req, MPI_STATUS_IGNORE); + + han_reorder_frag(rbuf, frag_reorder[last_buf], rdtype, rextent, + prev_frag_count, prev_frag_offset, rcount, + up_size, low_size, topo); + + for (int b = 0; b < 2; b++) { + han_free_tiered(&han_module->large_fragment_freelist, + &han_module->fragment_freelist, + frag_reorder_item[b], frag_reorder[b], + frag_reorder_src[b]); + } + } + + low_comm->c_coll->coll_bcast(rbuf, rcount * low_size * up_size, rdtype, + root_low_rank, low_comm, + low_comm->c_coll->coll_bcast_module); + return OMPI_SUCCESS; +} + /** * Short implementation of allgather that only does hierarchical * communications without tasks. @@ -300,6 +703,7 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, struct ompi_communicator_t *comm, mca_coll_base_module_t *module){ + /* create the subcommunicators */ mca_coll_han_module_t *han_module = (mca_coll_han_module_t *)module; @@ -336,101 +740,156 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, int up_size = ompi_comm_size(up_comm); int root_low_rank = 0; // node leader will be 0 on each rank - /* allocate the intermediary buffer - * to gather on leaders on the low sub communicator */ - ptrdiff_t rlb, rext; - ompi_datatype_get_extent (rdtype, &rlb, &rext); - char *tmp_buf = NULL; - char *tmp_buf_start = NULL; - char *tmp_send = NULL; - if (MPI_IN_PLACE == sbuf) { - scount = rcount; - sdtype = rdtype; - } - if (low_rank == root_low_rank) { - ptrdiff_t rsize, rgap = 0; - /* Compute the size to receive all the local data, including datatypes empty gaps */ - rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size, &rgap); - /* intermediary buffer on node leaders to gather on low comm */ - tmp_buf = (char *) malloc(rsize); - tmp_buf_start = tmp_buf - rgap; + /* Check if freelist-based optimization is enabled. + * Only use optimized path when the gathered data per node is large + * enough that pipeline/mapbycore benefit outweighs setup overhead. + * With MIN_PIPELINE_FRAGS=4, the threshold ensures at least 4 + * fragments worth of data, so the pipeline has enough stages to + * overlap igather and ibcast effectively. */ + size_t frag_size = mca_coll_han_component.han_fragment_size; + ptrdiff_t rextent_check; + ompi_datatype_type_extent(rdtype, &rextent_check); + size_t gathered_size = (size_t)rcount * (size_t)low_size * (size_t)rextent_check; + if (frag_size == 0 || gathered_size <= (HAN_MIN_PIPELINE_FRAGS * frag_size)) { + /* + * Simple path: gather to tmp_buf, allgather between leaders, + * reorder if needed, bcast to all ranks. + */ + ptrdiff_t rlb, rext; + ompi_datatype_get_extent (rdtype, &rlb, &rext); + char *tmp_buf = NULL; + char *tmp_buf_start = NULL; + char *tmp_send = NULL; if (MPI_IN_PLACE == sbuf) { - tmp_send = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; - ompi_datatype_copy_content_same_ddt(rdtype, rcount, tmp_buf_start, tmp_send); + scount = rcount; + sdtype = rdtype; } - } - - /* 1. low gather on node leaders into tmp_buf */ - if (MPI_IN_PLACE == sbuf) { if (low_rank == root_low_rank) { - low_comm->c_coll->coll_gather(MPI_IN_PLACE, scount, sdtype, - tmp_buf_start, rcount, rdtype, root_low_rank, - low_comm, low_comm->c_coll->coll_gather_module); + ptrdiff_t rsize, rgap = 0; + /* Compute the size to receive all the local data, including datatypes empty gaps */ + rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size, &rgap); + /* intermediary buffer on node leaders to gather on low comm */ + tmp_buf = (char *) malloc(rsize); + tmp_buf_start = tmp_buf - rgap; + if (MPI_IN_PLACE == sbuf) { + tmp_send = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; + ompi_datatype_copy_content_same_ddt(rdtype, rcount, tmp_buf_start, tmp_send); + } + } + + /* 1. low gather on node leaders into tmp_buf */ + if (MPI_IN_PLACE == sbuf) { + if (low_rank == root_low_rank) { + low_comm->c_coll->coll_gather(MPI_IN_PLACE, scount, sdtype, + tmp_buf_start, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } + else { + tmp_send = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; + low_comm->c_coll->coll_gather(tmp_send, rcount, rdtype, + NULL, rcount, rdtype, root_low_rank, + low_comm, low_comm->c_coll->coll_gather_module); + } } else { - tmp_send = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; - low_comm->c_coll->coll_gather(tmp_send, rcount, rdtype, - NULL, rcount, rdtype, root_low_rank, + low_comm->c_coll->coll_gather((char *)sbuf, scount, sdtype, + tmp_buf_start, rcount, rdtype, root_low_rank, low_comm, low_comm->c_coll->coll_gather_module); } - } - else { - low_comm->c_coll->coll_gather((char *)sbuf, scount, sdtype, - tmp_buf_start, rcount, rdtype, root_low_rank, - low_comm, low_comm->c_coll->coll_gather_module); - } - /* 2. allgather between node leaders, from tmp_buf to reorder_buf */ - if (low_rank == root_low_rank) { - /* allocate buffer to store unordered result on node leaders - * if the processes are mapped-by core, no need to reorder: - * distribution of ranks on core first and node next, - * in a increasing order for both patterns. - */ - char *reorder_buf = NULL; - char *reorder_buf_start = NULL; - if (han_module->is_mapbycore) { - reorder_buf_start = rbuf; - } else { - if (0 == low_rank && 0 == up_rank) { // first rank displays message - OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, - "[%d]: Future Allgather needs reordering: ", up_rank)); + /* 2. allgather between node leaders, from tmp_buf to reorder_buf */ + if (low_rank == root_low_rank) { + /* allocate buffer to store unordered result on node leaders + * if the processes are mapped-by core, no need to reorder: + * distribution of ranks on core first and node next, + * in a increasing order for both patterns. + */ + char *reorder_buf = NULL; + char *reorder_buf_start = NULL; + if (han_module->is_mapbycore) { + reorder_buf_start = rbuf; + } else { + if (0 == low_rank && 0 == up_rank) { // first rank displays message + OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, + "[%d]: Future Allgather needs reordering: ", up_rank)); + } + ptrdiff_t rsize, rgap = 0; + rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size * up_size, &rgap); + reorder_buf = (char *) malloc(rsize); + reorder_buf_start = reorder_buf - rgap; } - ptrdiff_t rsize, rgap = 0; - rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size * up_size, &rgap); - reorder_buf = (char *) malloc(rsize); - reorder_buf_start = reorder_buf - rgap; - } - /* 2a. inter node allgather */ - up_comm->c_coll->coll_allgather(tmp_buf_start, scount*low_size, sdtype, - reorder_buf_start, rcount*low_size, rdtype, - up_comm, up_comm->c_coll->coll_allgather_module); + /* 2a. inter node allgather */ + up_comm->c_coll->coll_allgather(tmp_buf_start, scount*low_size, sdtype, + reorder_buf_start, rcount*low_size, rdtype, + up_comm, up_comm->c_coll->coll_allgather_module); + + if (tmp_buf != NULL) { + free(tmp_buf); + tmp_buf = NULL; + tmp_buf_start = NULL; + } + + /* 2b. reorder the node leader's into rbuf. + * if ranks are not mapped in topological order, data needs to be reordered + * (see reorder_gather) + */ + if (!han_module->is_mapbycore) { + ompi_coll_han_reorder_gather(reorder_buf_start, + rbuf, rcount, rdtype, + comm, topo); + free(reorder_buf); + reorder_buf = NULL; + } - if (tmp_buf != NULL) { - free(tmp_buf); - tmp_buf = NULL; - tmp_buf_start = NULL; } - /* 2b. reorder the node leader's into rbuf. - * if ranks are not mapped in topological order, data needs to be reordered - * (see reorder_gather) + /* 3. up broadcast: leaders broadcast on their nodes */ + low_comm->c_coll->coll_bcast(rbuf, rcount*low_size*up_size, rdtype, + root_low_rank, low_comm, + low_comm->c_coll->coll_bcast_module); + + } else { + /* + * Freelist path: uses pre-allocated buffers and mapbycore/pipeline + * optimizations for large messages. */ - if (!han_module->is_mapbycore) { - ompi_coll_han_reorder_gather(reorder_buf_start, - rbuf, rcount, rdtype, - comm, topo); - free(reorder_buf); - reorder_buf = NULL; - } + ptrdiff_t rextent; + size_t frag_count; + size_t num_frags; + size_t max_elems; - } + ompi_datatype_type_extent(rdtype, &rextent); - /* 3. up broadcast: leaders broadcast on their nodes */ - low_comm->c_coll->coll_bcast(rbuf, rcount*low_size*up_size, rdtype, - root_low_rank, low_comm, - low_comm->c_coll->coll_bcast_module); + if (MPI_IN_PLACE == sbuf) { + scount = rcount; + sdtype = rdtype; + } + + /* Compute per-fragment element count */ + frag_count = rcount; + if (frag_size > 0 && rextent > 0) { + max_elems = frag_size / ((size_t)low_size * (size_t)rextent); + if (max_elems < 1) max_elems = 1; + if (max_elems < rcount) frag_count = max_elems; + } + num_frags = (rcount + frag_count - 1) / frag_count; + if (han_module->is_mapbycore) { + return han_allgather_mapbycore(sbuf, scount, sdtype, rbuf, rcount, + rdtype, up_comm, low_comm, w_rank, low_rank, up_rank, + low_size, up_size, root_low_rank); + } else if (num_frags == 1) { + return han_allgather_single_frag(sbuf, scount, sdtype, rbuf, rcount, + rdtype, han_module, up_comm, low_comm, comm, + w_rank, low_rank, up_rank, low_size, up_size, + root_low_rank, frag_size, topo); + } else { + return han_allgather_pipeline(sbuf, scount, sdtype, rbuf, rcount, + rdtype, han_module, up_comm, low_comm, + w_rank, low_rank, low_size, up_size, + root_low_rank, frag_size, frag_count, num_frags, topo); + } + } return OMPI_SUCCESS; -} +} \ No newline at end of file From 63d76d75f0b53337bcfef44b7ef8fe7bfd9921d6 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Mon, 23 Mar 2026 13:07:40 -0700 Subject: [PATCH 012/230] perf(han): Add persistent buffers for scatter, gather, and reduce Replace malloc/free on inter-node buffers with persistent realloc-to-HWM allocation in scatter, gather, and reduce collectives. Scatter: tiered allocation (persist realloc > large freelist > small freelist > malloc) for both inter-node and reorder buffers. Gather: persist realloc-to-HWM for root reorder and intra-node buffers. Reduce: freelist in simple path, persist realloc in task path. Removes 2-node pipeline from simple reduce for correctness. All persist paths gated on coll_han_use_persist_buffers MCA param. OSU results (baseline vs optimized): Graviton c7g 32ppn: scatter 3.1x, gather 1.3x, reduce 8.0x p5en 32ppn: scatter 6.3x, gather 1.3x, reduce 3.6x Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 21 +++ ompi/mca/coll/han/coll_han_gather.c | 90 ++++++++--- ompi/mca/coll/han/coll_han_module.c | 32 ++++ ompi/mca/coll/han/coll_han_reduce.c | 52 ++++-- ompi/mca/coll/han/coll_han_scatter.c | 231 +++++++++++++++++++++------ 5 files changed, 343 insertions(+), 83 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index 83721fabe50..c6d6f03e9cc 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -152,6 +152,7 @@ struct mca_coll_han_scatter_args_s { ompi_communicator_t *up_comm; ompi_communicator_t *low_comm; ompi_request_t *req; + mca_coll_han_module_t *han_module; void *sbuf; void *sbuf_inter_free; void *sbuf_reorder_free; @@ -165,6 +166,10 @@ struct mca_coll_han_scatter_args_s { int root_low_rank; int w_rank; bool noop; + opal_free_list_item_t *inter_fl_item; /* freelist item for inter-node buf */ + int inter_fl_src; /* HAN_ALLOC_{MALLOC,LARGE,SMALL} */ + opal_free_list_item_t *reorder_fl_item; /* freelist item for reorder buf */ + int reorder_fl_src; /* HAN_ALLOC_{MALLOC,LARGE,SMALL} */ }; typedef struct mca_coll_han_scatter_args_s mca_coll_han_scatter_args_t; @@ -173,6 +178,7 @@ struct mca_coll_han_gather_args_s { ompi_communicator_t *up_comm; ompi_communicator_t *low_comm; ompi_request_t *req; + mca_coll_han_module_t *han_module; void *sbuf; void *sbuf_inter_free; void *rbuf; @@ -437,6 +443,21 @@ typedef struct mca_coll_han_module_t { opal_free_list_t fragment_freelist; /* Large fragment pool for pipeline reorder buffers (1MB items) */ opal_free_list_t large_fragment_freelist; + /* Cached gather buffer for three-tier allocation */ + void *cached_gather_buf; + size_t cached_gather_buf_size; + /* Persistent buffer for scatter inter-node recv (realloc-to-HWM) */ + char *scatter_persist; + size_t scatter_persist_size; + /* Persistent scatter root reorder buffer (realloc-to-HWM) */ + char *scatter_reorder_persist; + size_t scatter_reorder_persist_size; + /* Persistent gather root reorder buffer (realloc-to-HWM) */ + char *gather_reorder_persist; + size_t gather_reorder_persist_size; + /* Persistent reduce task-based tmp buffer (realloc-to-HWM) */ + char *reduce_tmp_persist; + size_t reduce_tmp_persist_size; } mca_coll_han_module_t; OBJ_CLASS_DECLARATION(mca_coll_han_module_t); diff --git a/ompi/mca/coll/han/coll_han_gather.c b/ompi/mca/coll/han/coll_han_gather.c index e3259267b9a..8af7d72d510 100644 --- a/ompi/mca/coll/han/coll_han_gather.c +++ b/ompi/mca/coll/han/coll_han_gather.c @@ -46,7 +46,8 @@ mca_coll_han_set_gather_args(mca_coll_han_gather_args_t * args, int root_low_rank, struct ompi_communicator_t *up_comm, struct ompi_communicator_t *low_comm, - int w_rank, bool noop, bool is_mapbycore, ompi_request_t * req) + int w_rank, bool noop, bool is_mapbycore, ompi_request_t * req, + mca_coll_han_module_t *han_module) { args->cur_task = cur_task; args->sbuf = sbuf; @@ -65,6 +66,7 @@ mca_coll_han_set_gather_args(mca_coll_han_gather_args_t * args, args->noop = noop; args->is_mapbycore = is_mapbycore; args->req = req; + args->han_module = han_module; } @@ -156,7 +158,18 @@ mca_coll_han_gather_intra(const void *sbuf, size_t scount, rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * w_size, &rgap); - reorder_buf = (char *)malloc(rsize); //TODO:free + if (mca_coll_han_component.han_use_persist_buffers) { + if (han_module->gather_reorder_persist_size < (size_t)rsize) { + char *p = realloc(han_module->gather_reorder_persist, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + han_module->gather_reorder_persist = p; + han_module->gather_reorder_persist_size = rsize; + } + reorder_buf = han_module->gather_reorder_persist; + } else { + reorder_buf = (char *)malloc(rsize); + if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } /* rgap is the size of unused space at the start of the datatype */ reorder_rbuf = reorder_buf - rgap; @@ -180,7 +193,8 @@ mca_coll_han_gather_intra(const void *sbuf, size_t scount, mca_coll_han_gather_args_t *lg_args = malloc(sizeof(mca_coll_han_gather_args_t)); mca_coll_han_set_gather_args(lg_args, lg, (char *) sbuf, NULL, scount, sdtype, reorder_rbuf, rcount, rdtype, root, root_up_rank, root_low_rank, up_comm, - low_comm, w_rank, low_rank != root_low_rank, han_module->is_mapbycore, temp_request); + low_comm, w_rank, low_rank != root_low_rank, han_module->is_mapbycore, temp_request, + han_module); /* Init lg task */ init_task(lg, mca_coll_han_gather_lg_task, (void *) (lg_args)); /* Issure lg task */ @@ -193,7 +207,9 @@ mca_coll_han_gather_intra(const void *sbuf, size_t scount, ompi_coll_han_reorder_gather(reorder_buf, rbuf, rcount, rdtype, comm, topo); - free(reorder_buf); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(reorder_buf); + } } return OMPI_SUCCESS; @@ -212,15 +228,25 @@ int mca_coll_han_gather_lg_task(void *task_args) char *tmp_buf = NULL; char *tmp_rbuf = NULL; if (!t->noop) { - /* if the process is one of the node leader, allocate the intermediary - * buffer to gather on the low sub communicator */ + /* Intra-node gather buffer: persistent realloc-to-HWM or malloc */ int low_size = ompi_comm_size(t->low_comm); int low_rank = ompi_comm_rank(t->low_comm); ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&dtype->super, count * low_size, &rgap); - tmp_buf = (char *) malloc(rsize); + if (mca_coll_han_component.han_use_persist_buffers) { + if (t->han_module->cached_gather_buf_size < (size_t)rsize) { + char *p = realloc(t->han_module->cached_gather_buf, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + t->han_module->cached_gather_buf = p; + t->han_module->cached_gather_buf_size = rsize; + } + tmp_buf = (char *)t->han_module->cached_gather_buf; + } else { + tmp_buf = (char *)malloc(rsize); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } tmp_rbuf = tmp_buf - rgap; if (t->w_rank == t->root && MPI_IN_PLACE == t->sbuf) { ptrdiff_t rextent; @@ -286,9 +312,12 @@ int mca_coll_han_gather_ug_task(void *task_args) t->up_comm, t->up_comm->c_coll->coll_gather_module); - if (t->sbuf_inter_free != NULL) { - free(t->sbuf_inter_free); - t->sbuf_inter_free = NULL; + /* Free intra-node buffer when not using persist buffers */ + if (!mca_coll_han_component.han_use_persist_buffers) { + if (t->sbuf_inter_free != NULL) { + free(t->sbuf_inter_free); + t->sbuf_inter_free = NULL; + } } OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Gather: ug gather finish\n", t->w_rank)); @@ -371,23 +400,44 @@ mca_coll_han_gather_intra_simple(const void *sbuf, size_t scount, ptrdiff_t rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * w_size, &rgap); - reorder_buf = (char *)malloc(rsize); + if (mca_coll_han_component.han_use_persist_buffers) { + if (han_module->gather_reorder_persist_size < (size_t)rsize) { + char *p = realloc(han_module->gather_reorder_persist, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + han_module->gather_reorder_persist = p; + han_module->gather_reorder_persist_size = rsize; + } + reorder_buf = han_module->gather_reorder_persist; + } else { + reorder_buf = (char *)malloc(rsize); + if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } /* rgap is the size of unused space at the start of the datatype */ reorder_buf_start = reorder_buf - rgap; } } - /* allocate the intermediary buffer - * to gather on leaders on the low sub communicator */ - char *tmp_buf = NULL; // allocated memory - char *tmp_buf_start = NULL; // start of the data + /* Intra-node gather buffer: persistent realloc-to-HWM or malloc */ + char *tmp_buf = NULL; + char *tmp_buf_start = NULL; if (low_rank == root_low_rank) { ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&dtype->super, count * low_size, &rgap); - tmp_buf = (char *) malloc(rsize); + if (mca_coll_han_component.han_use_persist_buffers) { + if (han_module->cached_gather_buf_size < (size_t)rsize) { + char *p = realloc(han_module->cached_gather_buf, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + han_module->cached_gather_buf = p; + han_module->cached_gather_buf_size = rsize; + } + tmp_buf = (char *)han_module->cached_gather_buf; + } else { + tmp_buf = (char *)malloc(rsize); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } tmp_buf_start = tmp_buf - rgap; } @@ -414,10 +464,10 @@ mca_coll_han_gather_intra_simple(const void *sbuf, size_t scount, up_comm, up_comm->c_coll->coll_gather_module); - if (tmp_buf != NULL) { + /* Free intra-node buffer when not using persist buffers */ + if (!mca_coll_han_component.han_use_persist_buffers) { free(tmp_buf); tmp_buf = NULL; - tmp_buf_start = NULL; } OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Future Gather: ug gather finish\n", w_rank)); @@ -431,7 +481,9 @@ mca_coll_han_gather_intra_simple(const void *sbuf, size_t scount, ompi_coll_han_reorder_gather(reorder_buf_start, rbuf, rcount, rdtype, comm, topo); - free(reorder_buf); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(reorder_buf); + } } return OMPI_SUCCESS; diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index 0de7c987870..782c4cd1d8a 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -187,6 +187,16 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) module->cached_up_comms = NULL; module->cached_vranks = NULL; module->cached_topo = NULL; + module->cached_gather_buf = NULL; + module->cached_gather_buf_size = 0; + module->scatter_persist = NULL; + module->scatter_persist_size = 0; + module->scatter_reorder_persist = NULL; + module->scatter_reorder_persist_size = 0; + module->gather_reorder_persist = NULL; + module->gather_reorder_persist_size = 0; + module->reduce_tmp_persist = NULL; + module->reduce_tmp_persist_size = 0; module->is_mapbycore = false; module->storage_initialized = false; for( i = 0; i < NB_TOPO_LVL; i++ ) { @@ -247,6 +257,28 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) free(module->cached_topo); module->cached_topo = NULL; } + if (module->cached_gather_buf != NULL) { + free(module->cached_gather_buf); + module->cached_gather_buf = NULL; + module->cached_gather_buf_size = 0; + } + + free(module->scatter_persist); + module->scatter_persist = NULL; + module->scatter_persist_size = 0; + + free(module->scatter_reorder_persist); + module->scatter_reorder_persist = NULL; + module->scatter_reorder_persist_size = 0; + + free(module->gather_reorder_persist); + module->gather_reorder_persist = NULL; + module->gather_reorder_persist_size = 0; + + free(module->reduce_tmp_persist); + module->reduce_tmp_persist = NULL; + module->reduce_tmp_persist_size = 0; + for(i=0 ; isub_comm[i]) { ompi_comm_free(&(module->sub_comm[i])); diff --git a/ompi/mca/coll/han/coll_han_reduce.c b/ompi/mca/coll/han/coll_han_reduce.c index 097da6e7662..40e038fcd02 100644 --- a/ompi/mca/coll/han/coll_han_reduce.c +++ b/ompi/mca/coll/han/coll_han_reduce.c @@ -143,17 +143,16 @@ mca_coll_han_reduce_intra(const void *sbuf, /* node leaders require a buffer to store intermediate results */ void *tmp_rbuf = NULL; - void *tmp_rbuf_to_free = NULL; + bool is_tmp_rbuf = false; if (w_rank == root) { /* the global root already has one */ tmp_rbuf = rbuf; } else if (low_rank == root_low_rank) { /* allocate 2 temporary segments on node leaders that are not the global root */ - tmp_rbuf = malloc(2*extent*seg_count); - if (NULL == tmp_rbuf) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - tmp_rbuf_to_free = tmp_rbuf; + size_t needed = 2*extent*seg_count; + tmp_rbuf = malloc(needed); + if (NULL == tmp_rbuf) return OMPI_ERR_OUT_OF_RESOURCE; + is_tmp_rbuf = true; } /* Create t0 tasks for the first segment */ @@ -163,7 +162,7 @@ mca_coll_han_reduce_intra(const void *sbuf, mca_coll_han_set_reduce_args(t, t0, (char *) sbuf, (char *) tmp_rbuf, seg_count, dtype, op, root_up_rank, root_low_rank, up_comm, low_comm, num_segments, 0, w_rank, count - (num_segments - 1) * seg_count, - low_rank != root_low_rank, (NULL != tmp_rbuf_to_free)); + low_rank != root_low_rank, is_tmp_rbuf); /* Init the first task */ init_task(t0, mca_coll_han_reduce_t0_task, (void *) t); issue_task(t0); @@ -195,7 +194,9 @@ mca_coll_han_reduce_intra(const void *sbuf, } free(t); - free(tmp_rbuf_to_free); + if (is_tmp_rbuf) { + free(tmp_rbuf); + } return OMPI_SUCCESS; @@ -296,7 +297,8 @@ mca_coll_han_reduce_intra_simple(const void *sbuf, int ret; int *vranks, low_rank, low_size; ptrdiff_t rsize, rgap = 0; - void * tmp_buf; + void * tmp_buf = NULL; + opal_free_list_item_t *tmp_fl_item = NULL; mca_coll_han_module_t *han_module = (mca_coll_han_module_t *)module; @@ -345,11 +347,25 @@ mca_coll_han_reduce_intra_simple(const void *sbuf, /* Get root ranks for low and up comms */ mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank); + /* Freelist-backed simple reduce: low_comm reduce → up_comm reduce */ if (root_low_rank == low_rank && w_rank != root) { rsize = opal_datatype_span(&dtype->super, (int64_t)count, &rgap); - tmp_buf = malloc(rsize); - if (NULL == tmp_buf) { - return OMPI_ERROR; + if (mca_coll_han_component.han_use_persist_buffers) { + size_t frag_size = mca_coll_han_component.han_fragment_size; + if (frag_size > 0 && (size_t)rsize <= frag_size) { + fragment_item_t *fi = (fragment_item_t*)opal_free_list_get( + &han_module->fragment_freelist); + if (fi != NULL) { + tmp_buf = (char *)fi->buffer; + tmp_fl_item = (opal_free_list_item_t*)fi; + } + } + } + if (tmp_buf == NULL) { + tmp_buf = malloc(rsize); + if (NULL == tmp_buf) { + return OMPI_ERROR; + } } } else { /* global root rbuf is valid, local non-root do not need buffers */ @@ -364,7 +380,11 @@ mca_coll_han_reduce_intra_simple(const void *sbuf, low_comm, low_comm->c_coll->coll_reduce_module); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)){ if (root_low_rank == low_rank && w_rank != root){ - free(tmp_buf); + if (tmp_fl_item != NULL) { + opal_free_list_return(&han_module->fragment_freelist, tmp_fl_item); + } else { + free(tmp_buf); + } } OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "HAN/REDUCE: low comm reduce failed. " @@ -378,7 +398,11 @@ mca_coll_han_reduce_intra_simple(const void *sbuf, ret = up_comm->c_coll->coll_reduce((char *)tmp_buf, NULL, count, dtype, op, root_up_rank, up_comm, up_comm->c_coll->coll_reduce_module); - free(tmp_buf); + if (tmp_fl_item != NULL) { + opal_free_list_return(&han_module->fragment_freelist, tmp_fl_item); + } else { + free(tmp_buf); + } } else { /* Take advantage of any optimisation made for IN_PLACE * communications */ diff --git a/ompi/mca/coll/han/coll_han_scatter.c b/ompi/mca/coll/han/coll_han_scatter.c index 2122103a5dd..7a847379dd4 100644 --- a/ompi/mca/coll/han/coll_han_scatter.c +++ b/ompi/mca/coll/han/coll_han_scatter.c @@ -4,6 +4,8 @@ * reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Amazon.com, Inc. or its affiliates. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,6 +28,51 @@ static int mca_coll_han_scatter_us_task(void *task_args); static int mca_coll_han_scatter_ls_task(void *task_args); +/** + * Allocate from tiered freelists (large then small), falling back to malloc. + */ +static char *scatter_alloc_tiered(opal_free_list_t *large_fl, size_t large_size, + opal_free_list_t *small_fl, size_t small_size, + size_t needed, opal_free_list_item_t **item, + int *src) +{ + *item = NULL; + *src = HAN_ALLOC_MALLOC; + if (large_size > 0 && needed <= large_size) { + large_fragment_item_t *lfi = (large_fragment_item_t *)opal_free_list_get(large_fl); + if (lfi != NULL) { + *item = (opal_free_list_item_t *)lfi; + *src = HAN_ALLOC_LARGE; + return (char *)lfi->buffer; + } + } + if (small_size > 0 && needed <= small_size) { + fragment_item_t *fi = (fragment_item_t *)opal_free_list_get(small_fl); + if (fi != NULL) { + *item = (opal_free_list_item_t *)fi; + *src = HAN_ALLOC_SMALL; + return (char *)fi->buffer; + } + } + return (char *)malloc(needed); +} + +/** + * Free a tiered allocation based on src tag. + */ +static void scatter_free_tiered(opal_free_list_t *large_fl, + opal_free_list_t *small_fl, + opal_free_list_item_t *item, char *buf, int src) +{ + if (src == HAN_ALLOC_LARGE) { + opal_free_list_return(large_fl, item); + } else if (src == HAN_ALLOC_SMALL) { + opal_free_list_return(small_fl, item); + } else { + free(buf); + } +} + /* Only work with regular situation (each node has equal number of processes) */ static inline void @@ -44,7 +91,8 @@ mca_coll_han_set_scatter_args(mca_coll_han_scatter_args_t * args, int root_low_rank, struct ompi_communicator_t *up_comm, struct ompi_communicator_t *low_comm, - int w_rank, bool noop, ompi_request_t * req) + int w_rank, bool noop, ompi_request_t * req, + mca_coll_han_module_t *han_module) { args->cur_task = cur_task; args->sbuf = sbuf; @@ -63,6 +111,11 @@ mca_coll_han_set_scatter_args(mca_coll_han_scatter_args_t * args, args->w_rank = w_rank; args->noop = noop; args->req = req; + args->han_module = han_module; + args->inter_fl_item = NULL; + args->inter_fl_src = HAN_ALLOC_MALLOC; + args->reorder_fl_item = NULL; + args->reorder_fl_src = HAN_ALLOC_MALLOC; } /* @@ -138,6 +191,8 @@ mca_coll_han_scatter_intra(const void *sbuf, size_t scount, */ char *reorder_buf = NULL; char *reorder_sbuf = NULL; + opal_free_list_item_t *reorder_fl_item = NULL; + int reorder_fl_src = HAN_ALLOC_MALLOC; if (w_rank == root) { /* If the processes are mapped-by core, no need to reorder */ @@ -149,7 +204,16 @@ mca_coll_han_scatter_intra(const void *sbuf, size_t scount, ptrdiff_t ssize, sgap = 0, sextent; ompi_datatype_type_extent(sdtype, &sextent); ssize = opal_datatype_span(&sdtype->super, (int64_t) scount * w_size, &sgap); - reorder_buf = (char *) malloc(ssize); + if (mca_coll_han_component.han_use_persist_buffers) { + reorder_buf = scatter_alloc_tiered( + &han_module->large_fragment_freelist, + mca_coll_han_component.han_large_fragment_size, + &han_module->fragment_freelist, + mca_coll_han_component.han_fragment_size, + ssize, &reorder_fl_item, &reorder_fl_src); + } else { + reorder_buf = (char *)malloc(ssize); + } reorder_sbuf = reorder_buf - sgap; for (int i = 0; i < up_size; i++) { for (int j = 0; j < low_size; j++) { @@ -177,7 +241,9 @@ mca_coll_han_scatter_intra(const void *sbuf, size_t scount, mca_coll_han_set_scatter_args(us_args, us, reorder_sbuf, NULL, reorder_buf, scount, sdtype, (char *) rbuf, rcount, rdtype, root, root_up_rank, root_low_rank, up_comm, low_comm, w_rank, low_rank != root_low_rank, - temp_request); + temp_request, han_module); + us_args->reorder_fl_item = reorder_fl_item; + us_args->reorder_fl_src = reorder_fl_src; /* Init us task */ init_task(us, mca_coll_han_scatter_us_task, (void *) (us_args)); /* Issure us task */ @@ -209,8 +275,23 @@ int mca_coll_han_scatter_us_task(void *task_args) int low_size = ompi_comm_size(t->low_comm); ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&dtype->super, (int64_t) count * low_size, &rgap); - char *tmp_buf = (char *) malloc(rsize); + + /* Inter-node receive buffer: persistent realloc-to-HWM or malloc */ + char *tmp_buf; + if (mca_coll_han_component.han_use_persist_buffers) { + if (t->han_module->scatter_persist_size < (size_t)rsize) { + char *p = realloc(t->han_module->scatter_persist, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + t->han_module->scatter_persist = p; + t->han_module->scatter_persist_size = rsize; + } + tmp_buf = t->han_module->scatter_persist; + } else { + tmp_buf = (char *)malloc(rsize); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } char *tmp_rbuf = tmp_buf - rgap; + OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Scatter: us scatter\n", t->w_rank)); /* Inter node scatter */ @@ -223,9 +304,18 @@ int mca_coll_han_scatter_us_task(void *task_args) t->scount = count; } + /* Free reorder buffer (root only) */ if (t->sbuf_reorder_free != NULL && t->root == t->w_rank) { - free(t->sbuf_reorder_free); + if (mca_coll_han_component.han_use_persist_buffers) { + scatter_free_tiered(&t->han_module->large_fragment_freelist, + &t->han_module->fragment_freelist, + t->reorder_fl_item, t->sbuf_reorder_free, + t->reorder_fl_src); + } else { + free(t->sbuf_reorder_free); + } t->sbuf_reorder_free = NULL; + t->reorder_fl_item = NULL; } /* Create ls tasks for the current union segment */ mca_coll_task_t *ls = t->cur_task; @@ -249,9 +339,12 @@ int mca_coll_han_scatter_ls_task(void *task_args) t->rcount, t->rdtype, t->root_low_rank, t->low_comm, t->low_comm->c_coll->coll_scatter_module); - if (t->sbuf_inter_free != NULL && t->noop != true) { - free(t->sbuf_inter_free); - t->sbuf_inter_free = NULL; + /* Free inter-node buffer when not using persist buffers */ + if (!mca_coll_han_component.han_use_persist_buffers) { + if (t->sbuf_inter_free != NULL && !t->noop) { + free(t->sbuf_inter_free); + t->sbuf_inter_free = NULL; + } } OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d] Han Scatter: ls finish\n", t->w_rank)); @@ -308,7 +401,7 @@ mca_coll_han_scatter_intra_simple(const void *sbuf, size_t scount, int low_rank = ompi_comm_rank(low_comm); int low_size = ompi_comm_size(low_comm); /* Get root ranks for low and up comms */ - int root_low_rank, root_up_rank; /* root ranks for both sub-communicators */ + int root_low_rank, root_up_rank; mca_coll_han_get_ranks(vranks, root, low_size, &root_low_rank, &root_up_rank); if (w_rank == root) { @@ -323,7 +416,8 @@ mca_coll_han_scatter_intra_simple(const void *sbuf, size_t scount, * if the processes are mapped-by core, no need to reorder: * distribution of ranks on core first and node next, * in a increasing order for both patterns */ - char *reorder_buf = NULL; // allocated memory + char *reorder_buf = NULL; + bool reorder_is_sbuf = false; size_t block_size; ompi_datatype_type_size(dtype, &block_size); @@ -337,73 +431,110 @@ mca_coll_han_scatter_intra_simple(const void *sbuf, size_t scount, OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: Han scatter: no need to reorder: ", w_rank)); reorder_buf = (char *)sbuf; + reorder_is_sbuf = true; } else { /* Data must be copied, let's be efficient packing it */ OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: Han scatter: needs reordering or compacting: ", w_rank)); - reorder_buf = malloc(block_size * w_size); - if ( NULL == reorder_buf){ - return OMPI_ERROR; + size_t reorder_size = (size_t)block_size * w_size; + if (mca_coll_han_component.han_use_persist_buffers) { + if (han_module->scatter_reorder_persist_size < reorder_size) { + char *p = realloc(han_module->scatter_reorder_persist, reorder_size); + if (NULL == p) return OMPI_ERROR; + han_module->scatter_reorder_persist = p; + han_module->scatter_reorder_persist_size = reorder_size; + } + reorder_buf = han_module->scatter_reorder_persist; + } else { + reorder_buf = (char *)malloc(reorder_size); + if (NULL == reorder_buf) return OMPI_ERROR; } - /** Reorder and packing: - * Suppose, the message is 0 1 2 3 4 5 6 7 but the processes are - * mapped on 2 nodes, for example |0 2 4 6| |1 3 5 7|. The messages to - * leaders must be 0 2 4 6 and 1 3 5 7. - * So the upper scatter must send 0 2 4 6 1 3 5 7. - * In general, the topo[i*topolevel +1] must be taken. - */ ptrdiff_t extent, block_extent; ompi_datatype_type_extent(dtype, &extent); block_extent = extent * (ptrdiff_t)count; - for(int i = 0 ; i < w_size ; ++i){ - ompi_datatype_sndrcv((char*)sbuf + block_extent*topo[2*i+1], count, dtype, - reorder_buf + block_size*i, block_size, MPI_BYTE); + for (int i = 0; i < w_size; ++i) { + ompi_datatype_sndrcv((char *)sbuf + block_extent * topo[2 * i + 1], count, dtype, + reorder_buf + block_size * i, block_size, MPI_BYTE); } dtype = MPI_BYTE; count = block_size; } } - /* allocate the intermediary buffer - * to scatter from leaders on the low sub communicators */ - char *tmp_buf = NULL; // allocated memory + /* + * Persistent inter-node receive buffer. + * Grows to high-water mark via realloc so the virtual address + * stabilises after the first large call, keeping the NIC MR cache + * entry valid across iterations. + * + * When the total fits in a freelist item, use the freelist instead + * (the item address is also stable across get/return cycles). + */ + size_t tmp_total = block_size * low_size; + char *tmp_buf = NULL; + opal_free_list_item_t *tmp_fl_item = NULL; + int tmp_fl_src = HAN_ALLOC_MALLOC; + if (low_rank == root_low_rank) { - tmp_buf = (char *) malloc(block_size * low_size); - - /* 1. up scatter (internode) between node leaders */ - up_comm->c_coll->coll_scatter((char*) reorder_buf, - count * low_size, - dtype, - (char *)tmp_buf, - block_size * low_size, - MPI_BYTE, - root_up_rank, - up_comm, + if (mca_coll_han_component.han_use_persist_buffers) { + tmp_buf = scatter_alloc_tiered( + &han_module->large_fragment_freelist, + mca_coll_han_component.han_large_fragment_size, + &han_module->fragment_freelist, + mca_coll_han_component.han_fragment_size, + tmp_total, &tmp_fl_item, &tmp_fl_src); + /* If tiered alloc fell back to malloc (src==0), use persist instead */ + if (tmp_fl_src == HAN_ALLOC_MALLOC && tmp_buf != NULL) { + free(tmp_buf); + tmp_buf = NULL; + } + if (tmp_fl_src == HAN_ALLOC_MALLOC) { + if (han_module->scatter_persist_size < tmp_total) { + char *p = realloc(han_module->scatter_persist, tmp_total); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + han_module->scatter_persist = p; + han_module->scatter_persist_size = tmp_total; + } + tmp_buf = han_module->scatter_persist; + } + } else { + tmp_buf = (char *)malloc(tmp_total); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; + } + + up_comm->c_coll->coll_scatter((char *)reorder_buf, + count * low_size, dtype, + tmp_buf, + block_size * low_size, MPI_BYTE, + root_up_rank, up_comm, up_comm->c_coll->coll_scatter_module); } - /* 2. low scatter on nodes leaders */ - low_comm->c_coll->coll_scatter((char *)tmp_buf, - block_size, - MPI_BYTE, - (char*)rbuf, - rcount, - rdtype, - root_low_rank, - low_comm, + low_comm->c_coll->coll_scatter(tmp_buf, + block_size, MPI_BYTE, + (char *)rbuf, rcount, rdtype, + root_low_rank, low_comm, low_comm->c_coll->coll_scatter_module); if (low_rank == root_low_rank) { - free(tmp_buf); - tmp_buf = NULL; + if (mca_coll_han_component.han_use_persist_buffers) { + if (tmp_fl_src != HAN_ALLOC_MALLOC) { + scatter_free_tiered(&han_module->large_fragment_freelist, + &han_module->fragment_freelist, + tmp_fl_item, tmp_buf, tmp_fl_src); + } + /* persist buffer (src==0) is not freed */ + } else { + free(tmp_buf); + } } - if (reorder_buf != sbuf) { + + if (!mca_coll_han_component.han_use_persist_buffers && !reorder_is_sbuf) { free(reorder_buf); } return OMPI_SUCCESS; - } From 61049a7cdb84d087aa18cdb17b28c4f6d7293056 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Wed, 1 Apr 2026 16:04:41 -0700 Subject: [PATCH 013/230] perf(han/allgather): Persistent buffers and in-place gather for task-based path Three optimizations for the default task-based allgather: 1. Reorder buffer (uag_task, non-mapbycore): replace malloc/free with realloc-to-HWM persistent buffer on the HAN module. 2. Gather buffer (lg_task): use freelist for small messages, realloc-to-HWM persistent buffer for large messages that exceed the freelist item size. Previously the freelist fallback was always malloc, which thrashed the NIC MR cache for large messages (e.g. 32MB with 32 ppn). 3. Mapbycore in-place: when ranks are in topology order, gather directly into the correct slot of rbuf and use MPI_IN_PLACE for the inter-node allgather. This eliminates both tmp_buf and reorder_buf entirely. Benchmarks (Graviton c7g.16xlarge, 2 nodes x 32 ppn, EFA+RDMA): Mapbycore 1M-4M: 1.34-1.40x speedup Round-robin 512K-4M: 1.63-1.86x speedup No regressions at any message size. Correctness validated with OSU -c at all sizes 1KB-4MB. Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 6 ++ ompi/mca/coll/han/coll_han_allgather.c | 90 +++++++++++++++++++++++--- ompi/mca/coll/han/coll_han_module.c | 12 ++++ 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index c6d6f03e9cc..b14b5021d1c 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -455,6 +455,12 @@ typedef struct mca_coll_han_module_t { /* Persistent gather root reorder buffer (realloc-to-HWM) */ char *gather_reorder_persist; size_t gather_reorder_persist_size; + /* Persistent allgather reorder buffer for task-based path (realloc-to-HWM) */ + char *allgather_reorder_persist; + size_t allgather_reorder_persist_size; + /* Persistent allgather intra-node gather buffer (realloc-to-HWM) */ + char *allgather_gather_persist; + size_t allgather_gather_persist_size; /* Persistent reduce task-based tmp buffer (realloc-to-HWM) */ char *reduce_tmp_persist; size_t reduce_tmp_persist_size; diff --git a/ompi/mca/coll/han/coll_han_allgather.c b/ompi/mca/coll/han/coll_han_allgather.c index ce8c851247d..a0c378b2af9 100644 --- a/ompi/mca/coll/han/coll_han_allgather.c +++ b/ompi/mca/coll/han/coll_han_allgather.c @@ -239,15 +239,61 @@ int mca_coll_han_allgather_lg_task(void *task_args) if (!t->noop) { int low_size = ompi_comm_size(t->low_comm); ptrdiff_t rsize, rgap = 0; + + /* Mapbycore in-place: gather directly into rbuf slot, skip tmp_buf */ + if (t->is_mapbycore && mca_coll_han_component.han_use_persist_buffers) { + int up_rank = ompi_comm_rank(t->up_comm); + size_t total_count = t->rcount * low_size; + char *my_slot = (char *)t->rbuf + + (ptrdiff_t)up_rank * (ptrdiff_t)total_count * rext; + + if (MPI_IN_PLACE == t->sbuf) { + char *my_data = ((char*)t->rbuf) + + (ptrdiff_t)t->w_rank * (ptrdiff_t)t->rcount * rext; + ompi_datatype_copy_content_same_ddt(t->rdtype, t->rcount, + my_slot, my_data); + t->low_comm->c_coll->coll_gather(MPI_IN_PLACE, t->scount, t->sdtype, + my_slot, t->rcount, t->rdtype, + t->root_low_rank, t->low_comm, + t->low_comm->c_coll->coll_gather_module); + } else { + t->low_comm->c_coll->coll_gather((char *)t->sbuf, t->scount, t->sdtype, + my_slot, t->rcount, t->rdtype, + t->root_low_rank, t->low_comm, + t->low_comm->c_coll->coll_gather_module); + } + t->sbuf = my_slot; + t->sbuf_inter_free = NULL; + t->inter_frag = NULL; + + /* Create uag task */ + mca_coll_task_t *uag = t->cur_task; + init_task(uag, mca_coll_han_allgather_uag_task, (void *) t); + issue_task(uag); + return OMPI_SUCCESS; + } + rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size, &rgap); t->inter_frag = NULL; - if (mca_coll_han_component.han_fragment_size == 0 || t->han_module == NULL) { - tmp_buf = (char *) malloc(rsize); + if (mca_coll_han_component.han_use_persist_buffers && t->han_module != NULL) { + if ((size_t)rsize <= mca_coll_han_component.han_fragment_size + && mca_coll_han_component.han_fragment_size > 0) { + tmp_buf = han_alloc_frag(&t->han_module->fragment_freelist, + mca_coll_han_component.han_fragment_size, + (size_t)rsize, &t->inter_frag); + } else { + /* Too large for freelist — use realloc-to-HWM persist buffer */ + if (t->han_module->allgather_gather_persist_size < (size_t)rsize) { + char *p = realloc(t->han_module->allgather_gather_persist, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + t->han_module->allgather_gather_persist = p; + t->han_module->allgather_gather_persist_size = rsize; + } + tmp_buf = t->han_module->allgather_gather_persist; + } } else { - tmp_buf = han_alloc_frag(&t->han_module->fragment_freelist, - mca_coll_han_component.han_fragment_size, - (size_t)rsize, &t->inter_frag); + tmp_buf = (char *) malloc(rsize); } tmp_rbuf = tmp_buf - rgap; @@ -278,6 +324,12 @@ int mca_coll_han_allgather_lg_task(void *task_args) t->sbuf = tmp_rbuf; t->sbuf_inter_free = tmp_buf; + /* When using persist gather buffer, don't free it in uag_task */ + if (mca_coll_han_component.han_use_persist_buffers + && t->inter_frag == NULL && t->han_module != NULL + && tmp_buf == t->han_module->allgather_gather_persist) { + t->sbuf_inter_free = NULL; + } /* Create uag (upper level all-gather) task */ mca_coll_task_t *uag = t->cur_task; @@ -305,13 +357,33 @@ int mca_coll_han_allgather_uag_task(void *task_args) OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, "[%d]: HAN Allgather is bycore: ", t->w_rank)); reorder_rbuf = (char *) t->rbuf; + + /* When persist buffers gathered directly into rbuf, use in-place */ + if (mca_coll_han_component.han_use_persist_buffers + && t->sbuf_inter_free == NULL) { + t->up_comm->c_coll->coll_allgather(MPI_IN_PLACE, + t->scount * low_size, t->sdtype, + reorder_rbuf, t->rcount * low_size, t->rdtype, + t->up_comm, t->up_comm->c_coll->coll_allgather_module); + goto allgather_done; + } } else { ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&t->rdtype->super, (int64_t) t->rcount * low_size * up_size, &rgap); - reorder_buf = (char *) malloc(rsize); + if (mca_coll_han_component.han_use_persist_buffers && t->han_module != NULL) { + if (t->han_module->allgather_reorder_persist_size < (size_t)rsize) { + char *p = realloc(t->han_module->allgather_reorder_persist, rsize); + if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; + t->han_module->allgather_reorder_persist = p; + t->han_module->allgather_reorder_persist_size = rsize; + } + reorder_buf = t->han_module->allgather_reorder_persist; + } else { + reorder_buf = (char *) malloc(rsize); + } reorder_rbuf = reorder_buf - rgap; } @@ -353,12 +425,14 @@ int mca_coll_han_allgather_uag_task(void *task_args) (ptrdiff_t) t->rcount); } } - free(reorder_buf); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(reorder_buf); + } reorder_buf = NULL; } } - +allgather_done: /* Create lb (low level broadcast) task */ mca_coll_task_t *lb = t->cur_task; /* Init and issue lb task */ diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index 782c4cd1d8a..d366eca4c70 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -197,6 +197,10 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) module->gather_reorder_persist_size = 0; module->reduce_tmp_persist = NULL; module->reduce_tmp_persist_size = 0; + module->allgather_reorder_persist = NULL; + module->allgather_reorder_persist_size = 0; + module->allgather_gather_persist = NULL; + module->allgather_gather_persist_size = 0; module->is_mapbycore = false; module->storage_initialized = false; for( i = 0; i < NB_TOPO_LVL; i++ ) { @@ -279,6 +283,14 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) module->reduce_tmp_persist = NULL; module->reduce_tmp_persist_size = 0; + free(module->allgather_reorder_persist); + module->allgather_reorder_persist = NULL; + module->allgather_reorder_persist_size = 0; + + free(module->allgather_gather_persist); + module->allgather_gather_persist = NULL; + module->allgather_gather_persist_size = 0; + for(i=0 ; isub_comm[i]) { ompi_comm_free(&(module->sub_comm[i])); From 6ec3b937ab45fa496bb412bd8d0a91b1b52d5990 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Mon, 6 Apr 2026 13:23:07 -0700 Subject: [PATCH 014/230] We can't have OPAL cleanups in modules Modules are unloaded before the cleanup sequence triggers, and then the cleanup will call function pointers from unloaded objects. Signed-off-by: George Bosilca --- opal/mca/btl/uct/btl_uct_component.c | 33 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/opal/mca/btl/uct/btl_uct_component.c b/opal/mca/btl/uct/btl_uct_component.c index 7c5999facad..ef00b84b478 100644 --- a/opal/mca/btl/uct/btl_uct_component.c +++ b/opal/mca/btl/uct/btl_uct_component.c @@ -146,23 +146,6 @@ static int mca_btl_uct_component_register(void) MCA_BASE_VAR_TYPE_UNSIGNED_INT, NULL, 0, MCA_BASE_VAR_FLAG_SETTABLE, OPAL_INFO_LVL_4, MCA_BASE_VAR_SCOPE_LOCAL, &mca_btl_uct_component.connection_retry_timeout); - OBJ_CONSTRUCT(&mca_btl_uct_component.md_list, opal_list_t); - OBJ_CONSTRUCT(&mca_btl_uct_component.memory_domain_list, mca_btl_uct_include_list_t); - OBJ_CONSTRUCT(&mca_btl_uct_component.connection_domain_list, mca_btl_uct_include_list_t); - - int rc = mca_btl_uct_component_discover_mds(); - if (OPAL_SUCCESS != rc) { - return rc; - } - - rc = mca_btl_uct_component_generate_modules(&mca_btl_uct_component.md_list); - if (OPAL_SUCCESS != rc) { - return rc; - } - - mca_btl_uct_component.initialized = true; - opal_finalize_register_cleanup(mca_btl_uct_cleanup); - return OPAL_SUCCESS; } @@ -206,6 +189,22 @@ static int mca_btl_uct_component_open(void) opal_mem_hooks_register_release(mca_btl_uct_mem_release_cb, NULL); } + OBJ_CONSTRUCT(&mca_btl_uct_component.md_list, opal_list_t); + OBJ_CONSTRUCT(&mca_btl_uct_component.memory_domain_list, mca_btl_uct_include_list_t); + OBJ_CONSTRUCT(&mca_btl_uct_component.connection_domain_list, mca_btl_uct_include_list_t); + + int rc = mca_btl_uct_component_discover_mds(); + if (OPAL_SUCCESS != rc) { + return rc; + } + + rc = mca_btl_uct_component_generate_modules(&mca_btl_uct_component.md_list); + if (OPAL_SUCCESS != rc) { + return rc; + } + + mca_btl_uct_component.initialized = true; + return OPAL_SUCCESS; } From 818a7baab634e41f250392a42833bc622937a8d1 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Mon, 6 Apr 2026 13:23:27 -0700 Subject: [PATCH 015/230] Update the datatype tests to call opal_finalize In 98f3af0bf4c the datatype tests have been changed to call `opal_init` instead of `opal_util_init` in order to enable the newly added accelerator framework. This mean we now have a full initialization of OPAL, and that must be matched by a full finalize of OPAL and not by a `opal_util_finalize` (as it is the case in the current tests). Signed-off-by: George Bosilca --- test/datatype/checksum.c | 2 +- test/datatype/ddt_pack.c | 2 +- test/datatype/ddt_raw.c | 2 +- test/datatype/ddt_test.c | 2 +- test/datatype/external32.c | 2 +- test/datatype/opal_datatype_test.c | 2 +- test/datatype/partial.c | 2 +- test/datatype/position.c | 2 +- test/datatype/position_noncontig.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/datatype/checksum.c b/test/datatype/checksum.c index 39c47c2f730..cc1d3eaf0a2 100644 --- a/test/datatype/checksum.c +++ b/test/datatype/checksum.c @@ -151,7 +151,7 @@ int main(int argc, char *argv[]) free(packed); /* clean-ups all data allocations */ - opal_finalize_util(); + opal_finalize(); return 0; } diff --git a/test/datatype/ddt_pack.c b/test/datatype/ddt_pack.c index bdb6bc462ea..fc35d57992e 100644 --- a/test/datatype/ddt_pack.c +++ b/test/datatype/ddt_pack.c @@ -500,7 +500,7 @@ int main(int argc, char *argv[]) ompi_datatype_destroy(&dup_type); cleanup: - opal_finalize_util(); + opal_finalize(); return ret; } diff --git a/test/datatype/ddt_raw.c b/test/datatype/ddt_raw.c index f4847be3b2b..ccb1e35b13d 100644 --- a/test/datatype/ddt_raw.c +++ b/test/datatype/ddt_raw.c @@ -342,7 +342,7 @@ int main(int argc, char *argv[]) assert(pdt1 == NULL); /* clean-ups all data allocations */ - opal_finalize_util(); + opal_finalize(); return OMPI_SUCCESS; } diff --git a/test/datatype/ddt_test.c b/test/datatype/ddt_test.c index d8c879e3cfc..5f440a454f6 100644 --- a/test/datatype/ddt_test.c +++ b/test/datatype/ddt_test.c @@ -579,7 +579,7 @@ int main(int argc, char *argv[]) assert(pdt2 == NULL); /* clean-ups all data allocations */ - opal_finalize_util(); + opal_finalize(); return OMPI_SUCCESS; } diff --git a/test/datatype/external32.c b/test/datatype/external32.c index 9ef83afac57..12d773b3c0a 100644 --- a/test/datatype/external32.c +++ b/test/datatype/external32.c @@ -260,7 +260,7 @@ int main(int argc, char *argv[]) } } - opal_finalize_util(); + opal_finalize(); return 0; } diff --git a/test/datatype/opal_datatype_test.c b/test/datatype/opal_datatype_test.c index 06f3dd12695..bc30d4bb377 100644 --- a/test/datatype/opal_datatype_test.c +++ b/test/datatype/opal_datatype_test.c @@ -805,7 +805,7 @@ int main(int argc, char *argv[]) assert(pdt2 == NULL); /* clean-ups all data allocations */ - opal_finalize_util(); + opal_finalize(); return OPAL_SUCCESS; } diff --git a/test/datatype/partial.c b/test/datatype/partial.c index 9721bf5388a..1efa1e2438b 100644 --- a/test/datatype/partial.c +++ b/test/datatype/partial.c @@ -175,7 +175,7 @@ int main(int argc, char *argv[]) free(packed); /* clean-ups all data allocations */ - opal_finalize_util(); + opal_finalize(); return 0; } diff --git a/test/datatype/position.c b/test/datatype/position.c index bd4f2834833..777a2b32c04 100644 --- a/test/datatype/position.c +++ b/test/datatype/position.c @@ -267,7 +267,7 @@ int main(int argc, char *argv[]) } free(segments); - opal_finalize_util(); + opal_finalize(); return (0 == errors ? 0 : -1); } diff --git a/test/datatype/position_noncontig.c b/test/datatype/position_noncontig.c index 5d52dbb0243..61aa6d94b35 100644 --- a/test/datatype/position_noncontig.c +++ b/test/datatype/position_noncontig.c @@ -235,7 +235,7 @@ int main(int argc, char *argv[]) } free(segments); - opal_finalize_util(); + opal_finalize(); return (0 == errors ? 0 : -1); } From e40d601b21eea893856428829d0b37c060afa5d7 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Wed, 8 Apr 2026 10:27:19 -0400 Subject: [PATCH 016/230] Fix fix-my-copyright.pl script Improve detection of changed files in the current branch through some more elaborate git. Signed-off-by: Joseph Schuchart --- contrib/update-my-copyright.pl | 68 +++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/contrib/update-my-copyright.pl b/contrib/update-my-copyright.pl index 3ac826bfa32..1b3dd7a011f 100755 --- a/contrib/update-my-copyright.pl +++ b/contrib/update-my-copyright.pl @@ -269,6 +269,7 @@ sub quiet_print { # Returns a list of file names (relative to pwd) which git considers # to be modified. sub find_modified_files { + my %seen; my @files = (); # Number of path entries to remove from ${top}-relative paths. @@ -322,10 +323,73 @@ sub find_modified_files { my $relname = $fullname; $relname =~ s!^([^/]*/){$n_strip}!!g; - push @files, $relname - if (-f $relname); + if (-f $relname && !$seen{$relname}++) { + push @files, $relname; + } } } + # Also include files changed in commits on this branch that have not + # yet been pushed / are not in the base branch. This covers the common + # case of running the script after committing. + # + # Strategy: find a base ref whose merge-base with HEAD is not HEAD + # itself (i.e. there are actual commits on this branch). Try, in order: + # 1. The upstream tracking branch — but only if it is not the current + # branch pushed to a remote (which would give merge-base == HEAD). + # 2. origin/HEAD (the remote's default branch). + # 3. Well-known names: origin/main, origin/master, main, master. + my $head_sha = `git rev-parse HEAD 2>/dev/null`; + chomp($head_sha); + my $current_branch = `git rev-parse --abbrev-ref HEAD 2>/dev/null`; + chomp($current_branch); + + my $base_ref = ""; + my @candidates; + + # Upstream tracking branch (skip if it tracks the same branch on the remote) + my $upstream = `git rev-parse --abbrev-ref \@{upstream} 2>/dev/null`; + chomp($upstream); + if ($upstream) { + # e.g. "origin/bigcount-datatypes" tracks the same branch — skip it + my $upstream_branch = $upstream; + $upstream_branch =~ s!^[^/]+/!!; # strip "origin/" prefix + push @candidates, $upstream unless ($upstream_branch eq $current_branch); + } + + # Remote default branch and common well-known names (avoid origin/HEAD — + # it can be a stale symref pointing to the wrong branch) + push @candidates, "origin/main", "origin/master", "main", "master"; + + for my $candidate (@candidates) { + my $sha = `git rev-parse --verify $candidate 2>/dev/null`; + chomp($sha); + next unless $sha; + my $mb = `git merge-base HEAD $candidate 2>/dev/null`; + chomp($mb); + # Only useful if the merge-base is not HEAD itself + next unless ($mb && $mb ne $head_sha); + $base_ref = $candidate; + last; + } + + if ($base_ref) { + my $merge_base = `git merge-base HEAD $base_ref 2>/dev/null`; + chomp($merge_base); + quiet_print "==> Using base ref '$base_ref' (merge-base: $merge_base)\n"; + my $diff_cmd = "git diff --name-only --diff-filter=ACMR $merge_base HEAD -- ."; + quiet_print "==> Running: \"$diff_cmd\"\n"; + my @diff_files = split /\n/, `$diff_cmd`; + for my $fullname (@diff_files) { + my $relname = $fullname; + $relname =~ s!^([^/]*/){$n_strip}!!g; + if (-f $relname && !$seen{$relname}++) { + push @files, $relname; + } + } + } else { + quiet_print "==> WARNING: Could not determine base branch for branch diff\n"; + } + return @files; } From 8c2f63ddfdb9ee5abce431874ace7f2f1cc0d4f5 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Wed, 8 Apr 2026 18:34:33 -0400 Subject: [PATCH 017/230] comm: replace EXTRA_RETAIN mechanism with proper sub-communicator ownership The OMPI_COMM_EXTRA_RETAIN flag was a workaround for a finalize-time ordering problem: during MPI_Finalize, the communicator table is walked in ascending CID order, and each communicator is OBJ_RELEASE'd. If a sub-communicator (e.g., c_local_comm of an inter-communicator, or a HAN sub-communicator) had a lower CID than its parent, it would be destroyed first, leaving the parent with a dangling pointer. EXTRA_RETAIN solved this by conditionally bumping the refcount (only when the sub-comm CID was lower than the parent's), setting a flag on the communicator, and adding matching release logic in ompi_comm_free and special-case handling in the finalize loop. This made the ownership model implicit and spread across multiple files. Replace this with explicit reference-counted ownership: - In ompi_comm_set_nb(), OBJ_RETAIN c_local_comm when it is assigned to the parent inter-communicator, regardless of CID ordering. - In ompi_comm_destruct(), OBJ_RELEASE c_local_comm if the parent is an inter-communicator. This ensures proper cleanup in both the finalize path (where the destructor cascades the release) and the user path (where ompi_comm_free NULLs the field before the destructor runs). - In ompi_comm_free(), release the ownership reference on c_local_comm (OBJ_RELEASE) before calling ompi_comm_free() on it recursively. The first release undoes the ownership retain; the recursive free handles attribute cleanup and releases the creation reference. - Simplify the finalize loop in ompi_comm_finalize(): a single OBJ_RELEASE per communicator is sufficient. Sub-communicators retained by their parent survive until the parent's destructor cascades the release, regardless of CID ordering. - Remove the OMPI_COMM_EXTRA_RETAIN flag, OMPI_COMM_IS_EXTRA_RETAIN(), and OMPI_COMM_SET_EXTRA_RETAIN() from communicator.h. - Remove the conditional EXTRA_RETAIN block from ompi_comm_activate_complete() in comm_cid.c. For the HAN collective module: - Replace the HAN_SUBCOM_EXTRA_RETAIN macro (conditional OBJ_RETAIN + flag set) with unconditional OBJ_RETAIN on sub-communicators. - In the HAN module destructor, after ompi_comm_free() on each sub-communicator, use ompi_comm_lookup() to check whether the sub-comm survived (refcount > 0), and if so, OBJ_RELEASE it. This safely handles both the user path (sub-comm survives ompi_comm_free with refcount 1, lookup finds it, OBJ_RELEASE destroys it) and the finalize path (sub-comm is destroyed by ompi_comm_free, lookup returns NULL). Signed-off-by: George Bosilca --- ompi/communicator/comm.c | 36 ++++++---------------- ompi/communicator/comm_cid.c | 27 +--------------- ompi/communicator/comm_init.c | 44 +++++++++++++-------------- ompi/communicator/communicator.h | 7 +---- ompi/mca/coll/han/coll_han_module.c | 17 ++++++++++- ompi/mca/coll/han/coll_han_subcomms.c | 23 +++++--------- 6 files changed, 56 insertions(+), 98 deletions(-) diff --git a/ompi/communicator/comm.c b/ompi/communicator/comm.c index ce51aa7336a..bb08ee2b83a 100644 --- a/ompi/communicator/comm.c +++ b/ompi/communicator/comm.c @@ -28,6 +28,7 @@ * reserved. * Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved. * Copyright (c) 2025 BULL S.A.S. All rights reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -278,10 +279,14 @@ int ompi_comm_set_nb (ompi_communicator_t **ncomm, ompi_communicator_t *oldcomm, /* NTH: use internal idup function that takes a local group argument */ ompi_comm_idup_internal (old_localcomm, newcomm->c_local_group, NULL, NULL, &newcomm->c_local_comm, req); + if (NULL != newcomm->c_local_comm + && !OMPI_COMM_IS_INTRINSIC(newcomm->c_local_comm)) { + OBJ_RETAIN(newcomm->c_local_comm); + } } else { - /* take ownership of the old communicator (it must be an intracommunicator) */ assert (OMPI_COMM_IS_INTRA(oldcomm)); newcomm->c_local_comm = oldcomm; + OBJ_RETAIN(newcomm->c_local_comm); } } else { newcomm->c_remote_group = newcomm->c_local_group; @@ -2169,8 +2174,6 @@ static int ompi_comm_allgather_emulate_intra( void *inbuf, int incount, int ompi_comm_free( ompi_communicator_t **comm ) { int ret; - int cid = (*comm)->c_index; - int is_extra_retain = OMPI_COMM_IS_EXTRA_RETAIN(*comm); /* Release attributes. We do this now instead of during the communicator destructor for 2 reasons: @@ -2199,7 +2202,9 @@ int ompi_comm_free( ompi_communicator_t **comm ) } if ( OMPI_COMM_IS_INTER(*comm) ) { - if ( ! OMPI_COMM_IS_INTRINSIC((*comm)->c_local_comm)) { + if (NULL != (*comm)->c_local_comm + && ! OMPI_COMM_IS_INTRINSIC((*comm)->c_local_comm)) { + OBJ_RELEASE((*comm)->c_local_comm); ompi_comm_free (&(*comm)->c_local_comm); } } @@ -2222,29 +2227,6 @@ int ompi_comm_free( ompi_communicator_t **comm ) } OBJ_RELEASE( (*comm) ); - if ( is_extra_retain) { - /* This communicator has been marked as an "extra retain" - * communicator. This can happen if a communicator creates - * 'dependent' subcommunicators (e.g. for inter - * communicators or when using hierarch collective - * module *and* the cid of the dependent communicator - * turned out to be lower than of the parent one. - * In that case, the reference counter has been increased - * by one more, in order to handle the scenario, - * that the user did not free the communicator. - * Note, that if we enter this routine, we can - * decrease the counter by one more therefore. However, - * in ompi_comm_finalize, we only used OBJ_RELEASE instead - * of ompi_comm_free(), and the increased reference counter - * makes sure that the pointer to the dependent communicator - * still contains a valid object. - */ - ompi_communicator_t *tmpcomm = ompi_comm_lookup(cid); - if ( NULL != tmpcomm ){ - ompi_comm_free(&tmpcomm); - } - } - *comm = MPI_COMM_NULL; return OMPI_SUCCESS; } diff --git a/ompi/communicator/comm_cid.c b/ompi/communicator/comm_cid.c index ddf1657b9ab..86df2f6e48a 100644 --- a/ompi/communicator/comm_cid.c +++ b/ompi/communicator/comm_cid.c @@ -26,6 +26,7 @@ * Copyright (c) 2021 Nanook Consulting. All rights reserved. * Copyright (c) 2020-2026 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -60,8 +61,6 @@ /* for use when we don't have a PMIx that supports CID generation */ opal_atomic_int64_t ompi_comm_next_base_cid = 1; -/* A macro comparing two CIDs */ -#define OMPI_COMM_CID_IS_LOWER(comm1,comm2) ( ((comm1)->c_index < (comm2)->c_index)? 1:0) struct ompi_comm_cid_context_t; @@ -926,30 +925,6 @@ static int ompi_comm_activate_complete (ompi_comm_cid_context_t *context) return ret; } - /* For an inter communicator, we have to deal with the potential - * problem of what is happening if the local_comm that we created - * has a lower CID than the parent comm. This is not a problem - * as long as the user calls MPI_Comm_free on the inter communicator. - * However, if the communicators are not freed by the user but released - * by Open MPI in MPI_Finalize, we walk through the list of still available - * communicators and free them one by one. Thus, local_comm is freed before - * the actual inter-communicator. However, the local_comm pointer in the - * inter communicator will still contain the 'previous' address of the local_comm - * and thus this will lead to a segmentation violation. In order to prevent - * that from happening, we increase the reference counter local_comm - * by one if its CID is lower than the parent. We cannot increase however - * its reference counter if the CID of local_comm is larger than - * the CID of the inter communicators, since a regular MPI_Comm_free would - * leave in that the case the local_comm hanging around and thus we would not - * recycle CID's properly, which was the reason and the cause for this trouble. - */ - if (OMPI_COMM_IS_INTER(*newcomm)) { - if (OMPI_COMM_CID_IS_LOWER(*newcomm, comm)) { - OMPI_COMM_SET_EXTRA_RETAIN (*newcomm); - OBJ_RETAIN (*newcomm); - } - } - /* done */ return OMPI_SUCCESS; } diff --git a/ompi/communicator/comm_init.c b/ompi/communicator/comm_init.c index e348fb364d3..65f49f85e4e 100644 --- a/ompi/communicator/comm_init.c +++ b/ompi/communicator/comm_init.c @@ -26,7 +26,7 @@ * Copyright (c) 2018-2024 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. - * Copyright (c) 2023 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2023-2026 NVIDIA Corporation. All rights reserved. * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * @@ -388,31 +388,25 @@ static int ompi_comm_finalize (void) for ( i=3; ic_name); + ompi_comm_dump ( comm); + OBJ_RELEASE(comm); } } +#endif /* OPAL_ENABLE_DEBUG */ OBJ_DESTRUCT (&ompi_mpi_communicators); OBJ_DESTRUCT (&ompi_comm_hash); @@ -527,6 +521,12 @@ static void ompi_comm_destruct(ompi_communicator_t* comm) comm->c_topo = NULL; } + if (OMPI_COMM_IS_INTER(comm) && NULL != comm->c_local_comm + && !OMPI_COMM_IS_INTRINSIC(comm->c_local_comm)) { + OBJ_RELEASE(comm->c_local_comm); + comm->c_local_comm = NULL; + } + if (NULL != comm->c_local_group) { OBJ_RELEASE ( comm->c_local_group ); comm->c_local_group = NULL; diff --git a/ompi/communicator/communicator.h b/ompi/communicator/communicator.h index 914230702d5..3e0958cebc6 100644 --- a/ompi/communicator/communicator.h +++ b/ompi/communicator/communicator.h @@ -25,7 +25,7 @@ * Copyright (c) 2018-2026 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. - * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2024-2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -69,7 +69,6 @@ OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_communicator_t); #define OMPI_COMM_GRAPH 0x00000200 #define OMPI_COMM_DIST_GRAPH 0x00000400 #define OMPI_COMM_PML_ADDED 0x00001000 -#define OMPI_COMM_EXTRA_RETAIN 0x00004000 #define OMPI_COMM_MAPBY_NODE 0x00008000 #define OMPI_COMM_GLOBAL_INDEX 0x00010000 @@ -86,7 +85,6 @@ OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_communicator_t); #define OMPI_COMM_IS_DISJOINT_SET(comm) ((comm)->c_flags & OMPI_COMM_DISJOINT_SET) #define OMPI_COMM_IS_DISJOINT(comm) ((comm)->c_flags & OMPI_COMM_DISJOINT) #define OMPI_COMM_IS_PML_ADDED(comm) ((comm)->c_flags & OMPI_COMM_PML_ADDED) -#define OMPI_COMM_IS_EXTRA_RETAIN(comm) ((comm)->c_flags & OMPI_COMM_EXTRA_RETAIN) #define OMPI_COMM_IS_TOPO(comm) (OMPI_COMM_IS_CART((comm)) || \ OMPI_COMM_IS_GRAPH((comm)) || \ OMPI_COMM_IS_DIST_GRAPH((comm))) @@ -97,7 +95,6 @@ OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_communicator_t); #define OMPI_COMM_SET_INVALID(comm) ((comm)->c_flags |= OMPI_COMM_INVALID) #define OMPI_COMM_SET_PML_ADDED(comm) ((comm)->c_flags |= OMPI_COMM_PML_ADDED) -#define OMPI_COMM_SET_EXTRA_RETAIN(comm) ((comm)->c_flags |= OMPI_COMM_EXTRA_RETAIN) #define OMPI_COMM_SET_MAPBY_NODE(comm) ((comm)->c_flags |= OMPI_COMM_MAPBY_NODE) #define OMPI_COMM_ASSERT_NO_ANY_TAG 0x00000001 @@ -148,8 +145,6 @@ OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_communicator_t); */ #define OMPI_COMM_SENTINEL 0x00000001 -/* A macro comparing two CIDs */ -#define OMPI_COMM_CID_IS_LOWER(comm1,comm2) ( ((comm1)->c_index < (comm2)->c_index)? 1:0) OMPI_DECLSPEC extern opal_hash_table_t ompi_comm_hash; OMPI_DECLSPEC extern opal_pointer_array_t ompi_mpi_communicators; diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index 28338439e39..df0c91d553e 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -7,7 +7,7 @@ * Copyright (c) 2021 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved - * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2024-2026 NVIDIA Corporation. All rights reserved. * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. * $COPYRIGHT$ * @@ -116,7 +116,12 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) if (module->cached_low_comms != NULL) { for (i = 0; i < COLL_HAN_LOW_MODULES; i++) { + int cid = module->cached_low_comms[i]->c_index; ompi_comm_free(&(module->cached_low_comms[i])); + ompi_communicator_t *tmp = ompi_comm_lookup(cid); + if (NULL != tmp) { + OBJ_RELEASE(tmp); + } module->cached_low_comms[i] = NULL; } free(module->cached_low_comms); @@ -124,7 +129,12 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) } if (module->cached_up_comms != NULL) { for (i = 0; i < COLL_HAN_UP_MODULES; i++) { + int cid = module->cached_up_comms[i]->c_index; ompi_comm_free(&(module->cached_up_comms[i])); + ompi_communicator_t *tmp = ompi_comm_lookup(cid); + if (NULL != tmp) { + OBJ_RELEASE(tmp); + } module->cached_up_comms[i] = NULL; } free(module->cached_up_comms); @@ -140,7 +150,12 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) } for(i=0 ; isub_comm[i]) { + int cid = module->sub_comm[i]->c_index; ompi_comm_free(&(module->sub_comm[i])); + ompi_communicator_t *tmp = ompi_comm_lookup(cid); + if (NULL != tmp) { + OBJ_RELEASE(tmp); + } } } diff --git a/ompi/mca/coll/han/coll_han_subcomms.c b/ompi/mca/coll/han/coll_han_subcomms.c index 9fcd65dad9b..b1a99ae6e67 100644 --- a/ompi/mca/coll/han/coll_han_subcomms.c +++ b/ompi/mca/coll/han/coll_han_subcomms.c @@ -7,7 +7,7 @@ * Laboratory, ICS Forth. All rights reserved. * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2024-2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -46,15 +46,6 @@ (COMM)->c_coll->coll_##COLL##_module = (FALLBACKS).COLL.module; \ } while (0) -#define HAN_SUBCOM_EXTRA_RETAIN(COMM, PARENT_COMM) \ - do \ - { \ - if (OMPI_COMM_CID_IS_LOWER(COMM, PARENT_COMM)) { \ - OMPI_COMM_SET_EXTRA_RETAIN(COMM); \ - OBJ_RETAIN(COMM); \ - } \ - } while (0) - /* * Routine that creates the local hierarchical sub-communicators * Called each time a collective is called. @@ -216,9 +207,9 @@ int mca_coll_han_comm_create_new(struct ompi_communicator_t *comm, OBJ_DESTRUCT(&comm_info); - /* Ensure these communicators aren't released before the parent comm */ - HAN_SUBCOM_EXTRA_RETAIN(*low_comm, comm); - HAN_SUBCOM_EXTRA_RETAIN(*up_comm, comm); + /* Retain sub-communicators so they survive finalize ordering */ + OBJ_RETAIN(*low_comm); + OBJ_RETAIN(*up_comm); return OMPI_SUCCESS; @@ -390,12 +381,12 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, han_module->cached_up_comms = up_comms; han_module->cached_vranks = vranks; - /* Ensure these communicators aren't released before the parent comm */ + /* Retain sub-communicators so they survive finalize ordering */ for(int i = 0; i < COLL_HAN_LOW_MODULES; i++) { - HAN_SUBCOM_EXTRA_RETAIN(low_comms[i], comm); + OBJ_RETAIN(low_comms[i]); } for(int i = 0; i < COLL_HAN_UP_MODULES; i++) { - HAN_SUBCOM_EXTRA_RETAIN(up_comms[i], comm); + OBJ_RETAIN(up_comms[i]); } /* Reset the saved collectives to point back to HAN */ From 3900f2728bb9d66e9208d39ab295b9152c255653 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Wed, 8 Apr 2026 18:47:09 -0400 Subject: [PATCH 018/230] coll/acoll: add proper sub-communicator ownership via OBJ_RETAIN The ACOLL module creates many internal sub-communicators (local_comm, socket_comm, subgrp_comm, numa_comm, leader_comm, socket_ldr_comm, numa_comm_ldrs, local_r_comm, base_comm[][], split_comm[]) but never held ownership references on them. During MPI_Finalize, if a sub-comm has a lower CID than its parent, it could be released before the module's destructor runs, leading to use-after-free. Apply the same ownership model introduced for HAN in commit 9336f51cb2: - OBJ_RETAIN every sub-communicator immediately after creation. - Add a coll_acoll_subcomm_free() helper that saves the CID, calls ompi_comm_free (attribute cleanup + one OBJ_RELEASE), then uses ompi_comm_lookup to safely release the ownership reference. - Use this helper in both cleanup paths: the module destructor in coll_acoll_component.c and the re-initialization path in coll_acoll_utils.h. - Fix a pre-existing leak: numa_comm and numa_comm_ldrs were never freed in the module destructor; they are now. Signed-off-by: George Bosilca --- ompi/mca/coll/acoll/coll_acoll.h | 21 ++++++++++ ompi/mca/coll/acoll/coll_acoll_component.c | 47 +++++----------------- ompi/mca/coll/acoll/coll_acoll_utils.h | 27 +++++++++---- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/ompi/mca/coll/acoll/coll_acoll.h b/ompi/mca/coll/acoll/coll_acoll.h index fe1b44081e1..e5528aa62c4 100644 --- a/ompi/mca/coll/acoll/coll_acoll.h +++ b/ompi/mca/coll/acoll/coll_acoll.h @@ -1,6 +1,7 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -265,4 +266,24 @@ struct mca_coll_acoll_module_t { typedef struct mca_coll_acoll_module_t mca_coll_acoll_module_t; OMPI_DECLSPEC OBJ_CLASS_DECLARATION(mca_coll_acoll_module_t); +/** + * Free a sub-communicator that was OBJ_RETAIN'd by the module. + * Releases the ownership reference safely: ompi_comm_free handles + * attribute cleanup + one OBJ_RELEASE; if the sub-comm survives + * (ownership ref still held), ompi_comm_lookup finds it and + * OBJ_RELEASE drops it to zero. + */ +static inline void coll_acoll_subcomm_free(ompi_communicator_t **comm) +{ + if (NULL != *comm) { + int cid = (*comm)->c_index; + ompi_comm_free(comm); + ompi_communicator_t *tmp = ompi_comm_lookup(cid); + if (NULL != tmp) { + OBJ_RELEASE(tmp); + } + *comm = NULL; + } +} + #endif /* MCA_COLL_ACOLL_EXPORT_H */ diff --git a/ompi/mca/coll/acoll/coll_acoll_component.c b/ompi/mca/coll/acoll/coll_acoll_component.c index d364058990c..a318a8c14ef 100644 --- a/ompi/mca/coll/acoll/coll_acoll_component.c +++ b/ompi/mca/coll/acoll/coll_acoll_component.c @@ -1,6 +1,7 @@ /* -*- Mode: C; c-acoll-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -322,48 +323,22 @@ static void mca_coll_acoll_module_destruct(mca_coll_acoll_module_t *module) } } - if (subc->local_comm != NULL) { - ompi_comm_free(&(subc->local_comm)); - subc->local_comm = NULL; - } - - if (subc->local_r_comm != NULL) { - ompi_comm_free(&(subc->local_r_comm)); - subc->local_r_comm = NULL; - } - - if (subc->leader_comm != NULL) { - ompi_comm_free(&(subc->leader_comm)); - subc->leader_comm = NULL; - } - - if (subc->subgrp_comm != NULL) { - ompi_comm_free(&(subc->subgrp_comm)); - subc->subgrp_comm = NULL; - } - if (subc->socket_comm != NULL) { - ompi_comm_free(&(subc->socket_comm)); - subc->socket_comm = NULL; - } - - if (subc->socket_ldr_comm != NULL) { - ompi_comm_free(&(subc->socket_ldr_comm)); - subc->socket_ldr_comm = NULL; - } + coll_acoll_subcomm_free(&(subc->local_comm)); + coll_acoll_subcomm_free(&(subc->local_r_comm)); + coll_acoll_subcomm_free(&(subc->leader_comm)); + coll_acoll_subcomm_free(&(subc->subgrp_comm)); + coll_acoll_subcomm_free(&(subc->socket_comm)); + coll_acoll_subcomm_free(&(subc->socket_ldr_comm)); + coll_acoll_subcomm_free(&(subc->numa_comm)); + coll_acoll_subcomm_free(&(subc->numa_comm_ldrs)); for (int k = 0; k < MCA_COLL_ACOLL_NUM_BASE_LYRS; k++) { for (int j = 0; j < MCA_COLL_ACOLL_NUM_LAYERS; j++) { - if (subc->base_comm[k][j] != NULL) { - ompi_comm_free(&(subc->base_comm[k][j])); - subc->base_comm[k][j] = NULL; - } + coll_acoll_subcomm_free(&(subc->base_comm[k][j])); } } for (int k = 0; k < MCA_COLL_ACOLL_SPLIT_FACTOR_LIST_LEN; ++k) { - if (subc->split_comm[k] != NULL) { - ompi_comm_free(&(subc->split_comm[k])); - subc->split_comm[k] = NULL; - } + coll_acoll_subcomm_free(&(subc->split_comm[k])); } subc->initialized = 0; free(subc); diff --git a/ompi/mca/coll/acoll/coll_acoll_utils.h b/ompi/mca/coll/acoll/coll_acoll_utils.h index e15d38b7aaa..41d02381b5f 100644 --- a/ompi/mca/coll/acoll/coll_acoll_utils.h +++ b/ompi/mca/coll/acoll/coll_acoll_utils.h @@ -1,6 +1,7 @@ /* -*- Mode: C; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -286,6 +287,7 @@ static inline int mca_coll_acoll_create_base_comm(ompi_communicator_t **parent_c err = ompi_comm_split(parent_comm[i], color, rank[i], &subc->base_comm[base_lyr][i], false); if (MPI_SUCCESS != err) return err; + OBJ_RETAIN(subc->base_comm[base_lyr][i]); /* Find out local rank of root in base comm */ err = comm_grp_ranks_local(parent_comm[i], subc->base_comm[base_lyr][i], &is_root_node, @@ -448,12 +450,14 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->local_comm); /* Create socket-level subcommunicator */ err = ompi_comm_split_type(comm, OMPI_COMM_TYPE_SOCKET, 0, &comm_info, &(subc->socket_comm)); if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->socket_comm); OBJ_DESTRUCT(&comm_info); OBJ_CONSTRUCT(&comm_info, opal_info_t); opal_info_set(&comm_info, "ompi_comm_coll_preference", "libnbc,basic,^acoll"); @@ -463,10 +467,12 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->subgrp_comm); err = ompi_comm_split_type(comm, OMPI_COMM_TYPE_NUMA, 0, &comm_info, &(subc->numa_comm)); if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->numa_comm); subc->subgrp_size = ompi_comm_size(subc->subgrp_comm); OBJ_DESTRUCT(&comm_info); @@ -514,18 +520,14 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (subc->initialized) { if (subc->num_nodes > 1) { - ompi_comm_free(&(subc->leader_comm)); - subc->leader_comm = NULL; + coll_acoll_subcomm_free(&(subc->leader_comm)); } - ompi_comm_free(&(subc->socket_ldr_comm)); - subc->socket_ldr_comm = NULL; + coll_acoll_subcomm_free(&(subc->socket_ldr_comm)); } for (int i = 0; i < MCA_COLL_ACOLL_NUM_LAYERS; i++) { if (subc->initialized) { - ompi_comm_free(&(subc->base_comm[MCA_COLL_ACOLL_L3CACHE][i])); - subc->base_comm[MCA_COLL_ACOLL_L3CACHE][i] = NULL; - ompi_comm_free(&(subc->base_comm[MCA_COLL_ACOLL_NUMA][i])); - subc->base_comm[MCA_COLL_ACOLL_NUMA][i] = NULL; + coll_acoll_subcomm_free(&(subc->base_comm[MCA_COLL_ACOLL_L3CACHE][i])); + coll_acoll_subcomm_free(&(subc->base_comm[MCA_COLL_ACOLL_NUMA][i])); } subc->base_root[MCA_COLL_ACOLL_L3CACHE][i] = -1; subc->base_root[MCA_COLL_ACOLL_NUMA][i] = -1; @@ -577,6 +579,7 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->leader_comm); /* Find out local rank of root in leader comm */ err = comm_grp_ranks_local(comm, subc->leader_comm, &is_root_node, &subc->outer_grp_root, @@ -596,6 +599,7 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, err = ompi_comm_split(comm, color, rank, &subc->socket_ldr_comm, false); if (MPI_SUCCESS != err) return err; + OBJ_RETAIN(subc->socket_ldr_comm); /* Find out local rank of root in socket leader comm */ err = comm_grp_ranks_local(comm, subc->socket_ldr_comm, &is_root_socket, @@ -661,6 +665,7 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->socket_ldr_comm); /* Find out local rank of root in socket leader comm */ err = comm_grp_ranks_local(comm, subc->socket_ldr_comm, &is_root_socket, @@ -693,6 +698,10 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, numa_rank = ompi_comm_rank(subc->numa_comm); color = (0 == numa_rank) ? 0 : 1; err = ompi_comm_split(subc->local_comm, color, rank, &subc->numa_comm_ldrs, false); + if (MPI_SUCCESS != err) { + return err; + } + OBJ_RETAIN(subc->numa_comm_ldrs); /* Find out local rank of root in numa comm */ err = comm_grp_ranks_local(comm, subc->numa_comm, &subc->is_root_numa, &subc->numa_root, @@ -745,6 +754,7 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->local_r_comm); } err = mca_coll_acoll_derive_r2r_latency(comm, subc, acoll_module); @@ -770,6 +780,7 @@ static inline int mca_coll_acoll_comm_split_init(ompi_communicator_t *comm, if (MPI_SUCCESS != err) { return err; } + OBJ_RETAIN(subc->split_comm[ii]); } subc->derived_node_size = (size + subc->num_nodes - 1) / subc->num_nodes; From 91780b49b7d4a4299f05e8b7131258e5cb1b9a37 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Thu, 9 Apr 2026 12:56:52 -0600 Subject: [PATCH 019/230] prrte: advance sha to pull in b505058c27 Signed-off-by: Howard Pritchard --- 3rd-party/prrte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd-party/prrte b/3rd-party/prrte index 2d9b0aaaeea..a2d2b039a4f 160000 --- a/3rd-party/prrte +++ b/3rd-party/prrte @@ -1 +1 @@ -Subproject commit 2d9b0aaaeea49a0e7850aed95e5ace9340c7d847 +Subproject commit a2d2b039a4f0de9af2b36be90283591c82cdc794 From 6d8072a3ad88b0e95121f2d204e9316c2edd6212 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Wed, 8 Apr 2026 10:13:16 -0700 Subject: [PATCH 020/230] perf(han): Replace per-collective persist buffers with shared scratch buffers Replace 7 separate realloc-to-HWM persist buffers (scatter_persist, scatter_reorder_persist, gather_reorder_persist, cached_gather_buf, allgather_reorder_persist, allgather_gather_persist, reduce_tmp_persist) with 2 shared scratch buffers on the HAN module. Since MPI collectives are blocking and don't run concurrently on the same communicator, all collectives can share the same buffers. Two buffers are needed because some collectives (allgather, scatter, gather) use two temporary buffers with overlapping lifetimes. Add han_scratch_alloc() and han_scratch_or_malloc() inline helpers to encapsulate the realloc-to-HWM pattern, reducing code duplication across collective implementations. This addresses reviewer feedback to use a shared allocator instead of per-collective buffers, reducing memory waste and simplifying the code. Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 65 ++++++++++++--------- ompi/mca/coll/han/coll_han_allgather.c | 71 ++++++++++++++++------ ompi/mca/coll/han/coll_han_component.c | 2 +- ompi/mca/coll/han/coll_han_gather.c | 70 +++++++--------------- ompi/mca/coll/han/coll_han_module.c | 81 ++++++++++---------------- ompi/mca/coll/han/coll_han_scatter.c | 56 +++++++----------- 6 files changed, 162 insertions(+), 183 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index b14b5021d1c..3afded27af7 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -85,6 +85,34 @@ enum { HAN_ALLOC_SMALL = 2 }; +/** + * Grow a shared scratch buffer to at least 'needed' bytes (realloc-to-HWM). + * Returns the buffer pointer, or NULL on allocation failure. + */ +static inline char *han_scratch_alloc(char **buf, size_t *buf_size, size_t needed) +{ + if (*buf_size < needed) { + char *p = realloc(*buf, needed); + if (NULL == p) return NULL; + *buf = p; + *buf_size = needed; + } + return *buf; +} + +/** + * Allocate from scratch buffer (persist mode) or malloc (non-persist). + * Returns NULL on allocation failure. + */ +static inline char *han_scratch_or_malloc(char **scratch, size_t *scratch_size, + size_t needed, bool persist) +{ + if (persist) { + return han_scratch_alloc(scratch, scratch_size, needed); + } + return (char *)malloc(needed); +} + struct mca_coll_han_bcast_args_s { mca_coll_task_t *cur_task; @@ -166,8 +194,6 @@ struct mca_coll_han_scatter_args_s { int root_low_rank; int w_rank; bool noop; - opal_free_list_item_t *inter_fl_item; /* freelist item for inter-node buf */ - int inter_fl_src; /* HAN_ALLOC_{MALLOC,LARGE,SMALL} */ opal_free_list_item_t *reorder_fl_item; /* freelist item for reorder buf */ int reorder_fl_src; /* HAN_ALLOC_{MALLOC,LARGE,SMALL} */ }; @@ -431,11 +457,6 @@ typedef struct mca_coll_han_module_t { */ int dynamic_errors; - /* Persistent bounce buffer for alltoall — grows to high-water mark - via realloc so the NIC rcache registration stays valid. */ - char *alltoall_bounce; - size_t alltoall_bounce_size; - /* Sub-communicator */ struct ompi_communicator_t *sub_comm[NB_TOPO_LVL]; @@ -443,27 +464,13 @@ typedef struct mca_coll_han_module_t { opal_free_list_t fragment_freelist; /* Large fragment pool for pipeline reorder buffers (1MB items) */ opal_free_list_t large_fragment_freelist; - /* Cached gather buffer for three-tier allocation */ - void *cached_gather_buf; - size_t cached_gather_buf_size; - /* Persistent buffer for scatter inter-node recv (realloc-to-HWM) */ - char *scatter_persist; - size_t scatter_persist_size; - /* Persistent scatter root reorder buffer (realloc-to-HWM) */ - char *scatter_reorder_persist; - size_t scatter_reorder_persist_size; - /* Persistent gather root reorder buffer (realloc-to-HWM) */ - char *gather_reorder_persist; - size_t gather_reorder_persist_size; - /* Persistent allgather reorder buffer for task-based path (realloc-to-HWM) */ - char *allgather_reorder_persist; - size_t allgather_reorder_persist_size; - /* Persistent allgather intra-node gather buffer (realloc-to-HWM) */ - char *allgather_gather_persist; - size_t allgather_gather_persist_size; - /* Persistent reduce task-based tmp buffer (realloc-to-HWM) */ - char *reduce_tmp_persist; - size_t reduce_tmp_persist_size; + /* Shared scratch buffers for all collectives (realloc-to-HWM). + * Since collectives don't run concurrently on the same communicator, + * all collectives share these two buffers. Two are needed because + * some collectives use two temporary buffers with overlapping lifetimes + * (e.g., allgather uses a gather buffer and a reorder buffer). */ + char *scratch_buf[2]; + size_t scratch_buf_size[2]; } mca_coll_han_module_t; OBJ_CLASS_DECLARATION(mca_coll_han_module_t); @@ -642,7 +649,7 @@ ompi_coll_han_reorder_gather(const void *sbuf, void *rbuf, size_t rcount, struct ompi_datatype_t *rdtype, struct ompi_communicator_t *comm, - int * topo); + const int * topo); static inline struct mca_smsc_endpoint_t *mca_coll_han_get_smsc_endpoint (struct ompi_proc_t *proc) { extern opal_mutex_t mca_coll_han_lock; diff --git a/ompi/mca/coll/han/coll_han_allgather.c b/ompi/mca/coll/han/coll_han_allgather.c index a0c378b2af9..9aa9c376932 100644 --- a/ompi/mca/coll/han/coll_han_allgather.c +++ b/ompi/mca/coll/han/coll_han_allgather.c @@ -283,17 +283,15 @@ int mca_coll_han_allgather_lg_task(void *task_args) mca_coll_han_component.han_fragment_size, (size_t)rsize, &t->inter_frag); } else { - /* Too large for freelist — use realloc-to-HWM persist buffer */ - if (t->han_module->allgather_gather_persist_size < (size_t)rsize) { - char *p = realloc(t->han_module->allgather_gather_persist, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - t->han_module->allgather_gather_persist = p; - t->han_module->allgather_gather_persist_size = rsize; - } - tmp_buf = t->han_module->allgather_gather_persist; + /* Too large for freelist — use shared scratch buffer */ + tmp_buf = han_scratch_alloc(&t->han_module->scratch_buf[0], + &t->han_module->scratch_buf_size[0], + (size_t)rsize); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; } } else { tmp_buf = (char *) malloc(rsize); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; } tmp_rbuf = tmp_buf - rgap; @@ -327,7 +325,7 @@ int mca_coll_han_allgather_lg_task(void *task_args) /* When using persist gather buffer, don't free it in uag_task */ if (mca_coll_han_component.han_use_persist_buffers && t->inter_frag == NULL && t->han_module != NULL - && tmp_buf == t->han_module->allgather_gather_persist) { + && tmp_buf == t->han_module->scratch_buf[0]) { t->sbuf_inter_free = NULL; } @@ -374,13 +372,10 @@ int mca_coll_han_allgather_uag_task(void *task_args) (int64_t) t->rcount * low_size * up_size, &rgap); if (mca_coll_han_component.han_use_persist_buffers && t->han_module != NULL) { - if (t->han_module->allgather_reorder_persist_size < (size_t)rsize) { - char *p = realloc(t->han_module->allgather_reorder_persist, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - t->han_module->allgather_reorder_persist = p; - t->han_module->allgather_reorder_persist_size = rsize; - } - reorder_buf = t->han_module->allgather_reorder_persist; + reorder_buf = han_scratch_alloc(&t->han_module->scratch_buf[1], + &t->han_module->scratch_buf_size[1], + (size_t)rsize); + if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; } else { reorder_buf = (char *) malloc(rsize); } @@ -433,6 +428,7 @@ int mca_coll_han_allgather_uag_task(void *task_args) } allgather_done: + ; /* empty statement required after label before declaration */ /* Create lb (low level broadcast) task */ mca_coll_task_t *lb = t->cur_task; /* Init and issue lb task */ @@ -567,6 +563,9 @@ han_allgather_single_frag(const void *sbuf, size_t scount, reorder_buf = han_alloc_frag(&han_module->fragment_freelist, frag_size, (size_t)rsize, &fl_item); + if (NULL == reorder_buf) { + return OMPI_ERR_OUT_OF_RESOURCE; + } reorder_buf_start = reorder_buf - rgap; my_slot = reorder_buf_start + rextent * (ptrdiff_t)up_rank * (ptrdiff_t)total_count; @@ -629,6 +628,12 @@ han_allgather_pipeline(const void *sbuf, size_t scount, ompi_datatype_get_extent(rdtype, &rlb, &rext); ompi_datatype_type_extent(rdtype, &rextent); + /* Pipeline requires non-blocking collectives on up_comm */ + if (NULL == up_comm->c_coll->coll_ibcast + || NULL == up_comm->c_coll->coll_igather) { + return OMPI_ERR_NOT_SUPPORTED; + } + /* Allocate double-buffered reorder buffers */ char *frag_reorder[2] = {NULL, NULL}; opal_free_list_item_t *frag_reorder_item[2] = {NULL, NULL}; @@ -642,6 +647,15 @@ han_allgather_pipeline(const void *sbuf, size_t scount, &han_module->fragment_freelist, frag_size, frag_reorder_size, &frag_reorder_item[b], &frag_reorder_src[b]); + if (NULL == frag_reorder[b]) { + for (int i = 0; i < b; i++) { + han_free_tiered(&han_module->large_fragment_freelist, + &han_module->fragment_freelist, + frag_reorder_item[i], frag_reorder[i], + frag_reorder_src[i]); + } + return OMPI_ERR_OUT_OF_RESOURCE; + } } } @@ -681,6 +695,19 @@ han_allgather_pipeline(const void *sbuf, size_t scount, frag_size, (size_t)this_count * low_size * rextent, &inter_frag_item); + if (NULL == gather_buf) { + /* Clean up any outstanding ibcast and double buffers */ + if (ibcast_req != NULL) { + ompi_request_wait(&ibcast_req, MPI_STATUS_IGNORE); + } + for (int b = 0; b < 2; b++) { + han_free_tiered(&han_module->large_fragment_freelist, + &han_module->fragment_freelist, + frag_reorder_item[b], frag_reorder[b], + frag_reorder_src[b]); + } + return OMPI_ERR_OUT_OF_RESOURCE; + } if (MPI_IN_PLACE == sbuf) { char *my_data = ((char*)rbuf) + ((ptrdiff_t)w_rank * (ptrdiff_t)rcount + (ptrdiff_t)frag_offset) * rext; @@ -844,6 +871,9 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size, &rgap); /* intermediary buffer on node leaders to gather on low comm */ tmp_buf = (char *) malloc(rsize); + if (NULL == tmp_buf) { + return OMPI_ERR_OUT_OF_RESOURCE; + } tmp_buf_start = tmp_buf - rgap; if (MPI_IN_PLACE == sbuf) { tmp_send = ((char*)rbuf) + (ptrdiff_t)w_rank * (ptrdiff_t)rcount * rext; @@ -958,10 +988,17 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, w_rank, low_rank, up_rank, low_size, up_size, root_low_rank, frag_size, topo); } else { - return han_allgather_pipeline(sbuf, scount, sdtype, rbuf, rcount, + int rc = han_allgather_pipeline(sbuf, scount, sdtype, rbuf, rcount, rdtype, han_module, up_comm, low_comm, w_rank, low_rank, low_size, up_size, root_low_rank, frag_size, frag_count, num_frags, topo); + if (OMPI_ERR_NOT_SUPPORTED == rc) { + return han_allgather_single_frag(sbuf, scount, sdtype, rbuf, rcount, + rdtype, han_module, up_comm, low_comm, comm, + w_rank, low_rank, up_rank, low_size, up_size, + root_low_rank, frag_size, topo); + } + return rc; } } diff --git a/ompi/mca/coll/han/coll_han_component.c b/ompi/mca/coll/han/coll_han_component.c index c9c7fca2a17..017487b2cc7 100644 --- a/ompi/mca/coll/han/coll_han_component.c +++ b/ompi/mca/coll/han/coll_han_component.c @@ -652,7 +652,7 @@ static int han_register(void) cs->han_fragment_size = 0; (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, "fragment_size", - "Size of freelist fragment buffers for collective operations (currently used by allgather, 0 = disabled)", + "Size of freelist fragment buffers for collective operations (0 = disabled)", MCA_BASE_VAR_TYPE_UNSIGNED_LONG, NULL, 0, MCA_BASE_VAR_FLAG_SETTABLE, OPAL_INFO_LVL_6, MCA_BASE_VAR_SCOPE_ALL, diff --git a/ompi/mca/coll/han/coll_han_gather.c b/ompi/mca/coll/han/coll_han_gather.c index 8af7d72d510..63f98776b19 100644 --- a/ompi/mca/coll/han/coll_han_gather.c +++ b/ompi/mca/coll/han/coll_han_gather.c @@ -158,18 +158,11 @@ mca_coll_han_gather_intra(const void *sbuf, size_t scount, rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * w_size, &rgap); - if (mca_coll_han_component.han_use_persist_buffers) { - if (han_module->gather_reorder_persist_size < (size_t)rsize) { - char *p = realloc(han_module->gather_reorder_persist, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - han_module->gather_reorder_persist = p; - han_module->gather_reorder_persist_size = rsize; - } - reorder_buf = han_module->gather_reorder_persist; - } else { - reorder_buf = (char *)malloc(rsize); - if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; - } + reorder_buf = han_scratch_or_malloc(&han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + (size_t)rsize, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; /* rgap is the size of unused space at the start of the datatype */ reorder_rbuf = reorder_buf - rgap; @@ -235,18 +228,11 @@ int mca_coll_han_gather_lg_task(void *task_args) rsize = opal_datatype_span(&dtype->super, count * low_size, &rgap); - if (mca_coll_han_component.han_use_persist_buffers) { - if (t->han_module->cached_gather_buf_size < (size_t)rsize) { - char *p = realloc(t->han_module->cached_gather_buf, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - t->han_module->cached_gather_buf = p; - t->han_module->cached_gather_buf_size = rsize; - } - tmp_buf = (char *)t->han_module->cached_gather_buf; - } else { - tmp_buf = (char *)malloc(rsize); - if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; - } + tmp_buf = han_scratch_or_malloc(&t->han_module->scratch_buf[1], + &t->han_module->scratch_buf_size[1], + (size_t)rsize, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; tmp_rbuf = tmp_buf - rgap; if (t->w_rank == t->root && MPI_IN_PLACE == t->sbuf) { ptrdiff_t rextent; @@ -400,18 +386,11 @@ mca_coll_han_gather_intra_simple(const void *sbuf, size_t scount, ptrdiff_t rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * w_size, &rgap); - if (mca_coll_han_component.han_use_persist_buffers) { - if (han_module->gather_reorder_persist_size < (size_t)rsize) { - char *p = realloc(han_module->gather_reorder_persist, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - han_module->gather_reorder_persist = p; - han_module->gather_reorder_persist_size = rsize; - } - reorder_buf = han_module->gather_reorder_persist; - } else { - reorder_buf = (char *)malloc(rsize); - if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; - } + reorder_buf = han_scratch_or_malloc(&han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + (size_t)rsize, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == reorder_buf) return OMPI_ERR_OUT_OF_RESOURCE; /* rgap is the size of unused space at the start of the datatype */ reorder_buf_start = reorder_buf - rgap; } @@ -426,18 +405,11 @@ mca_coll_han_gather_intra_simple(const void *sbuf, size_t scount, rsize = opal_datatype_span(&dtype->super, count * low_size, &rgap); - if (mca_coll_han_component.han_use_persist_buffers) { - if (han_module->cached_gather_buf_size < (size_t)rsize) { - char *p = realloc(han_module->cached_gather_buf, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - han_module->cached_gather_buf = p; - han_module->cached_gather_buf_size = rsize; - } - tmp_buf = (char *)han_module->cached_gather_buf; - } else { - tmp_buf = (char *)malloc(rsize); - if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; - } + tmp_buf = han_scratch_or_malloc(&han_module->scratch_buf[1], + &han_module->scratch_buf_size[1], + (size_t)rsize, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; tmp_buf_start = tmp_buf - rgap; } @@ -504,7 +476,7 @@ ompi_coll_han_reorder_gather(const void *sbuf, void *rbuf, size_t count, struct ompi_datatype_t *dtype, struct ompi_communicator_t *comm, - int * topo) + const int * topo) { int i, topolevel = 2; // always 2 levels in topo #if OPAL_ENABLE_DEBUG diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index d366eca4c70..a355e7a42a0 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -86,12 +86,13 @@ OBJ_CLASS_INSTANCE(large_fragment_item_t, static void han_init_freelists(mca_coll_han_module_t *han_module) { + int rc; if (!mca_coll_han_component.han_use_persist_buffers) { return; } if (mca_coll_han_component.han_fragment_size > 0) { OBJ_CONSTRUCT(&han_module->fragment_freelist, opal_free_list_t); - opal_free_list_init(&han_module->fragment_freelist, + rc = opal_free_list_init(&han_module->fragment_freelist, sizeof(fragment_item_t), opal_cache_line_size, OBJ_CLASS(fragment_item_t), @@ -100,10 +101,17 @@ static void han_init_freelists(mca_coll_han_module_t *han_module) HAN_FRAG_MAX_COUNT, HAN_FRAG_GROWTH_BATCH, NULL, 0, NULL, NULL, NULL); + if (OPAL_SUCCESS != rc) { + OBJ_DESTRUCT(&han_module->fragment_freelist); + opal_output_verbose(0, mca_coll_han_component.han_output, + "coll:han: fragment freelist init failed, disabling persist buffers\n"); + mca_coll_han_component.han_use_persist_buffers = false; + return; + } } OBJ_CONSTRUCT(&han_module->large_fragment_freelist, opal_free_list_t); if (mca_coll_han_component.han_large_fragment_size > 0) { - opal_free_list_init(&han_module->large_fragment_freelist, + rc = opal_free_list_init(&han_module->large_fragment_freelist, sizeof(large_fragment_item_t), opal_cache_line_size, OBJ_CLASS(large_fragment_item_t), @@ -112,6 +120,16 @@ static void han_init_freelists(mca_coll_han_module_t *han_module) HAN_LARGE_FRAG_MAX, HAN_LARGE_FRAG_GROWTH, NULL, 0, NULL, NULL, NULL); + if (OPAL_SUCCESS != rc) { + OBJ_DESTRUCT(&han_module->large_fragment_freelist); + if (mca_coll_han_component.han_fragment_size > 0) { + OBJ_DESTRUCT(&han_module->fragment_freelist); + } + opal_output_verbose(0, mca_coll_han_component.han_output, + "coll:han: large fragment freelist init failed, disabling persist buffers\n"); + mca_coll_han_component.han_use_persist_buffers = false; + return; + } } } @@ -187,20 +205,10 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) module->cached_up_comms = NULL; module->cached_vranks = NULL; module->cached_topo = NULL; - module->cached_gather_buf = NULL; - module->cached_gather_buf_size = 0; - module->scatter_persist = NULL; - module->scatter_persist_size = 0; - module->scatter_reorder_persist = NULL; - module->scatter_reorder_persist_size = 0; - module->gather_reorder_persist = NULL; - module->gather_reorder_persist_size = 0; - module->reduce_tmp_persist = NULL; - module->reduce_tmp_persist_size = 0; - module->allgather_reorder_persist = NULL; - module->allgather_reorder_persist_size = 0; - module->allgather_gather_persist = NULL; - module->allgather_gather_persist_size = 0; + module->scratch_buf[0] = NULL; + module->scratch_buf_size[0] = 0; + module->scratch_buf[1] = NULL; + module->scratch_buf_size[1] = 0; module->is_mapbycore = false; module->storage_initialized = false; for( i = 0; i < NB_TOPO_LVL; i++ ) { @@ -211,8 +219,6 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) } module->dynamic_errors = 0; - module->alltoall_bounce = NULL; - module->alltoall_bounce_size = 0; han_module_clear(module); @@ -261,35 +267,12 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) free(module->cached_topo); module->cached_topo = NULL; } - if (module->cached_gather_buf != NULL) { - free(module->cached_gather_buf); - module->cached_gather_buf = NULL; - module->cached_gather_buf_size = 0; - } - - free(module->scatter_persist); - module->scatter_persist = NULL; - module->scatter_persist_size = 0; - - free(module->scatter_reorder_persist); - module->scatter_reorder_persist = NULL; - module->scatter_reorder_persist_size = 0; - - free(module->gather_reorder_persist); - module->gather_reorder_persist = NULL; - module->gather_reorder_persist_size = 0; - - free(module->reduce_tmp_persist); - module->reduce_tmp_persist = NULL; - module->reduce_tmp_persist_size = 0; - - free(module->allgather_reorder_persist); - module->allgather_reorder_persist = NULL; - module->allgather_reorder_persist_size = 0; - - free(module->allgather_gather_persist); - module->allgather_gather_persist = NULL; - module->allgather_gather_persist_size = 0; + free(module->scratch_buf[0]); + module->scratch_buf[0] = NULL; + module->scratch_buf_size[0] = 0; + free(module->scratch_buf[1]); + module->scratch_buf[1] = NULL; + module->scratch_buf_size[1] = 0; for(i=0 ; isub_comm[i]) { @@ -297,10 +280,6 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) } } - free(module->alltoall_bounce); - module->alltoall_bounce = NULL; - module->alltoall_bounce_size = 0; - han_module_clear(module); } diff --git a/ompi/mca/coll/han/coll_han_scatter.c b/ompi/mca/coll/han/coll_han_scatter.c index 7a847379dd4..65e5fae349e 100644 --- a/ompi/mca/coll/han/coll_han_scatter.c +++ b/ompi/mca/coll/han/coll_han_scatter.c @@ -112,8 +112,6 @@ mca_coll_han_set_scatter_args(mca_coll_han_scatter_args_t * args, args->noop = noop; args->req = req; args->han_module = han_module; - args->inter_fl_item = NULL; - args->inter_fl_src = HAN_ALLOC_MALLOC; args->reorder_fl_item = NULL; args->reorder_fl_src = HAN_ALLOC_MALLOC; } @@ -214,6 +212,9 @@ mca_coll_han_scatter_intra(const void *sbuf, size_t scount, } else { reorder_buf = (char *)malloc(ssize); } + if (NULL == reorder_buf) { + return OMPI_ERR_OUT_OF_RESOURCE; + } reorder_sbuf = reorder_buf - sgap; for (int i = 0; i < up_size; i++) { for (int j = 0; j < low_size; j++) { @@ -278,18 +279,11 @@ int mca_coll_han_scatter_us_task(void *task_args) /* Inter-node receive buffer: persistent realloc-to-HWM or malloc */ char *tmp_buf; - if (mca_coll_han_component.han_use_persist_buffers) { - if (t->han_module->scatter_persist_size < (size_t)rsize) { - char *p = realloc(t->han_module->scatter_persist, rsize); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - t->han_module->scatter_persist = p; - t->han_module->scatter_persist_size = rsize; - } - tmp_buf = t->han_module->scatter_persist; - } else { - tmp_buf = (char *)malloc(rsize); - if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; - } + tmp_buf = han_scratch_or_malloc(&t->han_module->scratch_buf[1], + &t->han_module->scratch_buf_size[1], + (size_t)rsize, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; char *tmp_rbuf = tmp_buf - rgap; OPAL_OUTPUT_VERBOSE((30, mca_coll_han_component.han_output, @@ -438,26 +432,19 @@ mca_coll_han_scatter_intra_simple(const void *sbuf, size_t scount, "[%d]: Han scatter: needs reordering or compacting: ", w_rank)); size_t reorder_size = (size_t)block_size * w_size; - if (mca_coll_han_component.han_use_persist_buffers) { - if (han_module->scatter_reorder_persist_size < reorder_size) { - char *p = realloc(han_module->scatter_reorder_persist, reorder_size); - if (NULL == p) return OMPI_ERROR; - han_module->scatter_reorder_persist = p; - han_module->scatter_reorder_persist_size = reorder_size; - } - reorder_buf = han_module->scatter_reorder_persist; - } else { - reorder_buf = (char *)malloc(reorder_size); - if (NULL == reorder_buf) return OMPI_ERROR; - } + reorder_buf = han_scratch_or_malloc(&han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + reorder_size, + mca_coll_han_component.han_use_persist_buffers); + if (NULL == reorder_buf) return OMPI_ERROR; ptrdiff_t extent, block_extent; ompi_datatype_type_extent(dtype, &extent); block_extent = extent * (ptrdiff_t)count; - for (int i = 0; i < w_size; ++i) { - ompi_datatype_sndrcv((char *)sbuf + block_extent * topo[2 * i + 1], count, dtype, - reorder_buf + block_size * i, block_size, MPI_BYTE); + for(int i = 0 ; i < w_size ; ++i){ + ompi_datatype_sndrcv((char*)sbuf + block_extent*topo[2*i+1], count, dtype, + reorder_buf + block_size*i, block_size, MPI_BYTE); } dtype = MPI_BYTE; count = block_size; @@ -492,13 +479,10 @@ mca_coll_han_scatter_intra_simple(const void *sbuf, size_t scount, tmp_buf = NULL; } if (tmp_fl_src == HAN_ALLOC_MALLOC) { - if (han_module->scatter_persist_size < tmp_total) { - char *p = realloc(han_module->scatter_persist, tmp_total); - if (NULL == p) return OMPI_ERR_OUT_OF_RESOURCE; - han_module->scatter_persist = p; - han_module->scatter_persist_size = tmp_total; - } - tmp_buf = han_module->scatter_persist; + tmp_buf = han_scratch_alloc(&han_module->scratch_buf[1], + &han_module->scratch_buf_size[1], + tmp_total); + if (NULL == tmp_buf) return OMPI_ERR_OUT_OF_RESOURCE; } } else { tmp_buf = (char *)malloc(tmp_total); From ca86067e210539230006bdca09c32d1e3b2d060a Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Fri, 10 Apr 2026 15:36:55 -0400 Subject: [PATCH 021/230] ob1: don't call btl_dump if the btl does not provide it We dump the btl during revoke, which leads to a Segfault if we're not careful. Signed-off-by: Joseph Schuchart --- ompi/mca/pml/ob1/pml_ob1.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ompi/mca/pml/ob1/pml_ob1.c b/ompi/mca/pml/ob1/pml_ob1.c index e0516d16fe0..4a6e2245376 100644 --- a/ompi/mca/pml/ob1/pml_ob1.c +++ b/ompi/mca/pml/ob1/pml_ob1.c @@ -27,6 +27,7 @@ * reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -721,6 +722,9 @@ int mca_pml_ob1_dump(struct ompi_communicator_t* comm, int verbose) /* dump all btls used for eager messages */ for( n = 0; n < ep->btl_eager.arr_size; n++ ) { mca_bml_base_btl_t* bml_btl = &ep->btl_eager.bml_btls[n]; + if (bml_btl->btl->btl_dump == NULL) { + continue; + } bml_btl->btl->btl_dump(bml_btl->btl, bml_btl->btl_endpoint, verbose); } } From aca3948f14701bb23d118e492cffc0c9f4c046c7 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Wed, 15 Apr 2026 10:49:10 -0700 Subject: [PATCH 022/230] perf(han): Use shared scratch buffers for scatterv and gatherv Replace malloc/free of bounce_buf and tmp_buf in scatterv and gatherv with the shared scratch buffer pattern (han_scratch_or_malloc). When persist buffers are enabled, these buffers are realloc-to-HWM and reused across calls, avoiding NIC MR cache invalidation. Uses scratch_buf[0] for root bounce buffer and scratch_buf[1] for node-leader inter-node buffer, consistent with scatter/gather. Benchmarks (Graviton c7g.16xlarge, 2N x 32ppn): Scatterv: 2.13-2.19x at 1M-4M (OSU), 2.25-2.39x (IMB) Gatherv: 2.57-2.60x at 1M-4M (OSU), 1.98-2.17x (IMB) No regressions at smaller sizes. Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han_gatherv.c | 14 ++++++++++---- ompi/mca/coll/han/coll_han_scatterv.c | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ompi/mca/coll/han/coll_han_gatherv.c b/ompi/mca/coll/han/coll_han_gatherv.c index fd600b9d1cd..cf62870bcf0 100644 --- a/ompi/mca/coll/han/coll_han_gatherv.c +++ b/ompi/mca/coll/han/coll_han_gatherv.c @@ -219,7 +219,10 @@ int mca_coll_han_gatherv_intra(const void *sbuf, size_t scount, struct ompi_data if (need_bounce_buf) { ptrdiff_t rsize, rgap; rsize = opal_datatype_span(&rdtype->super, total_up_rcounts, &rgap); - bounce_buf = malloc(rsize); + bounce_buf = han_scratch_or_malloc( + &han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + rsize, mca_coll_han_component.han_use_persist_buffers); if (!bounce_buf) { err = OMPI_ERR_OUT_OF_RESOURCE; goto root_out; @@ -276,7 +279,7 @@ int mca_coll_han_gatherv_intra(const void *sbuf, size_t scount, struct ompi_data if (up_peer_ub) { free(up_peer_ub); } - if (bounce_buf) { + if (bounce_buf && !mca_coll_han_component.han_use_persist_buffers) { free(bounce_buf); } @@ -338,7 +341,10 @@ int mca_coll_han_gatherv_intra(const void *sbuf, size_t scount, struct ompi_data total_rsize += low_rcounts[i]; } - tmp_buf = (char *) malloc(total_rsize); /* tmp_buf is still valid if total_rsize is 0 */ + tmp_buf = han_scratch_or_malloc( + &han_module->scratch_buf[1], + &han_module->scratch_buf_size[1], + total_rsize, mca_coll_han_component.han_use_persist_buffers); if (!tmp_buf) { err = OMPI_ERR_OUT_OF_RESOURCE; goto node_leader_out; @@ -363,7 +369,7 @@ int mca_coll_han_gatherv_intra(const void *sbuf, size_t scount, struct ompi_data if (low_displs) { free(low_displs); } - if (tmp_buf) { + if (tmp_buf && !mca_coll_han_component.han_use_persist_buffers) { free(tmp_buf); } diff --git a/ompi/mca/coll/han/coll_han_scatterv.c b/ompi/mca/coll/han/coll_han_scatterv.c index 18c67baff91..dfc23175ff5 100644 --- a/ompi/mca/coll/han/coll_han_scatterv.c +++ b/ompi/mca/coll/han/coll_han_scatterv.c @@ -226,7 +226,10 @@ int mca_coll_han_scatterv_intra(const void *sbuf, ompi_count_array_t scounts, om if (need_bounce_buf) { ptrdiff_t ssize, sgap; ssize = opal_datatype_span(&rdtype->super, total_up_scounts, &sgap); - bounce_buf = malloc(ssize); + bounce_buf = han_scratch_or_malloc( + &han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + ssize, mca_coll_han_component.han_use_persist_buffers); if (!bounce_buf) { err = OMPI_ERR_OUT_OF_RESOURCE; goto root_out; @@ -293,7 +296,7 @@ int mca_coll_han_scatterv_intra(const void *sbuf, ompi_count_array_t scounts, om if (up_peer_ub) { free(up_peer_ub); } - if (bounce_buf) { + if (bounce_buf && !mca_coll_han_component.han_use_persist_buffers) { free(bounce_buf); } @@ -355,7 +358,10 @@ int mca_coll_han_scatterv_intra(const void *sbuf, ompi_count_array_t scounts, om total_rsize += low_scounts[i]; } - tmp_buf = (char *) malloc(total_rsize); /* tmp_buf is still valid if total_rsize is 0 */ + tmp_buf = han_scratch_or_malloc( + &han_module->scratch_buf[1], + &han_module->scratch_buf_size[1], + total_rsize, mca_coll_han_component.han_use_persist_buffers); if (!tmp_buf) { err = OMPI_ERR_OUT_OF_RESOURCE; goto node_leader_out; @@ -382,7 +388,7 @@ int mca_coll_han_scatterv_intra(const void *sbuf, ompi_count_array_t scounts, om if (low_displs) { free(low_displs); } - if (tmp_buf) { + if (tmp_buf && !mca_coll_han_component.han_use_persist_buffers) { free(tmp_buf); } From c7dd1e2d26a33fb14a23b694c79e794d749ee4e9 Mon Sep 17 00:00:00 2001 From: Yin Li Date: Wed, 15 Apr 2026 10:49:10 -0700 Subject: [PATCH 023/230] perf(han): Persistent buffers and caching for alltoall/alltoallv Cache SMSC mappings, allgather results, and allreduce decisions across calls in alltoall and alltoallv, gated behind coll_han_use_persist_buffers MCA parameter (default false). When disabled, original code paths run. Alltoall optimizations: - SMSC peer mapping cache: reuse map_peer_region across calls when sbuf address and scount are unchanged - Persistent bounce buffer: realloc-to-HWM avoids munmap that invalidates NIC memory registration cache entries - Persistent recv buffer: stable MR addresses for inter-node receives - Allgather result cache: skip intra-node allgather on repeated calls - Dedicated han_alltoall_cache struct and alltoall_cache_setup helper Alltoallv optimizations: - Size-aware allreduce caching: skip decide_to_use_smsc_alg allreduce when avg_send_size < han_alltoallv_smsc_avg_send_limit (8KB default). At large sizes, allreduce always runs for correct algorithm selection. - Persistent serialization, gather, peer, and exchange buffers - MPI_IN_PLACE early return before caching logic - Dedicated han_alltoallv_cache struct and alltoallv_cache_setup helper Benchmarks (OSU, Graviton c7g 2N x 32ppn, 64 ranks): Alltoall: 1.1-1.2x at 1B-128B Alltoallv: 1.7x at 1B-64B, 1.25-1.35x at 128B-512B No regressions at 1KB+ Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 32 ++++ ompi/mca/coll/han/coll_han_alltoall.c | 252 +++++++++++++++++++------ ompi/mca/coll/han/coll_han_alltoallv.c | 138 +++++++++++--- ompi/mca/coll/han/coll_han_module.c | 29 +++ 4 files changed, 365 insertions(+), 86 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index 3afded27af7..80c018a3104 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -471,6 +471,38 @@ typedef struct mca_coll_han_module_t { * (e.g., allgather uses a gather buffer and a reorder buffer). */ char *scratch_buf[2]; size_t scratch_buf_size[2]; + + struct han_alltoall_cache { + char *bounce; + size_t bounce_size; + const void *cached_sbuf; + size_t cached_scount; + int cached_low_size; + char **low_bufs; + void **map_ctx; + void **gather_buf; + int cached_send_needs_bounce; + int cached_ii_push_data; + char *recv_buf; + size_t recv_buf_size; + } a2a_cache; + + struct han_alltoallv_cache { + uint8_t *serial_buf; + size_t serial_buf_size; + void *gather_out; + void *peers; + void *peer_types; + int low_size; + void **send_from; + void **recv_to; + size_t *send_counts; + size_t *recv_counts; + void **send_types; + void **recv_types; + bool smsc_decided; + int use_smsc; + } a2av_cache; } mca_coll_han_module_t; OBJ_CLASS_DECLARATION(mca_coll_han_module_t); diff --git a/ompi/mca/coll/han/coll_han_alltoall.c b/ompi/mca/coll/han/coll_han_alltoall.c index 489dd41e35a..27f6a1853c8 100644 --- a/ompi/mca/coll/han/coll_han_alltoall.c +++ b/ompi/mca/coll/han/coll_han_alltoall.c @@ -60,6 +60,60 @@ static inline int ring_partner(int rank, int round, int comm_size) { return ring_partner_no_skip(rank, round+1, comm_size); } + +/** + * Set up or reuse cached SMSC arrays for alltoall. + * Returns true if cache was valid (allgather + map can be skipped). + */ +static int alltoall_cache_setup( + mca_coll_han_module_t *han_module, + const void *sbuf, size_t scount, int low_size, + char ***low_bufs_out, void ***map_ctx_out, void ***gather_buf_out, + int *send_needs_bounce_out, int *ii_push_data_out) +{ + struct han_alltoall_cache *c = &han_module->a2a_cache; + const int nptrs_gather = 3; + + if (c->cached_sbuf == sbuf + && c->cached_scount == scount + && c->cached_low_size == low_size + && c->low_bufs != NULL) { + *low_bufs_out = c->low_bufs; + *map_ctx_out = c->map_ctx; + *gather_buf_out = c->gather_buf; + *send_needs_bounce_out = c->cached_send_needs_bounce; + *ii_push_data_out = c->cached_ii_push_data; + return 1; /* cache valid */ + } + + /* Invalidate old cache — unmap old SMSC regions */ + if (c->map_ctx) { + for (int i = 0; i < c->cached_low_size; i++) { + if (c->map_ctx[i]) + mca_smsc->unmap_peer_region(c->map_ctx[i]); + } + } + /* Allocate/reuse persistent arrays */ + if (c->cached_low_size < low_size) { + free(c->low_bufs); + free(c->map_ctx); + free(c->gather_buf); + c->cached_low_size = 0; + c->low_bufs = malloc(low_size * sizeof(char*)); + c->map_ctx = malloc(low_size * sizeof(void*)); + c->gather_buf = calloc(low_size * nptrs_gather, sizeof(void*)); + if (NULL == c->low_bufs || NULL == c->map_ctx || NULL == c->gather_buf) { + return -1; /* allocation failure */ + } + } + *low_bufs_out = c->low_bufs; + *map_ctx_out = c->map_ctx; + *gather_buf_out = c->gather_buf; + memset(c->map_ctx, 0, low_size * sizeof(void*)); + memset(c->gather_buf, 0, low_size * nptrs_gather * sizeof(void*)); + return 0; /* cache miss */ +} + int mca_coll_han_alltoall_using_smsc( const void *sbuf, size_t scount, struct ompi_datatype_t *sdtype, @@ -218,14 +272,31 @@ int mca_coll_han_alltoall_using_smsc( int64_t send_bytes_per_fan = low_size * packed_size; inter_send_reqs = malloc(sizeof(*inter_send_reqs) * fanout); inter_recv_reqs = malloc(sizeof(*inter_recv_reqs) * up_size ); - char **low_bufs = malloc(low_size * sizeof(*low_bufs)); - void **sbuf_map_ctx = malloc(low_size * sizeof(&sbuf_map_ctx)); - opal_free_list_item_t *send_fl_item = NULL; + /* Check if cached SMSC mappings are still valid */ + int a2a_cache_valid; + char **low_bufs = NULL; + void **sbuf_map_ctx = NULL; + opal_free_list_item_t *send_fl_item = NULL; const int nptrs_gather = 3; - void **gather_buf_out = calloc(low_size*nptrs_gather, sizeof(void*)); + void **gather_buf_out = NULL; int send_bounce_status = BOUNCE_NOT_INITIALIZED; + if (mca_coll_han_component.han_use_persist_buffers) { + int cache_rc = alltoall_cache_setup( + han_module, sbuf, scount, low_size, + &low_bufs, &sbuf_map_ctx, &gather_buf_out, + &send_needs_bounce, &ii_push_data); + if (cache_rc < 0) { rc = OMPI_ERR_OUT_OF_RESOURCE; goto cleanup; } + a2a_cache_valid = (cache_rc == 1); + } else { + /* Original upstream path — fresh allocations per call */ + a2a_cache_valid = 0; + low_bufs = malloc(low_size * sizeof(*low_bufs)); + sbuf_map_ctx = malloc(low_size * sizeof(*sbuf_map_ctx)); + gather_buf_out = calloc(low_size * nptrs_gather, sizeof(void*)); + } + do { start_allgather: if ( 0 == send_needs_bounce ) { @@ -233,70 +304,96 @@ int mca_coll_han_alltoall_using_smsc( send_bounce_status = BOUNCE_IS_FROM_RBUF; } else { if (send_bounce_status == BOUNCE_NOT_INITIALIZED || send_bounce_status == BOUNCE_IS_FROM_RBUF) { - if (send_bytes_per_fan * fanout < mca_coll_han_component.han_packbuf_bytes) { - send_fl_item = opal_free_list_get(&mca_coll_han_component.pack_buffers); - if (send_fl_item) { - send_bounce_status = BOUNCE_IS_FROM_FREELIST; - send_bounce = send_fl_item->ptr; + if (mca_coll_han_component.han_use_persist_buffers) { + /* Persistent bounce: realloc-to-HWM avoids munmap on free + * which would invalidate NIC memory registration cache entries. */ + size_t needed = send_bytes_per_fan * fanout; + if (han_module->a2a_cache.bounce_size < needed) { + char *p = realloc(han_module->a2a_cache.bounce, needed); + if (NULL == p) { rc = OMPI_ERR_OUT_OF_RESOURCE; goto cleanup; } + han_module->a2a_cache.bounce = p; + han_module->a2a_cache.bounce_size = needed; } - } - if (!send_fl_item) { - send_bounce = malloc(send_bytes_per_fan * fanout); + send_bounce = han_module->a2a_cache.bounce; send_bounce_status = BOUNCE_IS_FROM_MALLOC; + } else { + if (send_bytes_per_fan * fanout < mca_coll_han_component.han_packbuf_bytes) { + send_fl_item = opal_free_list_get(&mca_coll_han_component.pack_buffers); + if (send_fl_item) { + send_bounce_status = BOUNCE_IS_FROM_FREELIST; + send_bounce = send_fl_item->ptr; + } + } + if (!send_fl_item) { + send_bounce = malloc(send_bytes_per_fan * fanout); + send_bounce_status = BOUNCE_IS_FROM_MALLOC; + } } } } - if (ii_push_data) { - /* all ranks will push to the other ranks' bounce buffer */ - gather_buf_in[0] = send_bounce; - } else { - /* all ranks will pull from the other ranks' sbuf */ - gather_buf_in[0] = (void*)sbuf; - } - gather_buf_in[1] = (void*)(intptr_t)send_needs_bounce; - gather_buf_in[2] = (void*)(intptr_t)ii_push_data; + if (!a2a_cache_valid) { + if (ii_push_data) { + /* all ranks will push to the other ranks' bounce buffer */ + gather_buf_in[0] = send_bounce; + } else { + /* all ranks will pull from the other ranks' sbuf */ + gather_buf_in[0] = (void*)sbuf; + } + gather_buf_in[1] = (void*)(intptr_t)send_needs_bounce; + gather_buf_in[2] = (void*)(intptr_t)ii_push_data; - rc = low_comm->c_coll->coll_allgather(gather_buf_in, nptrs_gather, MPI_AINT, - gather_buf_out, nptrs_gather, MPI_AINT, low_comm, - low_comm->c_coll->coll_allgather_module); + rc = low_comm->c_coll->coll_allgather(gather_buf_in, nptrs_gather, MPI_AINT, + gather_buf_out, nptrs_gather, MPI_AINT, low_comm, + low_comm->c_coll->coll_allgather_module); - if (rc != 0) { - OPAL_OUTPUT_VERBOSE((40, mca_coll_han_component.han_output, - "Allgather failed with %d\n",rc)); - goto cleanup; - } + if (rc != 0) { + OPAL_OUTPUT_VERBOSE((40, mca_coll_han_component.han_output, + "Allgather failed with %d\n",rc)); + goto cleanup; + } - for (int jother=0; jother 1 || ii_push_data; - for (int jother=0; jothermap_peer_region( - smsc_ep, - MCA_RCACHE_FLAGS_PERSIST, - low_bufs[jother], - sextent*w_size*scount, - (void**) &low_bufs[jother] ); + if (!a2a_cache_valid) { + for (int jother=0; jothermap_peer_region( + smsc_ep, + MCA_RCACHE_FLAGS_PERSIST, + low_bufs[jother], + sextent*w_size*scount, + (void**) &low_bufs[jother] ); + } } - } + /* Update cache (only when persist buffers enabled) */ + if (mca_coll_han_component.han_use_persist_buffers) { + han_module->a2a_cache.cached_sbuf = sbuf; + han_module->a2a_cache.cached_scount = scount; + han_module->a2a_cache.cached_low_size = low_size; + han_module->a2a_cache.cached_send_needs_bounce = send_needs_bounce; + han_module->a2a_cache.cached_ii_push_data = ii_push_data; + } + } /* !a2a_cache_valid */ for (int jslot=0; jslot < fanout; jslot++) { inter_send_reqs[jslot] = MPI_REQUEST_NULL; @@ -305,12 +402,25 @@ int mca_coll_han_alltoall_using_smsc( /* pre-post all our receives. We will be ready to receive all data regardless of fan-out. (This is not an in-place algorithm)*/ + size_t recv_chunk_bytes = rextent * rcount * low_size; + size_t recv_total = recv_chunk_bytes * up_size; + if (mca_coll_han_component.han_use_persist_buffers) { + /* Use persistent recv buffer to keep MR addresses stable */ + if (han_module->a2a_cache.recv_buf_size < recv_total) { + char *p = realloc(han_module->a2a_cache.recv_buf, recv_total); + if (NULL == p) { rc = OMPI_ERR_OUT_OF_RESOURCE; goto cleanup; } + han_module->a2a_cache.recv_buf = p; + han_module->a2a_cache.recv_buf_size = recv_total; + } + } + int inter_recv_count = 0; for (int jround=0; jrounda2a_cache.recv_buf + recv_chunk_bytes * jround + : ((char*)rbuf) + rextent*rcount*first_remote_wrank; MCA_PML_CALL(irecv (recv_chunk, rcount*low_size, rdtype, first_remote_wrank+low_rank, @@ -415,6 +525,17 @@ int mca_coll_han_alltoall_using_smsc( /* wait for all irecv to complete */ ompi_request_wait_all(inter_recv_count, inter_recv_reqs, MPI_STATUS_IGNORE); + /* Copy from persistent recv buffer to application rbuf */ + if (mca_coll_han_component.han_use_persist_buffers) { + for (int jround=0; jrounda2a_cache.recv_buf + recv_chunk_bytes * jround, + recv_chunk_bytes); + } + } + cleanup: /* we may still have neighbors reading directly from our buffer, so we must ensure it is not modified */ @@ -423,22 +544,29 @@ int mca_coll_han_alltoall_using_smsc( low_comm->c_coll->coll_barrier(low_comm, low_comm->c_coll->coll_barrier_module); } - for (int jlow=0; jlowunmap_peer_region(sbuf_map_ctx[jlow]); + if (mca_coll_han_component.han_use_persist_buffers) { + /* SMSC mappings, bounce, and arrays are cached — do not free/unmap */ + } else { + for (int jlow=0; jlowunmap_peer_region(sbuf_map_ctx[jlow]); + } } } OBJ_DESTRUCT(&convertor); if (send_bounce_status == BOUNCE_IS_FROM_FREELIST) { opal_free_list_return(&mca_coll_han_component.pack_buffers, send_fl_item); - } else if (send_bounce_status == BOUNCE_IS_FROM_MALLOC) { + } else if (send_bounce_status == BOUNCE_IS_FROM_MALLOC + && !mca_coll_han_component.han_use_persist_buffers) { free(send_bounce); } free(inter_send_reqs); free(inter_recv_reqs); - free(sbuf_map_ctx); - free(low_bufs); - free(gather_buf_out); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(sbuf_map_ctx); + free(low_bufs); + free(gather_buf_out); + } OPAL_OUTPUT_VERBOSE((40, mca_coll_han_component.han_output, "Alltoall Complete with %d\n",rc)); diff --git a/ompi/mca/coll/han/coll_han_alltoallv.c b/ompi/mca/coll/han/coll_han_alltoallv.c index b3c25014b2f..4d19b0311db 100644 --- a/ompi/mca/coll/han/coll_han_alltoallv.c +++ b/ompi/mca/coll/han/coll_han_alltoallv.c @@ -582,6 +582,52 @@ static int alltoallv_sendrecv_w( return 0; } + +/** + * Set up persistent allocations for alltoallv. + * Grows arrays to high-water mark to avoid per-call malloc/free. + * Returns 0 on success, OMPI_ERR_OUT_OF_RESOURCE on failure. + */ +static int alltoallv_cache_setup( + struct han_alltoallv_cache *c, + size_t serialization_buf_length, int low_size) +{ + if (c->serial_buf_size < serialization_buf_length) { + free(c->serial_buf); + c->serial_buf = malloc(serialization_buf_length); + if (NULL == c->serial_buf) { + c->serial_buf_size = 0; + return OMPI_ERR_OUT_OF_RESOURCE; + } + c->serial_buf_size = serialization_buf_length; + } + if (c->low_size < low_size) { + free(c->gather_out); free(c->peers); free(c->peer_types); + free(c->send_from); free(c->recv_to); + free(c->send_counts); free(c->recv_counts); + free(c->send_types); free(c->recv_types); + c->low_size = 0; + c->gather_out = malloc(sizeof(struct gathered_data) * low_size); + c->peers = malloc(sizeof(struct peer_data) * low_size); + c->peer_types = malloc(sizeof(opal_datatype_t) * low_size); + c->send_from = malloc(sizeof(void*) * low_size); + c->recv_to = malloc(sizeof(void*) * low_size); + c->send_counts = malloc(sizeof(size_t) * low_size); + c->recv_counts = malloc(sizeof(size_t) * low_size); + c->send_types = malloc(sizeof(opal_datatype_t*) * low_size); + c->recv_types = malloc(sizeof(opal_datatype_t*) * low_size); + if (NULL == c->gather_out || NULL == c->peers || + NULL == c->peer_types || NULL == c->send_from || + NULL == c->recv_to || NULL == c->send_counts || + NULL == c->recv_counts|| NULL == c->send_types || + NULL == c->recv_types) { + return OMPI_ERR_OUT_OF_RESOURCE; + } + c->low_size = low_size; + } + return OMPI_SUCCESS; +} + static int decide_to_use_smsc_alg( int *use_smsc, const void *sbuf, @@ -769,11 +815,30 @@ int mca_coll_han_alltoallv_using_smsc( int w_size = ompi_comm_size(comm); int use_smsc; - rc = decide_to_use_smsc_alg(&use_smsc, - sbuf, scounts, sdispls, sdtype, rbuf, rcounts, rdispls, rdtype, comm); - if (rc != 0) { - opal_output_verbose(1, mca_coll_han_component.han_output, - "decide_to_use_smsc_alg failed during execution! rc=%d\n", rc); + if (sbuf == MPI_IN_PLACE) { + return han_module->previous_alltoallv(sbuf, scounts, sdispls, sdtype, rbuf, rcounts, rdispls, rdtype, + comm, han_module->previous_alltoallv_module); + } + + /* Cache the decide_to_use_smsc_alg result to avoid per-call allreduce. + * The first call runs the allreduce (all ranks participate). Every + * subsequent call reuses the cached result. This is safe because the + * decision depends on buffer types (GPU, contiguous) which don't change + * between calls, and the MCA parameter is globally consistent. */ + if (mca_coll_han_component.han_use_persist_buffers + && han_module->a2av_cache.smsc_decided) { + use_smsc = han_module->a2av_cache.use_smsc; + } else { + rc = decide_to_use_smsc_alg(&use_smsc, + sbuf, scounts, sdispls, sdtype, rbuf, rcounts, rdispls, rdtype, comm); + if (rc != 0) { + opal_output_verbose(1, mca_coll_han_component.han_output, + "decide_to_use_smsc_alg failed during execution! rc=%d\n", rc); + } + if (mca_coll_han_component.han_use_persist_buffers) { + han_module->a2av_cache.smsc_decided = true; + han_module->a2av_cache.use_smsc = use_smsc; + } } if (!use_smsc) { return han_module->previous_alltoallv(sbuf, scounts, sdispls, sdtype, rbuf, rcounts, rdispls, rdtype, @@ -790,22 +855,36 @@ int mca_coll_han_alltoallv_using_smsc( int up_rank = ompi_comm_rank(up_comm); struct gathered_data low_gather_in; - struct gathered_data *low_gather_out; + struct gathered_data *low_gather_out = NULL; low_gather_in.stype_serialized_length = ddt_pack_datatype(&sdtype->super, NULL); - uint8_t *serialization_buf; + uint8_t *serialization_buf = NULL; size_t serialization_buf_length = low_gather_in.stype_serialized_length + sizeof(struct peer_counts)*w_size; - /* allocate data */ - serialization_buf = malloc(serialization_buf_length); - low_gather_out = malloc(sizeof(*low_gather_out) * low_size); - struct peer_data *peers = malloc(sizeof(*peers) * low_size); - opal_datatype_t *peer_send_types = malloc(sizeof(*peer_send_types) * low_size); + struct peer_data *peers = NULL; + opal_datatype_t *peer_send_types = NULL; bool have_bufs_and_types = false; + if (mca_coll_han_component.han_use_persist_buffers) { + /* Persistent allocations (realloc-to-HWM) */ + rc = alltoallv_cache_setup(&han_module->a2av_cache, + serialization_buf_length, low_size); + if (rc != OMPI_SUCCESS) { goto cleanup; } + serialization_buf = han_module->a2av_cache.serial_buf; + low_gather_out = han_module->a2av_cache.gather_out; + peers = han_module->a2av_cache.peers; + peer_send_types = han_module->a2av_cache.peer_types; + } else { + /* Original upstream path — fresh allocations per call */ + serialization_buf = malloc(serialization_buf_length); + low_gather_out = malloc(sizeof(*low_gather_out) * low_size); + peers = malloc(sizeof(*peers) * low_size); + peer_send_types = malloc(sizeof(*peer_send_types) * low_size); + } + low_gather_in.serialization_buffer = serialization_buf; low_gather_in.sbuf = (void*)sbuf; // cast to discard the const @@ -831,6 +910,7 @@ int mca_coll_han_alltoallv_using_smsc( buf_packed += ddt_pack_datatype(&sdtype->super, serialization_buf + buf_packed); assert(buf_packed == serialization_buf_length); + /* Always run allgather — all ranks must participate (collective) */ rc = low_comm->c_coll->coll_allgather(&low_gather_in, sizeof(low_gather_in), MPI_BYTE, low_gather_out, sizeof(low_gather_in), MPI_BYTE, low_comm, low_comm->c_coll->coll_allgather_module); @@ -898,12 +978,21 @@ int mca_coll_han_alltoallv_using_smsc( } have_bufs_and_types = true; - send_from_addrs = malloc(sizeof(*send_from_addrs)*low_size); - recv_to_addrs = malloc(sizeof(*recv_to_addrs)*low_size); - send_counts = malloc(sizeof(*send_counts)*low_size); - recv_counts = malloc(sizeof(*recv_counts)*low_size); - send_types = malloc(sizeof(*send_types)*low_size); - recv_types = malloc(sizeof(*recv_types)*low_size); + if (mca_coll_han_component.han_use_persist_buffers) { + send_from_addrs = han_module->a2av_cache.send_from; + recv_to_addrs = han_module->a2av_cache.recv_to; + send_counts = han_module->a2av_cache.send_counts; + recv_counts = han_module->a2av_cache.recv_counts; + send_types = (opal_datatype_t **)han_module->a2av_cache.send_types; + recv_types = (opal_datatype_t **)han_module->a2av_cache.recv_types; + } else { + send_from_addrs = malloc(sizeof(*send_from_addrs)*low_size); + recv_to_addrs = malloc(sizeof(*recv_to_addrs)*low_size); + send_counts = malloc(sizeof(*send_counts)*low_size); + recv_counts = malloc(sizeof(*recv_counts)*low_size); + send_types = malloc(sizeof(*send_types)*low_size); + recv_types = malloc(sizeof(*recv_types)*low_size); + } /**** * Main exchange loop @@ -957,7 +1046,7 @@ int mca_coll_han_alltoallv_using_smsc( cleanup: low_comm->c_coll->coll_barrier(low_comm, low_comm->c_coll->coll_barrier_module); - if (send_from_addrs) { + if (send_from_addrs && !mca_coll_han_component.han_use_persist_buffers) { free(send_from_addrs); free(recv_to_addrs); free(send_counts); @@ -971,7 +1060,6 @@ int mca_coll_han_alltoallv_using_smsc( if (jlow != low_rank) { OBJ_DESTRUCT(&peer_send_types[jlow]); } - for (int jbuf=0; jbuf<2; jbuf++) { if (peers[jlow].map_ctx[jbuf]) { mca_smsc->unmap_peer_region(peers[jlow].map_ctx[jbuf]); @@ -979,10 +1067,12 @@ int mca_coll_han_alltoallv_using_smsc( } } } - free(serialization_buf); - free(low_gather_out); - free(peers); - free(peer_send_types); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(serialization_buf); + free(low_gather_out); + free(peers); + free(peer_send_types); + } OPAL_OUTPUT_VERBOSE((40, mca_coll_han_component.han_output, "Alltoall Complete with %d\n",rc)); diff --git a/ompi/mca/coll/han/coll_han_module.c b/ompi/mca/coll/han/coll_han_module.c index 9f69d9d7581..2ea27325728 100644 --- a/ompi/mca/coll/han/coll_han_module.c +++ b/ompi/mca/coll/han/coll_han_module.c @@ -209,6 +209,8 @@ static void mca_coll_han_module_construct(mca_coll_han_module_t * module) module->scratch_buf_size[0] = 0; module->scratch_buf[1] = NULL; module->scratch_buf_size[1] = 0; + memset(&module->a2a_cache, 0, sizeof(module->a2a_cache)); + memset(&module->a2av_cache, 0, sizeof(module->a2av_cache)); module->is_mapbycore = false; module->storage_initialized = false; for( i = 0; i < NB_TOPO_LVL; i++ ) { @@ -284,6 +286,33 @@ mca_coll_han_module_destruct(mca_coll_han_module_t * module) module->scratch_buf[1] = NULL; module->scratch_buf_size[1] = 0; + /* Alltoall cache cleanup */ + free(module->a2a_cache.bounce); + if (module->a2a_cache.map_ctx) { + if (mca_smsc) { + for (i = 0; i < module->a2a_cache.cached_low_size; i++) { + if (module->a2a_cache.map_ctx[i]) + mca_smsc->unmap_peer_region(module->a2a_cache.map_ctx[i]); + } + } + free(module->a2a_cache.map_ctx); + } + free(module->a2a_cache.low_bufs); + free(module->a2a_cache.gather_buf); + free(module->a2a_cache.recv_buf); + + /* Alltoallv cache cleanup */ + free(module->a2av_cache.serial_buf); + free(module->a2av_cache.gather_out); + free(module->a2av_cache.peers); + free(module->a2av_cache.peer_types); + free(module->a2av_cache.send_from); + free(module->a2av_cache.recv_to); + free(module->a2av_cache.send_counts); + free(module->a2av_cache.recv_counts); + free(module->a2av_cache.send_types); + free(module->a2av_cache.recv_types); + for(i=0 ; isub_comm[i]) { int cid = module->sub_comm[i]->c_index; From 19807e5e9dafc0a759c3b45632afec8ffca9dea3 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Thu, 16 Apr 2026 09:35:55 -0400 Subject: [PATCH 024/230] Call out BTLs that do not provide .btl_dump callback Signed-off-by: Joseph Schuchart --- ompi/mca/pml/ob1/pml_ob1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ompi/mca/pml/ob1/pml_ob1.c b/ompi/mca/pml/ob1/pml_ob1.c index 4a6e2245376..a08f5e7398c 100644 --- a/ompi/mca/pml/ob1/pml_ob1.c +++ b/ompi/mca/pml/ob1/pml_ob1.c @@ -723,6 +723,8 @@ int mca_pml_ob1_dump(struct ompi_communicator_t* comm, int verbose) for( n = 0; n < ep->btl_eager.arr_size; n++ ) { mca_bml_base_btl_t* bml_btl = &ep->btl_eager.bml_btls[n]; if (bml_btl->btl->btl_dump == NULL) { + opal_output(0, "BTL %s does not provide dump callback\n", + bml_btl->btl->btl_component->btl_version.mca_component_name); continue; } bml_btl->btl->btl_dump(bml_btl->btl, bml_btl->btl_endpoint, verbose); From 3b286ea0abb9c0116fbc93b8518dadba8413439c Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Thu, 16 Apr 2026 09:36:21 -0400 Subject: [PATCH 025/230] btl/uct: fall back to mca_btl_base_dump Signed-off-by: Joseph Schuchart --- opal/mca/btl/uct/btl_uct_module.c | 1 + 1 file changed, 1 insertion(+) diff --git a/opal/mca/btl/uct/btl_uct_module.c b/opal/mca/btl/uct/btl_uct_module.c index e847a45623f..f6c99a46cd0 100644 --- a/opal/mca/btl/uct/btl_uct_module.c +++ b/opal/mca/btl/uct/btl_uct_module.c @@ -356,6 +356,7 @@ mca_btl_uct_module_t mca_btl_uct_module_template = { .btl_finalize = mca_btl_uct_finalize, .btl_put = mca_btl_uct_put, .btl_get = mca_btl_uct_get, + .btl_dump = mca_btl_base_dump, .btl_register_mem = mca_btl_uct_register_mem, .btl_deregister_mem = mca_btl_uct_deregister_mem, .btl_atomic_op = mca_btl_uct_aop, From 0add05da4ff5d0d2a6dfcf15303e77757af6c363 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Fri, 17 Apr 2026 11:14:08 -0400 Subject: [PATCH 026/230] ci/backport: fix slash command permission check and update github-script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getCollaboratorPermissionLevel requires org-level "Members" read permission, which GITHUB_TOKEN cannot provide for organization repos, causing "Resource not accessible by integration" on every invocation. Replace with a check on author_association (OWNER/MEMBER/COLLABORATOR), which is available directly in the webhook payload. Also upgrade all actions/github-script@v7 to @v8 (Node.js 20 is deprecated and will be removed 2026-09-16). ci/backport: add reactions:write permission for slash command acknowledgement reactions.createForIssueComment requires a separate "reactions" write permission that is not covered by issues:write. Without it the call returns 403 ("Resource not accessible by integration"), which the catch block (only swallowing 422) re-throws as an unhandled error. ci/backport: swallow all reaction errors, drop invalid reactions permission 'reactions' is not a valid GITHUB_TOKEN permission scope (covered by issues:write in theory, but the call can still fail in some contexts). Since the 👀 reaction is a non-critical acknowledgement, swallow all errors rather than only 422, and remove the invalid permission entry that caused a workflow YAML validation error. ci/backport: replace reaction acknowledgement with a comment GITHUB_TOKEN cannot post reactions — 'reactions' is not a valid workflow permission scope and 'issues: write' does not cover it. Replace the createForIssueComment reaction with a plain comment listing the target branches, which works with the existing issues: write permission. ci/backport: check PR merged status from webhook payload, not API pulls.get requires pull-requests:read but that permission also appears to trigger "Resource not accessible by integration" in practice. The issue_comment webhook payload already carries context.payload.issue.pull_request.merged_at (non-null iff merged), so no API call is needed for this check at all. Also remove the now-unused pull-requests:read permission. ci/backport: make all comment postings best-effort Issues may be disabled on a repo (common for forks used for testing), causing every issues.createComment call to return 403 "Resource not accessible by integration" even with issues:write. Introduce a tryComment helper that swallows errors and logs a warning instead, so a missing Issues feature never aborts the workflow. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Joseph Schuchart --- .github/workflows/backport-command.yaml | 107 ++++++++---------------- .github/workflows/backport.yaml | 12 +-- 2 files changed, 41 insertions(+), 78 deletions(-) diff --git a/.github/workflows/backport-command.yaml b/.github/workflows/backport-command.yaml index c5738b2cd69..79378b17deb 100644 --- a/.github/workflows/backport-command.yaml +++ b/.github/workflows/backport-command.yaml @@ -29,12 +29,11 @@ jobs: if: github.event.issue.pull_request != null permissions: actions: write # trigger workflow_dispatch - issues: write # post reactions and comments - pull-requests: read # read PR merge status + issues: write # post comments steps: - name: Parse command and validate PR id: parse - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const body = context.payload.comment.body; @@ -42,6 +41,22 @@ jobs: const issueNumber = context.payload.issue.number; const login = context.payload.comment.user.login; + // Best-effort comment helper — if Issues are disabled on + // the repo (common for forks) the call returns 403 and we + // log a warning rather than aborting the workflow. + async function tryComment(text) { + try { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: text, + }); + } catch (err) { + core.warning(`Could not post comment: ${err.message}`); + } + } + // Detect a bare /backport with no arguments and reply helpfully. const bareMatch = /^\/backport\s*$/m.test(body); // Look for /backport with arguments at the start of any line. @@ -54,43 +69,20 @@ jobs: return; } - // Check actual repository permission level rather than - // author_association: MEMBER alone does not imply write - // access on org-owned public repos. - let permission = 'none'; - try { - const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ - owner: context.repo.owner, - repo: context.repo.repo, - username: login, - }); - // Use role_name rather than permission: the legacy - // permission field collapses 'maintain' into 'write', - // losing the distinction between the two tiers. - permission = data.role_name; // 'admin' | 'maintain' | 'write' | 'triage' | 'read' - } catch (err) { - if (err.status !== 404) throw err; - // 404 = not a collaborator; permission stays 'none' - } - if (!['admin', 'maintain', 'write'].includes(permission)) { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `âš ī¸ @${login} Backports can only be triggered by users with write, maintain, or admin access.`, - }); + // Use author_association from the webhook payload — no extra + // API call required. GITHUB_TOKEN cannot call + // getCollaboratorPermissionLevel on org repos (needs org-level + // "Members" read permission unavailable to GITHUB_TOKEN). + const assoc = context.payload.comment.author_association; + if (!['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc)) { + await tryComment(`âš ī¸ @${login} Backports can only be triggered by repository owners, organization members, or collaborators.`); core.setOutput('triggered', 'false'); return; } if (bareMatch && !match) { core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', - }); + await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); return; } if (!match) { @@ -103,12 +95,7 @@ jobs: if (branches.length === 0) { // e.g. "/backport ,,," — separators only, no real branch names core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', - }); + await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); return; } @@ -119,45 +106,21 @@ jobs: const invalidBranches = branches.filter(b => !validBranchRe.test(b)); if (invalidBranches.length > 0) { core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`, - }); + await tryComment(`âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`); return; } // Confirm the PR is actually merged. - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: issueNumber, - }); - - if (!pr.merged) { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ Cannot backport: this PR has not been merged yet.', - }); + // merged_at is present in the issue_comment webhook payload + // for PRs, so no extra API call is needed. + if (!context.payload.issue.pull_request.merged_at) { + await tryComment('âš ī¸ Cannot backport: this PR has not been merged yet.'); core.setOutput('triggered', 'false'); return; } - // Acknowledge the command with a 👀 reaction. - // Ignore 422 (reaction already exists) so re-runs don't fail. - try { - await github.rest.reactions.createForIssueComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: commentId, - content: 'eyes', - }); - } catch (err) { - if (err.status !== 422) throw err; - } + // Acknowledge the command with a comment. + await tryComment(`👀 Dispatching backport of this PR to: ${branches.map(b => `\`${b}\``).join(', ')}.`); core.setOutput('triggered', 'true'); core.setOutput('pr_number', String(issueNumber)); @@ -166,7 +129,7 @@ jobs: - name: Trigger backport workflow if: steps.parse.outputs.triggered == 'true' - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: PR_NUMBER: ${{ steps.parse.outputs.pr_number }} BRANCHES: ${{ steps.parse.outputs.branches }} diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml index ebff4e66ace..724f678707b 100644 --- a/.github/workflows/backport.yaml +++ b/.github/workflows/backport.yaml @@ -54,7 +54,7 @@ jobs: steps: - name: Determine backport targets id: targets - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | let branches = []; @@ -137,7 +137,7 @@ jobs: # Use paginate() so PRs with more than 100 commits are handled correctly. - name: Fetch PR metadata id: pr_meta - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const pr = await github.rest.pulls.get({ @@ -163,7 +163,7 @@ jobs: # work. Post a comment and skip if it does not. - name: Validate target branch exists id: validate - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | try { @@ -264,7 +264,7 @@ jobs: # All commits were already present in the target branch — no PR needed. - name: Comment when nothing to backport if: steps.cherry_pick.outputs.nothing_to_backport == 'true' - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | await github.rest.issues.createComment({ @@ -280,7 +280,7 @@ jobs: if: >- steps.cherry_pick.outputs.cherry_pick_failed == 'false' && steps.cherry_pick.outputs.nothing_to_backport == 'false' - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: ORIGINAL_TITLE: ${{ steps.pr_meta.outputs.title }} ORIGINAL_BODY: ${{ steps.pr_meta.outputs.body }} @@ -348,7 +348,7 @@ jobs: # developer knows to create the backport manually. - name: Comment on cherry-pick failure if: steps.cherry_pick.outputs.cherry_pick_failed == 'true' - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: FAILED_SHA: ${{ steps.cherry_pick.outputs.failed_sha }} with: From b4624fa434f81aad22fd8bcafe3f27140c9a530e Mon Sep 17 00:00:00 2001 From: Yin Li Date: Thu, 16 Apr 2026 17:00:49 -0700 Subject: [PATCH 027/230] coll/han: Enable persist buffers and set fragment sizes by default Set coll_han_use_persist_buffers default to true, and set fragment sizes to recommended values (64KB small, 1MB large). The optimization is safe for all tested platforms and provides significant gains with no regressions. Can be disabled at runtime with: --mca coll_han_use_persist_buffers false Also gate the simple allgather path's tmp_buf and reorder_buf behind the persist flag, consistent with all other HAN collectives. Signed-off-by: Yin Li --- ompi/mca/coll/han/coll_han.h | 6 ++++++ ompi/mca/coll/han/coll_han_allgather.c | 14 ++++++++++---- ompi/mca/coll/han/coll_han_alltoall.c | 4 +++- ompi/mca/coll/han/coll_han_alltoallv.c | 2 +- ompi/mca/coll/han/coll_han_component.c | 6 +++--- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/ompi/mca/coll/han/coll_han.h b/ompi/mca/coll/han/coll_han.h index 80c018a3104..01237afc9f7 100644 --- a/ompi/mca/coll/han/coll_han.h +++ b/ompi/mca/coll/han/coll_han.h @@ -91,6 +91,12 @@ enum { */ static inline char *han_scratch_alloc(char **buf, size_t *buf_size, size_t needed) { + if (0 == needed) { + /* Return a valid non-NULL pointer for zero-size allocations, + * matching malloc(0) behavior that callers rely on. */ + static char zero_len_sentinel; + return &zero_len_sentinel; + } if (*buf_size < needed) { char *p = realloc(*buf, needed); if (NULL == p) return NULL; diff --git a/ompi/mca/coll/han/coll_han_allgather.c b/ompi/mca/coll/han/coll_han_allgather.c index 9aa9c376932..6d561bf12ac 100644 --- a/ompi/mca/coll/han/coll_han_allgather.c +++ b/ompi/mca/coll/han/coll_han_allgather.c @@ -870,7 +870,9 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, /* Compute the size to receive all the local data, including datatypes empty gaps */ rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size, &rgap); /* intermediary buffer on node leaders to gather on low comm */ - tmp_buf = (char *) malloc(rsize); + tmp_buf = han_scratch_or_malloc(&han_module->scratch_buf[1], + &han_module->scratch_buf_size[1], + rsize, mca_coll_han_component.han_use_persist_buffers); if (NULL == tmp_buf) { return OMPI_ERR_OUT_OF_RESOURCE; } @@ -918,7 +920,9 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, } ptrdiff_t rsize, rgap = 0; rsize = opal_datatype_span(&rdtype->super, (int64_t)rcount * low_size * up_size, &rgap); - reorder_buf = (char *) malloc(rsize); + reorder_buf = han_scratch_or_malloc(&han_module->scratch_buf[0], + &han_module->scratch_buf_size[0], + rsize, mca_coll_han_component.han_use_persist_buffers); reorder_buf_start = reorder_buf - rgap; } @@ -927,7 +931,7 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, reorder_buf_start, rcount*low_size, rdtype, up_comm, up_comm->c_coll->coll_allgather_module); - if (tmp_buf != NULL) { + if (tmp_buf != NULL && !mca_coll_han_component.han_use_persist_buffers) { free(tmp_buf); tmp_buf = NULL; tmp_buf_start = NULL; @@ -941,7 +945,9 @@ mca_coll_han_allgather_intra_simple(const void *sbuf, size_t scount, ompi_coll_han_reorder_gather(reorder_buf_start, rbuf, rcount, rdtype, comm, topo); - free(reorder_buf); + if (!mca_coll_han_component.han_use_persist_buffers) { + free(reorder_buf); + } reorder_buf = NULL; } diff --git a/ompi/mca/coll/han/coll_han_alltoall.c b/ompi/mca/coll/han/coll_han_alltoall.c index 27f6a1853c8..af4e1e7ac68 100644 --- a/ompi/mca/coll/han/coll_han_alltoall.c +++ b/ompi/mca/coll/han/coll_han_alltoall.c @@ -63,7 +63,9 @@ static inline int ring_partner(int rank, int round, int comm_size) { /** * Set up or reuse cached SMSC arrays for alltoall. - * Returns true if cache was valid (allgather + map can be skipped). + * Returns 1 if cache was valid (allgather + map can be skipped), + * 0 on cache miss (arrays allocated, caller must populate), + * or -1 on allocation failure. */ static int alltoall_cache_setup( mca_coll_han_module_t *han_module, diff --git a/ompi/mca/coll/han/coll_han_alltoallv.c b/ompi/mca/coll/han/coll_han_alltoallv.c index 4d19b0311db..ad9c92892e9 100644 --- a/ompi/mca/coll/han/coll_han_alltoallv.c +++ b/ompi/mca/coll/han/coll_han_alltoallv.c @@ -586,7 +586,7 @@ static int alltoallv_sendrecv_w( /** * Set up persistent allocations for alltoallv. * Grows arrays to high-water mark to avoid per-call malloc/free. - * Returns 0 on success, OMPI_ERR_OUT_OF_RESOURCE on failure. + * Returns OMPI_SUCCESS on success, OMPI_ERR_OUT_OF_RESOURCE on failure. */ static int alltoallv_cache_setup( struct han_alltoallv_cache *c, diff --git a/ompi/mca/coll/han/coll_han_component.c b/ompi/mca/coll/han/coll_han_component.c index 017487b2cc7..9e7f1259feb 100644 --- a/ompi/mca/coll/han/coll_han_component.c +++ b/ompi/mca/coll/han/coll_han_component.c @@ -640,7 +640,7 @@ static int han_register(void) &(cs->max_dynamic_errors)); - cs->han_use_persist_buffers = false; + cs->han_use_persist_buffers = true; (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, "use_persist_buffers", "Use persistent/freelist buffers to avoid malloc/free in collectives (0 = disabled)", @@ -649,7 +649,7 @@ static int han_register(void) MCA_BASE_VAR_SCOPE_ALL, &(cs->han_use_persist_buffers)); - cs->han_fragment_size = 0; + cs->han_fragment_size = 65536; (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, "fragment_size", "Size of freelist fragment buffers for collective operations (0 = disabled)", @@ -658,7 +658,7 @@ static int han_register(void) MCA_BASE_VAR_SCOPE_ALL, &(cs->han_fragment_size)); - cs->han_large_fragment_size = 0; + cs->han_large_fragment_size = 1048576; (void) mca_base_component_var_register(&mca_coll_han_component.super.collm_version, "large_fragment_size", "Size of large freelist buffers for pipeline reorder (0 = use small fragments or malloc)", From 6117a395c89f517f6a548b33ba4ec49f45492ec6 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Tue, 21 Apr 2026 16:11:05 -0400 Subject: [PATCH 028/230] spc: add missing per-function counters for partitioned communication The five MPI partitioned communication functions were either recording to the wrong SPC counter or had no counter at all: - MPI_Pready_list and MPI_Pready_range were both recording to OMPI_SPC_PREADY (the MPI_Pready counter) instead of their own dedicated counters. Add OMPI_SPC_PREADY_LIST and OMPI_SPC_PREADY_RANGE and update the .c.in templates accordingly. - MPI_Precv_init and MPI_Psend_init had no SPC_RECORD call at all. Add OMPI_SPC_PRECV_INIT and OMPI_SPC_PSEND_INIT counters and wire them into the corresponding .c.in templates. - Update the OMPI_SPC_PREADY description in ompi_spc.c to refer only to MPI_Pready now that the list/range variants have their own entry. Also guard spc_example in examples/Makefile behind a runtime check so it is only compiled when the installation was built with --enable-spc. Previously it was an unconditional dependency of the 'all' target, causing build failures when SPC support was absent. Closes #9490 (rebased and corrected version of the closed PR; fixes applied to the .c.in templates rather than the generated .c files, and only the four genuinely missing enum values are added since OMPI_SPC_PARRIVED and OMPI_SPC_PREADY already landed on main). Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: George Bosilca --- examples/Makefile | 5 ++++- ompi/mpi/c/pready_list.c.in | 3 ++- ompi/mpi/c/pready_range.c.in | 2 +- ompi/mpi/c/precv_init.c.in | 2 ++ ompi/mpi/c/psend_init.c.in | 2 ++ ompi/runtime/ompi_spc.c | 6 +++++- ompi/runtime/ompi_spc.h | 4 ++++ 7 files changed, 20 insertions(+), 4 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 735b911923d..a92ff5400b7 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -74,7 +74,7 @@ EXAMPLES = \ # others if we have the appropriate Open MPI / OpenSHMEM language # bindings. -all: hello_c ring_c connectivity_c spc_example hello_sessions_c +all: hello_c ring_c connectivity_c hello_sessions_c @ if which ompi_info >/dev/null 2>&1 ; then \ $(MAKE) mpi; \ fi @@ -97,6 +97,9 @@ mpi: @ if ompi_info --parsable | grep -q bindings:java:yes >/dev/null; then \ $(MAKE) Hello.class Ring.class; \ fi + @ if ompi_info --parsable | grep -q enable-spc >/dev/null; then \ + $(MAKE) spc_example; \ + fi # OpenSHMEM examples diff --git a/ompi/mpi/c/pready_list.c.in b/ompi/mpi/c/pready_list.c.in index 086ff618954..d781514eb83 100644 --- a/ompi/mpi/c/pready_list.c.in +++ b/ompi/mpi/c/pready_list.c.in @@ -38,7 +38,8 @@ PROTOTYPE ERROR_CLASS pready_list(INT length, INT_ARRAY partitions, REQUEST request) { int rc = OMPI_SUCCESS; - SPC_RECORD(OMPI_SPC_PREADY, 1); + + SPC_RECORD(OMPI_SPC_PREADY_LIST, 1); if (MPI_PARAM_CHECK) { rc = OMPI_SUCCESS; diff --git a/ompi/mpi/c/pready_range.c.in b/ompi/mpi/c/pready_range.c.in index 7dfc2df59ae..1cc962198a8 100644 --- a/ompi/mpi/c/pready_range.c.in +++ b/ompi/mpi/c/pready_range.c.in @@ -39,7 +39,7 @@ PROTOTYPE ERROR_CLASS pready_range(INT partition_low, INT partition_high, REQUES { int rc; - SPC_RECORD(OMPI_SPC_PREADY, 1); + SPC_RECORD(OMPI_SPC_PREADY_RANGE, 1); if (MPI_PARAM_CHECK) { rc = OMPI_SUCCESS; diff --git a/ompi/mpi/c/precv_init.c.in b/ompi/mpi/c/precv_init.c.in index 31b1f3d97f8..ea7224fe936 100644 --- a/ompi/mpi/c/precv_init.c.in +++ b/ompi/mpi/c/precv_init.c.in @@ -42,6 +42,8 @@ PROTOTYPE ERROR_CLASS precv_init(BUFFER_OUT buf, INT partitions, PARTITIONED_COU { int rc; + SPC_RECORD(OMPI_SPC_PRECV_INIT, 1); + if (MPI_PARAM_CHECK) { rc = OMPI_SUCCESS; diff --git a/ompi/mpi/c/psend_init.c.in b/ompi/mpi/c/psend_init.c.in index 7ddf8335090..5458062008b 100644 --- a/ompi/mpi/c/psend_init.c.in +++ b/ompi/mpi/c/psend_init.c.in @@ -42,6 +42,8 @@ PROTOTYPE ERROR_CLASS psend_init(BUFFER buf, INT partitions, PARTITIONED_COUNT c { int rc; + SPC_RECORD(OMPI_SPC_PSEND_INIT, 1); + if (MPI_PARAM_CHECK) { rc = OMPI_SUCCESS; diff --git a/ompi/runtime/ompi_spc.c b/ompi/runtime/ompi_spc.c index 6f1d8aa7d6a..fb097ac6077 100644 --- a/ompi/runtime/ompi_spc.c +++ b/ompi/runtime/ompi_spc.c @@ -170,7 +170,11 @@ static const ompi_spc_event_t ompi_spc_events_desc[OMPI_SPC_NUM_COUNTERS] = { SET_COUNTER_ARRAY(OMPI_SPC_ISENDRECV, "The number of times MPI_Isendrecv was called.", false, false), SET_COUNTER_ARRAY(OMPI_SPC_ISENDRECV_REPLACE, "The number of times MPI_Isendrecv_replace was called.", false, false), SET_COUNTER_ARRAY(OMPI_SPC_PARRIVED, "The number of times MPI_Parrived was called.", false, false), - SET_COUNTER_ARRAY(OMPI_SPC_PREADY, "The number of times MPI_Pready (or similar functions) was called.", false, false), + SET_COUNTER_ARRAY(OMPI_SPC_PREADY, "The number of times MPI_Pready was called.", false, false), + SET_COUNTER_ARRAY(OMPI_SPC_PREADY_LIST, "The number of times MPI_Pready_list was called.", false, false), + SET_COUNTER_ARRAY(OMPI_SPC_PREADY_RANGE, "The number of times MPI_Pready_range was called.", false, false), + SET_COUNTER_ARRAY(OMPI_SPC_PRECV_INIT, "The number of times MPI_Precv_init was called.", false, false), + SET_COUNTER_ARRAY(OMPI_SPC_PSEND_INIT, "The number of times MPI_Psend_init was called.", false, false) }; /* An array of event structures to store the event data (value, attachments, flags) */ diff --git a/ompi/runtime/ompi_spc.h b/ompi/runtime/ompi_spc.h index 76ec7f25f16..ca61aa8a409 100644 --- a/ompi/runtime/ompi_spc.h +++ b/ompi/runtime/ompi_spc.h @@ -156,6 +156,10 @@ typedef enum ompi_spc_counters { OMPI_SPC_ISENDRECV_REPLACE, OMPI_SPC_PARRIVED, OMPI_SPC_PREADY, + OMPI_SPC_PREADY_LIST, + OMPI_SPC_PREADY_RANGE, + OMPI_SPC_PRECV_INIT, + OMPI_SPC_PSEND_INIT, OMPI_SPC_NUM_COUNTERS /* This serves as the number of counters. It must be last. */ } ompi_spc_counters_t; From 6a509ec08d558e27140f86d41e8a03e9b89d4970 Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Thu, 23 Apr 2026 08:08:08 -0700 Subject: [PATCH 029/230] ompi: Fix remnants of req_complete being a bool The CM PML and Persist Part components both still used the request object's req_complete field like a bool, despite it being a void*. Change both to use REQUEST_PENDING as expected. This fixes a number of warnings (errors on FreeBSD). Signed-off-by: Brian Barrett --- ompi/mca/part/persist/part_persist.h | 1 - ompi/mca/pml/cm/pml_cm_recvreq.h | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ompi/mca/part/persist/part_persist.h b/ompi/mca/part/persist/part_persist.h index 86fb9bac42d..c23899184d8 100644 --- a/ompi/mca/part/persist/part_persist.h +++ b/ompi/mca/part/persist/part_persist.h @@ -525,7 +525,6 @@ mca_part_persist_start(size_t count, ompi_request_t** requests) req->req_ompi.req_status.MPI_ERROR = OMPI_SUCCESS; req->req_ompi.req_status._cancelled = 0; req->req_part_complete = false; - req->req_ompi.req_complete = false; OPAL_ATOMIC_SWAP_PTR(&req->req_ompi.req_complete, REQUEST_PENDING); } diff --git a/ompi/mca/pml/cm/pml_cm_recvreq.h b/ompi/mca/pml/cm/pml_cm_recvreq.h index 1c1cca4616d..250305e6864 100644 --- a/ompi/mca/pml/cm/pml_cm_recvreq.h +++ b/ompi/mca/pml/cm/pml_cm_recvreq.h @@ -234,7 +234,7 @@ do { \ do { \ /* init/re-init the request */ \ request->req_base.req_pml_complete = false; \ - request->req_base.req_ompi.req_complete = false; \ + request->req_base.req_ompi.req_complete = REQUEST_PENDING; \ request->req_base.req_ompi.req_state = OMPI_REQUEST_ACTIVE; \ \ /* always set the req_status.MPI_TAG to ANY_TAG before starting the \ @@ -256,7 +256,7 @@ do { \ do { \ /* init/re-init the request */ \ request->req_base.req_pml_complete = false; \ - request->req_base.req_ompi.req_complete = false; \ + request->req_base.req_ompi.req_complete = REQUEST_PENDING; \ request->req_base.req_ompi.req_state = OMPI_REQUEST_ACTIVE; \ \ /* always set the req_status.MPI_TAG to ANY_TAG before starting the \ @@ -278,7 +278,7 @@ do { \ /* opal_output(0, "posting hvy request %d\n", request); */ \ /* init/re-init the request */ \ request->req_base.req_pml_complete = false; \ - request->req_base.req_ompi.req_complete = false; \ + request->req_base.req_ompi.req_complete = REQUEST_PENDING; \ request->req_base.req_ompi.req_state = OMPI_REQUEST_ACTIVE; \ \ /* always set the req_status.MPI_TAG to ANY_TAG before starting the \ From 7c713eb4e11f17ca6aa0600f22031fe521d8a829 Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Mon, 13 Apr 2026 12:09:21 -0700 Subject: [PATCH 030/230] ci: Run test enabling DSO components We have not been testing that building components as DSOs works properly and it had broken. 818a7baab6 fixes the underlying issue, so add a test to keep us from breaking it again. Signed-off-by: Brian Barrett --- .ci/community-jenkins/Jenkinsfile | 3 ++- .ci/community-jenkins/pr-builder.sh | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.ci/community-jenkins/Jenkinsfile b/.ci/community-jenkins/Jenkinsfile index 2c20d630ac1..adef64f2d17 100644 --- a/.ci/community-jenkins/Jenkinsfile +++ b/.ci/community-jenkins/Jenkinsfile @@ -59,7 +59,8 @@ def prepare_check_stages() { "--disable-dlopen", "--disable-oshmem", "--enable-builtin-atomic", - "--enable-ipv6" + "--enable-ipv6", + "--enable-mca-dso" ] def compilers = [ "gcc14", diff --git a/.ci/community-jenkins/pr-builder.sh b/.ci/community-jenkins/pr-builder.sh index 88426859bf0..ae0912a8b3b 100755 --- a/.ci/community-jenkins/pr-builder.sh +++ b/.ci/community-jenkins/pr-builder.sh @@ -241,10 +241,13 @@ fi echo "--> running make ${MAKE_J} ${MAKE_ARGS} all" make ${MAKE_J} ${MAKE_ARGS} all -echo "--> running make check" -make ${MAKE_ARGS} check +# while backwards, it is important to run "make install" before "make check", +# because many of the tests call opal_init(), which will fail unless it can find +# components. echo "--> running make install" make ${MAKE_ARGS} install +echo "--> running make check" +make ${MAKE_ARGS} check export PATH="${PREFIX}/bin":${PATH} From f313c046f2059f294070405565a819866f75de0d Mon Sep 17 00:00:00 2001 From: Gonzalosilvalde Date: Sat, 4 Apr 2026 00:47:52 +0200 Subject: [PATCH 031/230] btl/self: add accelerator-aware memory copy for put/get The btl/self component was not accelerator aware. Send-to-self operations involving GPU memory would copy data through the host instead of performing a direct device memory copy. Add mca_btl_self_memcpy() which checks whether src/dst buffers reside in accelerator memory via opal_accelerator.check_addr() and dispatches to opal_accelerator.mem_copy() accordingly, falling back to memcpy() when both buffers are in host memory. Signed-off-by: Gonzalosilvalde --- opal/mca/btl/self/btl_self.c | 57 ++++++++++++++++++++++++-- opal/mca/btl/self/btl_self_component.c | 2 + 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/opal/mca/btl/self/btl_self.c b/opal/mca/btl/self/btl_self.c index 1790d576780..f7ed1f9a49e 100644 --- a/opal/mca/btl/self/btl_self.c +++ b/opal/mca/btl/self/btl_self.c @@ -32,8 +32,57 @@ #include "btl_self_frag.h" #include "opal/class/opal_bitmap.h" #include "opal/datatype/opal_convertor.h" +#include "opal/mca/accelerator/accelerator.h" +#include "opal/mca/accelerator/base/base.h" +#include "opal/mca/btl/base/btl_base_error.h" #include "opal/util/proc.h" +/** + * Accelerator-aware memory copy. Checks whether src and/or dst reside + * in accelerator memory and dispatches to opal_accelerator.mem_copy() + * accordingly. Falls back to a regular memcpy() when both buffers are in + * host memory. + * + * @param dst (IN) Destination buffer (host or device memory) + * @param src (IN) Source buffer (host or device memory) + * @param size (IN) Number of bytes to copy + * @return OPAL_SUCCESS or error status on failure. + */ +static int mca_btl_self_memcpy(void *dst, const void *src, size_t size) +{ + int dst_dev = MCA_ACCELERATOR_NO_DEVICE_ID; + int src_dev = MCA_ACCELERATOR_NO_DEVICE_ID; + int dst_type, src_type; + int copy_type = MCA_ACCELERATOR_TRANSFER_DTOD; + uint64_t flags; + int rc; + + dst_type = opal_accelerator.check_addr(dst, &dst_dev, &flags); + src_type = opal_accelerator.check_addr(src, &src_dev, &flags); + + if (dst_type < 0 || src_type < 0) { + BTL_ERROR(("check_addr failed (dst_type=%d, src_type=%d)", dst_type, src_type)); + return OPAL_ERROR; + } + + if (0 == dst_type && 0 == src_type) { + memcpy(dst, src, size); + return OPAL_SUCCESS; + } else if (dst_type == 0 && src_type > 0) { + copy_type = MCA_ACCELERATOR_TRANSFER_DTOH; + dst_dev = MCA_ACCELERATOR_NO_DEVICE_ID; + } else if (dst_type > 0 && src_type == 0) { + copy_type = MCA_ACCELERATOR_TRANSFER_HTOD; + src_dev = MCA_ACCELERATOR_NO_DEVICE_ID; + } + + rc = opal_accelerator.mem_copy(dst_dev, src_dev, dst, src, size, copy_type); + if (OPAL_UNLIKELY(OPAL_SUCCESS != rc)) { + BTL_ERROR(("accelerator mem_copy failed (rc=%d)", rc)); + } + return rc; +} + /** * PML->BTL notification of change in the process list. * PML->BTL Notification that a receive fragment has been matched. @@ -268,9 +317,9 @@ static int mca_btl_self_put(mca_btl_base_module_t *btl, struct mca_btl_base_endp int flags, int order, mca_btl_base_rdma_completion_fn_t cbfunc, void *cbcontext, void *cbdata) { - memcpy((void *) (intptr_t) remote_address, local_address, size); + int rc = mca_btl_self_memcpy((void *) (intptr_t) remote_address, local_address, size); - cbfunc(btl, endpoint, local_address, NULL, cbcontext, cbdata, OPAL_SUCCESS); + cbfunc(btl, endpoint, local_address, NULL, cbcontext, cbdata, rc); return OPAL_SUCCESS; } @@ -282,9 +331,9 @@ static int mca_btl_self_get(mca_btl_base_module_t *btl, struct mca_btl_base_endp int flags, int order, mca_btl_base_rdma_completion_fn_t cbfunc, void *cbcontext, void *cbdata) { - memcpy(local_address, (void *) (intptr_t) remote_address, size); + int rc = mca_btl_self_memcpy(local_address, (void *) (intptr_t) remote_address, size); - cbfunc(btl, endpoint, local_address, NULL, cbcontext, cbdata, OPAL_SUCCESS); + cbfunc(btl, endpoint, local_address, NULL, cbcontext, cbdata, rc); return OPAL_SUCCESS; } diff --git a/opal/mca/btl/self/btl_self_component.c b/opal/mca/btl/self/btl_self_component.c index 4fc78e6abb8..109afba5271 100644 --- a/opal/mca/btl/self/btl_self_component.c +++ b/opal/mca/btl/self/btl_self_component.c @@ -110,6 +110,8 @@ static int mca_btl_self_component_register(void) mca_btl_self.btl_flags = MCA_BTL_FLAGS_RDMA | MCA_BTL_FLAGS_SEND_INPLACE | MCA_BTL_FLAGS_SEND; /* for self, remote completion is local completion */ mca_btl_self.btl_flags |= MCA_BTL_FLAGS_RDMA_REMOTE_COMPLETION; + /* put/get go directly to/from accelerator memory, no host staging */ + mca_btl_self.btl_flags |= MCA_BTL_FLAGS_ACCELERATOR_RDMA; mca_btl_self.btl_bandwidth = 100; mca_btl_self.btl_latency = 0; mca_btl_base_param_register(&mca_btl_self_component.super.btl_version, &mca_btl_self); From 37e8a72fe6c8e85cf453266abd5013eb7e3a4d88 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Sat, 25 Apr 2026 12:41:39 -0400 Subject: [PATCH 032/230] btl/sm: bound peer-supplied descriptor copy in endpoint destructor mca_btl_sm_endpoint_destructor() copied the serialized shmem descriptor stored at ep->seg_ds into a fixed-size stack-local opal_shmem_ds_t using opal_shmem_sizeof_shmem_ds(ep->seg_ds) as the length. That length is offsetof(seg_name) + strlen(seg_name) + 1, where seg_name is read from the heap allocation that was sized to whatever the peer announced via its modex. Two problems follow: strlen() can walk past the end of the heap object when the peer's serialized seg_name is not NUL-terminated within the allocated bytes, and the resulting length is then memcpy'd into the stack object with no clamp to its real size, so a sufficiently long walk overwrites adjacent stack data. Fix it on the receiver side, where the buffer is allocated: - Validate modex->seg_ds_size: must be > 0, must fit in opal_shmem_ds_t, and must not exceed the bytes actually delivered by the modex (msg_size). - Allocate the full sizeof(opal_shmem_ds_t) and zero it with calloc() so a short copy leaves the tail well-defined. - Force seg_name[OPAL_PATH_MAX - 1] = '\0' so any later strlen() over the buffer terminates inside it. With ep->seg_ds now always a full, well-formed struct, the destructor no longer needs the stack copy: detach reads the heap object directly and free() releases it afterwards. Closes #13781 Signed-off-by: George Bosilca Co-Authored-By: Claude Opus 4.7 --- opal/mca/btl/sm/btl_sm_module.c | 35 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/opal/mca/btl/sm/btl_sm_module.c b/opal/mca/btl/sm/btl_sm_module.c index ebf7aaaaecf..7c92537e08e 100644 --- a/opal/mca/btl/sm/btl_sm_module.c +++ b/opal/mca/btl/sm/btl_sm_module.c @@ -186,13 +186,32 @@ static int init_sm_endpoint(struct mca_btl_base_endpoint_t **ep_out, struct opal mca_btl_sm.super.btl_put = NULL; mca_btl_sm.super.btl_flags &= ~MCA_BTL_FLAGS_RDMA; } - /* store a copy of the segment information for detach */ - ep->seg_ds = malloc(modex->seg_ds_size); + /* Validate the peer-supplied descriptor length before trusting it. + * The modex must actually contain seg_ds_size bytes of seg_ds, and + * that length must fit in opal_shmem_ds_t. */ + const size_t modex_hdr_size = sizeof(*modex) - sizeof(modex->seg_ds); + if (modex->seg_ds_size <= 0 + || (size_t) modex->seg_ds_size > sizeof(opal_shmem_ds_t) + || msg_size < modex_hdr_size + || (size_t) modex->seg_ds_size > msg_size - modex_hdr_size) { + free(modex); + return OPAL_ERR_BAD_PARAM; + } + + /* Always allocate the full struct so later consumers (detach, + * opal_shmem_sizeof_shmem_ds) cannot read or write past the end + * of the heap object. */ + ep->seg_ds = calloc(1, sizeof(opal_shmem_ds_t)); if (NULL == ep->seg_ds) { + free(modex); return OPAL_ERR_OUT_OF_RESOURCE; } memcpy(ep->seg_ds, &modex->seg_ds, modex->seg_ds_size); + /* Guarantee seg_name is NUL-terminated even if the peer sent an + * unterminated path, so opal_shmem_sizeof_shmem_ds()'s strlen + * cannot run past the buffer. */ + ep->seg_ds->seg_name[OPAL_PATH_MAX - 1] = '\0'; ep->segment_base = opal_shmem_segment_attach(ep->seg_ds); if (NULL == ep->segment_base) { @@ -514,17 +533,11 @@ static void mca_btl_sm_endpoint_destructor(mca_btl_sm_endpoint_t *ep) OBJ_DESTRUCT(&ep->pending_frags_lock); if (ep->seg_ds) { - opal_shmem_ds_t seg_ds; - - /* opal_shmem_segment_detach expects a opal_shmem_ds_t and will - * stomp past the end of the seg_ds if it is too small (which - * ep->seg_ds probably is) */ - memcpy(&seg_ds, ep->seg_ds, opal_shmem_sizeof_shmem_ds(ep->seg_ds)); + /* ep->seg_ds is allocated full-size in init_sm_endpoint, so detach + * cannot read or write past the end of it. */ + opal_shmem_segment_detach(ep->seg_ds); free(ep->seg_ds); ep->seg_ds = NULL; - - /* disconnect from the peer's segment */ - opal_shmem_segment_detach(&seg_ds); } if (ep->fbox_out.fbox) { From 76b3db57fb6ef9447a8c740354a0a920e4fb69e5 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Wed, 22 Oct 2025 20:47:30 -0400 Subject: [PATCH 033/230] Big count support for datatypes Utilize the count and disp arrays for type-punning of int and MPI_Count arguments to datatype creation functions. Pack integer or MPI_Count depending on what is needed when packing a datatype. Adjust places where bigcount support for datatpyes was missing. Signed-off-by: Joseph Schuchart --- VERSION | 2 +- ompi/datatype/ompi_datatype.h | 51 +- ompi/datatype/ompi_datatype_args.c | 620 +++++++++++++----- ompi/datatype/ompi_datatype_create.c | 3 +- .../ompi_datatype_create_contiguous.c | 3 +- ompi/datatype/ompi_datatype_create_darray.c | 37 +- ompi/datatype/ompi_datatype_create_indexed.c | 69 +- ompi/datatype/ompi_datatype_create_struct.c | 35 +- ompi/datatype/ompi_datatype_create_subarray.c | 28 +- ompi/datatype/ompi_datatype_create_vector.c | 9 +- ompi/datatype/ompi_datatype_match_size.c | 5 +- ompi/datatype/ompi_datatype_module.c | 5 +- ompi/datatype/ompi_datatype_sndrcv.c | 13 +- ompi/mca/coll/base/coll_base_allgatherv.c | 46 +- .../base/coll_base_reduce_scatter_block.c | 10 +- ompi/mca/coll/inter/coll_inter_allgatherv.c | 16 +- ompi/mca/coll/inter/coll_inter_gatherv.c | 15 +- ompi/mca/coll/inter/coll_inter_scatterv.c | 17 +- .../mca/common/ompio/common_ompio_file_open.c | 5 +- .../common/ompio/common_ompio_file_read_all.c | 12 +- .../mca/common/ompio/common_ompio_file_view.c | 5 +- ompi/mca/fcoll/base/fcoll_base_coll_array.c | 19 +- .../dynamic/fcoll_dynamic_file_write_all.c | 5 +- .../fcoll_dynamic_gen2_file_write_all.c | 11 +- .../fcoll/vulcan/fcoll_vulcan_file_read_all.c | 9 +- .../vulcan/fcoll_vulcan_file_write_all.c | 9 +- ompi/mca/io/ompio/io_ompio.c | 5 +- ompi/mca/io/ompio/io_ompio_file_set_view.c | 5 +- ompi/mpi/c/get_elements.c.in | 4 +- ompi/mpi/c/type_contiguous.c.in | 25 +- ompi/mpi/c/type_create_darray.c.in | 55 +- ompi/mpi/c/type_create_f90_complex.c.in | 7 +- ompi/mpi/c/type_create_f90_integer.c.in | 6 +- ompi/mpi/c/type_create_f90_real.c.in | 5 +- ompi/mpi/c/type_create_hindexed.c.in | 60 +- ompi/mpi/c/type_create_hindexed_block.c.in | 46 +- ompi/mpi/c/type_create_hvector.c.in | 27 +- ompi/mpi/c/type_create_indexed_block.c.in | 32 +- ompi/mpi/c/type_create_resized.c.in | 7 +- ompi/mpi/c/type_create_struct.c.in | 67 +- ompi/mpi/c/type_create_subarray.c.in | 73 +-- ompi/mpi/c/type_dup.c.in | 3 +- ompi/mpi/c/type_get_contents.c | 28 +- ompi/mpi/c/type_get_contents_c.c | 28 +- ompi/mpi/c/type_get_envelope.c | 14 +- ompi/mpi/c/type_get_envelope.c.in | 59 -- ompi/mpi/c/type_get_envelope_c.c | 13 +- ompi/mpi/c/type_indexed.c.in | 52 +- ompi/mpi/c/type_size.c.in | 7 +- ompi/mpi/c/type_vector.c.in | 20 +- ompi/util/count_disp_array.h | 107 ++- opal/datatype/opal_convertor.c | 5 +- opal/datatype/opal_datatype.h | 5 +- opal/datatype/opal_datatype_add.c | 3 +- opal/datatype/opal_datatype_create.c | 5 +- opal/util/Makefile.am | 2 + opal/util/count_disp_array.h | 242 +++++++ test/datatype/ddt_lib.c | 27 +- test/datatype/ddt_pack.c | 36 +- test/datatype/external32.c | 7 +- test/datatype/large_data.c | 5 +- test/datatype/unpack_ooo.c | 4 +- 62 files changed, 1250 insertions(+), 905 deletions(-) delete mode 100644 ompi/mpi/c/type_get_envelope.c.in create mode 100644 opal/util/count_disp_array.h diff --git a/VERSION b/VERSION index 44eb7329d5d..20ae1c819c6 100644 --- a/VERSION +++ b/VERSION @@ -20,7 +20,7 @@ minor=1 release=0 # MPI Standard Compliance Level -mpi_standard_version=3 +mpi_standard_version=4 mpi_standard_subversion=1 # OMPI required dependency versions. diff --git a/ompi/datatype/ompi_datatype.h b/ompi/datatype/ompi_datatype.h index 495609d9a7b..c9ae0018513 100644 --- a/ompi/datatype/ompi_datatype.h +++ b/ompi/datatype/ompi_datatype.h @@ -13,6 +13,7 @@ * Copyright (c) 2021 IBM Corporation. All rights reserved. * Copyright (c) 2025 Triad National Security, LLC. All rights reserved. * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -41,6 +42,7 @@ #include "ompi/constants.h" #include "opal/datatype/opal_convertor.h" #include "opal/util/output.h" +#include "ompi/util/count_disp_array.h" #include "mpi.h" BEGIN_C_DECLS @@ -125,7 +127,7 @@ OMPI_DECLSPEC int32_t ompi_datatype_default_convertors_init( void ); OMPI_DECLSPEC int32_t ompi_datatype_default_convertors_fini( void ); OMPI_DECLSPEC void ompi_datatype_dump (const ompi_datatype_t* pData); -OMPI_DECLSPEC ompi_datatype_t* ompi_datatype_create( int32_t expectedSize ); +OMPI_DECLSPEC ompi_datatype_t* ompi_datatype_create( size_t expectedSize ); static inline int32_t ompi_datatype_is_committed( const ompi_datatype_t* type ) @@ -152,7 +154,7 @@ ompi_datatype_is_predefined( const ompi_datatype_t* type ) } static inline int32_t -ompi_datatype_is_contiguous_memory_layout( const ompi_datatype_t* type, int32_t count ) +ompi_datatype_is_contiguous_memory_layout( const ompi_datatype_t* type, size_t count ) { return opal_datatype_is_contiguous_memory_layout(&type->super, count); } @@ -190,27 +192,27 @@ ompi_datatype_add( ompi_datatype_t* pdtBase, const ompi_datatype_t* pdtAdd, size OMPI_DECLSPEC int32_t ompi_datatype_duplicate( const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_contiguous( int count, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_vector( int count, int bLength, int stride, +OMPI_DECLSPEC int32_t ompi_datatype_create_contiguous( size_t count, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); +OMPI_DECLSPEC int32_t ompi_datatype_create_vector( size_t count, size_t bLength, ptrdiff_t stride, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_hvector( int count, int bLength, ptrdiff_t stride, +OMPI_DECLSPEC int32_t ompi_datatype_create_hvector( size_t count, size_t bLength, ptrdiff_t stride, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_indexed( int count, const int* pBlockLength, const int* pDisp, +OMPI_DECLSPEC int32_t ompi_datatype_create_indexed( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_hindexed( int count, const int* pBlockLength, const ptrdiff_t* pDisp, +OMPI_DECLSPEC int32_t ompi_datatype_create_hindexed( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_indexed_block( int count, int bLength, const int* pDisp, +OMPI_DECLSPEC int32_t ompi_datatype_create_indexed_block( size_t count, size_t bLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_hindexed_block( int count, int bLength, const ptrdiff_t* pDisp, +OMPI_DECLSPEC int32_t ompi_datatype_create_hindexed_block( size_t count, size_t bLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_struct( int count, const int* pBlockLength, const ptrdiff_t* pDisp, +OMPI_DECLSPEC int32_t ompi_datatype_create_struct( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, ompi_datatype_t* const* pTypes, ompi_datatype_t** newType ); -OMPI_DECLSPEC int32_t ompi_datatype_create_darray( int size, int rank, int ndims, int const* gsize_array, - int const* distrib_array, int const* darg_array, - int const* psize_array, int order, const ompi_datatype_t* oldtype, +OMPI_DECLSPEC int32_t ompi_datatype_create_darray( int size, int rank, int ndims, const ompi_count_array_t gsize_array, + const int* distrib_array, const int* darg_array, + const int* psize_array, int order, const ompi_datatype_t* oldtype, ompi_datatype_t** newtype); -OMPI_DECLSPEC int32_t ompi_datatype_create_subarray(int ndims, int const* size_array, int const* subsize_array, - int const* start_array, int order, +OMPI_DECLSPEC int32_t ompi_datatype_create_subarray(int ndims, const ompi_count_array_t size_array, const ompi_count_array_t subsize_array, + const ompi_count_array_t start_array, int order, const ompi_datatype_t* oldtype, ompi_datatype_t** newtype); static inline int32_t ompi_datatype_create_resized( const ompi_datatype_t* oldType, @@ -297,25 +299,26 @@ ompi_datatype_copy_content_same_ddt( const ompi_datatype_t* type, size_t count, return 0; } -OMPI_DECLSPEC const ompi_datatype_t* ompi_datatype_match_size( int size, uint16_t datakind, uint16_t datalang ); +OMPI_DECLSPEC const ompi_datatype_t* ompi_datatype_match_size( size_t size, uint16_t datakind, uint16_t datalang ); /* * */ -OMPI_DECLSPEC int32_t ompi_datatype_sndrcv( const void *sbuf, int32_t scount, const ompi_datatype_t* sdtype, - void *rbuf, int32_t rcount, const ompi_datatype_t* rdtype); +OMPI_DECLSPEC int32_t ompi_datatype_sndrcv( const void *sbuf, size_t scount, const ompi_datatype_t* sdtype, + void *rbuf, size_t rcount, const ompi_datatype_t* rdtype); /* * */ OMPI_DECLSPEC int32_t ompi_datatype_get_args( const ompi_datatype_t* pData, int32_t which, - int32_t * ci, int32_t * i, - int32_t * ca, ptrdiff_t* a, - int32_t * cd, ompi_datatype_t** d, int32_t * type); + size_t * ci, int* i, + size_t * cl, MPI_Count* l, + size_t * ca, ptrdiff_t* a, + size_t * cd, ompi_datatype_t** d, int32_t * type); OMPI_DECLSPEC int32_t ompi_datatype_set_args( ompi_datatype_t* pData, - int32_t ci, const int32_t ** i, - int32_t ca, const ptrdiff_t* a, - int32_t cd, ompi_datatype_t* const * d,int32_t type); + size_t ci, size_t cl, const ompi_count_array_t *counts, + size_t ca, const ompi_disp_array_t a, + size_t cd, ompi_datatype_t* const * d,int32_t type); OMPI_DECLSPEC int32_t ompi_datatype_copy_args( const ompi_datatype_t* source_data, ompi_datatype_t* dest_data ); OMPI_DECLSPEC int32_t ompi_datatype_release_args( ompi_datatype_t* pData ); diff --git a/ompi/datatype/ompi_datatype_args.c b/ompi/datatype/ompi_datatype_args.c index 22e3c3f51f2..814ec57d8d0 100644 --- a/ompi/datatype/ompi_datatype_args.c +++ b/ompi/datatype/ompi_datatype_args.c @@ -16,6 +16,7 @@ * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2025-2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -41,19 +42,21 @@ static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype, void** packed_buffer, int* next_index ); static ompi_datatype_t* -__ompi_datatype_create_from_args( int32_t* i, ptrdiff_t * a, +__ompi_datatype_create_from_args( const int* i, const size_t *l, const ptrdiff_t * a, ompi_datatype_t** d, int32_t type ); typedef struct __dt_args { opal_atomic_int32_t ref_count; int32_t create_type; size_t total_pack_size; - int32_t ci; - int32_t ca; - int32_t cd; - int* i; - ptrdiff_t* a; - ompi_datatype_t** d; + size_t ci; + size_t ca; + size_t cd; + size_t cl; + ptrdiff_t* a; + ompi_datatype_t** d; + size_t* l; // array of size_t counts + int* i; // array of integer counts } ompi_datatype_args_t; /** @@ -71,30 +74,44 @@ typedef struct __dt_args { #define OMPI_DATATYPE_ALIGN_PTR(PTR, TYPE) #endif /* OPAL_ALIGN_WORD_SIZE_INTEGERS */ +/** + * Copies count elements from the given count array into either + * the integer or size_t destination depending on whether the + * count array is 32 or 64 bit. Advances the destination pointer. + */ +static inline void copy_count_array(size_t count, int**__restrict__ desti, size_t**__restrict__ destc, ompi_count_array_t array) { + size_t elem_size = opal_count_array_is_64bit(array) ? sizeof(size_t) : sizeof(int); + void *dest = opal_count_array_is_64bit(array) ? (void*)*destc : (void*)*desti; + memcpy(dest, opal_count_array_ptr(array), count * elem_size); + if (opal_count_array_is_64bit(array)) { + *destc += count; + } else { + *desti += count; + } +} + int32_t ompi_datatype_set_args( ompi_datatype_t* pData, - int32_t ci, const int32_t** i, - int32_t ca, const ptrdiff_t* a, - int32_t cd, ompi_datatype_t* const * d, int32_t type) + size_t ci, size_t cl, const ompi_count_array_t *counts, + size_t ca, const opal_disp_array_t a, + size_t cd, ompi_datatype_t* const * d, int32_t type) { - int pos; + size_t pos; assert( NULL == pData->args ); - int length = sizeof(ompi_datatype_args_t) + ci * sizeof(int) + - ca * sizeof(ptrdiff_t) + cd * sizeof(MPI_Datatype); + + size_t length = sizeof(ompi_datatype_args_t) + ci * sizeof(int) + + cl * sizeof(size_t) + ca * sizeof(ptrdiff_t) + + cd * sizeof(MPI_Datatype); char* buf = (char*)malloc( length ); ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)buf; + size_t *pl = NULL; + int *pi = NULL; pArgs->ci = ci; pArgs->i = NULL; + pArgs->cl = cl; pArgs->l = NULL; pArgs->ca = ca; pArgs->a = NULL; pArgs->cd = cd; pArgs->d = NULL; pArgs->create_type = type; - /** - * Some architectures require 64 bits pointers (to pointers) to - * be 64 bits aligned. As in the ompi_datatype_args_t structure we have - * 2 such array of pointers and one to an array of ints, if we start by - * setting the 64 bits aligned one we will not have any trouble. Problem - * originally reported on SPARC 64. - */ buf += sizeof(ompi_datatype_args_t); if( 0 != pArgs->ca ) { pArgs->a = (ptrdiff_t*)buf; @@ -104,10 +121,18 @@ int32_t ompi_datatype_set_args( ompi_datatype_t* pData, pArgs->d = (ompi_datatype_t**)buf; buf += pArgs->cd * sizeof(MPI_Datatype); } - if( 0 != pArgs->ci ) pArgs->i = (int*)buf; + if (0 != pArgs->cl ) { + pArgs->l = pl = (size_t*)buf; + buf += pArgs->cl * sizeof(size_t); + } + if( 0 != pArgs->ci ) { + pArgs->i = pi = (int*)buf; + buf += pArgs->ci * sizeof(int); + } pArgs->ref_count = 1; - pArgs->total_pack_size = (4 + ci) * sizeof(int) + + pArgs->total_pack_size = 5 * sizeof(size_t) + ci * sizeof(int) + + cl * sizeof(size_t) + cd * sizeof(MPI_Datatype) + ca * sizeof(ptrdiff_t); switch(type) { @@ -117,92 +142,113 @@ int32_t ompi_datatype_set_args( ompi_datatype_t* pData, break; case MPI_COMBINER_CONTIGUOUS: - pArgs->i[0] = i[0][0]; + copy_count_array(1, &pi, &pl, counts[0]); break; case MPI_COMBINER_VECTOR: - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; - pArgs->i[2] = i[2][0]; + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); + copy_count_array(1, &pi, &pl, counts[2]); break; case MPI_COMBINER_HVECTOR_INTEGER: case MPI_COMBINER_HVECTOR: - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); + if (cl > 0) { + // copy the stride + memcpy(pl, opal_count_array_ptr(counts[2]), sizeof(MPI_Count)); + pl++; + } break; - case MPI_COMBINER_INDEXED: - pos = 1; - pArgs->i[0] = i[0][0]; - memcpy( pArgs->i + pos, i[1], i[0][0] * sizeof(int) ); - pos += i[0][0]; - memcpy( pArgs->i + pos, i[2], i[0][0] * sizeof(int) ); + case MPI_COMBINER_INDEXED: { + size_t count = opal_count_array_get(counts[0], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(count, &pi, &pl, counts[1]); + copy_count_array(count, &pi, &pl, counts[2]); break; + } case MPI_COMBINER_HINDEXED_INTEGER: - case MPI_COMBINER_HINDEXED: - pArgs->i[0] = i[0][0]; - memcpy( pArgs->i + 1, i[1], i[0][0] * sizeof(int) ); + case MPI_COMBINER_HINDEXED: { + size_t count = opal_count_array_get(counts[0], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(count, &pi, &pl, counts[1]); + if (cl > 0) { + // copy the displacements + memcpy(pl, opal_count_array_ptr(counts[2]), count * sizeof(MPI_Count)); + pl += count; + } break; + } - case MPI_COMBINER_INDEXED_BLOCK: - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; - memcpy( pArgs->i + 2, i[2], i[0][0] * sizeof(int) ); + case MPI_COMBINER_INDEXED_BLOCK: { + size_t count = opal_count_array_get(counts[0], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); + copy_count_array(count, &pi, &pl, counts[2]); break; + } case MPI_COMBINER_STRUCT_INTEGER: - case MPI_COMBINER_STRUCT: - pArgs->i[0] = i[0][0]; - memcpy( pArgs->i + 1, i[1], i[0][0] * sizeof(int) ); + case MPI_COMBINER_STRUCT: { + size_t count = opal_count_array_get(counts[0], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(count, &pi, &pl, counts[1]); + if (cl > 0) { + // copy the displacements + memcpy(pl, opal_count_array_ptr(counts[2]), count * sizeof(MPI_Count)); + pl += count; + } break; + } - case MPI_COMBINER_SUBARRAY: - pos = 1; - pArgs->i[0] = i[0][0]; - memcpy( pArgs->i + pos, i[1], pArgs->i[0] * sizeof(int) ); - pos += pArgs->i[0]; - memcpy( pArgs->i + pos, i[2], pArgs->i[0] * sizeof(int) ); - pos += pArgs->i[0]; - memcpy( pArgs->i + pos, i[3], pArgs->i[0] * sizeof(int) ); - pos += pArgs->i[0]; - pArgs->i[pos] = i[4][0]; + case MPI_COMBINER_SUBARRAY: { + size_t count = opal_count_array_get(counts[0], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(count, &pi, &pl, counts[1]); + copy_count_array(count, &pi, &pl, counts[2]); + copy_count_array(count, &pi, &pl, counts[3]); + copy_count_array(1, &pi, &pl, counts[4]); break; + } - case MPI_COMBINER_DARRAY: - pos = 3; - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; - pArgs->i[2] = i[2][0]; - - memcpy( pArgs->i + pos, i[3], i[2][0] * sizeof(int) ); - pos += i[2][0]; - memcpy( pArgs->i + pos, i[4], i[2][0] * sizeof(int) ); - pos += i[2][0]; - memcpy( pArgs->i + pos, i[5], i[2][0] * sizeof(int) ); - pos += i[2][0]; - memcpy( pArgs->i + pos, i[6], i[2][0] * sizeof(int) ); - pos += i[2][0]; - pArgs->i[pos] = i[7][0]; + case MPI_COMBINER_DARRAY: { + size_t ndim = opal_count_array_get(counts[2], 0); + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); + copy_count_array(1, &pi, &pl, counts[2]); + copy_count_array(ndim, &pi, &pl, counts[3]); + copy_count_array(ndim, &pi, &pl, counts[4]); + copy_count_array(ndim, &pi, &pl, counts[5]); + copy_count_array(ndim, &pi, &pl, counts[6]); + copy_count_array(1, &pi, &pl, counts[7]); break; + } case MPI_COMBINER_F90_REAL: case MPI_COMBINER_F90_COMPLEX: - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); break; case MPI_COMBINER_F90_INTEGER: - pArgs->i[0] = i[0][0]; + copy_count_array(1, &pi, &pl, counts[0]); break; case MPI_COMBINER_RESIZED: break; case MPI_COMBINER_HINDEXED_BLOCK: - pArgs->i[0] = i[0][0]; - pArgs->i[1] = i[1][0]; + copy_count_array(1, &pi, &pl, counts[0]); + copy_count_array(1, &pi, &pl, counts[1]); + if (cl > 0) { + // copy the displacements + size_t count = opal_count_array_get(counts[0], 0); + memcpy(pl, opal_count_array_ptr(counts[2]), count * sizeof(MPI_Count)); + pl += count; + } break; default: @@ -211,7 +257,7 @@ int32_t ompi_datatype_set_args( ompi_datatype_t* pData, /* copy the array of MPI_Aint, aka ptrdiff_t */ if( pArgs->a != NULL ) - memcpy( pArgs->a, a, ca * sizeof(ptrdiff_t) ); + memcpy( pArgs->a, ompi_disp_array_ptr(a), ca * sizeof(ptrdiff_t) ); for( pos = 0; pos < cd; pos++ ) { pArgs->d[pos] = d[pos]; @@ -239,7 +285,7 @@ int32_t ompi_datatype_set_args( ompi_datatype_t* pData, int32_t ompi_datatype_print_args( const ompi_datatype_t* pData ) { - int32_t i; + size_t i; ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args; if( ompi_datatype_is_predefined(pData) ) { @@ -249,15 +295,22 @@ int32_t ompi_datatype_print_args( const ompi_datatype_t* pData ) if( pArgs == NULL ) return MPI_ERR_INTERN; - printf( "type %d count ints %d count disp %d count datatype %d\n", - pArgs->create_type, pArgs->ci, pArgs->ca, pArgs->cd ); + printf( "type %d count ints %zu count counts %zu count disp %zu count datatype %zu\n", + pArgs->create_type, pArgs->ci, pArgs->cl, pArgs->ca, pArgs->cd ); if( pArgs->i != NULL ) { - printf( "ints: " ); + printf( "ints: "); for( i = 0; i < pArgs->ci; i++ ) { printf( "%d ", pArgs->i[i] ); } printf( "\n" ); } + if( pArgs->l != NULL ) { + printf( "counts: "); + for( i = 0; i < pArgs->cl; i++ ) { + printf( "%zu ", pArgs->l[i] ); + } + printf( "\n" ); + } if( pArgs->a != NULL ) { printf( "MPI_Aint: " ); for( i = 0; i < pArgs->ca; i++ ) { @@ -309,9 +362,10 @@ int32_t ompi_datatype_print_args( const ompi_datatype_t* pData ) int32_t ompi_datatype_get_args( const ompi_datatype_t* pData, int32_t which, - int32_t* ci, int32_t* i, - int32_t* ca, ptrdiff_t* a, - int32_t* cd, ompi_datatype_t** d, int32_t* type) + size_t* ci, int* i, + size_t* cl, MPI_Count* l, + size_t* ca, ptrdiff_t* a, + size_t* cd, ompi_datatype_t** d, int32_t* type) { ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args; @@ -320,6 +374,7 @@ int32_t ompi_datatype_get_args( const ompi_datatype_t* pData, int32_t which, switch(which){ case 0: *ci = 0; + *cl = 0; *ca = 0; *cd = 0; *type = MPI_COMBINER_NAMED; @@ -335,17 +390,21 @@ int32_t ompi_datatype_get_args( const ompi_datatype_t* pData, int32_t which, switch(which){ case 0: /* GET THE LENGTHS */ *ci = pArgs->ci; + *cl = pArgs->cl; *ca = pArgs->ca; *cd = pArgs->cd; *type = pArgs->create_type; break; case 1: /* GET THE ARGUMENTS */ - if(*ci < pArgs->ci || *ca < pArgs->ca || *cd < pArgs->cd) { + if(*ci < pArgs->ci || *cl < pArgs->cl || *ca < pArgs->ca || *cd < pArgs->cd) { return MPI_ERR_ARG; } if( (NULL != i) && (NULL != pArgs->i) ) { memcpy( i, pArgs->i, pArgs->ci * sizeof(int) ); } + if( (NULL != l) && (NULL != pArgs->l) ) { + memcpy( l, pArgs->l, pArgs->cl * sizeof(size_t) ); + } if( (NULL != a) && (NULL != pArgs->a) ) { memcpy( a, pArgs->a, pArgs->ca * sizeof(ptrdiff_t) ); } @@ -384,7 +443,7 @@ int32_t ompi_datatype_copy_args( const ompi_datatype_t* source_data, */ int32_t ompi_datatype_release_args( ompi_datatype_t* pData ) { - int i; + size_t i; ompi_datatype_args_t* pArgs = (ompi_datatype_args_t*)pData->args; assert( 0 < pArgs->ref_count ); @@ -409,13 +468,16 @@ int32_t ompi_datatype_release_args( ompi_datatype_t* pData ) static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype, void** packed_buffer, int* next_index ) { - int i, *position = (int*)*packed_buffer; + size_t i; + int *iposition = NULL; ompi_datatype_args_t* args = (ompi_datatype_args_t*)datatype->args; char* next_packed = (char*)*packed_buffer; + iposition = (int*)next_packed; + if( ompi_datatype_is_predefined(datatype) ) { - position[0] = MPI_COMBINER_NAMED; - position[1] = datatype->id; /* On the OMPI - layer, copy the ompi_datatype.id */ + iposition[0] = MPI_COMBINER_NAMED; + iposition[1] = datatype->id; /* On the OMPI - layer, copy the ompi_datatype.id */ next_packed += (2 * sizeof(int)); *packed_buffer = next_packed; return OMPI_SUCCESS; @@ -427,28 +489,31 @@ static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype, packed_buffer, next_index ); } - position[0] = args->create_type; - position[1] = args->ci; - position[2] = args->ca; - position[3] = args->cd; - next_packed += (4 * sizeof(int)); - /* Spoiler: We will access the data in this storage structure, and thus we - * need to align it to the expected boundaries (special thanks to Sparc64). - * The simplest way is to ensure that prior to each type that must be 64 - * bits aligned, we have a pointer that is 64 bits aligned. That will minimize - * the memory requirements in all cases where no displacements are stored. - */ + iposition[0] = args->create_type; + next_packed += sizeof(int); + /* align pointer to 64 bits */ + OMPI_DATATYPE_ALIGN_PTR(next_packed, char*); + size_t *cposition = ((size_t*)next_packed); + cposition[0] = args->ci; + cposition[1] = args->cl; + cposition[2] = args->ca; + cposition[3] = args->cd; + next_packed += (4 * sizeof(size_t)); if( 0 < args->ca ) { - /* description of the displacements must be 64 bits aligned */ - OMPI_DATATYPE_ALIGN_PTR(next_packed, char*); - memcpy( next_packed, args->a, sizeof(ptrdiff_t) * args->ca ); next_packed += sizeof(ptrdiff_t) * args->ca; } - position = (int*)next_packed; + if ( 0 < args->cl ) { + memcpy( next_packed, args->l, sizeof(size_t) * args->cl ); + next_packed += sizeof(size_t) * args->cl; + } + /* advance int pointer */ + iposition = (int*)next_packed; + + /* skip the datatypes */ next_packed += sizeof(int) * args->cd; - /* copy the array of counts (32 bits aligned) */ + /* copy the array of 32bit counts at the end */ memcpy( next_packed, args->i, sizeof(int) * args->ci ); next_packed += args->ci * sizeof(int); @@ -456,9 +521,9 @@ static inline int __ompi_datatype_pack_description( ompi_datatype_t* datatype, for( i = 0; i < args->cd; i++ ) { ompi_datatype_t* temp_data = args->d[i]; if( ompi_datatype_is_predefined(temp_data) ) { - position[i] = temp_data->id; /* On the OMPI - layer, copy the ompi_datatype.id */ + iposition[i] = temp_data->id; /* On the OMPI - layer, copy the ompi_datatype.id */ } else { - position[i] = *next_index; + iposition[i] = *next_index; (*next_index)++; __ompi_datatype_pack_description( temp_data, (void**)&next_packed, @@ -548,13 +613,16 @@ size_t ompi_datatype_pack_description_length( ompi_datatype_t* datatype ) static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** packed_buffer, const struct ompi_proc_t* remote_processor ) { - int* position; + int* iposition; + size_t *cposition; ompi_datatype_t* datatype = NULL; ompi_datatype_t** array_of_datatype; ptrdiff_t* array_of_disp; - int* array_of_length; - int number_of_length, number_of_disp, number_of_datatype, data_id; - int create_type, i; + int* array_of_ints; + size_t *array_of_counts = NULL; + size_t number_of_ints, number_of_counts, number_of_disp, number_of_datatype, data_id; + int create_type; + size_t i; char* next_buffer; #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT @@ -567,9 +635,14 @@ static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** p #endif next_buffer = (char*)*packed_buffer; - position = (int*)next_buffer; - - create_type = position[0]; + cposition = (size_t*)next_buffer; + iposition = (int*)next_buffer; + + create_type = (int)iposition[0]; + next_buffer += sizeof(int); + /* align pointer to 64 bits */ + OMPI_DATATYPE_ALIGN_PTR(next_buffer, char*); + cposition = (size_t*)next_buffer; #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (need_swap) { create_type = opal_swap_bytes4(create_type); @@ -577,48 +650,50 @@ static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** p #endif if( MPI_COMBINER_NAMED == create_type ) { /* there we have a simple predefined datatype */ - data_id = position[1]; + data_id = iposition[1]; #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (need_swap) { data_id = opal_swap_bytes4(data_id); } #endif assert( data_id < OMPI_DATATYPE_MAX_PREDEFINED ); - *packed_buffer = position + 2; + *packed_buffer = iposition + 2; return (ompi_datatype_t*)ompi_datatype_basicDatatypes[data_id]; } - number_of_length = position[1]; - number_of_disp = position[2]; - number_of_datatype = position[3]; + number_of_ints = cposition[0]; + number_of_counts = cposition[1]; + number_of_disp = cposition[2]; + number_of_datatype = cposition[3]; #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (need_swap) { - number_of_length = opal_swap_bytes4(number_of_length); - number_of_disp = opal_swap_bytes4(number_of_disp); - number_of_datatype = opal_swap_bytes4(number_of_datatype); + number_of_ints = opal_swap_bytes8(number_of_ints); + number_of_counts = opal_swap_bytes8(number_of_counts); + number_of_disp = opal_swap_bytes8(number_of_disp); + number_of_datatype = opal_swap_bytes8(number_of_datatype); } #endif array_of_datatype = (ompi_datatype_t**)malloc( sizeof(ompi_datatype_t*) * number_of_datatype ); - next_buffer += (4 * sizeof(int)); /* move after the header */ - - /* description of the displacements (if ANY !) should always be aligned - on MPI_Aint, aka ptrdiff_t */ - if (number_of_disp > 0) { - OMPI_DATATYPE_ALIGN_PTR(next_buffer, char*); - } - + next_buffer += (4 * sizeof(size_t)); /* move after the header */ + /* the array of displacements */ array_of_disp = (ptrdiff_t*)next_buffer; next_buffer += number_of_disp * sizeof(ptrdiff_t); + if (number_of_counts > 0) { + array_of_counts = (size_t*)next_buffer; + next_buffer += number_of_counts * sizeof(size_t); + } /* the other datatypes */ - position = (int*)next_buffer; + iposition = (int*)next_buffer; next_buffer += number_of_datatype * sizeof(int); /* the array of lengths (32 bits aligned) */ - array_of_length = (int*)next_buffer; - next_buffer += (number_of_length * sizeof(int)); + if (number_of_ints > 0) { + array_of_ints = (int*)next_buffer; + next_buffer += number_of_ints * sizeof(int); + } for( i = 0; i < number_of_datatype; i++ ) { - data_id = position[i]; + data_id = iposition[i]; #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (need_swap) { data_id = opal_swap_bytes4(data_id); @@ -644,8 +719,11 @@ static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** p #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (need_swap) { - for (i = 0 ; i < number_of_length ; ++i) { - array_of_length[i] = opal_swap_bytes4(array_of_length[i]); + for (i = 0 ; i < number_of_ints ; ++i) { + array_of_ints[i] = opal_swap_bytes4(array_of_ints[i]); + } + for (i = 0 ; i < number_of_counts ; ++i) { + array_of_counts[i] = opal_swap_bytes8(array_of_counts[i]); } for (i = 0 ; i < number_of_disp ; ++i) { #if SIZEOF_PTRDIFF_T == 4 @@ -658,7 +736,7 @@ static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** p } } #endif - datatype = __ompi_datatype_create_from_args( array_of_length, array_of_disp, + datatype = __ompi_datatype_create_from_args( array_of_ints, array_of_counts, array_of_disp, array_of_datatype, create_type ); *packed_buffer = next_buffer; cleanup_and_exit: @@ -671,11 +749,14 @@ static ompi_datatype_t* __ompi_datatype_create_from_packed_description( void** p return datatype; } -static ompi_datatype_t* __ompi_datatype_create_from_args( int32_t* i, MPI_Aint* a, +static ompi_datatype_t* __ompi_datatype_create_from_args( const int* i, const size_t *l, const ptrdiff_t* a, ompi_datatype_t** d, int32_t type ) { + size_t count, ci = 0, cl = 0; ompi_datatype_t* datatype = NULL; + ompi_disp_array_t disp_array = OMPI_DISP_ARRAY_CREATE(a); + switch(type){ /******************************************************************/ case MPI_COMBINER_DUP: @@ -684,81 +765,243 @@ static ompi_datatype_t* __ompi_datatype_create_from_args( int32_t* i, MPI_Aint* assert(0); /* shouldn't happen */ break; /******************************************************************/ - case MPI_COMBINER_CONTIGUOUS: - ompi_datatype_create_contiguous( i[0], d[0], &datatype ); - ompi_datatype_set_args( datatype, 1, (const int **) &i, 0, NULL, 1, d, MPI_COMBINER_CONTIGUOUS ); + case MPI_COMBINER_CONTIGUOUS: { + ompi_count_array_t a_i[1]; + if (l == NULL) { + count = i[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + ci = 1; + } else { // large count variant + count = l[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + cl = 1; + } + ompi_datatype_create_contiguous( count, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_CONTIGUOUS ); break; + } /******************************************************************/ - case MPI_COMBINER_VECTOR: - ompi_datatype_create_vector( i[0], i[1], i[2], d[0], &datatype ); - { - const int* a_i[3] = {&i[0], &i[1], &i[2]}; - ompi_datatype_set_args( datatype, 3, a_i, 0, NULL, 1, d, MPI_COMBINER_VECTOR ); + case MPI_COMBINER_VECTOR: { + size_t blocklength, stride; + opal_count_array_t a_i[3]; + if (l == NULL) { + count = i[0]; + blocklength= i[1]; + stride = i[2]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(i + 2); + ci = 3; + } else { // large count variant + count = l[0]; + blocklength= l[1]; + stride = l[2]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 2); + cl = 3; } + ompi_datatype_create_vector( count, blocklength, stride, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_VECTOR ); break; + } /******************************************************************/ case MPI_COMBINER_HVECTOR_INTEGER: case MPI_COMBINER_HVECTOR: - ompi_datatype_create_hvector( i[0], i[1], a[0], d[0], &datatype ); { - const int* a_i[2] = {&i[0], &i[1]}; - ompi_datatype_set_args( datatype, 2, a_i, 1, a, 1, d, MPI_COMBINER_HVECTOR ); + size_t blocklength; + ptrdiff_t stride; + opal_count_array_t a_i[3]; + size_t ca = 0; + if (l == NULL) { + count = i[0]; + blocklength = i[1]; + stride = a[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + ci = 2; + ca = 1; // stride stored in disp_array + } else { // large count variant + count = l[0]; + blocklength = l[1]; + stride = l[2]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 2); + cl = 3; + } + ompi_datatype_create_hvector( count, blocklength, stride, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, ca, disp_array, 1, d, MPI_COMBINER_HVECTOR ); } break; /******************************************************************/ case MPI_COMBINER_INDEXED: /* TO CHECK */ - ompi_datatype_create_indexed( i[0], &(i[1]), &(i[1+i[0]]), d[0], &datatype ); { - const int* a_i[3] = {&i[0], &i[1], &(i[1+i[0]])}; - ompi_datatype_set_args( datatype, 2 * i[0] + 1, a_i, 0, NULL, 1, d, MPI_COMBINER_INDEXED ); + opal_count_array_t a_i[3]; + if (l == NULL) { + count = i[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(i + 1 + count); + ci = 2 * count + 1; + } else { + count = l[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 1 + count); + cl = 2 * count + 1; + } + ompi_datatype_create_indexed( count, a_i[1], a_i[2], d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_INDEXED ); } break; /******************************************************************/ case MPI_COMBINER_HINDEXED_INTEGER: case MPI_COMBINER_HINDEXED: - ompi_datatype_create_hindexed( i[0], &(i[1]), a, d[0], &datatype ); { - const int* a_i[2] = {&i[0], &i[1]}; - ompi_datatype_set_args( datatype, i[0] + 1, a_i, i[0], a, 1, d, MPI_COMBINER_HINDEXED ); + opal_count_array_t a_i[3]; + size_t ca = 0; + opal_disp_array_t disp_args; // for set_args + opal_disp_array_t displacements; // for create_hindexed + if (l == NULL) { + count = i[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + ci = count+1; + ca = count; + disp_args = disp_array; + displacements = disp_array; + } else { + count = l[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 1 + count); // displacements are MPI_Count + cl = 2*count+1; + disp_args = OMPI_DISP_ARRAY_NULL; + displacements = OMPI_DISP_ARRAY_CREATE(l + 1 + count); + } + ompi_datatype_create_hindexed( count, a_i[1], displacements, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, ca, disp_args, 1, d, MPI_COMBINER_HINDEXED ); } break; /******************************************************************/ case MPI_COMBINER_INDEXED_BLOCK: - ompi_datatype_create_indexed_block( i[0], i[1], &(i[2]), d[0], &datatype ); { - const int* a_i[3] = {&i[0], &i[1], &i[2]}; - ompi_datatype_set_args( datatype, i[0] + 2, a_i, 0, NULL, 1, d, MPI_COMBINER_INDEXED_BLOCK ); + opal_count_array_t a_i[3]; + size_t blocklength; + if (l == NULL) { + count = i[0]; + blocklength = i[1]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(i + 2); + ci = 2 + count; + } else { + count = l[0]; + blocklength = l[1]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 2); + cl = 2 + count; + } + ompi_datatype_create_indexed_block( count, blocklength, a_i[2], d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_INDEXED_BLOCK ); } break; /******************************************************************/ case MPI_COMBINER_STRUCT_INTEGER: case MPI_COMBINER_STRUCT: - ompi_datatype_create_struct( i[0], &(i[1]), a, d, &datatype ); { - const int* a_i[2] = {&i[0], &i[1]}; - ompi_datatype_set_args( datatype, i[0] + 1, a_i, i[0], a, i[0], d, MPI_COMBINER_STRUCT ); + opal_count_array_t a_i[3]; + opal_disp_array_t displacements; + opal_disp_array_t disp_args; + size_t ca = 0; + if (l == NULL) { + count = i[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + ci = 2 * count + 1; + displacements = disp_array; + disp_args = disp_array; + ca = count; + } else { + count = l[0]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 1 + count); + displacements = OMPI_DISP_ARRAY_CREATE(l + 1 + count); + disp_args = OMPI_DISP_ARRAY_NULL; + cl = 2*count + 1; + } + ompi_datatype_create_struct( count, a_i[1], displacements, d, &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, ca, disp_args, count, d, MPI_COMBINER_STRUCT ); } break; /******************************************************************/ case MPI_COMBINER_SUBARRAY: - ompi_datatype_create_subarray( i[0], &i[1 + 0 * i[0]], &i[1 + 1 * i[0]], - &i[1 + 2 * i[0]], i[1 + 3 * i[0]], - d[0], &datatype ); { - const int* a_i[5] = {&i[0], &i[1 + 0 * i[0]], &i[1 + 1 * i[0]], &i[1 + 2 * i[0]], &i[1 + 3 * i[0]]}; - ompi_datatype_set_args( datatype, 3 * i[0] + 2, a_i, 0, NULL, 1, d, MPI_COMBINER_SUBARRAY); + count = i[0]; // first element in int array + int order; + opal_count_array_t a_i[5]; + if (l == NULL) { + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(i + 1 + count); + a_i[3] = OMPI_COUNT_ARRAY_CREATE(i + 1 + 2*count); + a_i[4] = OMPI_COUNT_ARRAY_CREATE(i + 1 + 3*count); + order = i[3*count+1]; // last element in int array + ci = 3 * count + 2; + } else { + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); // ndim + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l); // sizes + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + count); // subsizes + a_i[3] = OMPI_COUNT_ARRAY_CREATE(l + 2*count); // starts + a_i[4] = OMPI_COUNT_ARRAY_CREATE(i+1); // order + order = i[1]; // second (and last) element in int array + cl = 3 * count; + ci = 2; + } + ompi_datatype_create_subarray( count, a_i[1], a_i[2], a_i[3], order, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_SUBARRAY ); } break; /******************************************************************/ case MPI_COMBINER_DARRAY: - ompi_datatype_create_darray( i[0] /* size */, i[1] /* rank */, i[2] /* ndims */, - &i[3 + 0 * i[2]], &i[3 + 1 * i[2]], - &i[3 + 2 * i[2]], &i[3 + 3 * i[2]], - i[3 + 4 * i[2]], d[0], &datatype ); { - const int* a_i[8] = {&i[0], &i[1], &i[2], &i[3 + 0 * i[2]], &i[3 + 1 * i[2]], &i[3 + 2 * i[2]], - &i[3 + 3 * i[2]], &i[3 + 4 * i[2]]}; - ompi_datatype_set_args( datatype, 4 * i[2] + 4, a_i, 0, NULL, 1, d, MPI_COMBINER_DARRAY); + int size = i[0]; + int rank = i[1]; + int ndims = i[2]; + ompi_count_array_t gsize_array; + const int *distrib_array; + const int *darg_array; + const int *psize_array; + int order; + if (l == NULL) { + gsize_array = OMPI_COUNT_ARRAY_CREATE(i + 3); + distrib_array = &i[3 + 1*ndims]; + darg_array = &i[3 + 2*ndims]; + psize_array = &i[3 + 3*ndims]; + order = i[3 + 4*ndims]; + ci = 4 + 4 * ndims; + } else { + gsize_array = OMPI_COUNT_ARRAY_CREATE(l); + distrib_array = &i[3 + 0*ndims]; + darg_array = &i[3 + 1*ndims]; + psize_array = &i[3 + 2*ndims]; + order = i[3 + 3*ndims]; + ci = 4 + 3 * ndims; + cl = ndims; + } + opal_count_array_t a_i[8] = {OMPI_COUNT_ARRAY_CREATE(&size), + OMPI_COUNT_ARRAY_CREATE(&rank), + OMPI_COUNT_ARRAY_CREATE(&ndims), + gsize_array, + OMPI_COUNT_ARRAY_CREATE(distrib_array), + OMPI_COUNT_ARRAY_CREATE(darg_array), + OMPI_COUNT_ARRAY_CREATE(psize_array), + OMPI_COUNT_ARRAY_CREATE(&order)}; + ompi_datatype_create_darray( size, rank, ndims, gsize_array, distrib_array, darg_array, psize_array, order, d[0], &datatype ); + ompi_datatype_set_args( datatype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, d, MPI_COMBINER_DARRAY); } break; /******************************************************************/ @@ -775,14 +1018,39 @@ static ompi_datatype_t* __ompi_datatype_create_from_args( int32_t* i, MPI_Aint* /******************************************************************/ case MPI_COMBINER_RESIZED: ompi_datatype_create_resized(d[0], a[0], a[1], &datatype); - ompi_datatype_set_args( datatype, 0, NULL, 2, a, 1, d, MPI_COMBINER_RESIZED ); + ompi_datatype_set_args( datatype, 0, 0, NULL, 2, disp_array, 1, d, MPI_COMBINER_RESIZED ); break; /******************************************************************/ case MPI_COMBINER_HINDEXED_BLOCK: - ompi_datatype_create_hindexed_block( i[0], i[1], a, d[0], &datatype ); { - const int* a_i[2] = {&i[0], &i[1]}; - ompi_datatype_set_args( datatype, 2, a_i, i[0], a, 1, d, MPI_COMBINER_HINDEXED_BLOCK ); + size_t bLength = 0; + size_t ca; + opal_disp_array_t displacements; // for create_hindexed_block + opal_disp_array_t disp_args; // for set_args + opal_count_array_t a_i[3];// = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(&bLength)}; + if (l == NULL) { + count = i[0]; + bLength = i[1]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(i); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(i + 1); + ci = 2; + displacements = disp_array; + disp_args = disp_array; + ca = count; // displacements stored in disp_array + } else { + count = l[0]; + bLength = l[1]; + a_i[0] = OMPI_COUNT_ARRAY_CREATE(l); + a_i[1] = OMPI_COUNT_ARRAY_CREATE(l + 1); + a_i[2] = OMPI_COUNT_ARRAY_CREATE(l + 2); + cl = 3; + displacements = OMPI_DISP_ARRAY_CREATE(l + 2); // displacements are MPI_Count + disp_args = OMPI_DISP_ARRAY_NULL; + ca = 0; + } + ompi_datatype_create_hindexed_block( count, bLength, displacements, d[0], &datatype ); + + ompi_datatype_set_args( datatype, ci, cl, a_i, ca, disp_args, 1, d, MPI_COMBINER_HINDEXED_BLOCK ); } break; /******************************************************************/ @@ -816,7 +1084,7 @@ ompi_datatype_t* ompi_datatype_get_single_predefined_type_from_args( ompi_dataty { ompi_datatype_t *predef = NULL, *current_type, *current_predef; ompi_datatype_args_t* args = (ompi_datatype_args_t*)type->args; - int i; + size_t i; if( ompi_datatype_is_predefined(type) ) return type; diff --git a/ompi/datatype/ompi_datatype_create.c b/ompi/datatype/ompi_datatype_create.c index 76e87a0593f..64f2740270e 100644 --- a/ompi/datatype/ompi_datatype_create.c +++ b/ompi/datatype/ompi_datatype_create.c @@ -13,6 +13,7 @@ * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. * Copyright (c) 2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -71,7 +72,7 @@ static void __ompi_datatype_release(ompi_datatype_t * datatype) OBJ_CLASS_INSTANCE(ompi_datatype_t, opal_datatype_t, __ompi_datatype_allocate, __ompi_datatype_release); -ompi_datatype_t * ompi_datatype_create( int32_t expectedSize ) +ompi_datatype_t * ompi_datatype_create( size_t expectedSize ) { int ret; ompi_datatype_t * datatype = (ompi_datatype_t*)OBJ_NEW(ompi_datatype_t); diff --git a/ompi/datatype/ompi_datatype_create_contiguous.c b/ompi/datatype/ompi_datatype_create_contiguous.c index 6a287caa41c..e0a7503713e 100644 --- a/ompi/datatype/ompi_datatype_create_contiguous.c +++ b/ompi/datatype/ompi_datatype_create_contiguous.c @@ -12,6 +12,7 @@ * All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -24,7 +25,7 @@ #include "ompi/datatype/ompi_datatype_internal.h" #include "mpi.h" -int32_t ompi_datatype_create_contiguous( int count, const ompi_datatype_t* oldType, +int32_t ompi_datatype_create_contiguous( size_t count, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ompi_datatype_t* pdt; diff --git a/ompi/datatype/ompi_datatype_create_darray.c b/ompi/datatype/ompi_datatype_create_darray.c index e0292755c4b..a06610cd580 100644 --- a/ompi/datatype/ompi_datatype_create_darray.c +++ b/ompi/datatype/ompi_datatype_create_darray.c @@ -16,6 +16,7 @@ * Copyright (c) 2016 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -30,7 +31,7 @@ #include "ompi/datatype/ompi_datatype.h" static int -block(const int *gsize_array, int dim, int ndims, int nprocs, +block(ompi_count_array_t gsize_array, int dim, int ndims, int nprocs, int rank, int darg, int order, ptrdiff_t orig_extent, ompi_datatype_t *type_old, ompi_datatype_t **type_new, ptrdiff_t *st_offset) @@ -38,7 +39,7 @@ block(const int *gsize_array, int dim, int ndims, int nprocs, int blksize, global_size, mysize, i, j, rc, start_loop, step; ptrdiff_t stride, disps[2]; - global_size = gsize_array[dim]; + global_size = ompi_count_array_get(gsize_array, dim); if (darg == MPI_DISTRIBUTE_DFLT_DARG) blksize = (global_size + nprocs - 1) / nprocs; @@ -62,7 +63,7 @@ block(const int *gsize_array, int dim, int ndims, int nprocs, if (OMPI_SUCCESS != rc) return rc; } else { for (i = start_loop ; i != dim ; i += step) { - stride *= gsize_array[i]; + stride *= ompi_count_array_get(gsize_array, i); } rc = ompi_datatype_create_hvector(mysize, 1, stride, type_old, type_new); if (OMPI_SUCCESS != rc) return rc; @@ -76,11 +77,11 @@ block(const int *gsize_array, int dim, int ndims, int nprocs, disps[0] = 0; disps[1] = orig_extent; if (order == MPI_ORDER_FORTRAN) { for(i=0; i<=dim; i++) { - disps[1] *= gsize_array[i]; + disps[1] *= ompi_count_array_get(gsize_array, i); } } else { for(i=ndims-1; i>=dim; i--) { - disps[1] *= gsize_array[i]; + disps[1] *= ompi_count_array_get(gsize_array, i); } } rc = opal_datatype_resize( &(*type_new)->super, disps[0], disps[1] ); @@ -91,7 +92,7 @@ block(const int *gsize_array, int dim, int ndims, int nprocs, static int -cyclic(const int *gsize_array, int dim, int ndims, int nprocs, +cyclic(ompi_count_array_t gsize_array, int dim, int ndims, int nprocs, int rank, int darg, int order, ptrdiff_t orig_extent, ompi_datatype_t* type_old, ompi_datatype_t **type_new, ptrdiff_t *st_offset) @@ -107,7 +108,7 @@ cyclic(const int *gsize_array, int dim, int ndims, int nprocs, } st_index = rank * blksize; - end_index = gsize_array[dim] - 1; + end_index = ompi_count_array_get(gsize_array, dim) - 1; if (end_index < st_index) { local_size = 0; @@ -123,11 +124,11 @@ cyclic(const int *gsize_array, int dim, int ndims, int nprocs, stride = nprocs*blksize*orig_extent; if (order == MPI_ORDER_FORTRAN) { for (i=0; idim; i--) { - stride *= gsize_array[i]; + stride *= ompi_count_array_get(gsize_array, i); } } @@ -142,7 +143,7 @@ cyclic(const int *gsize_array, int dim, int ndims, int nprocs, disps [0] = 0; disps [1] = count*stride; blklens[0] = 1; blklens[1] = rem; - rc = ompi_datatype_create_struct(2, blklens, disps, types, &type_tmp); + rc = ompi_datatype_create_struct(2, OMPI_COUNT_ARRAY_CREATE(blklens), OMPI_DISP_ARRAY_CREATE(disps), types, &type_tmp); ompi_datatype_destroy(type_new); /* even in error condition, need to destroy type_new, so check for error after destroy. */ @@ -154,11 +155,11 @@ cyclic(const int *gsize_array, int dim, int ndims, int nprocs, disps[0] = 0; disps[1] = orig_extent; if (order == MPI_ORDER_FORTRAN) { for(i=0; i<=dim; i++) { - disps[1] *= gsize_array[i]; + disps[1] *= ompi_count_array_get(gsize_array, i); } } else { for(i=ndims-1; i>=dim; i--) { - disps[1] *= gsize_array[i]; + disps[1] *= ompi_count_array_get(gsize_array, i); } } rc = opal_datatype_resize( &(*type_new)->super, disps[0], disps[1] ); @@ -174,10 +175,10 @@ cyclic(const int *gsize_array, int dim, int ndims, int nprocs, int32_t ompi_datatype_create_darray(int size, int rank, int ndims, - int const* gsize_array, - int const* distrib_array, - int const* darg_array, - int const* psize_array, + ompi_count_array_t gsize_array, + const int* distrib_array, + const int* darg_array, + const int* psize_array, int order, const ompi_datatype_t* oldtype, ompi_datatype_t** newtype) @@ -209,7 +210,7 @@ int32_t ompi_datatype_create_darray(int size, coords[i] = tmp_rank / procs; tmp_rank = tmp_rank % procs; /* compute the upper bound of the datatype, including all dimensions */ - displs[1] *= gsize_array[i]; + displs[1] *= ompi_count_array_get(gsize_array, i); } } @@ -275,7 +276,7 @@ int32_t ompi_datatype_create_darray(int size, */ displs[0] = st_offsets[start_loop]; for (i = start_loop + step; i != end_loop; i += step) { - tmp_size *= gsize_array[i - step]; + tmp_size *= ompi_count_array_get(gsize_array, i - step); displs[0] += tmp_size * st_offsets[i]; } displs[0] *= orig_extent; diff --git a/ompi/datatype/ompi_datatype_create_indexed.c b/ompi/datatype/ompi_datatype_create_indexed.c index 2684d9d7df0..29f8d8875c8 100644 --- a/ompi/datatype/ompi_datatype_create_indexed.c +++ b/ompi/datatype/ompi_datatype_create_indexed.c @@ -16,6 +16,7 @@ * Copyright (c) 2015-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2019 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -31,38 +32,38 @@ /* We try to merge together data that are contiguous */ -int32_t ompi_datatype_create_indexed( int count, const int* pBlockLength, const int* pDisp, +int32_t ompi_datatype_create_indexed( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ptrdiff_t extent, disp, endat; ompi_datatype_t* pdt; size_t dLength; - int i; + size_t i; /* ignore all cases that lead to an empty type */ ompi_datatype_type_size(oldType, &dLength); - for( i = 0; (i < count) && (0 == pBlockLength[i]); i++ ); /* find first non zero */ + for( i = 0; (i < count) && (0 == ompi_count_array_get(pBlockLength, i)); i++ ); /* find first non zero */ if( (i == count) || (0 == dLength) ) { return ompi_datatype_duplicate( &ompi_mpi_datatype_null.dt, newType); } - disp = pDisp[i]; - dLength = pBlockLength[i]; + disp = ompi_disp_array_get(pDisp, i); + dLength = ompi_count_array_get(pBlockLength, i); endat = disp + dLength; ompi_datatype_type_extent( oldType, &extent ); pdt = ompi_datatype_create( (count - i) * (2 + oldType->super.desc.used) ); for( i += 1; i < count; i++ ) { - if( 0 == pBlockLength[i] ) /* ignore empty length */ + if( 0 == ompi_count_array_get(pBlockLength, i) ) /* ignore empty length */ continue; - if( endat == pDisp[i] ) { /* contiguous with the previsious */ - dLength += pBlockLength[i]; - endat += pBlockLength[i]; + if( endat == ompi_disp_array_get(pDisp, i) ) { /* contiguous with the previsious */ + dLength += ompi_count_array_get(pBlockLength, i); + endat += ompi_count_array_get(pBlockLength, i); } else { ompi_datatype_add( pdt, oldType, dLength, disp * extent, extent ); - disp = pDisp[i]; - dLength = pBlockLength[i]; - endat = disp + pBlockLength[i]; + disp = ompi_disp_array_get(pDisp, i); + dLength = ompi_count_array_get(pBlockLength, i); + endat = disp + dLength; } } ompi_datatype_add( pdt, oldType, dLength, disp * extent, extent ); @@ -72,38 +73,38 @@ int32_t ompi_datatype_create_indexed( int count, const int* pBlockLength, const } -int32_t ompi_datatype_create_hindexed( int count, const int* pBlockLength, const ptrdiff_t* pDisp, +int32_t ompi_datatype_create_hindexed( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ptrdiff_t extent, disp, endat; ompi_datatype_t* pdt; size_t dLength; - int i; + size_t i; /* ignore all cases that lead to an empty type */ ompi_datatype_type_size(oldType, &dLength); - for( i = 0; (i < count) && (0 == pBlockLength[i]); i++ ); /* find first non zero */ + for( i = 0; (i < count) && (0 == ompi_count_array_get(pBlockLength, i)); i++ ); /* find first non zero */ if( (i == count) || (0 == dLength) ) { return ompi_datatype_duplicate( &ompi_mpi_datatype_null.dt, newType); } ompi_datatype_type_extent( oldType, &extent ); - disp = pDisp[i]; - dLength = pBlockLength[i]; + disp = ompi_disp_array_get(pDisp, i); + dLength = ompi_count_array_get(pBlockLength, i); endat = disp + dLength * extent; pdt = ompi_datatype_create( (count - i) * (2 + oldType->super.desc.used) ); for( i += 1; i < count; i++ ) { - if( 0 == pBlockLength[i] ) /* ignore empty length */ + if( 0 == ompi_count_array_get(pBlockLength, i) ) /* ignore empty length */ continue; - if( endat == pDisp[i] ) { /* contiguous with the previsious */ - dLength += pBlockLength[i]; - endat += pBlockLength[i] * extent; + if( endat == ompi_disp_array_get(pDisp, i) ) { /* contiguous with the previsious */ + dLength += ompi_count_array_get(pBlockLength, i); + endat += ompi_count_array_get(pBlockLength, i) * extent; } else { ompi_datatype_add( pdt, oldType, dLength, disp, extent ); - disp = pDisp[i]; - dLength = pBlockLength[i]; - endat = disp + pBlockLength[i] * extent; + disp = ompi_disp_array_get(pDisp, i); + dLength = ompi_count_array_get(pBlockLength, i); + endat = disp + dLength * extent; } } ompi_datatype_add( pdt, oldType, dLength, disp, extent ); @@ -113,30 +114,30 @@ int32_t ompi_datatype_create_hindexed( int count, const int* pBlockLength, const } -int32_t ompi_datatype_create_indexed_block( int count, int bLength, const int* pDisp, +int32_t ompi_datatype_create_indexed_block( size_t count, size_t bLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ptrdiff_t extent, disp, endat; ompi_datatype_t* pdt; size_t dLength; - int i; + size_t i; if( (count == 0) || (bLength == 0) ) { return ompi_datatype_duplicate(&ompi_mpi_datatype_null.dt, newType); } ompi_datatype_type_extent( oldType, &extent ); pdt = ompi_datatype_create( count * (2 + oldType->super.desc.used) ); - disp = pDisp[0]; + disp = ompi_disp_array_get(pDisp, 0); dLength = bLength; endat = disp + dLength; for( i = 1; i < count; i++ ) { - if( endat == pDisp[i] ) { + if( endat == ompi_disp_array_get(pDisp, i) ) { /* contiguous with the previsious */ dLength += bLength; endat += bLength; } else { ompi_datatype_add( pdt, oldType, dLength, disp * extent, extent ); - disp = pDisp[i]; + disp = ompi_disp_array_get(pDisp, i); dLength = bLength; endat = disp + bLength; } @@ -147,30 +148,30 @@ int32_t ompi_datatype_create_indexed_block( int count, int bLength, const int* p return OMPI_SUCCESS; } -int32_t ompi_datatype_create_hindexed_block( int count, int bLength, const ptrdiff_t* pDisp, +int32_t ompi_datatype_create_hindexed_block( size_t count, size_t bLength, const ompi_disp_array_t pDisp, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ptrdiff_t extent, disp, endat; ompi_datatype_t* pdt; size_t dLength; - int i; + size_t i; if( (count == 0) || (bLength == 0) ) { return ompi_datatype_duplicate(&ompi_mpi_datatype_null.dt, newType); } ompi_datatype_type_extent( oldType, &extent ); pdt = ompi_datatype_create( count * (2 + oldType->super.desc.used) ); - disp = pDisp[0]; + disp = ompi_disp_array_get(pDisp, 0); dLength = bLength; endat = disp + dLength * extent; for( i = 1; i < count; i++ ) { - if( endat == pDisp[i] ) { + if( endat == ompi_disp_array_get(pDisp, i) ) { /* contiguous with the previsious */ dLength += bLength; endat += bLength * extent; } else { ompi_datatype_add( pdt, oldType, dLength, disp, extent ); - disp = pDisp[i]; + disp = ompi_disp_array_get(pDisp, i); dLength = bLength; endat = disp + bLength * extent; } diff --git a/ompi/datatype/ompi_datatype_create_struct.c b/ompi/datatype/ompi_datatype_create_struct.c index 72d3251b936..bf4a05017c8 100644 --- a/ompi/datatype/ompi_datatype_create_struct.c +++ b/ompi/datatype/ompi_datatype_create_struct.c @@ -15,6 +15,7 @@ * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -28,16 +29,16 @@ #include "ompi/datatype/ompi_datatype.h" -int32_t ompi_datatype_create_struct( int count, const int* pBlockLength, const ptrdiff_t* pDisp, +int32_t ompi_datatype_create_struct( size_t count, const ompi_count_array_t pBlockLength, const ompi_disp_array_t pDisp, ompi_datatype_t* const * pTypes, ompi_datatype_t** newType ) { ptrdiff_t disp = 0, endto, lastExtent, lastDisp; ompi_datatype_t *pdt, *lastType; - int i, start_from; + size_t i, start_from; size_t lastBlock; /* Find first non-zero length element */ - for( i = 0; (i < count) && (0 == pBlockLength[i]); i++ ); + for( i = 0; (i < count) && (0 == ompi_count_array_get(pBlockLength, i)); i++ ); if( i == count ) { /* either nothing or nothing relevant */ return ompi_datatype_duplicate( &ompi_mpi_datatype_null.dt, newType); } @@ -46,22 +47,22 @@ int32_t ompi_datatype_create_struct( int count, const int* pBlockLength, const p */ start_from = i; lastType = (ompi_datatype_t*)pTypes[start_from]; - lastBlock = pBlockLength[start_from]; + lastBlock = ompi_count_array_get(pBlockLength, start_from); lastExtent = lastType->super.ub - lastType->super.lb; - lastDisp = pDisp[start_from]; - endto = pDisp[start_from] + lastExtent * lastBlock; + lastDisp = ompi_disp_array_get(pDisp, start_from); + endto = lastDisp + lastExtent * lastBlock; for( i = (start_from + 1); i < count; i++ ) { - if( (pTypes[i] == lastType) && (pDisp[i] == endto) ) { - lastBlock += pBlockLength[i]; + if( (pTypes[i] == lastType) && (ompi_disp_array_get(pDisp, i) == endto) ) { + lastBlock += ompi_count_array_get(pBlockLength, i); endto = lastDisp + lastBlock * lastExtent; } else { disp += lastType->super.desc.used; if( lastBlock > 1 ) disp += 2; lastType = (ompi_datatype_t*)pTypes[i]; lastExtent = lastType->super.ub - lastType->super.lb; - lastBlock = pBlockLength[i]; - lastDisp = pDisp[i]; + lastBlock = ompi_count_array_get(pBlockLength, i); + lastDisp = ompi_disp_array_get(pDisp, i); endto = lastDisp + lastExtent * lastBlock; } } @@ -69,24 +70,24 @@ int32_t ompi_datatype_create_struct( int count, const int* pBlockLength, const p if( lastBlock != 1 ) disp += 2; lastType = (ompi_datatype_t*)pTypes[start_from]; - lastBlock = pBlockLength[start_from]; + lastBlock = ompi_count_array_get(pBlockLength, start_from); lastExtent = lastType->super.ub - lastType->super.lb; - lastDisp = pDisp[start_from]; - endto = pDisp[start_from] + lastExtent * lastBlock; + lastDisp = ompi_disp_array_get(pDisp, start_from); + endto = lastDisp + lastExtent * lastBlock; pdt = ompi_datatype_create( (int32_t)disp ); /* Do again the same loop but now add the elements */ for( i = (start_from + 1); i < count; i++ ) { - if( (pTypes[i] == lastType) && (pDisp[i] == endto) ) { - lastBlock += pBlockLength[i]; + if( (pTypes[i] == lastType) && (ompi_disp_array_get(pDisp, i) == endto) ) { + lastBlock += ompi_count_array_get(pBlockLength, i); endto = lastDisp + lastBlock * lastExtent; } else { ompi_datatype_add( pdt, lastType, lastBlock, lastDisp, lastExtent ); lastType = (ompi_datatype_t*)pTypes[i]; lastExtent = lastType->super.ub - lastType->super.lb; - lastBlock = pBlockLength[i]; - lastDisp = pDisp[i]; + lastBlock = ompi_count_array_get(pBlockLength, i); + lastDisp = ompi_disp_array_get(pDisp, i); endto = lastDisp + lastExtent * lastBlock; } } diff --git a/ompi/datatype/ompi_datatype_create_subarray.c b/ompi/datatype/ompi_datatype_create_subarray.c index fcf44407725..d82251e708c 100644 --- a/ompi/datatype/ompi_datatype_create_subarray.c +++ b/ompi/datatype/ompi_datatype_create_subarray.c @@ -15,6 +15,7 @@ * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2014-2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -29,9 +30,9 @@ #include "ompi/datatype/ompi_datatype.h" int32_t ompi_datatype_create_subarray(int ndims, - int const* size_array, - int const* subsize_array, - int const* start_array, + const ompi_count_array_t size_array, + const ompi_count_array_t subsize_array, + const ompi_count_array_t start_array, int order, const ompi_datatype_t* oldtype, ompi_datatype_t** newtype) @@ -54,9 +55,9 @@ int32_t ompi_datatype_create_subarray(int ndims, ompi_datatype_duplicate(&ompi_mpi_datatype_null.dt, newtype); return MPI_SUCCESS; } - ompi_datatype_create_contiguous( subsize_array[0], oldtype, &last_type ); - size = size_array[0]; - displ = start_array[0]; + ompi_datatype_create_contiguous( ompi_count_array_get(subsize_array, 0), oldtype, &last_type ); + size = ompi_count_array_get(size_array, 0); + displ = ompi_count_array_get(start_array, 0); goto replace_subarray_type; } @@ -74,19 +75,22 @@ int32_t ompi_datatype_create_subarray(int ndims, * first dimension data outside the loop, such that we dont have to create * a duplicate of the oldtype just to be able to free it. */ - ompi_datatype_create_vector( subsize_array[i+step], subsize_array[i], size_array[i], + ompi_datatype_create_vector( ompi_count_array_get(subsize_array, i+step), + ompi_count_array_get(subsize_array, i), + ompi_count_array_get(size_array, i), oldtype, newtype ); last_type = *newtype; - size = (MPI_Aint)size_array[i] * (MPI_Aint)size_array[i+step]; - displ = (MPI_Aint)start_array[i] + (MPI_Aint)start_array[i+step] * (MPI_Aint)size_array[i]; + size = (MPI_Aint)ompi_count_array_get(size_array, i) * (MPI_Aint)ompi_count_array_get(size_array, i+step); + displ = (MPI_Aint)ompi_count_array_get(start_array, i) + + (MPI_Aint)ompi_count_array_get(start_array, i+step) * (MPI_Aint)ompi_count_array_get(size_array, i); for( i += 2 * step; i != end_loop; i += step ) { - ompi_datatype_create_hvector( subsize_array[i], 1, size * extent, + ompi_datatype_create_hvector( ompi_count_array_get(subsize_array, i), 1, size * extent, last_type, newtype ); ompi_datatype_destroy( &last_type ); - displ += size * start_array[i]; - size *= size_array[i]; + displ += size * ompi_count_array_get(start_array, i); + size *= ompi_count_array_get(size_array, i); last_type = *newtype; } diff --git a/ompi/datatype/ompi_datatype_create_vector.c b/ompi/datatype/ompi_datatype_create_vector.c index c4829a4b54c..134bcfc50e5 100644 --- a/ompi/datatype/ompi_datatype_create_vector.c +++ b/ompi/datatype/ompi_datatype_create_vector.c @@ -15,6 +15,7 @@ * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -28,7 +29,7 @@ #include "ompi/datatype/ompi_datatype.h" -int32_t ompi_datatype_create_vector( int count, int bLength, int stride, +int32_t ompi_datatype_create_vector( size_t count, size_t bLength, ptrdiff_t stride, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ompi_datatype_t *pTempData, *pData; @@ -39,7 +40,7 @@ int32_t ompi_datatype_create_vector( int count, int bLength, int stride, } pData = ompi_datatype_create( oldType->super.desc.used + 2 ); - if( (bLength == stride) || (1 >= count) ) { /* the elements are contiguous */ + if( (bLength == (size_t)stride) || (1 >= count) ) { /* the elements are contiguous */ ompi_datatype_add( pData, oldType, (size_t)count * bLength, 0, extent ); } else { if( 1 == bLength ) { @@ -57,7 +58,7 @@ int32_t ompi_datatype_create_vector( int count, int bLength, int stride, } -int32_t ompi_datatype_create_hvector( int count, int bLength, ptrdiff_t stride, +int32_t ompi_datatype_create_hvector( size_t count, size_t bLength, ptrdiff_t stride, const ompi_datatype_t* oldType, ompi_datatype_t** newType ) { ompi_datatype_t *pTempData, *pData; @@ -68,7 +69,7 @@ int32_t ompi_datatype_create_hvector( int count, int bLength, ptrdiff_t stride, } pTempData = ompi_datatype_create( oldType->super.desc.used + 2 ); - if( ((extent * bLength) == stride) || (1 >= count) ) { /* contiguous */ + if( ((extent * bLength) == (size_t)stride) || (1 >= count) ) { /* contiguous */ pData = pTempData; ompi_datatype_add( pData, oldType, count * bLength, 0, extent ); } else { diff --git a/ompi/datatype/ompi_datatype_match_size.c b/ompi/datatype/ompi_datatype_match_size.c index 1e036c7003b..ff48eeface8 100644 --- a/ompi/datatype/ompi_datatype_match_size.c +++ b/ompi/datatype/ompi_datatype_match_size.c @@ -12,6 +12,7 @@ * All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -26,7 +27,7 @@ extern int32_t ompi_datatype_number_of_predefined_data; -const ompi_datatype_t* ompi_datatype_match_size( int size, uint16_t datakind, uint16_t datalang ) +const ompi_datatype_t* ompi_datatype_match_size( size_t size, uint16_t datakind, uint16_t datalang ) { int32_t i; const ompi_datatype_t* datatype; @@ -45,7 +46,7 @@ const ompi_datatype_t* ompi_datatype_match_size( int size, uint16_t datakind, ui continue; if( (datatype->super.flags & OMPI_DATATYPE_FLAG_DATA_TYPE) != datakind ) continue; - if( (size_t)size == datatype->super.size ) { + if( size == datatype->super.size ) { return datatype; } } diff --git a/ompi/datatype/ompi_datatype_module.c b/ompi/datatype/ompi_datatype_module.c index 2a11e6ef090..3cf875069a5 100644 --- a/ompi/datatype/ompi_datatype_module.c +++ b/ompi/datatype/ompi_datatype_module.c @@ -22,6 +22,7 @@ * reserved. * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -441,7 +442,9 @@ opal_pointer_array_t ompi_datatype_f_to_c_table = {{0}}; displ[1] = (ptrdiff_t)(&(s[0].v2)); \ displ[1] -= base; \ \ - ompi_datatype_create_struct( 2, bLength, displ, types, &ptype ); \ + ompi_datatype_create_struct( 2, OMPI_COUNT_ARRAY_CREATE(bLength), \ + OMPI_DISP_ARRAY_CREATE(displ), types, \ + &ptype ); \ displ[0] = (ptrdiff_t)(&(s[1])); \ displ[0] -= base; \ if( displ[0] != (displ[1] + (ptrdiff_t)sizeof(type2)) ) \ diff --git a/ompi/datatype/ompi_datatype_sndrcv.c b/ompi/datatype/ompi_datatype_sndrcv.c index 967c7509271..c8877a9cf33 100644 --- a/ompi/datatype/ompi_datatype_sndrcv.c +++ b/ompi/datatype/ompi_datatype_sndrcv.c @@ -13,6 +13,7 @@ * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2014-2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -42,8 +43,8 @@ * - communicator * Returns: - MPI_SUCCESS or error code */ -int32_t ompi_datatype_sndrcv( const void *sbuf, int32_t scount, const ompi_datatype_t* sdtype, - void *rbuf, int32_t rcount, const ompi_datatype_t* rdtype) +int32_t ompi_datatype_sndrcv( const void *sbuf, size_t scount, const ompi_datatype_t* sdtype, + void *rbuf, size_t rcount, const ompi_datatype_t* rdtype) { opal_convertor_t send_convertor, recv_convertor; struct iovec iov; @@ -73,11 +74,11 @@ int32_t ompi_datatype_sndrcv( const void *sbuf, int32_t scount, const ompi_datat iov_count = 1; iov.iov_base = (IOVBASE_TYPE*)rbuf; iov.iov_len = scount * sdtype->super.size; - if( (int32_t)iov.iov_len > rcount ) iov.iov_len = rcount; + if( iov.iov_len > rcount ) iov.iov_len = rcount; opal_convertor_pack( &send_convertor, &iov, &iov_count, &max_data ); OBJ_DESTRUCT( &send_convertor ); - return ((max_data < (size_t)rcount) ? MPI_ERR_TRUNCATE : MPI_SUCCESS); + return ((max_data < rcount) ? MPI_ERR_TRUNCATE : MPI_SUCCESS); } /* If send packed. */ @@ -90,11 +91,11 @@ int32_t ompi_datatype_sndrcv( const void *sbuf, int32_t scount, const ompi_datat iov_count = 1; iov.iov_base = (IOVBASE_TYPE*)sbuf; iov.iov_len = rcount * rdtype->super.size; - if( (int32_t)iov.iov_len > scount ) iov.iov_len = scount; + if( iov.iov_len > scount ) iov.iov_len = scount; opal_convertor_unpack( &recv_convertor, &iov, &iov_count, &max_data ); OBJ_DESTRUCT( &recv_convertor ); - return (((size_t)scount > max_data) ? MPI_ERR_TRUNCATE : MPI_SUCCESS); + return ((scount > max_data) ? MPI_ERR_TRUNCATE : MPI_SUCCESS); } iov.iov_len = length = 64 * 1024; diff --git a/ompi/mca/coll/base/coll_base_allgatherv.c b/ompi/mca/coll/base/coll_base_allgatherv.c index 337e09f7c77..9d86772181f 100644 --- a/ompi/mca/coll/base/coll_base_allgatherv.c +++ b/ompi/mca/coll/base/coll_base_allgatherv.c @@ -16,6 +16,7 @@ * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -101,7 +102,8 @@ int ompi_coll_base_allgatherv_intra_bruck(const void *sbuf, size_t scount, mca_coll_base_module_t *module) { int line = -1, err = 0, rank, size, sendto, recvfrom, distance, blockcount, i; - int *new_rcounts = NULL, *new_rdispls = NULL, *new_scounts = NULL, *new_sdispls = NULL; + size_t *new_rcounts = NULL, *new_scounts = NULL; + ptrdiff_t *new_rdispls = NULL, *new_sdispls = NULL; ptrdiff_t rlb, rext; char *tmpsend = NULL, *tmprecv = NULL; struct ompi_datatype_t *new_rdtype, *new_sdtype; @@ -142,11 +144,11 @@ int ompi_coll_base_allgatherv_intra_bruck(const void *sbuf, size_t scount, blockcount = 1; tmpsend = (char*) rbuf; - new_rcounts = (int*) calloc(4*size, sizeof(int)); + new_rcounts = (size_t*) calloc(4*size, sizeof(size_t)); if (NULL == new_rcounts) { err = -1; line = __LINE__; goto err_hndl; } - new_rdispls = new_rcounts + size; - new_scounts = new_rdispls + size; - new_sdispls = new_scounts + size; + new_scounts = new_rcounts + size; + new_rdispls = (ptrdiff_t*) (new_scounts + size); + new_sdispls = new_rdispls + size; for (distance = 1; distance < size; distance<<=1) { @@ -168,10 +170,12 @@ int ompi_coll_base_allgatherv_intra_bruck(const void *sbuf, size_t scount, new_rcounts[i] = ompi_count_array_get(rcounts, tmp_rrank); new_rdispls[i] = ompi_disp_array_get(rdispls, tmp_rrank); } - err = ompi_datatype_create_indexed(blockcount, new_scounts, new_sdispls, + err = ompi_datatype_create_indexed(blockcount, OMPI_COUNT_ARRAY_CREATE(new_scounts), + OMPI_DISP_ARRAY_CREATE(new_sdispls), rdtype, &new_sdtype); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } - err = ompi_datatype_create_indexed(blockcount, new_rcounts, new_rdispls, + err = ompi_datatype_create_indexed(blockcount, OMPI_COUNT_ARRAY_CREATE(new_rcounts), + OMPI_DISP_ARRAY_CREATE(new_rdispls), rdtype, &new_rdtype); err = ompi_datatype_commit(&new_sdtype); @@ -513,7 +517,8 @@ ompi_coll_base_allgatherv_intra_neighborexchange(const void *sbuf, size_t scount int neighbor[2], offset_at_step[2], recv_data_from[2], send_data_from; size_t new_scounts[2], new_rcounts[2]; ptrdiff_t new_sdispls[2], new_rdispls[2]; - int tmp_new_scounts[2], tmp_new_rcounts[2], tmp_new_sdispls[2], tmp_new_rdispls[2]; + size_t tmp_new_scounts[2], tmp_new_rcounts[2]; + ptrdiff_t tmp_new_sdispls[2], tmp_new_rdispls[2]; ptrdiff_t rlb, rext; char *tmpsend = NULL, *tmprecv = NULL; struct ompi_datatype_t *new_rdtype, *new_sdtype; @@ -611,7 +616,8 @@ ompi_coll_base_allgatherv_intra_neighborexchange(const void *sbuf, size_t scount tmp_new_scounts[1] = new_scounts[1]; tmp_new_sdispls[0] = new_sdispls[0]; tmp_new_sdispls[1] = new_sdispls[1]; - err = ompi_datatype_create_indexed(2, tmp_new_scounts, tmp_new_sdispls, rdtype, + err = ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(tmp_new_scounts), + OMPI_DISP_ARRAY_CREATE(tmp_new_sdispls), rdtype, &new_sdtype); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } err = ompi_datatype_commit(&new_sdtype); @@ -626,7 +632,8 @@ ompi_coll_base_allgatherv_intra_neighborexchange(const void *sbuf, size_t scount tmp_new_rcounts[1] = new_rcounts[1]; tmp_new_rdispls[0] = new_rdispls[0]; tmp_new_rdispls[1] = new_rdispls[1]; - err = ompi_datatype_create_indexed(2, tmp_new_rcounts, tmp_new_rdispls, rdtype, + err = ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(tmp_new_rcounts), + OMPI_DISP_ARRAY_CREATE(tmp_new_rdispls), rdtype, &new_rdtype); if (MPI_SUCCESS != err) { line = __LINE__; goto err_hndl; } err = ompi_datatype_commit(&new_rdtype); @@ -757,7 +764,6 @@ ompi_coll_base_allgatherv_intra_basic_default(const void *sbuf, size_t scount, MPI_Aint extent, lb; char *send_buf = NULL; struct ompi_datatype_t *newtype, *send_type; - int *tmp_rcounts, *tmp_disps; size = ompi_comm_size(comm); rank = ompi_comm_rank(comm); @@ -801,22 +807,8 @@ ompi_coll_base_allgatherv_intra_basic_default(const void *sbuf, size_t scount, * datatype. */ - /* TODO:BIGCOUNT: Remove temporaries once ompi_datatype interface is updated */ - tmp_rcounts = malloc(size * sizeof(int)); - if (NULL == tmp_rcounts) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - tmp_disps = malloc(size * sizeof(int)); - if (NULL == tmp_disps) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - for (int i = 0; i < size; i++) { - tmp_rcounts[i] = ompi_count_array_get(rcounts, i); - tmp_disps[i] = ompi_disp_array_get(disps, i); - } - err = ompi_datatype_create_indexed(size,tmp_rcounts,tmp_disps,rdtype,&newtype); - free(tmp_rcounts); - free(tmp_disps); + err = ompi_datatype_create_indexed(size, rcounts, disps, + rdtype, &newtype); if (MPI_SUCCESS != err) { return err; } diff --git a/ompi/mca/coll/base/coll_base_reduce_scatter_block.c b/ompi/mca/coll/base/coll_base_reduce_scatter_block.c index f72469d1a00..ca4a6989bec 100644 --- a/ompi/mca/coll/base/coll_base_reduce_scatter_block.c +++ b/ompi/mca/coll/base/coll_base_reduce_scatter_block.c @@ -19,6 +19,7 @@ * and Information Sciences. All rights reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved. * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -202,7 +203,8 @@ ompi_coll_base_reduce_scatter_block_intra_recursivedoubling( struct ompi_datatype_t *dtypesend = NULL, *dtyperecv = NULL; char *tmprecv_raw = NULL, *tmpbuf_raw = NULL, *tmprecv, *tmpbuf; ptrdiff_t span, gap, totalcount, extent; - int blocklens[2], displs[2]; + size_t blocklens[2]; + ptrdiff_t displs[2]; int err = MPI_SUCCESS; int comm_size = ompi_comm_size(comm); int rank = ompi_comm_rank(comm); @@ -270,7 +272,8 @@ ompi_coll_base_reduce_scatter_block_intra_recursivedoubling( rcount * (comm_size - cur_tree_root - mask) : 0; displs[0] = 0; displs[1] = comm_size * rcount - blocklens[1]; - err = ompi_datatype_create_indexed(2, blocklens, displs, dtype, &dtypesend); + err = ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(blocklens), + OMPI_DISP_ARRAY_CREATE(displs), dtype, &dtypesend); if (MPI_SUCCESS != err) { goto cleanup_and_return; } err = ompi_datatype_commit(&dtypesend); if (MPI_SUCCESS != err) { goto cleanup_and_return; } @@ -281,7 +284,8 @@ ompi_coll_base_reduce_scatter_block_intra_recursivedoubling( rcount * (comm_size - remote_tree_root - mask) : 0; displs[0] = 0; displs[1] = comm_size * rcount - blocklens[1]; - err = ompi_datatype_create_indexed(2, blocklens, displs, dtype, &dtyperecv); + err = ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(blocklens), + OMPI_DISP_ARRAY_CREATE(displs), dtype, &dtyperecv); if (MPI_SUCCESS != err) { goto cleanup_and_return; } err = ompi_datatype_commit(&dtyperecv); if (MPI_SUCCESS != err) { goto cleanup_and_return; } diff --git a/ompi/mca/coll/inter/coll_inter_allgatherv.c b/ompi/mca/coll/inter/coll_inter_allgatherv.c index fa7c9e14301..a0c7881bcff 100644 --- a/ompi/mca/coll/inter/coll_inter_allgatherv.c +++ b/ompi/mca/coll/inter/coll_inter_allgatherv.c @@ -13,6 +13,7 @@ * Copyright (c) 2015-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -107,21 +108,8 @@ mca_coll_inter_allgatherv_inter(const void *sbuf, size_t scount, goto exit; } - /* TODO:BIGCOUNT: Remove tehese temporaries once ompi_datatype is updated for bigcount */ - int *tmp_rcounts = malloc(sizeof(int) * size); - int *tmp_disps = malloc(sizeof(int) * size); - if (NULL == tmp_rcounts || NULL == tmp_disps) { - err = OMPI_ERR_OUT_OF_RESOURCE; - goto exit; - } - for (i = 0; i < size; ++i) { - tmp_rcounts[i] = (int) ompi_count_array_get(rcounts, i); - tmp_disps[i] = (int) ompi_disp_array_get(disps, i); - } - ompi_datatype_create_indexed(size,tmp_rcounts,tmp_disps,rdtype,&ndtype); + ompi_datatype_create_indexed(size,rcounts,disps,rdtype,&ndtype); ompi_datatype_commit(&ndtype); - free(tmp_rcounts); - free(tmp_disps); if (0 == rank) { /* Exchange data between roots */ diff --git a/ompi/mca/coll/inter/coll_inter_gatherv.c b/ompi/mca/coll/inter/coll_inter_gatherv.c index 1e1d8840a44..73d3716ca8e 100644 --- a/ompi/mca/coll/inter/coll_inter_gatherv.c +++ b/ompi/mca/coll/inter/coll_inter_gatherv.c @@ -13,6 +13,7 @@ * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -62,20 +63,8 @@ mca_coll_inter_gatherv_inter(const void *sbuf, size_t scount, size_local = ompi_comm_size(comm); if (MPI_ROOT == root) { /* I am the root, receiving the data from zero. */ - /* TODO:BIGCOUNT: Remove these temporaries once ompi_datatype is updated for bigcount */ - int *tmp_rcounts = malloc(sizeof(int) * size); - int *tmp_disps = malloc(sizeof(int) * size); - if (NULL == tmp_rcounts || NULL == tmp_disps) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - for (i = 0; i < size; ++i) { - tmp_rcounts[i] = ompi_count_array_get(rcounts, i); - tmp_disps[i] = ompi_disp_array_get(disps, i); - } - ompi_datatype_create_indexed(size, tmp_rcounts, tmp_disps, rdtype, &ndtype); + ompi_datatype_create_indexed(size, rcounts, disps, rdtype, &ndtype); ompi_datatype_commit(&ndtype); - free(tmp_rcounts); - free(tmp_disps); err = MCA_PML_CALL(recv(rbuf, 1, ndtype, 0, MCA_COLL_BASE_TAG_GATHERV, diff --git a/ompi/mca/coll/inter/coll_inter_scatterv.c b/ompi/mca/coll/inter/coll_inter_scatterv.c index 5d98e1ea099..9f97af68a45 100644 --- a/ompi/mca/coll/inter/coll_inter_scatterv.c +++ b/ompi/mca/coll/inter/coll_inter_scatterv.c @@ -13,6 +13,7 @@ * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -100,9 +101,9 @@ mca_coll_inter_scatterv_inter(const void *sbuf, ompi_count_array_t scounts, displace[i] = displace[i-1] + counts[i-1]; } } - /* perform the scatterv locally */ OMPI_COUNT_ARRAY_INIT(&counts_arg, counts); OMPI_DISP_ARRAY_INIT(&displace_arg, displace); + /* perform the scatterv locally */ err = comm->c_local_comm->c_coll->coll_scatterv(ptmp, counts_arg, displace_arg, rdtype, rbuf, rcount, rdtype, 0, comm->c_local_comm, @@ -139,20 +140,8 @@ mca_coll_inter_scatterv_inter(const void *sbuf, ompi_count_array_t scounts, return err; } - /* TODO:BIGCOUNT: Remove these temporaries once ompi_datatype is updated for bigcount */ - int *tmp_scounts = malloc(sizeof(int) * size); - int *tmp_disps = malloc(sizeof(int) * size); - if (NULL == tmp_scounts || NULL == tmp_disps) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - for (i = 0; i < size; ++i) { - tmp_scounts[i] = (int) ompi_count_array_get(scounts, i); - tmp_disps[i] = (int) ompi_disp_array_get(disps, i); - } - ompi_datatype_create_indexed(size,tmp_scounts,tmp_disps,sdtype,&ndtype); + ompi_datatype_create_indexed(size,scounts,disps,sdtype,&ndtype); ompi_datatype_commit(&ndtype); - free(tmp_scounts); - free(tmp_disps); err = MCA_PML_CALL(send(sbuf, 1, ndtype, 0, MCA_COLL_BASE_TAG_SCATTERV, diff --git a/ompi/mca/common/ompio/common_ompio_file_open.c b/ompi/mca/common/ompio/common_ompio_file_open.c index 9104b175e70..bf2c195b89d 100644 --- a/ompi/mca/common/ompio/common_ompio_file_open.c +++ b/ompi/mca/common/ompio/common_ompio_file_open.c @@ -17,6 +17,7 @@ * Copyright (c) 2018 DataDirect Networks. All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -502,8 +503,8 @@ int mca_common_ompio_set_file_defaults (ompio_file_t *fh) } ompi_datatype_create_struct (2, - blocklen, - d, + OMPI_COUNT_ARRAY_CREATE(blocklen), + OMPI_DISP_ARRAY_CREATE(d), types, &fh->f_iov_type); ompi_datatype_commit (&fh->f_iov_type); diff --git a/ompi/mca/common/ompio/common_ompio_file_read_all.c b/ompi/mca/common/ompio/common_ompio_file_read_all.c index 1b2f8d6c474..862da9ebeb5 100644 --- a/ompi/mca/common/ompio/common_ompio_file_read_all.c +++ b/ompi/mca/common/ompio/common_ompio_file_read_all.c @@ -16,6 +16,7 @@ * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -502,6 +503,9 @@ mca_common_ompio_base_file_read_all (struct ompio_file_t *fh, *****************************************************************/ bytes_received = 0; + /** + * TODO: replace with big count? + */ while (bytes_to_read_in_cycle) { /* This next block identifies which process is the holder ** of the sorted[current_index] element; @@ -774,8 +778,8 @@ mca_common_ompio_base_file_read_all (struct ompio_file_t *fh, send_req[i] = MPI_REQUEST_NULL; if ( 0 < disp_index[i] ) { ompi_datatype_create_hindexed(disp_index[i], - blocklen_per_process[i], - displs_per_process[i], + OMPI_COUNT_ARRAY_CREATE(blocklen_per_process[i]), + OMPI_DISP_ARRAY_CREATE(displs_per_process[i]), MPI_BYTE, &sendtype[i]); ompi_datatype_commit(&sendtype[i]); @@ -854,8 +858,8 @@ mca_common_ompio_base_file_read_all (struct ompio_file_t *fh, } ompi_datatype_create_hindexed(block_index+1, - blocklength_proc, - displs_proc, + OMPI_COUNT_ARRAY_CREATE(blocklength_proc), + OMPI_DISP_ARRAY_CREATE(displs_proc), MPI_BYTE, &newType); ompi_datatype_commit(&newType); diff --git a/ompi/mca/common/ompio/common_ompio_file_view.c b/ompi/mca/common/ompio/common_ompio_file_view.c index 8ea15de14d6..5f966d2f189 100644 --- a/ompi/mca/common/ompio/common_ompio_file_view.c +++ b/ompi/mca/common/ompio/common_ompio_file_view.c @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. * Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -47,8 +48,8 @@ static int datatype_duplicate (ompi_datatype_t *oldtype, ompi_datatype_t **newt ompi_datatype_destroy (&type); return MPI_ERR_INTERN; } - - ompi_datatype_set_args( type, 0, NULL, 0, NULL, 1, &oldtype, MPI_COMBINER_DUP ); + + ompi_datatype_set_args( type, 0, 0, NULL, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_DUP ); *newtype = type; return OMPI_SUCCESS; diff --git a/ompi/mca/fcoll/base/fcoll_base_coll_array.c b/ompi/mca/fcoll/base/fcoll_base_coll_array.c index 68f25ace6fb..6f888c1dd29 100644 --- a/ompi/mca/fcoll/base/fcoll_base_coll_array.c +++ b/ompi/mca/fcoll/base/fcoll_base_coll_array.c @@ -14,6 +14,7 @@ * Copyright (c) 2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -50,7 +51,6 @@ int ompi_fcoll_base_coll_allgatherv_array (void *sbuf, int err = OMPI_SUCCESS; ptrdiff_t extent, lb; int i, rank, j; - int *tmp_rcounts = NULL, *tmp_disps = NULL; char *send_buf = NULL; struct ompi_datatype_t *newtype, *send_type; @@ -93,24 +93,11 @@ int ompi_fcoll_base_coll_allgatherv_array (void *sbuf, return err; } - /* TODO:BIGCOUNT: remove tmp_rcounts and tmp_disps once the ompi_datatype - * interface is udpated to use size_t/ptrdiff_t - */ - tmp_rcounts = (int *)malloc(2 * procs_per_group * sizeof(int)); - if (NULL == tmp_rcounts) { - return OMPI_ERR_OUT_OF_RESOURCE; - } - tmp_disps = tmp_rcounts + procs_per_group; - for (i = 0; i < procs_per_group; i++) { - tmp_rcounts[i] = (int) rcounts[i]; - tmp_disps[i] = (int) disps[i]; - } err = ompi_datatype_create_indexed (procs_per_group, - tmp_rcounts, - tmp_disps, + OMPI_COUNT_ARRAY_CREATE(rcounts), + OMPI_DISP_ARRAY_CREATE(disps), rdtype, &newtype); - free(tmp_rcounts); if (MPI_SUCCESS != err) { return err; } diff --git a/ompi/mca/fcoll/dynamic/fcoll_dynamic_file_write_all.c b/ompi/mca/fcoll/dynamic/fcoll_dynamic_file_write_all.c index 2ce3ef5d27f..0560bdbe2c4 100644 --- a/ompi/mca/fcoll/dynamic/fcoll_dynamic_file_write_all.c +++ b/ompi/mca/fcoll/dynamic/fcoll_dynamic_file_write_all.c @@ -16,6 +16,7 @@ * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -784,8 +785,8 @@ mca_fcoll_dynamic_file_write_all (struct ompio_file_t *fh, recv_req[i] = MPI_REQUEST_NULL; if ( 0 < disp_index[i] ) { ompi_datatype_create_hindexed(disp_index[i], - blocklen_per_process[i], - displs_per_process[i], + OMPI_COUNT_ARRAY_CREATE(blocklen_per_process[i]), + OMPI_DISP_ARRAY_CREATE(displs_per_process[i]), MPI_BYTE, &recvtype[i]); ompi_datatype_commit(&recvtype[i]); diff --git a/ompi/mca/fcoll/dynamic_gen2/fcoll_dynamic_gen2_file_write_all.c b/ompi/mca/fcoll/dynamic_gen2/fcoll_dynamic_gen2_file_write_all.c index 1f9b5f8bef7..bcd5195148b 100644 --- a/ompi/mca/fcoll/dynamic_gen2/fcoll_dynamic_gen2_file_write_all.c +++ b/ompi/mca/fcoll/dynamic_gen2/fcoll_dynamic_gen2_file_write_all.c @@ -17,6 +17,7 @@ * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -1160,13 +1161,13 @@ static int shuffle_init ( int index, int cycles, int aggregator, int rank, mca_i reqs[i] = MPI_REQUEST_NULL; if ( 0 < data->disp_index[i] ) { ompi_datatype_create_hindexed(data->disp_index[i], - data->blocklen_per_process[i], - data->displs_per_process[i], + OMPI_COUNT_ARRAY_CREATE(data->blocklen_per_process[i]), + OMPI_DISP_ARRAY_CREATE(data->displs_per_process[i]), MPI_BYTE, &data->recvtype[i]); ompi_datatype_commit(&data->recvtype[i]); opal_datatype_type_size(&data->recvtype[i]->super, &datatype_size); - + if (datatype_size){ ret = MCA_PML_CALL(irecv(data->global_buf, 1, @@ -1240,8 +1241,8 @@ static int shuffle_init ( int index, int cycles, int aggregator, int rank, mca_i if ( 0 <= block_index ) { ompi_datatype_create_hindexed(block_index+1, - blocklength_proc, - displs_proc, + OMPI_COUNT_ARRAY_CREATE(blocklength_proc), + OMPI_DISP_ARRAY_CREATE(displs_proc), MPI_BYTE, &newType); ompi_datatype_commit(&newType); diff --git a/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_read_all.c b/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_read_all.c index f6a492e621c..ebef7b3cb92 100644 --- a/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_read_all.c +++ b/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_read_all.c @@ -16,6 +16,7 @@ * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -840,8 +841,8 @@ static int shuffle_init (int index, int cycles, int aggregator, int rank, mca_io reqs[i] = MPI_REQUEST_NULL; if (0 < data->disp_index[i]) { ompi_datatype_create_hindexed (data->disp_index[i], - data->blocklen_per_process[i], - data->displs_per_process[i], + OMPI_COUNT_ARRAY_CREATE(data->blocklen_per_process[i]), + OMPI_DISP_ARRAY_CREATE(data->displs_per_process[i]), MPI_BYTE, &data->recvtype[i]); ompi_datatype_commit (&data->recvtype[i]); @@ -918,8 +919,8 @@ static int shuffle_init (int index, int cycles, int aggregator, int rank, mca_io if (0 <= block_index) { ompi_datatype_create_hindexed (block_index+1, - blocklength_proc, - displs_proc, + OMPI_COUNT_ARRAY_CREATE(blocklength_proc), + OMPI_DISP_ARRAY_CREATE(displs_proc), MPI_BYTE, &newType); ompi_datatype_commit (&newType); diff --git a/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_write_all.c b/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_write_all.c index b6e9be6d2ca..61aa8b32920 100644 --- a/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_write_all.c +++ b/ompi/mca/fcoll/vulcan/fcoll_vulcan_file_write_all.c @@ -17,6 +17,7 @@ * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -833,8 +834,8 @@ static int shuffle_init (int index, int num_cycles, int aggregator, int rank, reqs[i] = MPI_REQUEST_NULL; if (0 < data->disp_index[i]) { ompi_datatype_create_hindexed(data->disp_index[i], - data->blocklen_per_process[i], - data->displs_per_process[i], + OMPI_COUNT_ARRAY_CREATE(data->blocklen_per_process[i]), + OMPI_DISP_ARRAY_CREATE(data->displs_per_process[i]), MPI_BYTE, &data->recvtype[i]); ompi_datatype_commit(&data->recvtype[i]); @@ -909,8 +910,8 @@ static int shuffle_init (int index, int num_cycles, int aggregator, int rank, if ( 0 <= block_index ) { ompi_datatype_create_hindexed(block_index+1, - blocklength_proc, - displs_proc, + OMPI_COUNT_ARRAY_CREATE(blocklength_proc), + OMPI_DISP_ARRAY_CREATE(displs_proc), MPI_BYTE, &newType); ompi_datatype_commit(&newType); diff --git a/ompi/mca/io/ompio/io_ompio.c b/ompi/mca/io/ompio/io_ompio.c index 506b6897e46..bb8ba0a695a 100644 --- a/ompi/mca/io/ompio/io_ompio.c +++ b/ompi/mca/io/ompio/io_ompio.c @@ -16,6 +16,7 @@ * Copyright (c) 2015-2018 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -183,8 +184,8 @@ int ompi_io_ompio_generate_current_file_view (struct ompio_file_t *fh, d[i] -= base; } ompi_datatype_create_struct (3, - blocklen, - d, + OMPI_COUNT_ARRAY_CREATE(blocklen), + OMPI_DISP_ARRAY_CREATE(d), types, &io_array_type); ompi_datatype_commit (&io_array_type); diff --git a/ompi/mca/io/ompio/io_ompio_file_set_view.c b/ompi/mca/io/ompio/io_ompio_file_set_view.c index 5a4f8136295..5124f2d1793 100644 --- a/ompi/mca/io/ompio/io_ompio_file_set_view.c +++ b/ompi/mca/io/ompio/io_ompio_file_set_view.c @@ -13,6 +13,7 @@ * Copyright (c) 2015-2018 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2016-2017 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -48,8 +49,8 @@ static int datatype_duplicate (ompi_datatype_t *oldtype, ompi_datatype_t **newt ompi_datatype_destroy (&type); return MPI_ERR_INTERN; } - - ompi_datatype_set_args( type, 0, NULL, 0, NULL, 1, &oldtype, MPI_COMBINER_DUP ); + + ompi_datatype_set_args( type, 0, 0, NULL, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_DUP ); *newtype = type; return OMPI_SUCCESS; diff --git a/ompi/mpi/c/get_elements.c.in b/ompi/mpi/c/get_elements.c.in index 49483f92f5d..9c9d1513c87 100644 --- a/ompi/mpi/c/get_elements.c.in +++ b/ompi/mpi/c/get_elements.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -66,7 +67,8 @@ PROTOTYPE ERROR_CLASS Get_elements(STATUS status, DATATYPE datatype, COUNT_OUT c ret = ompi_datatype_get_elements (datatype, status->_ucount, &internal_count); if (OMPI_SUCCESS == ret || OMPI_ERR_VALUE_OUT_OF_BOUNDS == ret) { - if (OMPI_SUCCESS == ret && internal_count <= INT_MAX) { + /* check if value fits if compiling the legacy int API */ + if (OMPI_SUCCESS == ret && (internal_count <= INT_MAX || sizeof(*count) > sizeof(int))) { *count = internal_count; } else { /* If we have more elements that we can represent with a signed int then we must diff --git a/ompi/mpi/c/type_contiguous.c.in b/ompi/mpi/c/type_contiguous.c.in index cc88f3cab77..853f12cc9ca 100644 --- a/ompi/mpi/c/type_contiguous.c.in +++ b/ompi/mpi/c/type_contiguous.c.in @@ -17,6 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,11 +33,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - PROTOTYPE ERROR_CLASS type_contiguous(COUNT count, DATATYPE oldtype, @@ -56,12 +52,6 @@ PROTOTYPE ERROR_CLASS type_contiguous(COUNT count, } else if( count < 0 ) { return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_COUNT, FUNC_NAME); } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif } rc = ompi_datatype_create_contiguous( count, oldtype, newtype ); @@ -69,13 +59,14 @@ PROTOTYPE ERROR_CLASS type_contiguous(COUNT count, /* data description */ { + ompi_count_array_t a_i[1] = {OMPI_COUNT_ARRAY_CREATE(&count)}; #if OMPI_BIGCOUNT_SRC - int icount = (int)count; - const int* a_i[1] = {&icount}; -#else - const int* a_i[1] = {&count}; -#endif - ompi_datatype_set_args( *newtype, 1, a_i, 0, NULL, 1, &oldtype, MPI_COMBINER_CONTIGUOUS ); + ompi_datatype_set_args( *newtype, 0, 1, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_CONTIGUOUS ); +#else // OMPI_BIGCOUNT_SRC + ompi_datatype_set_args( *newtype, 1, 0, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_CONTIGUOUS ); +#endif // OMPI_BIGCOUNT_SRC } OMPI_ERRHANDLER_NOHANDLE_RETURN(rc, rc, FUNC_NAME ); diff --git a/ompi/mpi/c/type_create_darray.c.in b/ompi/mpi/c/type_create_darray.c.in index fcf00c8fe14..bbf2114d067 100644 --- a/ompi/mpi/c/type_create_darray.c.in +++ b/ompi/mpi/c/type_create_darray.c.in @@ -17,6 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -33,11 +34,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - PROTOTYPE ERROR_CLASS type_create_darray(INT size, INT rank, @@ -51,7 +47,6 @@ PROTOTYPE ERROR_CLASS type_create_darray(INT size, DATATYPE_OUT newtype) { int i, rc; - int *igsize_array = NULL; MEMCHECKER( memchecker_datatype(oldtype); @@ -75,14 +70,6 @@ PROTOTYPE ERROR_CLASS type_create_darray(INT size, return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, FUNC_NAME); } if( ndims > 0 ) { -#if OMPI_BIGCOUNT_SRC - for( i = 0; i < ndims; i++ ) { - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, gsize_array[i]); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } - } -#endif for( i = 0; i < ndims; i++ ) { if( (MPI_DISTRIBUTE_BLOCK != distrib_array[i]) && (MPI_DISTRIBUTE_CYCLIC != distrib_array[i]) && @@ -104,30 +91,32 @@ PROTOTYPE ERROR_CLASS type_create_darray(INT size, } } -#if OMPI_BIGCOUNT_SRC - igsize_array = (int *)malloc(ndims * sizeof(int)); - if (NULL == igsize_array) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (int ii=0;iiname, sizeof(datatype->name), "COMBINER %s", (*newtype)->name); - a_i[0] = &p; - a_i[1] = &r; - ompi_datatype_set_args( datatype, 2, a_i, 0, NULL, 0, NULL, MPI_COMBINER_F90_COMPLEX ); + ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&p), OMPI_COUNT_ARRAY_CREATE(&r)}; + ompi_datatype_set_args( datatype, 2, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 0, NULL, MPI_COMBINER_F90_COMPLEX ); rc = opal_hash_table_set_value_uint64( &ompi_mpi_f90_complex_hashtable, key, datatype ); if (OMPI_SUCCESS != rc) { diff --git a/ompi/mpi/c/type_create_f90_integer.c.in b/ompi/mpi/c/type_create_f90_integer.c.in index 222794a9884..ff9c006936b 100644 --- a/ompi/mpi/c/type_create_f90_integer.c.in +++ b/ompi/mpi/c/type_create_f90_integer.c.in @@ -19,6 +19,7 @@ * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -75,7 +76,6 @@ PROTOTYPE ERROR_CLASS type_create_f90_integer(INT r, DATATYPE_OUT newtype) if( *newtype != &ompi_mpi_datatype_null.dt ) { ompi_datatype_t* datatype; - const int* a_i[1]; int rc; if( OPAL_SUCCESS == opal_hash_table_get_value_uint32( &ompi_mpi_f90_integer_hashtable, @@ -97,8 +97,8 @@ PROTOTYPE ERROR_CLASS type_create_f90_integer(INT r, DATATYPE_OUT newtype) snprintf(datatype->name, sizeof(datatype->name), "COMBINER %s", (*newtype)->name); - a_i[0] = &r; - ompi_datatype_set_args( datatype, 1, a_i, 0, NULL, 0, NULL, MPI_COMBINER_F90_INTEGER ); + ompi_count_array_t a_i[1] = {OMPI_COUNT_ARRAY_CREATE(&r)}; + ompi_datatype_set_args( datatype, 1, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 0, NULL, MPI_COMBINER_F90_INTEGER ); rc = opal_hash_table_set_value_uint32( &ompi_mpi_f90_integer_hashtable, r, datatype ); if (OMPI_SUCCESS != rc) { diff --git a/ompi/mpi/c/type_create_f90_real.c.in b/ompi/mpi/c/type_create_f90_real.c.in index e7d2e28bde9..54566ba5671 100644 --- a/ompi/mpi/c/type_create_f90_real.c.in +++ b/ompi/mpi/c/type_create_f90_real.c.in @@ -21,6 +21,7 @@ * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -84,7 +85,6 @@ PROTOTYPE ERROR_CLASS type_create_f90_real(INT p, INT r, DATATYPE_OUT newtype) if( *newtype != &ompi_mpi_datatype_null.dt ) { ompi_datatype_t* datatype; - const int* a_i[2] = {&p, &r}; int rc; key = (((uint64_t)p_key) << 32) | ((uint64_t)r_key); @@ -107,7 +107,8 @@ PROTOTYPE ERROR_CLASS type_create_f90_real(INT p, INT r, DATATYPE_OUT newtype) snprintf(datatype->name, sizeof(datatype->name), "COMBINER %s", (*newtype)->name); - ompi_datatype_set_args( datatype, 2, a_i, 0, NULL, 0, NULL, MPI_COMBINER_F90_REAL ); + ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&p), OMPI_COUNT_ARRAY_CREATE(&r)}; + ompi_datatype_set_args( datatype, 2, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 0, NULL, MPI_COMBINER_F90_REAL ); rc = opal_hash_table_set_value_uint64( &ompi_mpi_f90_real_hashtable, key, datatype ); if (OMPI_SUCCESS != rc) { diff --git a/ompi/mpi/c/type_create_hindexed.c.in b/ompi/mpi/c/type_create_hindexed.c.in index 79e03f91bb2..bd8cdf6f4cf 100644 --- a/ompi/mpi/c/type_create_hindexed.c.in +++ b/ompi/mpi/c/type_create_hindexed.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -33,12 +34,6 @@ #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - - PROTOTYPE ERROR_CLASS type_create_hindexed(COUNT count, COUNT_ARRAY array_of_blocklengths, AINT_COUNT_ARRAY array_of_displacements, @@ -46,8 +41,6 @@ PROTOTYPE ERROR_CLASS type_create_hindexed(COUNT count, DATATYPE_OUT newtype) { int rc, i; - int *iarray_of_blocklengths = NULL; - MPI_Aint *iarray_of_displacements = NULL; MEMCHECKER( memchecker_datatype(oldtype); @@ -73,34 +66,14 @@ PROTOTYPE ERROR_CLASS type_create_hindexed(COUNT count, FUNC_NAME ); } } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif - } - -#if OMPI_BIGCOUNT_SRC - iarray_of_blocklengths = (int *)malloc(count * sizeof(int)); - if (NULL == iarray_of_blocklengths) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); } - iarray_of_displacements = (MPI_Aint *)malloc(count * sizeof(MPI_Aint)); - if (NULL == iarray_of_displacements) { - free( iarray_of_blocklengths); - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (i = 0; i < (int)count; i++) { - iarray_of_blocklengths[i] = (int)array_of_blocklengths[i]; - iarray_of_displacements[i] = (MPI_Aint)array_of_displacements[i]; - } -#else - iarray_of_blocklengths = (int *)array_of_blocklengths; - iarray_of_displacements = (MPI_Aint *)array_of_displacements; -#endif - rc = ompi_datatype_create_hindexed( count, iarray_of_blocklengths, iarray_of_displacements, + /* + * TODO: array_of_displacements can be either MPI_Aint or MPI_Count. + * The call below takes a ompi_disp_array_t which maps to MPI_Aint. + */ + rc = ompi_datatype_create_hindexed( count, OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_DISP_ARRAY_CREATE(array_of_displacements), oldtype, newtype ); if( rc != MPI_SUCCESS ) { ompi_datatype_destroy( newtype ); @@ -108,15 +81,22 @@ PROTOTYPE ERROR_CLASS type_create_hindexed(COUNT count, } /* data description */ { - const int* a_i[2] = {(int *)&count, iarray_of_blocklengths}; +#if OMPI_BIGCOUNT_SRC + ompi_count_array_t a_i[3] = { + OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_COUNT_ARRAY_CREATE(array_of_displacements)}; - ompi_datatype_set_args( *newtype, count + 1, a_i, count, iarray_of_displacements, + ompi_datatype_set_args( *newtype, 0, 2*count + 1, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_HINDEXED ); +#else + ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths)}; + ompi_datatype_set_args( *newtype, count + 1, 0, + a_i, count, OMPI_DISP_ARRAY_CREATE(array_of_displacements), + 1, &oldtype, MPI_COMBINER_HINDEXED ); +#endif } -#if OMPI_BIGCOUNT_SRC - free(iarray_of_blocklengths); - free(iarray_of_displacements); -#endif return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_create_hindexed_block.c.in b/ompi/mpi/c/type_create_hindexed_block.c.in index f7bbadd3631..0fea130d1a5 100644 --- a/ompi/mpi/c/type_create_hindexed_block.c.in +++ b/ompi/mpi/c/type_create_hindexed_block.c.in @@ -9,6 +9,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -25,10 +26,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ PROTOTYPE ERROR_CLASS type_create_hindexed_block(COUNT count, COUNT blocklength, @@ -37,7 +34,6 @@ PROTOTYPE ERROR_CLASS type_create_hindexed_block(COUNT count, DATATYPE_OUT newtype) { int rc; - MPI_Aint *iarray_of_displacements = NULL; MEMCHECKER( memchecker_datatype(oldtype); @@ -56,40 +52,32 @@ PROTOTYPE ERROR_CLASS type_create_hindexed_block(COUNT count, return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_TYPE, FUNC_NAME ); } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif - } - -#if OMPI_BIGCOUNT_SRC - iarray_of_displacements = (MPI_Aint *)malloc(count * sizeof(MPI_Aint)); - if (NULL == iarray_of_displacements) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (int ii = 0; ii < (int)count; ii++) { - iarray_of_displacements[ii] = (MPI_Aint)array_of_displacements[ii]; } -#else - iarray_of_displacements = (MPI_Aint *)array_of_displacements; -#endif - rc = ompi_datatype_create_hindexed_block( count, blocklength, iarray_of_displacements, + rc = ompi_datatype_create_hindexed_block( count, blocklength, OMPI_DISP_ARRAY_CREATE(array_of_displacements), oldtype, newtype ); if( rc != MPI_SUCCESS ) { ompi_datatype_destroy( newtype ); OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } { - const int* a_i[2] = {(int *)&count, (int *)&blocklength}; - ompi_datatype_set_args( *newtype, 2, a_i, count, iarray_of_displacements, 1, &oldtype, - MPI_COMBINER_HINDEXED_BLOCK ); - } #if OMPI_BIGCOUNT_SRC - free(iarray_of_displacements); + ompi_count_array_t a_i[3] = { + OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(array_of_displacements)}; + ompi_datatype_set_args( *newtype, 0, count + 2, + a_i, 0, OMPI_DISP_ARRAY_NULL, + 1, &oldtype, + MPI_COMBINER_HINDEXED_BLOCK ); +#else + ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(&blocklength)}; + + ompi_datatype_set_args( *newtype, 2, 0, + a_i, count, OMPI_DISP_ARRAY_CREATE(array_of_displacements), 1, &oldtype, + MPI_COMBINER_HINDEXED_BLOCK ); #endif + } return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_create_hvector.c.in b/ompi/mpi/c/type_create_hvector.c.in index cb93050d05c..537b7c772f3 100644 --- a/ompi/mpi/c/type_create_hvector.c.in +++ b/ompi/mpi/c/type_create_hvector.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,10 +33,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ PROTOTYPE ERROR_CLASS type_create_hvector(COUNT count, COUNT blocklength, @@ -62,12 +59,6 @@ PROTOTYPE ERROR_CLASS type_create_hvector(COUNT count, return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_TYPE, FUNC_NAME ); } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif } rc = ompi_datatype_create_hvector ( count, blocklength, stride, oldtype, @@ -75,10 +66,20 @@ PROTOTYPE ERROR_CLASS type_create_hvector(COUNT count, OMPI_ERRHANDLER_NOHANDLE_CHECK(rc, rc, FUNC_NAME ); { - const int* a_i[2] = {(int *)&count, (int *)&blocklength}; - MPI_Aint a_a[1] = {stride}; +#if OMPI_BIGCOUNT_SRC + ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(&stride)}; - ompi_datatype_set_args( *newtype, 2, a_i, 1, a_a, 1, &oldtype, MPI_COMBINER_HVECTOR ); + ompi_datatype_set_args( *newtype, 0, 3, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_HVECTOR ); +#else + const ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength)}; + + ompi_datatype_set_args( *newtype, 2, 0, + a_i, 1, OMPI_DISP_ARRAY_CREATE(&stride), 1, &oldtype, MPI_COMBINER_HVECTOR ); +#endif } return MPI_SUCCESS; diff --git a/ompi/mpi/c/type_create_indexed_block.c.in b/ompi/mpi/c/type_create_indexed_block.c.in index 24732bf5086..fae61965100 100644 --- a/ompi/mpi/c/type_create_indexed_block.c.in +++ b/ompi/mpi/c/type_create_indexed_block.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,11 +33,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - PROTOTYPE ERROR_CLASS type_create_indexed_block(COUNT count, COUNT blocklength, @@ -45,7 +41,6 @@ PROTOTYPE ERROR_CLASS type_create_indexed_block(COUNT count, DATATYPE_OUT newtype) { int rc; - int *iarray_of_displacements = NULL; MEMCHECKER( memchecker_datatype(oldtype); @@ -66,32 +61,23 @@ PROTOTYPE ERROR_CLASS type_create_indexed_block(COUNT count, } } -#if OMPI_BIGCOUNT_SRC - iarray_of_displacements = (int *)malloc(count * sizeof(int)); - if (NULL == iarray_of_displacements) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (int ii = 0; ii < (int)count; ii++) { - iarray_of_displacements[ii] = (int)array_of_displacements[ii]; - } -#else - iarray_of_displacements = (int *)array_of_displacements; -#endif - rc = ompi_datatype_create_indexed_block( count, blocklength, iarray_of_displacements, + rc = ompi_datatype_create_indexed_block( count, blocklength, OMPI_COUNT_ARRAY_CREATE(array_of_displacements), oldtype, newtype ); if( rc != MPI_SUCCESS ) { ompi_datatype_destroy( newtype ); OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } { - const int* a_i[3] = {(int *)&count, (int *)&blocklength, iarray_of_displacements}; + ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(array_of_displacements)}; - ompi_datatype_set_args( *newtype, 2 + count, a_i, 0, NULL, 1, &oldtype, + ompi_datatype_set_args( *newtype, + (sizeof(count) != sizeof(size_t)) ? count + 2 : 0, + (sizeof(count) == sizeof(size_t)) ? count + 2 : 0, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_INDEXED_BLOCK ); } -#if OMPI_BIGCOUNT_SRC - free(iarray_of_displacements); -#endif return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_create_resized.c.in b/ompi/mpi/c/type_create_resized.c.in index 9e07109ec7b..a1ac7b54362 100644 --- a/ompi/mpi/c/type_create_resized.c.in +++ b/ompi/mpi/c/type_create_resized.c.in @@ -13,6 +13,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -56,10 +57,8 @@ PROTOTYPE ERROR_CLASS type_create_resized(DATATYPE oldtype, } { - MPI_Aint a_a[2]; - a_a[0] = lb; - a_a[1] = extent; - ompi_datatype_set_args( *newtype, 0, NULL, 2, a_a, 1, &oldtype, MPI_COMBINER_RESIZED ); + MPI_Count a_a[2] = {lb, extent}; + ompi_datatype_set_args( *newtype, 0, 0, NULL, 2, OMPI_DISP_ARRAY_CREATE(a_a), 1, &oldtype, MPI_COMBINER_RESIZED ); } return MPI_SUCCESS; diff --git a/ompi/mpi/c/type_create_struct.c.in b/ompi/mpi/c/type_create_struct.c.in index accea45f603..418753af67c 100644 --- a/ompi/mpi/c/type_create_struct.c.in +++ b/ompi/mpi/c/type_create_struct.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,20 +33,13 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - PROTOTYPE ERROR_CLASS type_create_struct(COUNT count, COUNT_ARRAY array_of_blocklengths, AINT_COUNT_ARRAY array_of_displacements, DATATYPE_ARRAY array_of_types, DATATYPE_OUT newtype) { - int i, rc, icount = (int)count; - int *iarray_of_blocklengths = NULL; - MPI_Aint *iarray_of_displacements = NULL; + int i, rc; if ( count > 0 ) { for ( i = 0; i < count; i++ ) { @@ -77,54 +71,37 @@ PROTOTYPE ERROR_CLASS type_create_struct(COUNT count, FUNC_NAME); } } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif } -#if OMPI_BIGCOUNT_SRC - iarray_of_blocklengths = (int *)malloc(count * sizeof(int)); - if (NULL == iarray_of_blocklengths) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - iarray_of_displacements = (MPI_Aint *)malloc(count * sizeof(MPI_Aint)); - if (NULL == iarray_of_displacements) { - free(iarray_of_blocklengths); - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (int ii = 0; ii < (int)count; ii++) { - iarray_of_blocklengths[ii] = (int)array_of_blocklengths[ii]; - iarray_of_displacements[ii] = (MPI_Aint)array_of_displacements[ii]; - } -#else - iarray_of_blocklengths = (int *)array_of_blocklengths; - iarray_of_displacements = (MPI_Aint *)array_of_displacements; -#endif - rc = ompi_datatype_create_struct( icount, iarray_of_blocklengths, iarray_of_displacements, + /** + * TODO: The array of displacements can be either MPI_Aint or MPI_Count. + * The call below takes a ompi_disp_array_t which maps to MPI_Aint. + */ + rc = ompi_datatype_create_struct( count, OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_DISP_ARRAY_CREATE(array_of_displacements), array_of_types, newtype ); if( rc != MPI_SUCCESS ) { ompi_datatype_destroy( newtype ); -#if OMPI_BIGCOUNT_SRC - free(iarray_of_blocklengths); - free(iarray_of_displacements); -#endif - OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, + OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } { - const int* a_i[2] = {(int *)&icount, iarray_of_blocklengths}; - - ompi_datatype_set_args( *newtype, icount + 1, a_i, icount, iarray_of_displacements, - icount, array_of_types, MPI_COMBINER_STRUCT ); - } #if OMPI_BIGCOUNT_SRC - free(iarray_of_blocklengths); - free(iarray_of_displacements); + ompi_count_array_t a_i[3] = { + OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_COUNT_ARRAY_CREATE(array_of_displacements)}; + ompi_datatype_set_args( *newtype, 0, 2*count + 1, + a_i, 0, OMPI_DISP_ARRAY_NULL, + count, array_of_types, MPI_COMBINER_STRUCT ); +#else + ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths)}; + ompi_datatype_set_args( *newtype, count + 1, 0, + a_i, count, OMPI_DISP_ARRAY_CREATE(array_of_displacements), + count, array_of_types, MPI_COMBINER_STRUCT ); #endif + } return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_create_subarray.c.in b/ompi/mpi/c/type_create_subarray.c.in index d25cde247c4..d401fc0ed48 100644 --- a/ompi/mpi/c/type_create_subarray.c.in +++ b/ompi/mpi/c/type_create_subarray.c.in @@ -17,6 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -33,10 +34,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ PROTOTYPE ERROR_CLASS type_create_subarray(INT ndims, COUNT_ARRAY size_array, @@ -47,9 +44,6 @@ PROTOTYPE ERROR_CLASS type_create_subarray(INT ndims, DATATYPE_OUT newtype) { int32_t i, rc; - int *isize_array = NULL; - int *isubsize_array = NULL; - int *istart_array = NULL; MEMCHECKER( memchecker_datatype(oldtype); @@ -67,20 +61,6 @@ PROTOTYPE ERROR_CLASS type_create_subarray(INT ndims, return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, FUNC_NAME); } for( i = 0; i < ndims; i++ ) { -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, size_array[i]); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, subsize_array[i]); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, start_array[i]); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif if( (subsize_array[i] < 1) || (subsize_array[i] > size_array[i]) ) { return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, FUNC_NAME); } else if( (start_array[i] < 0) || (start_array[i] > (size_array[i] - subsize_array[i])) ) { @@ -89,45 +69,26 @@ PROTOTYPE ERROR_CLASS type_create_subarray(INT ndims, } } -#if OMPI_BIGCOUNT_SRC - isize_array = (int *)malloc(ndims * sizeof(int)); - if (NULL == isize_array) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - isubsize_array = (int *)malloc(ndims * sizeof(int)); - if (NULL == isubsize_array) { - free(isize_array); - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - istart_array = (int *)malloc(ndims * sizeof(int)); - if (NULL == istart_array) { - free(isize_array); - free(isubsize_array); - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - for (int ii = 0; ii < ndims; ii++) { - isize_array[ii] = (int)size_array[ii]; - isubsize_array[ii] = (int)subsize_array[ii]; - istart_array[ii] = (int)start_array[ii]; - } -#else - isize_array = (int *)size_array; - isubsize_array = (int *)subsize_array; - istart_array = (int *)start_array; -#endif - rc = ompi_datatype_create_subarray( ndims, isize_array, isubsize_array, istart_array, + rc = ompi_datatype_create_subarray( ndims, OMPI_COUNT_ARRAY_CREATE(size_array), OMPI_COUNT_ARRAY_CREATE(subsize_array), + OMPI_COUNT_ARRAY_CREATE(start_array), order, oldtype, newtype); if( OMPI_SUCCESS == rc ) { - const int* a_i[5] = {&ndims, isize_array, isubsize_array, istart_array, &order}; - - ompi_datatype_set_args( *newtype, 3 * ndims + 2, a_i, 0, NULL, 1, &oldtype, + ompi_count_array_t a_i[5] = {OMPI_COUNT_ARRAY_CREATE(&ndims), + OMPI_COUNT_ARRAY_CREATE(size_array), + OMPI_COUNT_ARRAY_CREATE(subsize_array), + OMPI_COUNT_ARRAY_CREATE(start_array), + OMPI_COUNT_ARRAY_CREATE(&order)}; + size_t ci, cl; + if (sizeof(size_array[0]) == sizeof(size_t)) { + ci = 2; + cl = 3*ndims; + } else { + ci = 3*ndims + 2; + cl = 0; + } + ompi_datatype_set_args( *newtype, ci, cl, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_SUBARRAY ); } -#if OMPI_BIGCOUNT_SRC - free(isize_array); - free(isubsize_array); - free(istart_array); -#endif OMPI_ERRHANDLER_NOHANDLE_RETURN(rc, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/type_dup.c.in b/ompi/mpi/c/type_dup.c.in index 41abec68692..d3b6a70a286 100644 --- a/ompi/mpi/c/type_dup.c.in +++ b/ompi/mpi/c/type_dup.c.in @@ -13,6 +13,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -52,7 +53,7 @@ PROTOTYPE ERROR_CLASS type_dup (DATATYPE type, DATATYPE_OUT newtype) OMPI_ERRHANDLER_NOHANDLE_RETURN( ret, ret, FUNC_NAME ); } - ompi_datatype_set_args( *newtype, 0, NULL, 0, NULL, 1, &type, MPI_COMBINER_DUP ); + ompi_datatype_set_args( *newtype, 0, 0, NULL, 0, OMPI_DISP_ARRAY_NULL, 1, &type, MPI_COMBINER_DUP ); /* Copy all the old attributes, if there were any. This is done here (vs. ompi_datatype_duplicate()) because MPI_TYPE_DUP is the diff --git a/ompi/mpi/c/type_get_contents.c b/ompi/mpi/c/type_get_contents.c index b2998818d5d..cbf96d964eb 100644 --- a/ompi/mpi/c/type_get_contents.c +++ b/ompi/mpi/c/type_get_contents.c @@ -11,6 +11,7 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -65,9 +66,30 @@ int MPI_Type_get_contents(MPI_Datatype mtype, } } - rc = ompi_datatype_get_args( mtype, 1, &max_integers, array_of_integers, - &max_addresses, array_of_addresses, - &max_datatypes, array_of_datatypes, NULL ); + size_t ci, cl, ca, cd; + int32_t type; + rc = ompi_datatype_get_args( mtype, 0, &ci, NULL, + &cl, NULL, + &ca, NULL, + &cd, NULL, &type ); + if( rc != MPI_SUCCESS ) { + OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_INTERN, + MPI_ERR_INTERN, FUNC_NAME ); + } + // check that we have enough space and no large counts + if (cl > 0 || + ci > (size_t)max_integers || + ca > (size_t)max_addresses || + cd > (size_t)max_datatypes) { + OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_TYPE, + MPI_ERR_TYPE, FUNC_NAME ); + } + // now get the contents + ci = max_integers, cl = 0, ca = max_addresses, cd = max_datatypes; + rc = ompi_datatype_get_args( mtype, 1, &ci, array_of_integers, + &cl, NULL, + &ca, array_of_addresses, + &cd, array_of_datatypes, NULL ); if( rc != MPI_SUCCESS ) { OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_INTERN, MPI_ERR_INTERN, FUNC_NAME ); diff --git a/ompi/mpi/c/type_get_contents_c.c b/ompi/mpi/c/type_get_contents_c.c index 6be23ccc4c4..db3883064ae 100644 --- a/ompi/mpi/c/type_get_contents_c.c +++ b/ompi/mpi/c/type_get_contents_c.c @@ -11,6 +11,7 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -67,10 +68,29 @@ int MPI_Type_get_contents_c(MPI_Datatype mtype, } } -/* TODO:BIGCOUNT: Need to embiggen ompi_datatype_get_args */ - rc = ompi_datatype_get_args( mtype, 1, (int *)&max_integers, array_of_integers, - (int *)&max_addresses, array_of_addresses, - (int *)&max_datatypes, array_of_datatypes, NULL ); + size_t ci, cl, ca, cd; + int32_t type; + rc = ompi_datatype_get_args( mtype, 0, &ci, NULL, + &cl, NULL, + &ca, NULL, + &cd, NULL, &type ); + if( rc != MPI_SUCCESS ) { + OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_INTERN, + MPI_ERR_INTERN, FUNC_NAME ); + } + // check that we have enough space + if (cl > (size_t)max_large_counts || + ci > (size_t)max_integers || + ca > (size_t)max_addresses || + cd > (size_t)max_datatypes) { + OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_TYPE, + MPI_ERR_TYPE, FUNC_NAME ); + } + + rc = ompi_datatype_get_args( mtype, 1, &ci, array_of_integers, + &cl, array_of_large_counts, + &ca, array_of_addresses, + &cd, array_of_datatypes, NULL ); if( rc != MPI_SUCCESS ) { OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_INTERN, MPI_ERR_INTERN, FUNC_NAME ); diff --git a/ompi/mpi/c/type_get_envelope.c b/ompi/mpi/c/type_get_envelope.c index 2d6861ec5d0..4e8b9ef3e5e 100644 --- a/ompi/mpi/c/type_get_envelope.c +++ b/ompi/mpi/c/type_get_envelope.c @@ -11,6 +11,7 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -61,7 +62,16 @@ int MPI_Type_get_envelope(MPI_Datatype type, } } - rc = ompi_datatype_get_args( type, 0, num_integers, NULL, num_addresses, NULL, - num_datatypes, NULL, combiner ); + size_t ci, cl, ca, cd; + rc = ompi_datatype_get_args( type, 0, &ci, NULL, &cl, NULL, &ca, NULL, + &cd, NULL, combiner ); + /* error out if we have large counts or any of the parameters don't fit */ + if (OMPI_SUCCESS == rc && (ci > INT_MAX || cl > 0 || ca > INT_MAX || cd > INT_MAX)) { + return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_TYPE, + FUNC_NAME ); + } + *num_integers = (int)ci; + *num_addresses = (int)ca; + *num_datatypes = (int)cd; OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } diff --git a/ompi/mpi/c/type_get_envelope.c.in b/ompi/mpi/c/type_get_envelope.c.in deleted file mode 100644 index e5395d796e4..00000000000 --- a/ompi/mpi/c/type_get_envelope.c.in +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#include "ompi/mpi/c/bindings.h" -#include "ompi/runtime/params.h" -#include "ompi/communicator/communicator.h" -#include "ompi/errhandler/errhandler.h" -#include "ompi/datatype/ompi_datatype.h" -#include "ompi/memchecker.h" - -PROTOTYPE ERROR_CLASS Type_get_envelope(DATATYPE type, - INT_OUT num_integers, - INT_OUT num_addresses, - INT_OUT num_datatypes, - INT_OUT combiner) -{ - int rc; - - MEMCHECKER( - memchecker_datatype(type); - ); - - if( MPI_PARAM_CHECK ) { - OMPI_ERR_INIT_FINALIZE(FUNC_NAME); - if (NULL == type || MPI_DATATYPE_NULL == type) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_TYPE, - FUNC_NAME ); - } else if (NULL == num_integers || NULL == num_addresses || - NULL == num_datatypes || NULL == combiner) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, - FUNC_NAME ); - } - } - - rc = ompi_datatype_get_args( type, 0, num_integers, NULL, num_addresses, NULL, - num_datatypes, NULL, combiner ); - OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); -} diff --git a/ompi/mpi/c/type_get_envelope_c.c b/ompi/mpi/c/type_get_envelope_c.c index 24229e327cf..0c21e3d8c86 100644 --- a/ompi/mpi/c/type_get_envelope_c.c +++ b/ompi/mpi/c/type_get_envelope_c.c @@ -11,6 +11,7 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -61,9 +62,15 @@ int MPI_Type_get_envelope_c(MPI_Datatype type, } } -/* TODO:BIGCOUNT: Need to embiggen ompi_datatype_get_args */ - rc = ompi_datatype_get_args( type, 0, (int *)num_integers, NULL, (int *)num_addresses, NULL, - (int *)num_datatypes, NULL, combiner ); + size_t ci, cl, ca, cd; + rc = ompi_datatype_get_args( type, 0, &ci, NULL, &cl, NULL, &ca, NULL, + &cd, NULL, combiner ); + if( rc == MPI_SUCCESS ) { + *num_integers = (MPI_Count)ci; + *num_addresses = (MPI_Count)ca; + *num_large_counts = (MPI_Count)cl; + *num_datatypes = (MPI_Count)cd; + } OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } diff --git a/ompi/mpi/c/type_indexed.c.in b/ompi/mpi/c/type_indexed.c.in index c3ff80c1b1c..8069518f846 100644 --- a/ompi/mpi/c/type_indexed.c.in +++ b/ompi/mpi/c/type_indexed.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2025-2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,11 +33,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ - PROTOTYPE ERROR_CLASS type_indexed(COUNT count, COUNT_ARRAY array_of_blocklengths, @@ -45,8 +41,6 @@ PROTOTYPE ERROR_CLASS type_indexed(COUNT count, DATATYPE_OUT newtype) { int rc, i; - int *iarray_of_blocklengths; - int *iarray_of_displacements; MEMCHECKER( memchecker_datatype(oldtype); @@ -66,12 +60,6 @@ PROTOTYPE ERROR_CLASS type_indexed(COUNT count, return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, FUNC_NAME); } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(rc, FUNC_NAME); - } -#endif for( i = 0; i < count; i++ ) { if( array_of_blocklengths[i] < 0 ) { return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_ARG, @@ -80,44 +68,26 @@ PROTOTYPE ERROR_CLASS type_indexed(COUNT count, } } -#if OMPI_BIGCOUNT_SRC - iarray_of_blocklengths = (int *)malloc(count * sizeof(int)); - if (NULL == iarray_of_blocklengths) { - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - iarray_of_displacements = (int *)malloc(count * sizeof(int)); - if (NULL == iarray_of_displacements) { - free(iarray_of_blocklengths); - return OMPI_ERRHANDLER_NOHANDLE_INVOKE(MPI_ERR_NO_MEM, FUNC_NAME); - } - - for (int ii = 0; ii < (int)count; ii++) { - iarray_of_blocklengths[ii] = (int)array_of_blocklengths[ii]; - iarray_of_displacements[ii] = (int)array_of_displacements[ii]; - } -#else - iarray_of_blocklengths = (int *)array_of_blocklengths; - iarray_of_displacements = (int *)array_of_displacements; -#endif - rc = ompi_datatype_create_indexed ( count, iarray_of_blocklengths, - iarray_of_displacements, + rc = ompi_datatype_create_indexed ( count, OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_DISP_ARRAY_CREATE(array_of_displacements), oldtype, newtype ); if( rc != MPI_SUCCESS ) { ompi_datatype_destroy( newtype ); - OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, + OMPI_ERRHANDLER_NOHANDLE_RETURN( rc, rc, FUNC_NAME ); } { - const int* a_i[3] = {(int *)&count, iarray_of_blocklengths, iarray_of_displacements}; + const ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(array_of_blocklengths), + OMPI_DISP_ARRAY_CREATE(array_of_displacements)}; - ompi_datatype_set_args( *newtype, 2 * count + 1, a_i, 0, NULL, 1, &oldtype, + ompi_datatype_set_args( *newtype, + (sizeof(count) != 8) ? 2 * count + 1 : 0, + (sizeof(count) == 8) ? 2 * count + 1 : 0, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_INDEXED ); } -#if OMPI_BIGCOUNT_SRC - free(iarray_of_blocklengths); - free(iarray_of_displacements); -#endif return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_size.c.in b/ompi/mpi/c/type_size.c.in index 6e0897dd7aa..b8f1ef0c0ef 100644 --- a/ompi/mpi/c/type_size.c.in +++ b/ompi/mpi/c/type_size.c.in @@ -17,6 +17,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -51,7 +52,11 @@ PROTOTYPE ERROR_CLASS type_size(DATATYPE type, COUNT_OUT size) opal_datatype_type_size ( &type->super, &type_size); - *size = (type_size > (size_t) INT_MAX) ? MPI_UNDEFINED : (int) type_size; + if (sizeof(*size) == sizeof(int) && type_size > (size_t) INT_MAX) { + *size = MPI_UNDEFINED; + } else { + *size = (MPI_Count) type_size; + } return MPI_SUCCESS; } diff --git a/ompi/mpi/c/type_vector.c.in b/ompi/mpi/c/type_vector.c.in index 08bad80d75f..af8be19097e 100644 --- a/ompi/mpi/c/type_vector.c.in +++ b/ompi/mpi/c/type_vector.c.in @@ -16,6 +16,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -32,10 +33,6 @@ #include "ompi/datatype/ompi_datatype.h" #include "ompi/memchecker.h" -/* - * TODO:BIGCOUNT this file will need to be updated once - * the datatype framework supports bigcount - */ PROTOTYPE ERROR_CLASS type_vector(COUNT count, COUNT blocklength, @@ -62,21 +59,20 @@ PROTOTYPE ERROR_CLASS type_vector(COUNT count, OMPI_ERRHANDLER_NOHANDLE_RETURN( MPI_ERR_ARG, MPI_ERR_ARG, FUNC_NAME ); } -#if OMPI_BIGCOUNT_SRC - OMPI_CHECK_MPI_COUNT_INT_CONVERSION_OVERFLOW(rc, count); - if (OMPI_SUCCESS != rc) { - OMPI_ERRHANDLER_NOHANDLE_RETURN(rc, rc, FUNC_NAME); - } -#endif } rc = ompi_datatype_create_vector ( count, blocklength, stride, oldtype, newtype ); OMPI_ERRHANDLER_NOHANDLE_CHECK(rc, rc, FUNC_NAME ); { - const int* a_i[3] = {(int *)&count, (int *)&blocklength, (int *)&stride}; + const ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(&stride)}; - ompi_datatype_set_args( *newtype, 3, a_i, 0, NULL, 1, &oldtype, MPI_COMBINER_VECTOR ); + ompi_datatype_set_args( *newtype, + (sizeof(count) != 8) ? 3 : 0, + (sizeof(count) == 8) ? 3 : 0, + a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_VECTOR ); } return MPI_SUCCESS; diff --git a/ompi/util/count_disp_array.h b/ompi/util/count_disp_array.h index f95d65dc858..61780b3fc14 100644 --- a/ompi/util/count_disp_array.h +++ b/ompi/util/count_disp_array.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2024 Triad National Security, LLC. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -9,125 +10,107 @@ #ifndef OMPI_UTIL_COUNT_DISP_ARRAY_H #define OMPI_UTIL_COUNT_DISP_ARRAY_H -#include -#include -#include +#include "opal/util/count_disp_array.h" /* * NOTE: This code chooses between 64-bit and 32-bit pointers by using the * least significant bit as a flag (which is possible since these * pointers will always be multiples of 4 or 8). */ -typedef intptr_t ompi_count_array_t; +typedef opal_count_array_t ompi_count_array_t; + +#define OMPI_COUNT_ARRAY_NULL OPAL_COUNT_ARRAY_NULL /* Initialize an int variant of the count array */ static inline void ompi_count_array_init(ompi_count_array_t *array, const int *data) { - *array = (intptr_t)data | 0x1L; + opal_count_array_init(array, data); } /* Initialize a bigcount variant of the count array */ static inline void ompi_count_array_init_c(ompi_count_array_t *array, const size_t *data) { - *array = (intptr_t)data; + opal_count_array_init_c(array, data); } -#if OPAL_C_HAVE__GENERIC -#define OMPI_COUNT_ARRAY_INIT(array, data) _Generic((data), \ - int *: ompi_count_array_init, \ - const int *: ompi_count_array_init, \ - size_t *: ompi_count_array_init_c, \ - const size_t *: ompi_count_array_init_c, \ - const MPI_Count *: ompi_count_array_init_c)(array, (const void *) data) -#else -#define OMPI_COUNT_ARRAY_INIT(array, data) \ - do { \ - if (sizeof(*(data)) == sizeof(int)) { \ - ompi_count_array_init(array, (const int *) (data)); \ - } else if (sizeof(*(data)) == sizeof(size_t)) { \ - ompi_count_array_init_c(array, (const size_t *) (data)); \ - } \ - } while (0) -#endif +#define OMPI_COUNT_ARRAY_INIT(array, data) OPAL_COUNT_ARRAY_INIT(array, data) + + +static inline ompi_count_array_t ompi_count_array_create(const int *data) +{ + return opal_count_array_create(data); +} + +static inline ompi_count_array_t ompi_count_array_create_c(const size_t *data) +{ + return opal_count_array_create_c(data); +} + +#define OMPI_COUNT_ARRAY_CREATE(data) OPAL_COUNT_ARRAY_CREATE(data) /* Return if the internal type is 64-bit or not */ static inline bool ompi_count_array_is_64bit(ompi_count_array_t array) { - return !(array & 0x1L) && sizeof(size_t) == 8; + return opal_count_array_is_64bit(array); } static inline const void *ompi_count_array_ptr(ompi_count_array_t array) { - if (OPAL_LIKELY(array & 0x1L)){ - return (const void *)(array & ~0x1L); - } - return (const void *) array; + return opal_count_array_ptr(array); } /* Get a count in the array at index i */ static inline size_t ompi_count_array_get(ompi_count_array_t array, size_t i) { - if (OPAL_LIKELY(array & 0x1L)){ - const int *iptr = (const int *)(array & ~0x1L); - return iptr[i]; - } - return ((const size_t *)array)[i]; + return opal_count_array_get(array, i); } -typedef intptr_t ompi_disp_array_t; +typedef opal_disp_array_t ompi_disp_array_t; + +#define OMPI_DISP_ARRAY_NULL OPAL_DISP_ARRAY_NULL /* Initialize an int variant of the disp array */ static inline void ompi_disp_array_init(ompi_disp_array_t *array, const int *data) { - *array = (intptr_t)data | 0x1L; + opal_disp_array_init(array, data); } /* Initialize a bigcount variant of the disp array */ static inline void ompi_disp_array_init_c(ompi_disp_array_t *array, const ptrdiff_t *data) { - *array = (intptr_t)data; + opal_disp_array_init_c(array, data); } -#if OPAL_C_HAVE__GENERIC -#define OMPI_DISP_ARRAY_INIT(array, data) _Generic((data), \ - int *: ompi_disp_array_init, \ - const int *: ompi_disp_array_init, \ - ptrdiff_t *: ompi_disp_array_init_c, \ - const ptrdiff_t *: ompi_disp_array_init_c)(array, data) -#else -#define OMPI_DISP_ARRAY_INIT(array, data) \ - do { \ - if (sizeof(*(data)) == sizeof(int)) { \ - ompi_disp_array_init(array, (const int *) (data)); \ - } else if (sizeof(*(data)) == sizeof(ptrdiff_t)) { \ - ompi_disp_array_init_c(array, (const ptrdiff_t *) (data)); \ - } \ - } while(0) -#endif +#define OMPI_DISP_ARRAY_INIT(array, data) OPAL_DISP_ARRAY_INIT(array, data) + +static inline ompi_disp_array_t ompi_disp_array_create(const int *data) +{ + return opal_disp_array_create(data); +} + +static inline ompi_disp_array_t ompi_disp_array_create_c(const ptrdiff_t *data) +{ + return opal_disp_array_create_c(data); +} + +#define OMPI_DISP_ARRAY_CREATE(data) OPAL_DISP_ARRAY_CREATE(data) /* Return if the internal type is 64-bit or not */ static inline bool ompi_disp_array_is_64bit(ompi_disp_array_t array) { - return !(array & 0x1L) && sizeof(ptrdiff_t) == 8; + return opal_disp_array_is_64bit(array); } /* Get a displacement in the array at index i */ static inline ptrdiff_t ompi_disp_array_get(ompi_disp_array_t array, size_t i) { - if (OPAL_LIKELY(array & 0x1L)){ - const int *iptr = (const int *)(array & ~0x1L); - return iptr[i]; - } - return ((const ptrdiff_t *)array)[i]; + return opal_disp_array_get(array, i); } /* Get a direct pointer to the data */ static inline const void *ompi_disp_array_ptr(ompi_disp_array_t array) { - if (OPAL_LIKELY(array & 0x1L)){ - return (const void *)(array & ~0x1L); - } - return (const void *)array; + return opal_disp_array_ptr(array); } #endif diff --git a/opal/datatype/opal_convertor.c b/opal/datatype/opal_convertor.c index 8550683a60d..2780f3ce604 100644 --- a/opal/datatype/opal_convertor.c +++ b/opal/datatype/opal_convertor.c @@ -17,6 +17,7 @@ * Copyright (c) 2017 Intel, Inc. All rights reserved * Copyright (c) 2022 Amazon.com, Inc. or its affiliates. All Rights reserved. * Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -253,7 +254,7 @@ int32_t opal_convertor_pack(opal_convertor_t *pConv, struct iovec *iov, uint32_t * environment. The convertor contain minimal information, we only * use the bConverted to manage the conversion. */ - uint32_t i; + size_t i; unsigned char *base_pointer; size_t pending_length = pConv->local_size - pConv->bConverted; @@ -303,7 +304,7 @@ int32_t opal_convertor_unpack(opal_convertor_t *pConv, struct iovec *iov, uint32 * environment. The convertor contain minimal information, we only * use the bConverted to manage the conversion. */ - uint32_t i; + size_t i; unsigned char *base_pointer; size_t pending_length = pConv->local_size - pConv->bConverted; diff --git a/opal/datatype/opal_datatype.h b/opal/datatype/opal_datatype.h index 5e953ccfb6b..48203487822 100644 --- a/opal/datatype/opal_datatype.h +++ b/opal/datatype/opal_datatype.h @@ -20,6 +20,7 @@ * reserved. * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -196,8 +197,8 @@ OPAL_DECLSPEC extern const opal_datatype_t opal_datatype_unsigned_long; */ int opal_datatype_register_params(void); OPAL_DECLSPEC int32_t opal_datatype_init(void); -OPAL_DECLSPEC opal_datatype_t *opal_datatype_create(int32_t expectedSize); -OPAL_DECLSPEC int32_t opal_datatype_create_desc(opal_datatype_t *datatype, int32_t expectedSize); +OPAL_DECLSPEC opal_datatype_t *opal_datatype_create(ssize_t expectedSize); +OPAL_DECLSPEC int32_t opal_datatype_create_desc(opal_datatype_t *datatype, ssize_t expectedSize); OPAL_DECLSPEC int32_t opal_datatype_commit(opal_datatype_t *pData); OPAL_DECLSPEC int32_t opal_datatype_destroy(opal_datatype_t **); OPAL_DECLSPEC int32_t opal_datatype_is_monotonic(opal_datatype_t *type); diff --git a/opal/datatype/opal_datatype_add.c b/opal/datatype/opal_datatype_add.c index 2618ad3ba5b..72607a67e07 100644 --- a/opal/datatype/opal_datatype_add.c +++ b/opal/datatype/opal_datatype_add.c @@ -14,6 +14,7 @@ * Copyright (c) 2014 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -127,7 +128,7 @@ static inline int IMAX(int a, int b) int32_t opal_datatype_add(opal_datatype_t *pdtBase, const opal_datatype_t *pdtAdd, size_t count, ptrdiff_t disp, ptrdiff_t extent) { - uint32_t newLength, place_needed = 0, i; + opal_datatype_count_t newLength, place_needed = 0, i; short localFlags = 0; /* no specific options yet */ dt_elem_desc_t *pLast, *pLoop = NULL; ptrdiff_t lb, ub, true_lb, true_ub, epsilon, old_true_ub; diff --git a/opal/datatype/opal_datatype_create.c b/opal/datatype/opal_datatype_create.c index 536bdb6bd87..85dc317b348 100644 --- a/opal/datatype/opal_datatype_create.c +++ b/opal/datatype/opal_datatype_create.c @@ -13,6 +13,7 @@ * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -91,7 +92,7 @@ static void opal_datatype_destruct(opal_datatype_t *datatype) OBJ_CLASS_INSTANCE(opal_datatype_t, opal_object_t, opal_datatype_construct, opal_datatype_destruct); -opal_datatype_t *opal_datatype_create(int32_t expectedSize) +opal_datatype_t *opal_datatype_create(ssize_t expectedSize) { opal_datatype_t *datatype = (opal_datatype_t *) OBJ_NEW(opal_datatype_t); @@ -107,7 +108,7 @@ opal_datatype_t *opal_datatype_create(int32_t expectedSize) return datatype; } -int32_t opal_datatype_create_desc(opal_datatype_t *datatype, int32_t expectedSize) +int32_t opal_datatype_create_desc(opal_datatype_t *datatype, ssize_t expectedSize) { if (expectedSize == -1) { expectedSize = DT_INCREASE_STACK; diff --git a/opal/util/Makefile.am b/opal/util/Makefile.am index afd657b5b09..3ccaa2f7685 100644 --- a/opal/util/Makefile.am +++ b/opal/util/Makefile.am @@ -21,6 +21,7 @@ # All Rights reserved. # Copyright (c) 2021 Google, LLC. All rights reserved. # Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2026 Stony Brook University. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -55,6 +56,7 @@ headers = \ bit_ops.h \ clock_gettime.h \ cmd_line.h \ + count_disp_array.h \ crc.h \ ethtool.h \ error.h \ diff --git a/opal/util/count_disp_array.h b/opal/util/count_disp_array.h new file mode 100644 index 00000000000..d962e69b6b2 --- /dev/null +++ b/opal/util/count_disp_array.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2024 Triad National Security, LLC. All rights reserved. + * Copyright (c) 2025-2026 Stony Brook University. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ +#ifndef OPAL_UTIL_COUNT_DISP_ARRAY_H +#define OPAL_UTIL_COUNT_DISP_ARRAY_H + +#include +#include +#include +#include +#include "opal_config.h" + +/* + * NOTE: This code chooses between 64-bit and 32-bit pointers by using the + * least significant bit as a flag (which is possible since these + * pointers will always be multiples of 4 or 8). + */ +typedef intptr_t opal_count_array_t; + +/** + * Sanity check to make sure the compiler respects the alignment assumptions + * that allow us to use the least significant bit as a flag. + */ +_Static_assert(_Alignof(int) >= 2, "int alignment assumption violated"); +_Static_assert(_Alignof(size_t) >= 2, "size_t alignment assumption violated"); + +#define OPAL_COUNT_ARRAY_NULL ((opal_count_array_t)0) + +/** + * Initialize an int variant of the count array. + * Assumes is aligned to at least 2 bytes (i.e., least significant bit is 0). + */ +static inline void opal_count_array_init(opal_count_array_t *array, const int *data) +{ + assert(((intptr_t)data & 0x1L) == 0); + *array = (intptr_t)data | 0x1L; +} + +/* Initialize a bigcount variant of the count array */ +static inline void opal_count_array_init_c(opal_count_array_t *array, const size_t *data) +{ + *array = (intptr_t)data; +} + +#if OPAL_C_HAVE__GENERIC +#define OPAL_COUNT_ARRAY_INIT(array, data) _Generic((data), \ + int *: opal_count_array_init, \ + const int *: opal_count_array_init, \ + size_t *: opal_count_array_init_c, \ + const size_t *: opal_count_array_init_c, \ + MPI_Count *: opal_count_array_init_c, \ + const MPI_Count *: opal_count_array_init_c)(array, (const void *) data) +#else +#define OPAL_COUNT_ARRAY_INIT(array, data) \ + do { \ + if (sizeof(*(data)) == sizeof(int)) { \ + opal_count_array_init(array, (const int *) (data)); \ + } else if (sizeof(*(data)) == sizeof(size_t)) { \ + opal_count_array_init_c(array, (const size_t *) (data)); \ + } \ + } while (0) +#endif + + +static inline opal_count_array_t opal_count_array_create(const int *data) +{ + opal_count_array_t array; + opal_count_array_init(&array, data); + return array; +} + +static inline opal_count_array_t opal_count_array_create_c(const size_t *data) +{ + opal_count_array_t array; + opal_count_array_init_c(&array, data); + return array; +} + +static inline opal_count_array_t opal_count_array_create_with_size(const void *data, size_t size) +{ + if (size == sizeof(int)) { + return opal_count_array_create(data); + } else { + return opal_count_array_create_c(data); + } +} + +#define OPAL_COUNT_ARRAY_CREATE(data) opal_count_array_create_with_size((data), sizeof(*(data))) + + +/* Return if the internal type is 64-bit or not */ +static inline bool opal_count_array_is_64bit(opal_count_array_t array) +{ + return !(array & 0x1L) && sizeof(size_t) == 8; +} + +static inline size_t opal_count_array_sizeof(opal_count_array_t array) +{ + return opal_count_array_is_64bit(array) ? sizeof(size_t) : sizeof(int); +} + +static inline const void *opal_count_array_ptr(opal_count_array_t array) +{ + if (OPAL_LIKELY(array & 0x1L)){ + return (const void *)(array & ~0x1L); + } + return (const void *) array; +} + +/* Get a count in the array at index i */ +static inline size_t opal_count_array_get(opal_count_array_t array, size_t i) +{ + if (OPAL_LIKELY(array & 0x1L)){ + const int *iptr = (const int *)(array & ~0x1L); + return (size_t)iptr[i]; + } + return ((const size_t *)array)[i]; +} + +/* Set a count in the array at index i */ +static inline void opal_count_array_set(opal_count_array_t array, size_t i, size_t val) +{ + if (OPAL_LIKELY(array & 0x1L)){ + int *iptr = (int *)(array & ~0x1L); + iptr[i] = (int)val; + } else { + size_t *sptr = (size_t *)array; + sptr[i] = val; + } +} + +typedef intptr_t opal_disp_array_t; + +#define OPAL_DISP_ARRAY_NULL ((opal_disp_array_t)0) + +/* Initialize an int variant of the disp array */ +static inline void opal_disp_array_init(opal_disp_array_t *array, const int *data) +{ + *array = (intptr_t)data | 0x1L; +} + +/* Initialize a bigcount variant of the disp array */ +static inline void opal_disp_array_init_c(opal_disp_array_t *array, const ptrdiff_t *data) +{ + *array = (intptr_t)data; +} + +#if OPAL_C_HAVE__GENERIC +#define OPAL_DISP_ARRAY_INIT(array, data) _Generic((data), \ + int *: opal_disp_array_init, \ + const int *: opal_disp_array_init, \ + ptrdiff_t *: opal_disp_array_init_c, \ + const ptrdiff_t *: opal_disp_array_init_c)(array, data) +#else +#define OPAL_DISP_ARRAY_INIT(array, data) \ + do { \ + if (sizeof(*(data)) == sizeof(int)) { \ + opal_disp_array_init(array, (const int *) (data)); \ + } else if (sizeof(*(data)) == sizeof(ptrdiff_t)) { \ + opal_disp_array_init_c(array, (const ptrdiff_t *) (data)); \ + } \ + } while(0) +#endif + + + +static inline opal_disp_array_t opal_disp_array_create(const int *data) +{ + opal_disp_array_t array; + opal_disp_array_init(&array, data); + return array; +} + +static inline opal_disp_array_t opal_disp_array_create_c(const ptrdiff_t *data) +{ + opal_disp_array_t array; + opal_disp_array_init_c(&array, data); + return array; +} + +static inline opal_disp_array_t opal_disp_array_create_with_size(const void *data, size_t size) +{ + if (size == sizeof(int)) { + return opal_disp_array_create(data); + } else { + return opal_disp_array_create_c(data); + } +} + +#define OPAL_DISP_ARRAY_CREATE(data) opal_disp_array_create_with_size(data, sizeof(*(data))) + + +/* Return if the internal type is 64-bit or not */ +static inline bool opal_disp_array_is_64bit(opal_disp_array_t array) +{ + return !(array & 0x1L) && sizeof(ptrdiff_t) == 8; +} + +static inline size_t opal_disp_array_sizeof(opal_disp_array_t array) +{ + return opal_disp_array_is_64bit(array) ? sizeof(ptrdiff_t) : sizeof(int); +} + +/* Get a displacement in the array at index i */ +static inline ptrdiff_t opal_disp_array_get(opal_disp_array_t array, size_t i) +{ + if (OPAL_LIKELY(array & 0x1L)){ + const int *iptr = (const int *)(array & ~0x1L); + return iptr[i]; + } + return ((const ptrdiff_t *)array)[i]; +} + +/* Set a displacement in the array at index i */ +static inline void opal_disp_array_set(opal_disp_array_t array, size_t i, ptrdiff_t val) +{ + if (OPAL_LIKELY(array & 0x1L)){ + int *iptr = (int *)(array & ~0x1L); + iptr[i] = (int)val; + } else { + ptrdiff_t *pptr = (ptrdiff_t *)array; + pptr[i] = val; + } +} + + +/* Get a direct pointer to the data */ +static inline const void *opal_disp_array_ptr(opal_disp_array_t array) +{ + if (OPAL_LIKELY(array & 0x1L)){ + return (const void *)(array & ~0x1L); + } + return (const void *)array; +} + +#endif diff --git a/test/datatype/ddt_lib.c b/test/datatype/ddt_lib.c index 0a0e9dc7e01..fae69584544 100644 --- a/test/datatype/ddt_lib.c +++ b/test/datatype/ddt_lib.c @@ -14,6 +14,7 @@ * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2018 Los Alamos National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -134,7 +135,8 @@ ompi_datatype_t *upper_matrix(unsigned int mat_size) blocklen[i] = mat_size - i; } - ompi_datatype_create_indexed(mat_size, blocklen, disp, &ompi_mpi_double.dt, &upper); + ompi_datatype_create_indexed(mat_size, OMPI_COUNT_ARRAY_CREATE(blocklen), + OMPI_DISP_ARRAY_CREATE(disp), &ompi_mpi_double.dt, &upper); ompi_datatype_commit(&upper); if (outputFlags & DUMP_DATA_AFTER_COMMIT) { ompi_datatype_dump(upper); @@ -158,7 +160,8 @@ ompi_datatype_t *lower_matrix(unsigned int mat_size) blocklen[i] = i; } - ompi_datatype_create_indexed(mat_size, blocklen, disp, &ompi_mpi_double.dt, &upper); + ompi_datatype_create_indexed(mat_size, OMPI_COUNT_ARRAY_CREATE(blocklen), + OMPI_DISP_ARRAY_CREATE(disp), &ompi_mpi_double.dt, &upper); free(disp); free(blocklen); return upper; @@ -175,7 +178,8 @@ ompi_datatype_t *test_matrix_borders(unsigned int size, unsigned int width) disp[1] = (size - width) * sizeof(double); blocklen[1] = width; - ompi_datatype_create_indexed(2, blocklen, disp, &ompi_mpi_double.dt, &pdt_line); + ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(blocklen), + OMPI_DISP_ARRAY_CREATE(disp), &ompi_mpi_double.dt, &pdt_line); ompi_datatype_create_contiguous(size, pdt_line, &pdt); OBJ_RELEASE(pdt_line); /*assert( pdt_line == NULL );*/ return pdt; @@ -224,7 +228,8 @@ ompi_datatype_t *test_struct_char_double(void) displ[0] = (char *) &(data.c) - (char *) &(data); displ[1] = (char *) &(data.d) - (char *) &(data); - ompi_datatype_create_struct(2, lengths, displ, types, &pdt); + ompi_datatype_create_struct(2, OMPI_COUNT_ARRAY_CREATE(lengths), + OMPI_DISP_ARRAY_CREATE(displ), types, &pdt); ompi_datatype_commit(&pdt); if (outputFlags & DUMP_DATA_AFTER_COMMIT) { ompi_datatype_dump(pdt); @@ -276,7 +281,8 @@ ompi_datatype_t *test_create_blacs_type(void) { ompi_datatype_t *pdt; - ompi_datatype_create_indexed(18, blacs_length, blacs_indices, &ompi_mpi_int.dt, &pdt); + ompi_datatype_create_indexed(18, OMPI_COUNT_ARRAY_CREATE(blacs_length), + OMPI_DISP_ARRAY_CREATE(blacs_indices), &ompi_mpi_int.dt, &pdt); ompi_datatype_commit(&pdt); if (outputFlags & DUMP_DATA_AFTER_COMMIT) { ompi_datatype_dump(pdt); @@ -327,7 +333,8 @@ ompi_datatype_t *test_struct(void) types[1] = pdt1; - ompi_datatype_create_struct(3, lengths, disp, types, &pdt); + ompi_datatype_create_struct(3, OMPI_COUNT_ARRAY_CREATE(lengths), + OMPI_DISP_ARRAY_CREATE(disp), types, &pdt); OBJ_RELEASE(pdt1); /*assert( pdt1 == NULL );*/ if (outputFlags & DUMP_DATA_AFTER_COMMIT) { ompi_datatype_dump(pdt); @@ -356,7 +363,8 @@ ompi_datatype_t *create_struct_constant_gap_resized_ddt(ompi_datatype_t *type) disps[1] -= disps[2]; /* 8 */ disps[0] -= disps[2]; /* 16 */ - ompi_datatype_create_struct(2, blocklens, disps, types, &temp_type); + ompi_datatype_create_struct(2, OMPI_COUNT_ARRAY_CREATE(blocklens), + OMPI_DISP_ARRAY_CREATE(disps), types, &temp_type); ompi_datatype_create_resized(temp_type, 0, sizeof(data[0]), &struct_type); ompi_datatype_commit(&struct_type); OBJ_RELEASE(temp_type); @@ -394,7 +402,7 @@ ompi_datatype_t *create_strange_dt(void) dispi[0] = (int) ((char *) &(v[0].i1) - (char *) &(v[0])); /* 0 */ dispi[1] = (int) (((char *) (&(v[0].i2)) - (char *) &(v[0])) / sizeof(int)); /* 2 */ - ompi_datatype_create_indexed_block(2, 1, dispi, &ompi_mpi_int.dt, &pdtTemp); + ompi_datatype_create_indexed_block(2, 1, OMPI_DISP_ARRAY_CREATE(dispi), &ompi_mpi_int.dt, &pdtTemp); #ifdef USE_RESIZED /* optional */ displ[0] = 0; @@ -411,7 +419,8 @@ ompi_datatype_t *create_strange_dt(void) displ[0] = 0; displ[1] = (long) ((char *) &(t[0].v[0]) - (char *) &(t[0])); displ[2] = (long) ((char *) &(t[0].last) - (char *) &(t[0])); - ompi_datatype_create_struct(3, pBlock, displ, types, &pdtTemp); + ompi_datatype_create_struct(3, OMPI_COUNT_ARRAY_CREATE(pBlock), + OMPI_DISP_ARRAY_CREATE(displ), types, &pdtTemp); #ifdef USE_RESIZED /* optional */ displ[1] = (char *) &(t[1]) - (char *) &(t[0]); diff --git a/test/datatype/ddt_pack.c b/test/datatype/ddt_pack.c index fc35d57992e..acc16a6f9b4 100644 --- a/test/datatype/ddt_pack.c +++ b/test/datatype/ddt_pack.c @@ -16,6 +16,7 @@ * Copyright (c) 2018 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2020 Intel, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -118,14 +119,14 @@ int main(int argc, char *argv[]) types[1] = &ompi_mpi_int.dt; types[2] = &ompi_mpi_int.dt; types[3] = &ompi_mpi_int.dt; - ret = ompi_datatype_create_struct(4, blen, disp, types, &struct_type); + ret = ompi_datatype_create_struct(4, OMPI_COUNT_ARRAY_CREATE(blen), OMPI_DISP_ARRAY_CREATE(disp), types, &struct_type); if (ret != 0) goto cleanup; { int count = 4; - const int *a_i[2] = {&count, blen}; - ret = ompi_datatype_set_args(struct_type, count + 1, a_i, count, disp, count, types, + const ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(blen)}; + ret = ompi_datatype_set_args(struct_type, count + 1, 0, a_i, count, OMPI_DISP_ARRAY_CREATE(disp), count, types, MPI_COMBINER_STRUCT); if (ret != 0) goto cleanup; @@ -190,9 +191,11 @@ int main(int argc, char *argv[]) int count = 2; int blocklength = 1; int stride = 1; - const int *a_i[3] = {&count, &blocklength, &stride}; + const ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(&stride)}; ompi_datatype_t *type = &ompi_mpi_int.dt; - ret = ompi_datatype_set_args(vec_type, 3, a_i, 0, NULL, 1, &type, MPI_COMBINER_VECTOR); + ret = ompi_datatype_set_args(vec_type, 3, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &type, MPI_COMBINER_VECTOR); if (ret != 0) goto cleanup; } @@ -251,16 +254,18 @@ int main(int argc, char *argv[]) blen[0] = 0; blen[1] = 20 * sizeof(double); - ret = ompi_datatype_create_indexed_block(2, 10, blen, &ompi_mpi_double.dt, &newType); + ret = ompi_datatype_create_indexed_block(2, 10, OMPI_COUNT_ARRAY_CREATE(blen), &ompi_mpi_double.dt, &newType); if (ret != 0) goto cleanup; { int count = 2; int blocklength = 10; - const int *a_i[3] = {&count, &blocklength, blen}; + const ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(blen)}; ompi_datatype_t *oldtype = &ompi_mpi_double.dt; - ompi_datatype_set_args(newType, 2 + count, a_i, 0, NULL, 1, &oldtype, + ompi_datatype_set_args(newType, 2 + count, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &oldtype, MPI_COMBINER_INDEXED_BLOCK); if (ret != 0) goto cleanup; @@ -322,15 +327,16 @@ int main(int argc, char *argv[]) disp[0] = 0; disp[1] = 20 * sizeof(double); - ret = ompi_datatype_create_hindexed(2, blen, disp, &ompi_mpi_double.dt, &newType); + ret = ompi_datatype_create_hindexed(2, OMPI_COUNT_ARRAY_CREATE(blen), + OMPI_DISP_ARRAY_CREATE(disp), &ompi_mpi_double.dt, &newType); if (ret != 0) goto cleanup; { int count = 2; - const int *a_i[2] = {&count, blen}; + const ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(blen)}; ompi_datatype_t *oldtype = &ompi_mpi_double.dt; - ret = ompi_datatype_set_args(newType, count + 1, a_i, count, disp, 1, &oldtype, + ret = ompi_datatype_set_args(newType, count + 1, 0, a_i, count, OMPI_DISP_ARRAY_CREATE(disp), 1, &oldtype, MPI_COMBINER_HINDEXED); if (ret != 0) goto cleanup; @@ -388,14 +394,14 @@ int main(int argc, char *argv[]) disp[1] = 64; types[0] = &ompi_mpi_int.dt; types[1] = newType; - ret = ompi_datatype_create_struct(2, blen, disp, types, &struct_type); + ret = ompi_datatype_create_struct(2, OMPI_COUNT_ARRAY_CREATE(blen), OMPI_DISP_ARRAY_CREATE(disp), types, &struct_type); if (ret != 0) goto cleanup; { int count = 2; - const int *a_i[2] = {&count, blen}; - ret = ompi_datatype_set_args(struct_type, count + 1, a_i, count, disp, count, types, + const ompi_count_array_t a_i[2] = {OMPI_COUNT_ARRAY_CREATE(&count), OMPI_COUNT_ARRAY_CREATE(blen)}; + ret = ompi_datatype_set_args(struct_type, count + 1, 0, a_i, count, OMPI_DISP_ARRAY_CREATE(disp), count, types, MPI_COMBINER_STRUCT); if (ret != 0) goto cleanup; @@ -461,7 +467,7 @@ int main(int argc, char *argv[]) if (ret != 0) goto cleanup; ompi_datatype_t *type = &ompi_mpi_int.dt; - ret = ompi_datatype_set_args(dup_type, 0, NULL, 0, NULL, 1, &type, MPI_COMBINER_DUP); + ret = ompi_datatype_set_args(dup_type, 0, 0, NULL, 0, OMPI_DISP_ARRAY_NULL, 1, &type, MPI_COMBINER_DUP); if (ret != 0) goto cleanup; packed_ddt_len = ompi_datatype_pack_description_length(dup_type); diff --git a/test/datatype/external32.c b/test/datatype/external32.c index 12d773b3c0a..091b9b9c216 100644 --- a/test/datatype/external32.c +++ b/test/datatype/external32.c @@ -3,6 +3,7 @@ * Copyright (c) 2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -230,10 +231,12 @@ int main(int argc, char *argv[]) ompi_datatype_create_vector(count, blocklength, stride, &ompi_mpi_int.dt, &ddt); { - const int *a_i[3] = {&count, &blocklength, &stride}; + const ompi_count_array_t a_i[3] = {OMPI_COUNT_ARRAY_CREATE(&count), + OMPI_COUNT_ARRAY_CREATE(&blocklength), + OMPI_COUNT_ARRAY_CREATE(&stride)}; ompi_datatype_t *type = &ompi_mpi_int.dt; - ompi_datatype_set_args(ddt, 3, a_i, 0, NULL, 1, &type, MPI_COMBINER_VECTOR); + ompi_datatype_set_args(ddt, 3, 0, a_i, 0, OMPI_DISP_ARRAY_NULL, 1, &type, MPI_COMBINER_VECTOR); } ompi_datatype_commit(&ddt); diff --git a/test/datatype/large_data.c b/test/datatype/large_data.c index 5558d6a6455..99e3db9a778 100644 --- a/test/datatype/large_data.c +++ b/test/datatype/large_data.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -105,7 +106,7 @@ int main(int argc, char *argv[]) /* * Large sparse datatype: indexed contiguous */ - ompi_datatype_create_indexed(2, scounts, sdispls, ddt, &stype); + ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(scounts), OMPI_DISP_ARRAY_CREATE(sdispls), ddt, &stype); ompi_datatype_commit(&stype); packed = count_length_via_convertor_raw("1. INDEX", stype, 1); @@ -121,7 +122,7 @@ int main(int argc, char *argv[]) /* * Large contiguous datatype: indexed contiguous */ - ompi_datatype_create_indexed(2, rcounts, rdispls, ddt, &rtype); + ompi_datatype_create_indexed(2, OMPI_COUNT_ARRAY_CREATE(rcounts), OMPI_DISP_ARRAY_CREATE(rdispls), ddt, &rtype); ompi_datatype_commit(&rtype); packed = count_length_via_convertor_raw("2. INDEX", rtype, 1); diff --git a/test/datatype/unpack_ooo.c b/test/datatype/unpack_ooo.c index 7fdfe790916..dd78d71240a 100644 --- a/test/datatype/unpack_ooo.c +++ b/test/datatype/unpack_ooo.c @@ -6,6 +6,7 @@ * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -264,7 +265,8 @@ static int unpack_ooo(void) len[0] = 1; len[1] = 1; - rc = ompi_datatype_create_struct(2, len, disp, type, &newtype); + rc = ompi_datatype_create_struct(2, OMPI_COUNT_ARRAY_CREATE(len), + OMPI_DISP_ARRAY_CREATE(disp), type, &newtype); if (OMPI_SUCCESS != rc) { fprintf(stderr, "could not create struct\n"); return 1; From b8eeabf68d802af4a5c0ad41128c8eacf5ce456e Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Thu, 20 Nov 2025 06:29:22 -0700 Subject: [PATCH 034/230] nbc: rework the way to add arrays to clean up Turns out that in the course of working on PR #13280 , it was discovered that auxiliary arrays associated with a non-blocking/persistent collective requests were not in fact being cleaned up upon either completion of the non-blocking request or freeing of the persistent request except for instances where the 'c' interface detected certain cases for the arguments (in particular user-defined data types). So all the additions to the fortran code to cleanup temporary arrays needed, for example, when default integer type does not map to 'c' int, was not actually doing anything in the general case. This PR also hides the way the auxiliary array info is associated with the request rather than having the current array of pointers in the nbc request exposed in many different places. This PR also fixes up some problems found with handling of some of the arrays within the f90/f08 code as well as suppressing some compiler warnings. Signed-off-by: Howard Pritchard --- ompi/mca/coll/base/coll_base_util.c | 27 ++++++++++- ompi/mca/coll/base/coll_base_util.h | 45 +++++++++++++++++++ ompi/mpi/fortran/mpif-h/allgatherv_init_f.c | 13 +++--- ompi/mpi/fortran/mpif-h/alltoallv_init_f.c | 17 +++---- ompi/mpi/fortran/mpif-h/alltoallw_init_f.c | 23 +++++----- ompi/mpi/fortran/mpif-h/gatherv_init_f.c | 13 +++--- ompi/mpi/fortran/mpif-h/iallgatherv_f.c | 13 +++--- ompi/mpi/fortran/mpif-h/ialltoallv_f.c | 17 +++---- ompi/mpi/fortran/mpif-h/ialltoallw_f.c | 23 +++++----- ompi/mpi/fortran/mpif-h/igatherv_f.c | 13 +++--- .../fortran/mpif-h/ineighbor_allgatherv_f.c | 13 +++--- .../fortran/mpif-h/ineighbor_alltoallv_f.c | 17 +++---- .../fortran/mpif-h/ineighbor_alltoallw_f.c | 15 ++++--- ompi/mpi/fortran/mpif-h/ireduce_scatter_f.c | 9 ++-- ompi/mpi/fortran/mpif-h/iscatterv_f.c | 13 +++--- .../mpif-h/neighbor_allgatherv_init_f.c | 11 ++--- .../mpif-h/neighbor_alltoallv_init_f.c | 17 ++++--- .../mpif-h/neighbor_alltoallw_init_f.c | 15 +++---- .../fortran/mpif-h/reduce_scatter_init_f.c | 9 ++-- ompi/mpi/fortran/mpif-h/scatterv_init_f.c | 13 +++--- .../use-mpi-f08/allgatherv_init_ts.c.in | 5 ++- .../use-mpi-f08/alltoallv_init_ts.c.in | 5 ++- .../use-mpi-f08/alltoallw_init_ts.c.in | 8 ++-- ompi/mpi/fortran/use-mpi-f08/base/bigcount.h | 5 +-- .../fortran/use-mpi-f08/gatherv_init_ts.c.in | 3 ++ .../fortran/use-mpi-f08/iallgatherv_ts.c.in | 10 +++-- .../fortran/use-mpi-f08/ialltoallv_ts.c.in | 14 +++--- .../fortran/use-mpi-f08/ialltoallw_ts.c.in | 17 +++---- ompi/mpi/fortran/use-mpi-f08/igatherv_ts.c.in | 3 ++ .../use-mpi-f08/ineighbor_allgatherv_ts.c.in | 11 +++-- .../use-mpi-f08/ineighbor_alltoallv_ts.c.in | 13 +++--- .../use-mpi-f08/ineighbor_alltoallw_ts.c.in | 19 +++++--- .../use-mpi-f08/ireduce_scatter_ts.c.in | 5 ++- .../mpi/fortran/use-mpi-f08/iscatterv_ts.c.in | 5 ++- .../neighbor_allgatherv_init_ts.c.in | 3 ++ .../neighbor_alltoallv_init_ts.c.in | 3 ++ .../neighbor_alltoallw_init_ts.c.in | 11 +++-- .../use-mpi-f08/reduce_scatter_init_ts.c.in | 5 ++- .../fortran/use-mpi-f08/scatterv_init_ts.c.in | 5 ++- 39 files changed, 313 insertions(+), 173 deletions(-) diff --git a/ompi/mca/coll/base/coll_base_util.c b/ompi/mca/coll/base/coll_base_util.c index ba74aa01350..470a8bd4ab2 100644 --- a/ompi/mca/coll/base/coll_base_util.c +++ b/ompi/mca/coll/base/coll_base_util.c @@ -14,6 +14,8 @@ * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. * * Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * * $COPYRIGHT$ * @@ -134,7 +136,7 @@ int ompi_rounddown(int num, int factor) /** * Release all objects and arrays stored into the nbc_request. * The release_arrays are temporary memory to stored the values - * converted from Fortran, and should disappear in same time as the + * converted from Fortran or elsewhere, and should disappear in same time as the * request itself. */ static void @@ -268,6 +270,7 @@ static void release_vecs_callback(ompi_coll_base_nbc_request_t *request) } request->data.refcounted.vecs.rtypes = NULL; } + release_objs_callback(request); } static int complete_vecs_callback(struct ompi_request_t *req) { @@ -346,13 +349,33 @@ int ompi_coll_base_retain_datatypes_w( ompi_request_t *req, return OMPI_SUCCESS; } +int ompi_coll_base_add_release_arrays_cb(ompi_request_t *req) +{ + ompi_coll_base_nbc_request_t *request = (ompi_coll_base_nbc_request_t *)req; + + assert(NULL != request); + + if (req->req_persistent && (NULL == req->req_free)) { + request->cb.req_free = req->req_free; + req->req_free = free_objs_callback; + } else if(NULL == req->req_complete_cb) { + request->cb.req_complete_cb = req->req_complete_cb; + request->req_complete_cb_data = req->req_complete_cb_data; + req->req_complete_cb = complete_objs_callback; + req->req_complete_cb_data = request; + } + return OMPI_SUCCESS; +} + static void nbc_req_constructor(ompi_coll_base_nbc_request_t *req) { req->cb.req_complete_cb = NULL; req->req_complete_cb_data = NULL; req->data.refcounted.objs.objs[0] = NULL; req->data.refcounted.objs.objs[1] = NULL; - req->data.release_arrays[0] = NULL; + for (int i = 0; i < OMPI_REQ_NB_RELEASE_ARRAYS; i++ ) { + req->data.release_arrays[i] = NULL; + } } OBJ_CLASS_INSTANCE(ompi_coll_base_nbc_request_t, ompi_request_t, nbc_req_constructor, NULL); diff --git a/ompi/mca/coll/base/coll_base_util.h b/ompi/mca/coll/base/coll_base_util.h index 7bceaa7dcc0..3a52cdebdd8 100644 --- a/ompi/mca/coll/base/coll_base_util.h +++ b/ompi/mca/coll/base/coll_base_util.h @@ -12,6 +12,8 @@ * Copyright (c) 2014-2020 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -95,6 +97,42 @@ ompi_coll_base_nbc_reserve_tags(ompi_communicator_t* comm, int32_t reserve) return tag; } +/** + * Append an array to a request object to be freed upon completion + * of the associated operation. + * The request object must be of type ompi_coll_base_nbc_request_t. + */ +__opal_attribute_always_inline__ static inline int +ompi_coll_base_append_array_to_release(struct ompi_request_t *req, void *array_ptr) +{ + int i, ret = OMPI_SUCCESS; + struct ompi_coll_base_nbc_request_t *request = (struct ompi_coll_base_nbc_request_t *)req; + + /* + * important sanity check - doing steps below on a non-libnbc request can lead + * to difficult to debug memory corruption problems + */ + assert(request->super.req_type == OMPI_REQUEST_COLL); + + for(i = 0; i < OMPI_REQ_NB_RELEASE_ARRAYS; i++ ) { + if (NULL == request->data.release_arrays[i]) { + break; + } + } + + if (OMPI_REQ_NB_RELEASE_ARRAYS > i) { + request->data.release_arrays[i] = array_ptr; + ++i; + if (OMPI_REQ_NB_RELEASE_ARRAYS > i) { + request->data.release_arrays[i] = NULL; + } + } else { + ret = OMPI_ERR_OUT_OF_RESOURCE; + } + + return ret; +} + typedef struct ompi_coll_base_nbc_request_t ompi_coll_base_nbc_request_t; /* @@ -188,6 +226,13 @@ int ompi_coll_base_retain_datatypes_w( ompi_request_t *request, ompi_datatype_t * const rtypes[], bool use_topo); +/** + * If necessary, set callback to free extra memory regions + * set in release_arrays. Not set if a callback is already + * associated with the request. + */ +int ompi_coll_base_add_release_arrays_cb(ompi_request_t *request); + /* File reading function */ int ompi_coll_base_file_getnext_long(FILE *fptr, int *fileline, long* val); int ompi_coll_base_file_getnext_size_t(FILE *fptr, int *fileline, size_t* val); diff --git a/ompi/mpi/fortran/mpif-h/allgatherv_init_f.c b/ompi/mpi/fortran/mpif-h/allgatherv_init_f.c index 0d98627c440..2fa6646e89d 100644 --- a/ompi/mpi/fortran/mpif-h/allgatherv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/allgatherv_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -77,7 +79,7 @@ void ompi_allgatherv_init_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendty MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; MPI_Info c_info; - int size, idx = 0, ierr_c; + int size, ierr_c; OMPI_ARRAY_NAME_DECL(recvcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -105,12 +107,11 @@ void ompi_allgatherv_init_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendty if (NULL != ierr) *ierr = OMPI_INT_2_FINT(ierr_c); if (MPI_SUCCESS == ierr_c) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request,OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request,OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); diff --git a/ompi/mpi/fortran/mpif-h/alltoallv_init_f.c b/ompi/mpi/fortran/mpif-h/alltoallv_init_f.c index 1a10b0eadad..286e5e8f08a 100644 --- a/ompi/mpi/fortran/mpif-h/alltoallv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/alltoallv_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -77,7 +79,7 @@ void ompi_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sdispl MPI_Datatype c_sendtype, c_recvtype; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -109,14 +111,13 @@ void ompi_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sdispl if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(sdispls); diff --git a/ompi/mpi/fortran/mpif-h/alltoallw_init_f.c b/ompi/mpi/fortran/mpif-h/alltoallw_init_f.c index 24b0489ba43..97a1d6b5549 100644 --- a/ompi/mpi/fortran/mpif-h/alltoallw_init_f.c +++ b/ompi/mpi/fortran/mpif-h/alltoallw_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -78,7 +80,7 @@ void ompi_alltoallw_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Datatype *c_sendtypes = NULL, *c_recvtypes; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -119,20 +121,19 @@ void ompi_alltoallw_init_f(char *sendbuf, MPI_Fint *sendcounts, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[idx++] = c_recvtypes; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); } if (NULL != c_sendtypes) { - nb_request->data.release_arrays[idx++] = c_sendtypes; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); } } - nb_request->data.release_arrays[idx] = NULL; + ompi_coll_base_add_release_arrays_cb(c_request); } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(sdispls); diff --git a/ompi/mpi/fortran/mpif-h/gatherv_init_f.c b/ompi/mpi/fortran/mpif-h/gatherv_init_f.c index a87a5c9ddcc..060548c000a 100644 --- a/ompi/mpi/fortran/mpif-h/gatherv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/gatherv_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -77,7 +79,7 @@ void ompi_gatherv_init_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, MPI_Datatype c_sendtype, c_recvtype; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(recvcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -104,12 +106,11 @@ void ompi_gatherv_init_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); diff --git a/ompi/mpi/fortran/mpif-h/iallgatherv_f.c b/ompi/mpi/fortran/mpif-h/iallgatherv_f.c index 37926247905..b0ae5ce3388 100644 --- a/ompi/mpi/fortran/mpif-h/iallgatherv_f.c +++ b/ompi/mpi/fortran/mpif-h/iallgatherv_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -76,7 +78,7 @@ void ompi_iallgatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, ierr_c; + int size, ierr_c; OMPI_ARRAY_NAME_DECL(recvcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -107,11 +109,10 @@ void ompi_iallgatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } } diff --git a/ompi/mpi/fortran/mpif-h/ialltoallv_f.c b/ompi/mpi/fortran/mpif-h/ialltoallv_f.c index b519a3c82cb..cc23bfb1232 100644 --- a/ompi/mpi/fortran/mpif-h/ialltoallv_f.c +++ b/ompi/mpi/fortran/mpif-h/ialltoallv_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -76,7 +78,7 @@ void ompi_ialltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sdispls, MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -113,13 +115,12 @@ void ompi_ialltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *sdispls, OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(rdispls); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } } diff --git a/ompi/mpi/fortran/mpif-h/ialltoallw_f.c b/ompi/mpi/fortran/mpif-h/ialltoallw_f.c index 1c5dd1400f3..b4bf9f08f28 100644 --- a/ompi/mpi/fortran/mpif-h/ialltoallw_f.c +++ b/ompi/mpi/fortran/mpif-h/ialltoallw_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -78,7 +80,7 @@ void ompi_ialltoallw_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Comm c_comm; MPI_Datatype *c_sendtypes = NULL, *c_recvtypes; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -128,17 +130,16 @@ void ompi_ialltoallw_f(char *sendbuf, MPI_Fint *sendcounts, OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(rdispls); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); } - if (sdispls != OMPI_ARRAY_NAME_CONVERT(sdispls)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); + if ((void *)sdispls != (void *)OMPI_ARRAY_NAME_CONVERT(sdispls)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); } - nb_request->data.release_arrays[idx++] = c_recvtypes; - nb_request->data.release_arrays[idx++] = c_sendtypes; - nb_request->data.release_arrays[idx] = NULL; + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + ompi_coll_base_add_release_arrays_cb(c_request); } } diff --git a/ompi/mpi/fortran/mpif-h/igatherv_f.c b/ompi/mpi/fortran/mpif-h/igatherv_f.c index 8af9e33b914..d0458dbe3fb 100644 --- a/ompi/mpi/fortran/mpif-h/igatherv_f.c +++ b/ompi/mpi/fortran/mpif-h/igatherv_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -76,7 +78,7 @@ void ompi_igatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(recvcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -106,11 +108,10 @@ void ompi_igatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *sendtype, OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } } diff --git a/ompi/mpi/fortran/mpif-h/ineighbor_allgatherv_f.c b/ompi/mpi/fortran/mpif-h/ineighbor_allgatherv_f.c index 390e3dd2a74..b2ec0a5903d 100644 --- a/ompi/mpi/fortran/mpif-h/ineighbor_allgatherv_f.c +++ b/ompi/mpi/fortran/mpif-h/ineighbor_allgatherv_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -79,7 +81,7 @@ void ompi_ineighbor_allgatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *s MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, ierr_c; + int size, ierr_c; OMPI_ARRAY_NAME_DECL(recvcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -106,12 +108,11 @@ void ompi_ineighbor_allgatherv_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fint *s if (NULL != ierr) *ierr = OMPI_INT_2_FINT(ierr_c); if (MPI_SUCCESS == ierr_c) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); diff --git a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c index 144b2efec08..c72f4ef4dec 100644 --- a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c +++ b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallv_f.c @@ -14,7 +14,7 @@ * Copyright (c) 2013 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2015 Research Organization for Information Science - * Copyright (c) 2026 Triad National Security, LLC. All rights + * Copyright (c) 2025-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -81,7 +81,7 @@ void ompi_ineighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *s MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int indegree, outdegree, idx = 0, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -123,11 +123,12 @@ void ompi_ineighbor_alltoallv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fint *s OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(rdispls); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); - nb_request->data.release_arrays[idx] = NULL; + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); + ompi_coll_base_add_release_arrays_cb(c_request); + } } } diff --git a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c index b18597a4ce4..fd79fb26e15 100644 --- a/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c +++ b/ompi/mpi/fortran/mpif-h/ineighbor_alltoallw_f.c @@ -83,7 +83,7 @@ void ompi_ineighbor_alltoallw_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Comm c_comm; MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Request c_request; - int indegree, outdegree, idx = 0, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -131,11 +131,12 @@ void ompi_ineighbor_alltoallw_f(char *sendbuf, MPI_Fint *sendcounts, free(c_sendtypes); free(c_recvtypes); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = c_sendtypes; - nb_request->data.release_arrays[idx++] = c_recvtypes; - nb_request->data.release_arrays[idx] = NULL; + if((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + } + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + ompi_coll_base_add_release_arrays_cb(c_request); } } diff --git a/ompi/mpi/fortran/mpif-h/ireduce_scatter_f.c b/ompi/mpi/fortran/mpif-h/ireduce_scatter_f.c index d09a397cac6..df4f0271ef6 100644 --- a/ompi/mpi/fortran/mpif-h/ireduce_scatter_f.c +++ b/ompi/mpi/fortran/mpif-h/ireduce_scatter_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -100,8 +102,9 @@ void ompi_ireduce_scatter_f(char *sendbuf, char *recvbuf, if ( REQUEST_COMPLETE(c_request)) { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[0] = recvcounts; - nb_request->data.release_arrays[1] = NULL; + if((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, recvcounts); + ompi_coll_base_add_release_arrays_cb(c_request); + } } } diff --git a/ompi/mpi/fortran/mpif-h/iscatterv_f.c b/ompi/mpi/fortran/mpif-h/iscatterv_f.c index 01226a83ea8..682656ce16e 100644 --- a/ompi/mpi/fortran/mpif-h/iscatterv_f.c +++ b/ompi/mpi/fortran/mpif-h/iscatterv_f.c @@ -13,6 +13,8 @@ * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -78,7 +80,7 @@ void ompi_iscatterv_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Comm c_comm; MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -108,11 +110,10 @@ void ompi_iscatterv_f(char *sendbuf, MPI_Fint *sendcounts, OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); } else { - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } } diff --git a/ompi/mpi/fortran/mpif-h/neighbor_allgatherv_init_f.c b/ompi/mpi/fortran/mpif-h/neighbor_allgatherv_init_f.c index 532365e2aa7..86b51a12552 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_allgatherv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_allgatherv_init_f.c @@ -15,6 +15,8 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -108,11 +110,10 @@ void ompi_neighbor_allgatherv_init_f(char *sendbuf, MPI_Fint *sendcount, MPI_Fin if (NULL != ierr) *ierr = OMPI_INT_2_FINT(ierr_c); if (MPI_SUCCESS == ierr_c) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (recvcounts != OMPI_ARRAY_NAME_CONVERT(recvcounts)) { - nb_request->data.release_arrays[0] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[1] = OMPI_ARRAY_NAME_CONVERT(displs); - nb_request->data.release_arrays[2] = NULL; + if ((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c index 8bfb79dd964..a97742a971a 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallv_init_f.c @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2026 Triad National Security, LLC. All rights + * Copyright (c) 2025-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -83,7 +83,7 @@ void ompi_neighbor_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fin MPI_Datatype c_sendtype, c_recvtype; MPI_Info c_info; MPI_Request c_request; - int indegree, outdegree, idx = 0, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(sdispls); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -120,14 +120,13 @@ void ompi_neighbor_alltoallv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Fin if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sdispls); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(rdispls); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sdispls)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(rdispls)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(sdispls); diff --git a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c index 30f9f575c89..bbddcb431d5 100644 --- a/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c +++ b/ompi/mpi/fortran/mpif-h/neighbor_alltoallw_init_f.c @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2026 Triad National Security, LLC. All rights + * Copyright (c) 2025-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -84,7 +84,7 @@ void ompi_neighbor_alltoallw_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Info c_info; MPI_Request c_request; - int indegree, outdegree, idx = 0, c_ierr; + int indegree, outdegree, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(recvcounts); @@ -128,13 +128,12 @@ void ompi_neighbor_alltoallw_init_f(char *sendbuf, MPI_Fint *sendcounts, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[idx++] = c_sendtypes; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(recvcounts); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); } - nb_request->data.release_arrays[idx] = NULL; + ompi_coll_base_add_release_arrays_cb(c_request); } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); diff --git a/ompi/mpi/fortran/mpif-h/reduce_scatter_init_f.c b/ompi/mpi/fortran/mpif-h/reduce_scatter_init_f.c index d60a69dbfef..5754d449ac6 100644 --- a/ompi/mpi/fortran/mpif-h/reduce_scatter_init_f.c +++ b/ompi/mpi/fortran/mpif-h/reduce_scatter_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -100,9 +102,10 @@ void ompi_reduce_scatter_init_f(char *sendbuf, char *recvbuf, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - nb_request->data.release_arrays[0] = OMPI_ARRAY_NAME_CONVERT(recvcounts); - nb_request->data.release_arrays[1] = NULL; + if((void *)recvcounts != (void *)OMPI_ARRAY_NAME_CONVERT(recvcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(recvcounts)); + ompi_coll_base_add_release_arrays_cb(c_request); + } } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(recvcounts); } diff --git a/ompi/mpi/fortran/mpif-h/scatterv_init_f.c b/ompi/mpi/fortran/mpif-h/scatterv_init_f.c index 394984214dd..75740f0d7f3 100644 --- a/ompi/mpi/fortran/mpif-h/scatterv_init_f.c +++ b/ompi/mpi/fortran/mpif-h/scatterv_init_f.c @@ -12,6 +12,8 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2025 Triad National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -78,7 +80,7 @@ void ompi_scatterv_init_f(char *sendbuf, MPI_Fint *sendcounts, MPI_Datatype c_sendtype, c_recvtype; MPI_Info c_info; MPI_Request c_request; - int size, idx = 0, c_ierr; + int size, c_ierr; OMPI_ARRAY_NAME_DECL(sendcounts); OMPI_ARRAY_NAME_DECL(displs); @@ -105,12 +107,11 @@ void ompi_scatterv_init_f(char *sendbuf, MPI_Fint *sendcounts, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; - if (sendcounts != OMPI_ARRAY_NAME_CONVERT(sendcounts)) { - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(sendcounts); - nb_request->data.release_arrays[idx++] = OMPI_ARRAY_NAME_CONVERT(displs); + if ((void *)sendcounts != (void *)OMPI_ARRAY_NAME_CONVERT(sendcounts)) { + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(sendcounts)); + ompi_coll_base_append_array_to_release(c_request, OMPI_ARRAY_NAME_CONVERT(displs)); + ompi_coll_base_add_release_arrays_cb(c_request); } - nb_request->data.release_arrays[idx] = NULL; } else { OMPI_ARRAY_FINT_2_INT_CLEANUP(sendcounts); OMPI_ARRAY_FINT_2_INT_CLEANUP(displs); diff --git a/ompi/mpi/fortran/use-mpi-f08/allgatherv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/allgatherv_init_ts.c.in index c559a5f107a..9c540a98e4d 100644 --- a/ompi/mpi/fortran/use-mpi-f08/allgatherv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/allgatherv_init_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -97,4 +97,7 @@ PROTOTYPE VOID allgatherv_init(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE sendty } OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/alltoallv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/alltoallv_init_ts.c.in index 0b1608fd32f..853a4039d94 100644 --- a/ompi/mpi/fortran/use-mpi-f08/alltoallv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/alltoallv_init_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -85,4 +85,7 @@ PROTOTYPE VOID alltoallv_init(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP_ARRA OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/alltoallw_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/alltoallw_init_ts.c.in index 34765cd1af1..ae239107b7d 100644 --- a/ompi/mpi/fortran/use-mpi-f08/alltoallw_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/alltoallw_init_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -88,10 +88,12 @@ PROTOTYPE VOID alltoallw_init(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); if (NULL != c_sendtypes) { - free(c_sendtypes); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); } - free(c_recvtypes); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + ompi_coll_base_add_release_arrays_cb(c_request); } + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); diff --git a/ompi/mpi/fortran/use-mpi-f08/base/bigcount.h b/ompi/mpi/fortran/use-mpi-f08/base/bigcount.h index d7dd109005b..535737f2011 100644 --- a/ompi/mpi/fortran/use-mpi-f08/base/bigcount.h +++ b/ompi/mpi/fortran/use-mpi-f08/base/bigcount.h @@ -45,11 +45,10 @@ #define OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(array, tmp_array, c_request, c_ierr, idx) \ do { \ if (MPI_SUCCESS == (c_ierr)) { \ - ompi_coll_base_nbc_request_t* nb_request = (ompi_coll_base_nbc_request_t*)c_request; \ if ((void *)(array) != (void *)(tmp_array) && (tmp_array) != NULL) { \ - nb_request->data.release_arrays[(idx)++] = tmp_array; \ + ompi_coll_base_append_array_to_release((c_request), (tmp_array)); \ + (idx)++; \ } \ - nb_request->data.release_arrays[idx] = NULL; \ } else { \ OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP((array), (tmp_array)); \ } \ diff --git a/ompi/mpi/fortran/use-mpi-f08/gatherv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/gatherv_init_ts.c.in index da4c954cebb..5c35dd094e6 100644 --- a/ompi/mpi/fortran/use-mpi-f08/gatherv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/gatherv_init_ts.c.in @@ -111,5 +111,8 @@ PROTOTYPE VOID gatherv_init(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE sendtype, OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/iallgatherv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/iallgatherv_ts.c.in index 0323d69bb33..4a279711df2 100644 --- a/ompi/mpi/fortran/use-mpi-f08/iallgatherv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/iallgatherv_ts.c.in @@ -25,7 +25,7 @@ PROTOTYPE VOID iallgatherv(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE sendtype, BUFFER_ASYNC_OUT x2, COUNT_ARRAY recvcounts, DISP_ARRAY displs, DATATYPE recvtype, COMM comm, REQUEST_OUT request) { - int c_ierr; + int c_ierr, idx = 0; MPI_Comm c_comm = PMPI_Comm_f2c(*comm); @COUNT_TYPE@ c_sendcount = (@COUNT_TYPE@)*sendcount; MPI_Datatype c_sendtype = NULL, c_senddatatype = NULL; @@ -86,6 +86,10 @@ PROTOTYPE VOID iallgatherv(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE sendtype, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(displs, tmp_displs); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } + } diff --git a/ompi/mpi/fortran/use-mpi-f08/ialltoallv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ialltoallv_ts.c.in index 1e6b401f934..fc12804dbb7 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ialltoallv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ialltoallv_ts.c.in @@ -26,7 +26,7 @@ PROTOTYPE VOID ialltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP_ARRAY sd DISP_ARRAY rdispls, DATATYPE recvtype, COMM comm, REQUEST_OUT request) { - int c_ierr; + int c_ierr, idx = 0; MPI_Comm c_comm = PMPI_Comm_f2c(*comm); char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); MPI_Datatype c_sendtype = NULL, c_recvtype = PMPI_Type_f2c(*recvtype); @@ -76,8 +76,12 @@ PROTOTYPE VOID ialltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP_ARRAY sd if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sendcounts, tmp_sendcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sdispls, tmp_sdispls); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(rdispls, tmp_rdispls); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } + } diff --git a/ompi/mpi/fortran/use-mpi-f08/ialltoallw_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ialltoallw_ts.c.in index dbeebf41910..23b2c19a343 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ialltoallw_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ialltoallw_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -30,7 +30,7 @@ PROTOTYPE VOID ialltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype *c_sendtypes = NULL, *c_recvtypes; MPI_Request c_request; - int size, c_ierr; + int size, idx = 0, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @DISP_TYPE@ *tmp_sdispls = NULL; @@ -82,12 +82,13 @@ PROTOTYPE VOID ialltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sendcounts, tmp_sendcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sdispls, tmp_sdispls); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(rdispls, tmp_rdispls); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx);; + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); if (NULL != c_sendtypes) { - free(c_sendtypes); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); } - free(c_recvtypes); + ompi_coll_base_add_release_arrays_cb(c_request); } diff --git a/ompi/mpi/fortran/use-mpi-f08/igatherv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/igatherv_ts.c.in index f5f51bbd023..ea156532277 100644 --- a/ompi/mpi/fortran/use-mpi-f08/igatherv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/igatherv_ts.c.in @@ -101,5 +101,8 @@ PROTOTYPE VOID igatherv(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE sendtype, OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/ineighbor_allgatherv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ineighbor_allgatherv_ts.c.in index 6cffe2c3007..13c1e80361a 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ineighbor_allgatherv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ineighbor_allgatherv_ts.c.in @@ -15,7 +15,7 @@ * reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -35,7 +35,7 @@ PROTOTYPE VOID ineighbor_allgatherv(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE s @COUNT_TYPE@ c_sendcount = (@COUNT_TYPE@) *sendcount; MPI_Datatype c_recvtype = PMPI_Type_f2c(*recvtype); MPI_Request c_request; - int size, c_ierr; + int size, c_ierr, idx = 0; @COUNT_TYPE@ *tmp_recvcounts = NULL; @DISP_TYPE@ *tmp_displs = NULL; @@ -73,6 +73,9 @@ PROTOTYPE VOID ineighbor_allgatherv(BUFFER_ASYNC x1, COUNT sendcount, DATATYPE s if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(displs, tmp_displs); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in index d83aacd28c5..2eac4c05b8c 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallv_ts.c.in @@ -32,7 +32,7 @@ PROTOTYPE VOID ineighbor_alltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype c_sendtype, c_recvtype; MPI_Request c_request; - int indegree, outdegree, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @DISP_TYPE@ *tmp_sdispls = NULL; @@ -82,8 +82,11 @@ PROTOTYPE VOID ineighbor_alltoallv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, DISP if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sendcounts, tmp_sendcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sdispls, tmp_sdispls); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(rdispls, tmp_rdispls); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts,c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in index 05652526d65..fb8babef69a 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ineighbor_alltoallw_ts.c.in @@ -33,7 +33,7 @@ PROTOTYPE VOID ineighbor_alltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, MPI_Comm c_comm = PMPI_Comm_f2c(*comm); MPI_Datatype *c_sendtypes, *c_recvtypes; MPI_Request c_request; - int indegree, outdegree, c_ierr; + int indegree, outdegree, idx = 0, c_ierr; char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @COUNT_TYPE@ *tmp_recvcounts = NULL; @@ -87,10 +87,15 @@ PROTOTYPE VOID ineighbor_alltoallw(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, rdispls, c_recvtypes, c_comm, &c_request); if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); - if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); - - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(sendcounts, tmp_sendcounts); - OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP(recvcounts, tmp_recvcounts); - free(c_sendtypes); - free(c_recvtypes); + if (MPI_SUCCESS == c_ierr) { + *request = PMPI_Request_c2f(c_request); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); + OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + ompi_coll_base_add_release_arrays_cb(c_request); + } else { + free(c_sendtypes); + free(c_recvtypes); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/ireduce_scatter_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/ireduce_scatter_ts.c.in index e6c319b03e3..ad5a874dab4 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ireduce_scatter_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/ireduce_scatter_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -62,5 +62,8 @@ PROTOTYPE VOID ireduce_scatter(BUFFER_ASYNC x1, BUFFER_ASYNC_OUT x2, if (MPI_SUCCESS == c_ierr) *request = PMPI_Request_c2f(c_request); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/iscatterv_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/iscatterv_ts.c.in index 7f983faed51..b783198dca3 100644 --- a/ompi/mpi/fortran/use-mpi-f08/iscatterv_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/iscatterv_ts.c.in @@ -13,7 +13,7 @@ * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -106,4 +106,7 @@ PROTOTYPE VOID iscatterv(BUFFER_ASYNC x1, COUNT_ARRAY sendcounts, OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_allgatherv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_allgatherv_init_ts.c.in index 394debf1c27..2d59884292e 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_allgatherv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_allgatherv_init_ts.c.in @@ -84,4 +84,7 @@ PROTOTYPE VOID neighbor_allgatherv_init(BUFFER x1, COUNT sendcount, DATATYPE sen OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in index 6d7e08e8570..24442c09e4a 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallv_init_ts.c.in @@ -95,4 +95,7 @@ PROTOTYPE VOID neighbor_alltoallv_init(BUFFER x1, COUNT_ARRAY sendcounts, DISP_A OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } } diff --git a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in index 78d136ebf6b..c6da64686b6 100644 --- a/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/neighbor_alltoallw_init_ts.c.in @@ -40,7 +40,7 @@ PROTOTYPE VOID neighbor_alltoallw_init(BUFFER x1, COUNT_ARRAY sendcounts, char *sendbuf = OMPI_CFI_BASE_ADDR(x1), *recvbuf = OMPI_CFI_BASE_ADDR(x2); @COUNT_TYPE@ *tmp_sendcounts = NULL; @COUNT_TYPE@ *tmp_recvcounts = NULL; - MPI_Aint *tmp_sdispls = NULL, *tmp_rdispls; + MPI_Aint *tmp_sdispls = NULL, *tmp_rdispls = NULL; c_info = PMPI_Info_f2c(*info); @@ -100,13 +100,16 @@ PROTOTYPE VOID neighbor_alltoallw_init(BUFFER x1, COUNT_ARRAY sendcounts, if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *request = PMPI_Request_c2f(c_request); + ompi_coll_base_append_array_to_release(c_request, c_sendtypes); + ompi_coll_base_append_array_to_release(c_request, c_recvtypes); + ompi_coll_base_add_release_arrays_cb(c_request); + } else { + free(c_sendtypes); + free(c_recvtypes); } OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(rdispls, tmp_rdispls, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sdispls, tmp_sdispls, c_request, c_ierr, idx); - - free(c_sendtypes); - free(c_recvtypes); } diff --git a/ompi/mpi/fortran/use-mpi-f08/reduce_scatter_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/reduce_scatter_init_ts.c.in index a9a9d02a64b..c39c8ec33e9 100644 --- a/ompi/mpi/fortran/use-mpi-f08/reduce_scatter_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/reduce_scatter_init_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -74,6 +74,9 @@ PROTOTYPE VOID reduce_scatter_init(BUFFER x1, BUFFER_OUT x2, } OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(recvcounts, tmp_recvcounts, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); diff --git a/ompi/mpi/fortran/use-mpi-f08/scatterv_init_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/scatterv_init_ts.c.in index 046f0669336..3f0756dbb7e 100644 --- a/ompi/mpi/fortran/use-mpi-f08/scatterv_init_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/scatterv_init_ts.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015-2021 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024 Triad National Security, LLC. All rights + * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -110,6 +110,9 @@ PROTOTYPE VOID scatterv_init(BUFFER x1, COUNT_ARRAY sendcounts, OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(sendcounts, tmp_sendcounts, c_request, c_ierr, idx); OMPI_FORTRAN_BIGCOUNT_ARRAY_CLEANUP_NONBLOCKING(displs, tmp_displs, c_request, c_ierr, idx); + if (idx > 0) { + ompi_coll_base_add_release_arrays_cb(c_request); + } if ((c_recvdatatype != NULL ) && (c_recvdatatype != c_recvtype)){ ompi_datatype_destroy(&c_recvdatatype); From f30a6ca7e532d53e2de2dfb19570d046b5d651b7 Mon Sep 17 00:00:00 2001 From: Tomislav Janjusic Date: Wed, 29 Apr 2026 10:35:51 -0500 Subject: [PATCH 035/230] docs: add docs on ucc Signed-off-by: Tomislav Janjusic --- docs/tuning-apps/collectives/components.rst | 2 +- docs/tuning-apps/collectives/index.rst | 1 + docs/tuning-apps/collectives/ucc.rst | 173 ++++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 docs/tuning-apps/collectives/ucc.rst diff --git a/docs/tuning-apps/collectives/components.rst b/docs/tuning-apps/collectives/components.rst index 921f7e12036..382c7febbf8 100644 --- a/docs/tuning-apps/collectives/components.rst +++ b/docs/tuning-apps/collectives/components.rst @@ -27,7 +27,7 @@ The following provides a list of components and their primary target scenario: between algorithms for each operation and message size. See :doc:`tuned` for more details. - ``ucc``: component using the `UCC library `_ - for collective operations. + for collective operations. See :doc:`ucc` for more details. - ``xhc``: shared memory collective component, employing hierarchical & topology-aware algorithms, with XPMEM for data transfers. See :doc:`xhc` for more details. diff --git a/docs/tuning-apps/collectives/index.rst b/docs/tuning-apps/collectives/index.rst index 2e49cae2d15..d4c8871335b 100644 --- a/docs/tuning-apps/collectives/index.rst +++ b/docs/tuning-apps/collectives/index.rst @@ -11,5 +11,6 @@ components additional information on how to utilize them. components tuned + ucc acoll xhc diff --git a/docs/tuning-apps/collectives/ucc.rst b/docs/tuning-apps/collectives/ucc.rst new file mode 100644 index 00000000000..e212aa5ff74 --- /dev/null +++ b/docs/tuning-apps/collectives/ucc.rst @@ -0,0 +1,173 @@ +The ``ucc`` Component +===================== + +The ``ucc`` collective component uses the `Unified Collective +Communication (UCC) library `_ to +offload selected MPI collective operations to UCC. This component is +useful on systems where UCC has been configured for the target transport +or accelerator environment. + +Building with UCC +----------------- + +Open MPI must be configured with UCC support: + +.. code-block:: sh + + shell$ ./configure --with-ucc=/path/to/ucc-install + +If UCC support is explicitly requested and the UCC headers and library +cannot be found, ``configure`` aborts. The ``ucc`` component is disabled +when Open MPI is configured with progress thread support, because the UCC +driver does not currently support progress threads. + +Enabling the Component +---------------------- + +The component is not enabled by default. Enable it at run time and give +it a high enough priority to be selected: + +.. code-block:: sh + + shell$ mpirun --mca coll_ucc_enable 1 \ + --mca coll_ucc_priority 100 \ + -np 64 ./my_mpi_app + +The ``ucc`` component is considered only for intracommunicators whose +size is at least ``coll_ucc_np``. The default value of ``coll_ucc_np`` +is ``2``. + +UCC Layers and Protocols +------------------------ + +For each MPI communicator selected for UCC, Open MPI creates a UCC +``team``: the UCC group object used to initialize and execute collective +operations. Inside UCC, collective implementations are selected through +two kinds of layers: + +* Collective layers (CLs), such as ``basic`` and ``hier``, decide how a + collective is decomposed. +* Team layers (TLs), such as ``ucp``, ``self``, ``cuda``, ``nccl``, + ``rccl``, ``sharp``, and ``mlx5``, provide the underlying transport or + accelerator implementation. + +For example, the ``ucp`` TL uses UCX/UCP transports such as InfiniBand, +RoCE, and shared memory; ``sharp`` uses SHARP in-network collective +offload; and ``nccl`` or ``rccl`` can be used for GPU collectives on +CUDA or ROCm memory. + +The ``basic`` CL is the general-purpose layer. The ``hier`` CL can use +system hierarchy when it is available; for example, it may split work +across ``NODE`` and ``NET`` subgroups, plus the ``FULL`` group, and then +pipeline phases through different TLs. A typical hierarchical protocol +could use an intra-node reduction, an inter-node operation such as +SHARP, and an intra-node broadcast. + +The exact CLs, TLs, and algorithms available depend on how UCC was +built. Use UCC's own tools to inspect the installed library: + +.. code-block:: sh + + shell$ ucc_info -s # Show available CLs and TLs + shell$ ucc_info -A # Show supported collective algorithms + shell$ ucc_info -caf # Show UCC configuration variables + +Open MPI's ``coll_ucc_cls`` MCA parameter is passed to UCC as its +``CLS`` setting. It can be used to restrict team creation to specific +UCC collective layers, for example: + +.. code-block:: sh + + shell$ mpirun --mca coll_ucc_enable 1 \ + --mca coll_ucc_cls hier \ + ./my_mpi_app + +For lower-level TL tuning, use UCC environment variables such as +``UCC_TL__TUNE`` or a UCC configuration file. UCC scores TLs +based on factors including the collective type, message size, memory +type, and team size. + +Selecting Collective Operations +------------------------------- + +Use ``coll_ucc_cts`` to choose which collective operations the component +should provide. By default, the component enables all supported blocking +and nonblocking operations. + +.. code-block:: sh + + shell$ mpirun --mca coll_ucc_enable 1 \ + --mca coll_ucc_cts allreduce,iallreduce,bcast,ibcast \ + ./my_mpi_app + +Prefix the value with ``^`` to start from all supported operations and +disable specific operations from that set: + +.. code-block:: sh + + shell$ mpirun --mca coll_ucc_enable 1 \ + --mca coll_ucc_cts ^alltoall,ialltoall \ + ./my_mpi_app + +The supported operation names are: + +* ``barrier``, ``bcast``, ``allreduce``, ``alltoall``, ``alltoallv``, + ``allgather``, ``allgatherv``, ``reduce``, ``gather``, ``gatherv``, + ``reduce_scatter_block``, ``reduce_scatter``, ``scatterv``, and + ``scatter`` +* ``ibarrier``, ``ibcast``, ``iallreduce``, ``ialltoall``, + ``ialltoallv``, ``iallgather``, ``iallgatherv``, ``ireduce``, + ``igather``, ``igatherv``, ``ireduce_scatter_block``, + ``ireduce_scatter``, ``iscatterv``, and ``iscatter`` + +The aliases ``colls_b``, ``colls_i`` (or ``colls_nb``), and ``colls_p`` +select all blocking, nonblocking, and persistent collective operations, +respectively. Individual persistent collective operations can be +selected by adding the ``_init`` suffix to the blocking operation name, +for example ``allreduce_init``. + +Other MCA Parameters +-------------------- + +.. list-table:: + :header-rows: 1 + :widths: 30 15 55 + + * - Parameter + - Default + - Description + * - ``coll_ucc_enable`` + - ``0`` + - Enable or disable the component. + * - ``coll_ucc_priority`` + - ``10`` + - Component selection priority. + * - ``coll_ucc_verbose`` + - ``0`` + - Verbosity level for component logging. + * - ``coll_ucc_np`` + - ``2`` + - Minimum communicator size for enabling the component. + * - ``coll_ucc_cls`` + - UCC default + - Comma-separated list of UCC collective layers to use for team + creation, passed to UCC as ``CLS``. + * - ``coll_ucc_cts`` + - All supported blocking and nonblocking operations + - Comma-separated list of UCC collective types to enable. + +Verifying Selection +------------------- + +Use ``coll_base_verbose`` to check which collective component Open MPI +selects for each operation: + +.. code-block:: sh + + shell$ mpirun --mca coll_ucc_enable 1 \ + --mca coll_ucc_priority 100 \ + --mca coll_base_verbose 20 \ + ./my_mpi_app + +See :doc:`components` for more details about interpreting collective +component selection output. From 6d1749489db2cc0be689296e208f24166a2c4c6b Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Wed, 29 Apr 2026 20:29:29 -0400 Subject: [PATCH 036/230] ompi/comm: release c_keyhash instead of destructing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c_keyhash is allocated via OBJ_NEW in ompi_attr_hash_init, so cleanup must use OBJ_RELEASE — not OBJ_DESTRUCT, which runs the destructor without freeing the heap-allocated opal_hash_table_t struct itself. This leaks 72 bytes (sizeof(opal_hash_table_t)) on every world-model init, as flagged by LeakSanitizer in issue #13783. In addition make sure we release the attributes even for other communicators in the comm destructor (ompi_comm_destruct). Signed-off-by: George Bosilca --- ompi/communicator/comm_init.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ompi/communicator/comm_init.c b/ompi/communicator/comm_init.c index 65f49f85e4e..8cec884d24a 100644 --- a/ompi/communicator/comm_init.c +++ b/ompi/communicator/comm_init.c @@ -343,9 +343,6 @@ static int ompi_comm_finalize (void) /* tear down MPI-3 predefined communicators (not initialized unless using MPI_Init) */ OBJ_DESTRUCT( &ompi_mpi_comm_self ); ompi_attr_delete_predefined_keyvals_for_wm(); - /* Destroy the keyhash even is user defined attributes are still attached. */ - OBJ_DESTRUCT(ompi_mpi_comm_world.comm.c_keyhash); - ompi_mpi_comm_world.comm.c_keyhash = NULL; OBJ_DESTRUCT( &ompi_mpi_comm_world ); ompi_comm_intrinsic_init = false; @@ -401,7 +398,8 @@ static int ompi_comm_finalize (void) for ( i=3; ic_name); + opal_output(0, "WARNING: %u(%s) unnamed MPI_Comm handles still allocated at MPI_FINALIZE", + ompi_comm_get_local_cid(comm), comm->c_name); ompi_comm_dump ( comm); OBJ_RELEASE(comm); } @@ -515,6 +513,12 @@ static void ompi_comm_destruct(ompi_communicator_t* comm) MCA_PML_CALL(del_comm (comm)); } + /* Release the attributes */ + if( NULL != comm->c_keyhash) { + OBJ_RELEASE(comm->c_keyhash); + comm->c_keyhash = NULL; + } + /* Release topology module */ if (NULL != comm->c_topo) { OBJ_RELEASE(comm->c_topo); From e624b382b607d6d62eaf6b1987b6b19583dd3964 Mon Sep 17 00:00:00 2001 From: "DUPRAT, JULIEN" Date: Wed, 18 Feb 2026 09:00:59 +0100 Subject: [PATCH 037/230] Dynamic instance name Signed-off-by: DUPRAT, JULIEN --- ompi/instance/instance.c | 6 +++++- ompi/instance/instance.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ompi/instance/instance.c b/ompi/instance/instance.c index 6d50d32ffb2..a37cfe1232f 100644 --- a/ompi/instance/instance.c +++ b/ompi/instance/instance.c @@ -9,6 +9,7 @@ * Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. * Copyright (c) 2026 Nanook Consulting All rights reserved. + * Copyright (c) 2026 BULL S.A.S. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -108,8 +109,9 @@ static opal_finalize_domain_t ompi_instance_common_domain; static void ompi_instance_construct (ompi_instance_t *instance) { instance->i_f_to_c_index = opal_pointer_array_add (&ompi_instance_f_to_c_table, instance); + instance->i_name = (char*) malloc (MPI_MAX_OBJECT_NAME); instance->i_name[0] = '\0'; - instance->i_flags = 0; + instance->i_flags = 0; instance->i_keyhash = NULL; OBJ_CONSTRUCT(&instance->s_lock, opal_mutex_t); instance->errhandler_type = OMPI_ERRHANDLER_TYPE_INSTANCE; @@ -118,6 +120,8 @@ static void ompi_instance_construct (ompi_instance_t *instance) static void ompi_instance_destruct(ompi_instance_t *instance) { + free(instance->i_name); + instance->i_name = NULL; OBJ_DESTRUCT(&instance->s_lock); } diff --git a/ompi/instance/instance.h b/ompi/instance/instance.h index ce5fb25919c..fc79dfe1b15 100644 --- a/ompi/instance/instance.h +++ b/ompi/instance/instance.h @@ -29,7 +29,7 @@ struct ompi_instance_t { opal_infosubscriber_t super; opal_mutex_t s_lock; int i_thread_level; - char i_name[MPI_MAX_OBJECT_NAME]; + char *i_name; uint32_t i_flags; /* Attributes */ From b1d72a7d20d2f93f1bfc3569bb47948942c44c1a Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Thu, 30 Apr 2026 08:47:17 -0700 Subject: [PATCH 038/230] tests: More BSD hacks in datatype tests Trying to get strsep() defined in the reduce_local test ends up opening a can of worms in other defines. But continue the good fight, and add some more hacks so that the rest of the includes can get at gettimeofday(). Signed-off-by: Brian Barrett --- test/datatype/reduce_local.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/datatype/reduce_local.c b/test/datatype/reduce_local.c index a7e4a68a344..960826b59fc 100644 --- a/test/datatype/reduce_local.c +++ b/test/datatype/reduce_local.c @@ -1,3 +1,4 @@ + /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2019-2020 The University of Tennessee and The University @@ -16,6 +17,10 @@ /* needed for strsep() */ #define _DEFAULT_SOURCE #define _BSD_SOURCE +/* if we set all these flags, we need to also let sys/time.h define + gettimeofday() */ +#define __BSD_VISIBLE 1 +#define _XOPEN_SOURCE 700 /* needed for posix_memalign() and getopt() */ #define _POSIX_C_SOURCE 200809L From 425ce8c34555a33498f983a53e93d579f79a63bc Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Thu, 30 Apr 2026 08:47:47 -0700 Subject: [PATCH 039/230] tests: Remove a bunch of shadow warnings Signed-off-by: Brian Barrett --- test/datatype/to_self.c | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/datatype/to_self.c b/test/datatype/to_self.c index e7158bb7561..3f23c0faf64 100644 --- a/test/datatype/to_self.c +++ b/test/datatype/to_self.c @@ -218,19 +218,19 @@ static int cycles = 100; static int trials = 20; static int warmups = 2; -static void print_result(int length, int trials, double *timers) +static void print_result(int length, int num_trials, double *timers) { double bandwidth, clock_prec, temp; double min_time, max_time, average, std_dev = 0.0; - double ordered[trials]; + double ordered[num_trials]; int t, pos, quartile_start, quartile_end; - for (t = 0; t < trials; ordered[t] = timers[t], t++) + for (t = 0; t < num_trials; ordered[t] = timers[t], t++) ; - for (t = 0; t < trials - 1; t++) { + for (t = 0; t < num_trials - 1; t++) { temp = ordered[t]; pos = t; - for (int i = t + 1; i < trials; i++) { + for (int i = t + 1; i < num_trials; i++) { if (temp > ordered[i]) { temp = ordered[i]; pos = i; @@ -242,8 +242,8 @@ static void print_result(int length, int trials, double *timers) ordered[pos] = temp; } } - quartile_start = trials - (3 * trials) / 4; - quartile_end = trials - (1 * trials) / 4; + quartile_start = num_trials - (3 * num_trials) / 4; + quartile_end = num_trials - (1 * num_trials) / 4; clock_prec = MPI_Wtick(); min_time = ordered[quartile_start]; max_time = ordered[quartile_start]; @@ -266,7 +266,7 @@ static void print_result(int length, int trials, double *timers) min_time, max_time, (100.0 * std_dev) / average); } -static int pack(int cycles, MPI_Datatype sdt, int scount, void *sbuf, void *packed_buf) +static int pack(int num_cycles, MPI_Datatype sdt, int scount, void *sbuf, void *packed_buf) { int position, myself, c, t, outsize; double timers[trials]; @@ -277,7 +277,7 @@ static int pack(int cycles, MPI_Datatype sdt, int scount, void *sbuf, void *pack MPI_Comm_rank(MPI_COMM_WORLD, &myself); for (t = 0; t < warmups; t++) { - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { position = 0; MPI_Pack(sbuf, scount, sdt, packed_buf, outsize, &position, MPI_COMM_WORLD); } @@ -285,17 +285,17 @@ static int pack(int cycles, MPI_Datatype sdt, int scount, void *sbuf, void *pack for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { position = 0; MPI_Pack(sbuf, scount, sdt, packed_buf, outsize, &position, MPI_COMM_WORLD); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(outsize, trials, timers); return 0; } -static int unpack(int cycles, void *packed_buf, MPI_Datatype rdt, int rcount, void *rbuf) +static int unpack(int num_cycles, void *packed_buf, MPI_Datatype rdt, int rcount, void *rbuf) { int position, myself, c, t, insize; double timers[trials]; @@ -306,7 +306,7 @@ static int unpack(int cycles, void *packed_buf, MPI_Datatype rdt, int rcount, vo MPI_Comm_rank(MPI_COMM_WORLD, &myself); for (t = 0; t < warmups; t++) { - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { position = 0; MPI_Unpack(packed_buf, insize, &position, rbuf, rcount, rdt, MPI_COMM_WORLD); } @@ -314,17 +314,17 @@ static int unpack(int cycles, void *packed_buf, MPI_Datatype rdt, int rcount, vo for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { position = 0; MPI_Unpack(packed_buf, insize, &position, rbuf, rcount, rdt, MPI_COMM_WORLD); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(insize, trials, timers); return 0; } -static int isend_recv(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, +static int isend_recv(int num_cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, int rcount, void *rbuf) { int myself, tag = 0, c, t, slength, rlength; @@ -341,18 +341,18 @@ static int isend_recv(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_ for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { MPI_Isend(sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &req); MPI_Recv(rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &status); MPI_Wait(&req, &status); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(rlength, trials, timers); return 0; } -static int irecv_send(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, +static int irecv_send(int num_cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, int rcount, void *rbuf) { int myself, tag = 0, c, t, slength, rlength; @@ -369,18 +369,18 @@ static int irecv_send(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_ for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { MPI_Irecv(rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &req); MPI_Send(sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD); MPI_Wait(&req, &status); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(rlength, trials, timers); return 0; } -static int isend_irecv_wait(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, +static int isend_irecv_wait(int num_cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, int rcount, void *rbuf) { int myself, tag = 0, c, t, slength, rlength; @@ -397,18 +397,18 @@ static int isend_irecv_wait(int cycles, MPI_Datatype sdt, int scount, void *sbuf for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { MPI_Isend(sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &requests[0]); MPI_Irecv(rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &requests[1]); MPI_Waitall(2, requests, statuses); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(rlength, trials, timers); return 0; } -static int irecv_isend_wait(int cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, +static int irecv_isend_wait(int num_cycles, MPI_Datatype sdt, int scount, void *sbuf, MPI_Datatype rdt, int rcount, void *rbuf) { int myself, tag = 0, c, t, slength, rlength; @@ -425,12 +425,12 @@ static int irecv_isend_wait(int cycles, MPI_Datatype sdt, int scount, void *sbuf for (t = 0; t < trials; t++) { timers[t] = MPI_Wtime(); - for (c = 0; c < cycles; c++) { + for (c = 0; c < num_cycles; c++) { MPI_Irecv(rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &requests[0]); MPI_Isend(sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &requests[1]); MPI_Waitall(2, requests, statuses); } - timers[t] = (MPI_Wtime() - timers[t]) / cycles; + timers[t] = (MPI_Wtime() - timers[t]) / num_cycles; } print_result(rlength, trials, timers); return 0; From b8338de166b69bf1018a4ae9ea3d1f5634aea16d Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Thu, 23 Apr 2026 10:54:19 -0700 Subject: [PATCH 040/230] ci: Add FreeBSD test Signed-off-by: Brian Barrett --- .ci/community-jenkins/Jenkinsfile | 1 + .ci/community-jenkins/pr-builder.sh | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.ci/community-jenkins/Jenkinsfile b/.ci/community-jenkins/Jenkinsfile index 2c20d630ac1..bf1bb6ce67e 100644 --- a/.ci/community-jenkins/Jenkinsfile +++ b/.ci/community-jenkins/Jenkinsfile @@ -71,6 +71,7 @@ def prepare_check_stages() { "rhel8", "amazon_linux_2023-arm64", "amazon_linux_2023-x86_64", + "freebsd_15", "ubuntu_20.04", "ubuntu_24.04-arm64", "ubuntu_24.04-x86_64" diff --git a/.ci/community-jenkins/pr-builder.sh b/.ci/community-jenkins/pr-builder.sh index 88426859bf0..53cb973af41 100755 --- a/.ci/community-jenkins/pr-builder.sh +++ b/.ci/community-jenkins/pr-builder.sh @@ -164,6 +164,12 @@ fi CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-silent-rules" +# Work around the fact that FreeBSD's hwloc package installs Ze and +# that breaks something in the cudasm path on FreeBSD. +if test "${PLATFORM_ID}" = "FreeBSD" ; then + CONFIGURE_ARGS="${CONFIGURE_ARGS} --without-ze" +fi + echo "--> Compiler setup: $CONFIGURE_ARGS" # From 4f54b388329df36b2cb37632b21a3e6d770c04b1 Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Thu, 30 Apr 2026 10:43:56 -0700 Subject: [PATCH 041/230] pml/ob1: add memory barriers to sendreq and recvreq lock/unlock on weakly-ordered architectures On weakly-ordered architectures (ARM64), the ob1 send and receive request locks (req_lock) use relaxed atomics without memory barriers. This allows the request completion path to race ahead of request processing when multiple threads are involved. For send requests, the failure mode is: Thread A holds the lock and runs schedule_once, processing a send range. Thread B handles a completion callback, decrements req_state to 0 via a relaxed atomic, acquires the lock (relaxed, no acquire barrier), and completes the request. The sendreq is returned to the free list with stale send ranges still linked, causing an infinite loop in schedule_once when the sendreq is recycled. For receive requests, the same pattern applies: lock_recv_request and unlock_recv_request use identical relaxed atomics. A recvreq can be completed and recycled while another thread still holds a reference, leading to use-after-free crashes in recv_request_pml_complete. Add opal_atomic_wmb() before the relaxed atomic decrement in both unlock_send_request and unlock_recv_request to ensure all stores performed under the lock are visible before the lock is released. Add opal_atomic_rmb() after successful lock acquisition in both lock_send_request and lock_recv_request to ensure the new holder sees all stores from the previous holder. This follows the established OMPI pattern of caller-imposed barriers around relaxed atomic primitives, consistent with the approach in d373a953a6 ("request: add memory barriers for sync struct handoff on weakly-ordered architectures"). Observed as a deadlock (sendreq) and segfault (recvreq) under MPI_THREAD_MULTIPLE on ARM64 (Graviton4) clusters. Signed-off-by: Brett Kleinschmidt --- ompi/mca/pml/ob1/pml_ob1_recvreq.h | 5 ++++- ompi/mca/pml/ob1/pml_ob1_sendreq.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ompi/mca/pml/ob1/pml_ob1_recvreq.h b/ompi/mca/pml/ob1/pml_ob1_recvreq.h index a266e3388bb..c93a322515d 100644 --- a/ompi/mca/pml/ob1/pml_ob1_recvreq.h +++ b/ompi/mca/pml/ob1/pml_ob1_recvreq.h @@ -65,11 +65,14 @@ OBJ_CLASS_DECLARATION(mca_pml_ob1_recv_request_t); static inline bool lock_recv_request(mca_pml_ob1_recv_request_t *recvreq) { - return OPAL_THREAD_ADD_FETCH32(&recvreq->req_lock, 1) == 1; + bool ret = OPAL_THREAD_ADD_FETCH32(&recvreq->req_lock, 1) == 1; + opal_atomic_rmb(); + return ret; } static inline bool unlock_recv_request(mca_pml_ob1_recv_request_t *recvreq) { + opal_atomic_wmb(); return OPAL_THREAD_ADD_FETCH32(&recvreq->req_lock, -1) == 0; } diff --git a/ompi/mca/pml/ob1/pml_ob1_sendreq.h b/ompi/mca/pml/ob1/pml_ob1_sendreq.h index e9946e90528..494cde155d6 100644 --- a/ompi/mca/pml/ob1/pml_ob1_sendreq.h +++ b/ompi/mca/pml/ob1/pml_ob1_sendreq.h @@ -79,11 +79,14 @@ OBJ_CLASS_DECLARATION(mca_pml_ob1_send_range_t); static inline bool lock_send_request(mca_pml_ob1_send_request_t *sendreq) { - return OPAL_THREAD_ADD_FETCH32(&sendreq->req_lock, 1) == 1; + bool ret = OPAL_THREAD_ADD_FETCH32(&sendreq->req_lock, 1) == 1; + opal_atomic_rmb(); + return ret; } static inline bool unlock_send_request(mca_pml_ob1_send_request_t *sendreq) { + opal_atomic_wmb(); return OPAL_THREAD_ADD_FETCH32(&sendreq->req_lock, -1) == 0; } From 38bc508b08a3e80b162897a98990dea3bcea87b8 Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Wed, 25 Mar 2026 10:27:36 -0700 Subject: [PATCH 042/230] pml/ob1: add release barriers at unlocked completion paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On weakly-ordered architectures (ARM64), ob1 completion paths that bypass the request lock perform relaxed atomic writes to req_state, req_bytes_delivered, req_bytes_received, or req_pipeline_depth, then immediately call send_request_pml_complete_check or recv_request_pml_complete_check. Without a release barrier before the atomic update, another thread's complete_check (which has an acquire barrier from commit 0b0f9d14aa6, 2007) may observe the updated counter but not the preceding stores — leading to request recycling with stale internal state. Add opal_atomic_wmb() before each OPAL_THREAD_ADD_FETCH or pml_complete_check call at the following unlocked sites: sendreq.c: rndv_completion_request, mca_pml_ob1_rget_completion, mca_pml_ob1_frag_completion, mca_pml_ob1_put_completion, mca_pml_ob1_send_request_put recvreq.c: mca_pml_ob1_put_completion, mca_pml_ob1_rget_completion, mca_pml_ob1_recv_request_progress_frag, mca_pml_ob1_recv_request_frag_copy_finished, mca_pml_ob1_recv_request_progress_rndv recvfrag.c: mca_pml_ob1_recv_frag_callback_ack These pair with the existing opal_atomic_rmb() at the top of send_request_pml_complete_check and recv_request_pml_complete_check. On ARM64, wmb compiles to dmb st and rmb to dmb ld, which together establish cross-thread visibility through the relaxed atomic intermediary. On x86 (TSO), both are no-ops. Also removes a TODO comment ("TODO -- read ordering") in mca_pml_ob1_put_completion that identified this exact missing barrier since 2016 (commit 1e2019ce2a9). Observed as segfaults and infinite loops under MPI_THREAD_MULTIPLE on 128-rank Graviton4 (ARM64) clusters after deploying the lock ordering fix, which masked these unlocked paths. Related to #13761, #12011, #11999 Signed-off-by: Brett Kleinschmidt --- ompi/mca/pml/ob1/pml_ob1_recvfrag.c | 4 ++++ ompi/mca/pml/ob1/pml_ob1_recvreq.c | 15 +++++++++++++++ ompi/mca/pml/ob1/pml_ob1_sendreq.c | 19 ++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ompi/mca/pml/ob1/pml_ob1_recvfrag.c b/ompi/mca/pml/ob1/pml_ob1_recvfrag.c index 8e1d4d2e0cf..3445c45188a 100644 --- a/ompi/mca/pml/ob1/pml_ob1_recvfrag.c +++ b/ompi/mca/pml/ob1/pml_ob1_recvfrag.c @@ -768,6 +768,10 @@ void mca_pml_ob1_recv_frag_callback_ack (mca_btl_base_module_t *btl, sendreq->req_send.req_base.req_convertor.stream = stream; } + /* ensure all prior stores (copy_in_out, rdma_frag, throttle_sends, + * req_state, accelerator flags) are visible before complete_check + * may recycle the request */ + opal_atomic_wmb(); if (send_request_pml_complete_check(sendreq) == false) mca_pml_ob1_send_request_schedule(sendreq); } diff --git a/ompi/mca/pml/ob1/pml_ob1_recvreq.c b/ompi/mca/pml/ob1/pml_ob1_recvreq.c index a6a2866f2a2..74c8113ff7a 100644 --- a/ompi/mca/pml/ob1/pml_ob1_recvreq.c +++ b/ompi/mca/pml/ob1/pml_ob1_recvreq.c @@ -228,6 +228,9 @@ static void mca_pml_ob1_put_completion (mca_pml_ob1_rdma_frag_t *frag, int64_t r if (OPAL_LIKELY(0 < rdma_size)) { + /* ensure pipeline_depth and frag cleanup are visible before + * bytes_received update that complete_check observes */ + opal_atomic_wmb(); /* check completion status */ OPAL_THREAD_ADD_FETCH_SIZE_T(&recvreq->req_bytes_received, rdma_size); SPC_USER_OR_MPI(recvreq->req_recv.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)rdma_size, @@ -443,6 +446,9 @@ static void mca_pml_ob1_rget_completion (mca_btl_base_module_t* btl, struct mca_ MCA_PML_OB1_RDMA_FRAG_RETURN(frag); } + /* ensure all prior stores (bytes_received, error status, frag cleanup) + * are visible before complete_check may recycle the request */ + opal_atomic_wmb(); recv_request_pml_complete_check(recvreq); MCA_PML_OB1_PROGRESS_PENDING(bml_btl); @@ -596,6 +602,9 @@ void mca_pml_ob1_recv_request_progress_frag( mca_pml_ob1_recv_request_t* recvreq recvreq->req_recv.req_base.req_datatype); ); + /* ensure unpack stores are visible before bytes_received update + * that complete_check observes */ + opal_atomic_wmb(); OPAL_THREAD_ADD_FETCH_SIZE_T(&recvreq->req_bytes_received, bytes_received); SPC_USER_OR_MPI(recvreq->req_recv.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)bytes_received, OMPI_SPC_BYTES_RECEIVED_USER, OMPI_SPC_BYTES_RECEIVED_MPI); @@ -674,6 +683,9 @@ void mca_pml_ob1_recv_request_frag_copy_finished( mca_btl_base_module_t* btl, * known that the data has been copied out of the descriptor. */ des->des_cbfunc(NULL, NULL, des, 0); + /* ensure copy and descriptor cleanup are visible before + * bytes_received update that complete_check observes */ + opal_atomic_wmb(); OPAL_THREAD_ADD_FETCH_SIZE_T(&recvreq->req_bytes_received, bytes_received); SPC_USER_OR_MPI(recvreq->req_recv.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)bytes_received, OMPI_SPC_BYTES_RECEIVED_USER, OMPI_SPC_BYTES_RECEIVED_MPI); @@ -887,6 +899,9 @@ void mca_pml_ob1_recv_request_progress_rndv( mca_pml_ob1_recv_request_t* recvreq SPC_USER_OR_MPI(recvreq->req_recv.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)bytes_received, OMPI_SPC_BYTES_RECEIVED_USER, OMPI_SPC_BYTES_RECEIVED_MPI); } + /* ensure all prior stores (unpack, match, bytes_received) are visible + * before complete_check may recycle the request */ + opal_atomic_wmb(); /* check completion status */ if(recv_request_pml_complete_check(recvreq) == false && recvreq->req_rdma_offset < recvreq->req_send_offset) { diff --git a/ompi/mca/pml/ob1/pml_ob1_sendreq.c b/ompi/mca/pml/ob1/pml_ob1_sendreq.c index 0dd246917c0..f40dff6ce89 100644 --- a/ompi/mca/pml/ob1/pml_ob1_sendreq.c +++ b/ompi/mca/pml/ob1/pml_ob1_sendreq.c @@ -261,6 +261,10 @@ mca_pml_ob1_rndv_completion_request( mca_bml_base_btl_t* bml_btl, SPC_USER_OR_MPI(sendreq->req_send.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)req_bytes_delivered, OMPI_SPC_BYTES_SENT_USER, OMPI_SPC_BYTES_SENT_MPI); + /* ensure bytes_delivered is visible before req_state update, so that + * another thread's complete_check sees consistent state */ + opal_atomic_wmb(); + /* advance the request */ OPAL_THREAD_ADD_FETCH32(&sendreq->req_state, -1); @@ -360,6 +364,9 @@ mca_pml_ob1_rget_completion (mca_pml_ob1_rdma_frag_t *frag, int64_t rdma_length) MCA_PML_OB1_RDMA_FRAG_RETURN(frag); } + /* ensure all prior stores (bytes_delivered, rdma_frag, error status) + * are visible before complete_check may recycle the request */ + opal_atomic_wmb(); send_request_pml_complete_check(sendreq); if( OPAL_LIKELY(0 < rdma_length) ) { @@ -440,6 +447,9 @@ mca_pml_ob1_frag_completion( mca_btl_base_module_t* btl, sizeof(mca_pml_ob1_frag_hdr_t)); } + /* ensure prior non-atomic stores (e.g. error status) are visible + * before atomic updates that complete_check will observe */ + opal_atomic_wmb(); OPAL_THREAD_ADD_FETCH32(&sendreq->req_pipeline_depth, -1); OPAL_THREAD_ADD_FETCH_SIZE_T(&sendreq->req_bytes_delivered, req_bytes_delivered); SPC_USER_OR_MPI(sendreq->req_send.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)req_bytes_delivered, @@ -1318,11 +1328,13 @@ static void mca_pml_ob1_put_completion (mca_btl_base_module_t* btl, struct mca_b /* check completion status */ if( OPAL_UNLIKELY(OMPI_SUCCESS == status) ) { - /* TODO -- read ordering */ mca_pml_ob1_send_fin (sendreq->req_send.req_base.req_proc, bml_btl, frag->rdma_hdr.hdr_rdma.hdr_frag, frag->rdma_length, 0, 0); + /* ensure send_fin stores are visible before bytes_delivered + * update that complete_check observes */ + opal_atomic_wmb(); /* check for request completion */ OPAL_THREAD_ADD_FETCH_SIZE_T(&sendreq->req_bytes_delivered, frag->rdma_length); SPC_USER_OR_MPI(sendreq->req_send.req_base.req_ompi.req_status.MPI_TAG, (ompi_spc_value_t)frag->rdma_length, @@ -1411,6 +1423,7 @@ void mca_pml_ob1_send_request_put (mca_pml_ob1_send_request_t *sendreq, mca_pml_ob1_rdma_frag_t* frag; if(hdr->hdr_common.hdr_flags & MCA_PML_OB1_HDR_TYPE_ACK) { + opal_atomic_wmb(); /* ensure prior stores visible before req_state update */ OPAL_THREAD_ADD_FETCH32(&sendreq->req_state, -1); } @@ -1434,6 +1447,10 @@ void mca_pml_ob1_send_request_put (mca_pml_ob1_send_request_t *sendreq, /* rget fallback on put */ frag = sendreq->rdma_frag; sendreq->rdma_frag = NULL; + /* ensure rdma_frag = NULL is visible before req_state signals + * completion — plain store of 0 is the completion trigger that + * complete_check observes */ + opal_atomic_wmb(); sendreq->req_state = 0; } From 26cb66488e127e9c76915605bfc8882789570ae0 Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Thu, 30 Apr 2026 11:00:07 -0700 Subject: [PATCH 043/230] pml/ob1: drain stale send ranges on sendreq reuse send_request_start_seq does not clear req_send_ranges when a sendreq is recycled from the free list. Stale ranges with all range_btls[].length == 0 cause schedule_once to spin forever. Drain any leftover ranges back to the send_ranges free list at the start of each new sendreq lifecycle, guarded by OPAL_UNLIKELY for zero overhead in the common case. Fixes: infinite loop in schedule_once with data_remaining > 0, size = 0 Refs: #13761, #12011, #11999 Signed-off-by: Brett Kleinschmidt --- ompi/mca/pml/ob1/pml_ob1_sendreq.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ompi/mca/pml/ob1/pml_ob1_sendreq.h b/ompi/mca/pml/ob1/pml_ob1_sendreq.h index 494cde155d6..6d2a8b09d13 100644 --- a/ompi/mca/pml/ob1/pml_ob1_sendreq.h +++ b/ompi/mca/pml/ob1/pml_ob1_sendreq.h @@ -471,6 +471,17 @@ mca_pml_ob1_send_request_start_seq (mca_pml_ob1_send_request_t* sendreq, mca_bml sendreq->req_pending = MCA_PML_OB1_SEND_PENDING_NONE; sendreq->req_send.req_base.req_sequence = seqn; + /* drain any stale send ranges left from a previous lifecycle; + * not protected by a lock as the sendreq is owned exclusively + * by the current thread at this point in the lifecycle. */ + if (OPAL_UNLIKELY(!opal_list_is_empty(&sendreq->req_send_ranges))) { + opal_list_item_t *item; + OPAL_OUTPUT_VERBOSE((1, mca_pml_ob1_output, "stale send ranges on reused sendreq")); + while (NULL != (item = opal_list_remove_first(&sendreq->req_send_ranges))) { + opal_free_list_return(&mca_pml_ob1.send_ranges, (opal_free_list_item_t *)item); + } + } + MCA_PML_BASE_SEND_START( &sendreq->req_send ); for(size_t i = 0; i < mca_bml_base_btl_array_get_size(&endpoint->btl_eager); i++) { From 15d49d570cb34b83bc0fbfc02f61c8e34a3a1a2e Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Fri, 17 Apr 2026 07:57:00 -0700 Subject: [PATCH 044/230] pml/ob1: fix memory barrier placement in recv_req_matched recv_req_matched() sets req_match_received = true before the wmb, allowing the flag to be visible to other threads before the stores it gates (req_bytes_packed, MPI_SOURCE, MPI_TAG) on weakly-ordered architectures. recv_request_pml_complete_check() uses req_match_received as the gate for evaluating req_bytes_received >= req_bytes_packed. When req_match_received is visible before req_bytes_packed, complete_check can read a stale req_bytes_packed from a previous request lifecycle, causing a spurious MPI_ERR_TRUNCATE in recv_request_pml_complete(). Move the wmb before the store to req_match_received so that all prior stores (req_bytes_packed, MPI_SOURCE, MPI_TAG) are visible before the flag signals complete_check. This pairs with the existing rmb at the top of recv_request_pml_complete_check(). Observed as intermittent MPI_ERR_TRUNCATE on MPI_Mrecv on ARM64 (Graviton 4) clusters under production workloads. Signed-off-by: Brett Kleinschmidt --- ompi/mca/pml/ob1/pml_ob1_recvreq.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ompi/mca/pml/ob1/pml_ob1_recvreq.h b/ompi/mca/pml/ob1/pml_ob1_recvreq.h index c93a322515d..558975c2597 100644 --- a/ompi/mca/pml/ob1/pml_ob1_recvreq.h +++ b/ompi/mca/pml/ob1/pml_ob1_recvreq.h @@ -250,9 +250,10 @@ static inline void recv_req_matched(mca_pml_ob1_recv_request_t *req, { req->req_recv.req_base.req_ompi.req_status.MPI_SOURCE = hdr->hdr_src; req->req_recv.req_base.req_ompi.req_status.MPI_TAG = hdr->hdr_tag; - req->req_match_received = true; - + /* ensure MPI_SOURCE, MPI_TAG, and req_bytes_packed (set by caller) + * are visible before req_match_received signals complete_check */ opal_atomic_wmb(); + req->req_match_received = true; if(req->req_recv.req_bytes_packed > 0) { #if OPAL_ENABLE_HETEROGENEOUS_SUPPORT From c2516c7d019afd76d3c7dda46e7848708bd750f3 Mon Sep 17 00:00:00 2001 From: Brett Kleinschmidt Date: Tue, 28 Apr 2026 12:00:00 -0700 Subject: [PATCH 045/230] pml/ob1: clear req_match_received during mrecv/imrecv reinit mca_pml_ob1_mrecv and mca_pml_ob1_imrecv reinitialize the recv request for reuse after Mprobe but do not clear req_match_received. The field stays true from the Mprobe phase. recv_request_pml_complete_check gates on req_match_received && (req_bytes_received >= req_bytes_packed). After reinit zeros both counters the stale true lets complete_check pass on any concurrent thread (0 >= 0), causing a premature recv_request_pml_complete before progress_match/progress_rndv has run. The concurrent thread reaches the request through a stale rdma_req pointer from a previous lifecycle of the same recvreq (recycled via the free list). Clear req_match_received in both mrecv and imrecv reinit, consistent with recv_req_start. Add wmb to pair with the rmb at the top of recv_request_pml_complete_check. Also add the missing req_ack_sent = false to mrecv, matching imrecv. Observed as intermittent deadlock on ARM64 (i4g.8xlarge) under MPI_THREAD_MULTIPLE with 4 ranks per node. Signed-off-by: Brett Kleinschmidt --- ompi/mca/pml/ob1/pml_ob1_irecv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ompi/mca/pml/ob1/pml_ob1_irecv.c b/ompi/mca/pml/ob1/pml_ob1_irecv.c index 4ccb8ea00f2..7c2e89c2fb8 100644 --- a/ompi/mca/pml/ob1/pml_ob1_irecv.c +++ b/ompi/mca/pml/ob1/pml_ob1_irecv.c @@ -233,6 +233,9 @@ mca_pml_ob1_imrecv( void *buf, recvreq->req_rdma_idx = 0; recvreq->req_pending = false; recvreq->req_ack_sent = false; + recvreq->req_match_received = false; + /* release: pair with rmb in recv_request_pml_complete_check */ + opal_atomic_wmb(); MCA_PML_BASE_RECV_START(&recvreq->req_recv); @@ -325,6 +328,10 @@ mca_pml_ob1_mrecv( void *buf, recvreq->req_rdma_cnt = 0; recvreq->req_rdma_idx = 0; recvreq->req_pending = false; + recvreq->req_ack_sent = false; + recvreq->req_match_received = false; + /* release: pair with rmb in recv_request_pml_complete_check */ + opal_atomic_wmb(); MCA_PML_BASE_RECV_START(&recvreq->req_recv); From 2fca88e80681000faed7fa308b2a930e181571f4 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Thu, 30 Apr 2026 15:00:22 -0600 Subject: [PATCH 046/230] PMIX: advance sha to dbe39f0e to pick up cornelis OPA support etc. Signed-off-by: Howard Pritchard --- 3rd-party/openpmix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd-party/openpmix b/3rd-party/openpmix index 61bd925224e..dbe39f0ecd5 160000 --- a/3rd-party/openpmix +++ b/3rd-party/openpmix @@ -1 +1 @@ -Subproject commit 61bd925224ee512041dea591eacc0d675cfea22e +Subproject commit dbe39f0ecd5d21ead734ed65d01b4cf81158af68 From 2ee493df7f4513118f9f8eebfa8be573b4d65ba3 Mon Sep 17 00:00:00 2001 From: Matthew Whitlock Date: Fri, 1 May 2026 10:34:02 -0600 Subject: [PATCH 047/230] btl/ofi try to identify/report failed procs when not identifiable from failed op's context Signed-off-by: Matthew Whitlock --- opal/mca/btl/ofi/btl_ofi.h | 2 + opal/mca/btl/ofi/btl_ofi_component.c | 4 +- opal/mca/btl/ofi/btl_ofi_context.c | 62 +++++++++++++++++++++------- opal/mca/btl/ofi/btl_ofi_endpoint.h | 4 +- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/opal/mca/btl/ofi/btl_ofi.h b/opal/mca/btl/ofi/btl_ofi.h index 20345d02c6b..085eee27471 100644 --- a/opal/mca/btl/ofi/btl_ofi.h +++ b/opal/mca/btl/ofi/btl_ofi.h @@ -80,7 +80,9 @@ enum mca_btl_ofi_hdr_type { MCA_BTL_OFI_TYPE_TOTAL }; +struct mca_btl_ofi_module_t; struct mca_btl_ofi_context_t { + struct mca_btl_ofi_module_t *btl; int32_t context_id; /* transmit context */ diff --git a/opal/mca/btl/ofi/btl_ofi_component.c b/opal/mca/btl/ofi/btl_ofi_component.c index 3f1e277dd69..744faa27fcc 100644 --- a/opal/mca/btl/ofi/btl_ofi_component.c +++ b/opal/mca/btl/ofi/btl_ofi_component.c @@ -625,7 +625,7 @@ static int mca_btl_ofi_init_device(struct fi_info *info) /* create contexts */ module->contexts = mca_btl_ofi_context_alloc_scalable(ofi_info, domain, ep, av, - num_contexts_to_create); + module, num_contexts_to_create); } else { /* warn the user if they want more than 1 context */ @@ -647,7 +647,7 @@ static int mca_btl_ofi_init_device(struct fi_info *info) module->is_scalable_ep = false; /* create contexts */ - module->contexts = mca_btl_ofi_context_alloc_normal(ofi_info, domain, ep, av); + module->contexts = mca_btl_ofi_context_alloc_normal(ofi_info, domain, ep, av, module); } if (NULL == module->contexts) { diff --git a/opal/mca/btl/ofi/btl_ofi_context.c b/opal/mca/btl/ofi/btl_ofi_context.c index 6a492d4382c..8bc3edd302c 100644 --- a/opal/mca/btl/ofi/btl_ofi_context.c +++ b/opal/mca/btl/ofi/btl_ofi_context.c @@ -62,7 +62,8 @@ static int init_context_freelists(mca_btl_ofi_context_t *context) * USE WITH NORMAL ENDPOINT ONLY */ mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_normal(struct fi_info *info, struct fid_domain *domain, - struct fid_ep *ep, struct fid_av *av) + struct fid_ep *ep, struct fid_av *av, + struct mca_btl_ofi_module_t *btl) { int rc; uint32_t cq_flags = FI_TRANSMIT | FI_SEND | FI_RECV; @@ -115,6 +116,7 @@ mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_normal(struct fi_info *info, context->tx_ctx = ep; context->rx_ctx = ep; context->context_id = 0; + context->btl = btl; my_context = NULL; return context; @@ -132,6 +134,7 @@ mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_normal(struct fi_info *info, mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_scalable(struct fi_info *info, struct fid_domain *domain, struct fid_ep *sep, struct fid_av *av, + struct mca_btl_ofi_module_t* btl, size_t num_contexts) { BTL_VERBOSE(("creating %zu contexts", num_contexts)); @@ -234,6 +237,7 @@ mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_scalable(struct fi_info *info, /* assign the id */ contexts[i].context_id = i; + contexts[i].btl = btl; } return contexts; @@ -387,34 +391,60 @@ int mca_btl_ofi_context_progress(mca_btl_ofi_context_t *context) BTL_ERROR(("%s:%d: Error returned from fi_cq_readerr: %s(%d)", __FILE__, __LINE__, fi_strerror(-ret), ret)); MCA_BTL_OFI_ABORT(); - } else if(NULL != cqerr.op_context){ + } else { switch(cqerr.err) { case FI_EREMOTEIO: case FI_EHOSTUNREACH: case FI_ECONNABORTED: case FI_ECONNRESET: + case FI_ENOTCONN: #ifdef FI_EHOSTDOWN // FI_EHOSTDOWN added in libfabric 1.6.0 case FI_EHOSTDOWN: #endif case FI_EIO: { - mca_btl_ofi_completion_context_t *c_ctx = - (mca_btl_ofi_completion_context_t*) cqerr.op_context; - mca_btl_ofi_base_completion_t *comp = - (mca_btl_ofi_base_completion_t*) c_ctx->comp; - mca_btl_ofi_module_t *ofi_btl = - (mca_btl_ofi_module_t*) comp->btl; - if(ofi_btl->ofi_error_cb){ - opal_proc_t *ep_proc = NULL; - if(comp->endpoint){ - ep_proc = comp->endpoint->ep_proc; + if (context->btl->ofi_error_cb) { + opal_proc_t* proc = NULL; + if (NULL != cqerr.op_context) { + mca_btl_ofi_completion_context_t *c_ctx = + (mca_btl_ofi_completion_context_t*) cqerr.op_context; + mca_btl_ofi_base_completion_t *comp = + (mca_btl_ofi_base_completion_t*) c_ctx->comp; + if (NULL != comp->endpoint) { + proc = comp->endpoint->ep_proc; + } } - ofi_btl->ofi_error_cb(comp->btl, 0, ep_proc, - "IO error reported by libfabric"); +#if (FI_MAJOR_VERSION > 1) || ((FI_MAJOR_VERSION > 0) && (FI_MINOR_VERSION >= 20)) + // Starting with v1.20, cqerr provides an fi_addr_t + if (NULL == proc) { + mca_btl_ofi_endpoint_t *ep = NULL; + OPAL_LIST_FOREACH(ep, &context->btl->endpoints, mca_btl_ofi_endpoint_t){ + if (ep->peer_addr == cqerr.src_addr) { + proc = ep->ep_proc; + break; + } + } + } +#endif + const char* base_str = "IO error reported by libfabric: "; + const char* fi_str = fi_strerror(cqerr.err); + size_t base_len = strlen(base_str); + size_t fi_len = strlen(fi_str); + char* err_str = malloc(base_len + fi_len + 1); + for(size_t i = 0; i < base_len; i++) err_str[i] = base_str[i]; + for(size_t i = 0; i < fi_len; i++) err_str[i+base_len] = fi_str[i]; + err_str[base_len+fi_len] = '\0'; + if (cqerr.op_context || proc) { + // Report any errors linked to an operation or known proc + context->btl->ofi_error_cb(&context->btl->super, 0, proc, err_str); + } + free(err_str); } - ++events; - complete_op_context(context, cqerr.op_context, OPAL_ERR_UNREACH); + if (NULL != cqerr.op_context) { + ++events; + complete_op_context(context, cqerr.op_context, OPAL_ERR_UNREACH); + } break; } default: diff --git a/opal/mca/btl/ofi/btl_ofi_endpoint.h b/opal/mca/btl/ofi/btl_ofi_endpoint.h index f6b420273af..088330fe04f 100644 --- a/opal/mca/btl/ofi/btl_ofi_endpoint.h +++ b/opal/mca/btl/ofi/btl_ofi_endpoint.h @@ -57,11 +57,13 @@ mca_btl_base_endpoint_t *mca_btl_ofi_endpoint_create(opal_proc_t *proc, struct f mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_scalable(struct fi_info *info, struct fid_domain *domain, struct fid_ep *sep, struct fid_av *av, + struct mca_btl_ofi_module_t *btl, size_t num_contexts); mca_btl_ofi_context_t *mca_btl_ofi_context_alloc_normal(struct fi_info *info, struct fid_domain *domain, - struct fid_ep *ep, struct fid_av *av); + struct fid_ep *ep, struct fid_av *av, + struct mca_btl_ofi_module_t *btl); void mca_btl_ofi_context_finalize(mca_btl_ofi_context_t *context, bool scalable_ep); mca_btl_ofi_context_t *get_ofi_context(mca_btl_ofi_module_t *btl); From 41b1150c3fa008082d8634593210b68446c5a075 Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Mon, 4 May 2026 12:21:31 -0700 Subject: [PATCH 048/230] Revert "ci/backport: fix slash command permission check and update github-script" GitHub does not trigger actions on triggers that were created by the GITHUB_TOKEN of an action. Meaning that any PR created by this bot won't have any of our GitHub Actions CI run on it. Reverting until we can find a better solution. This reverts commit 0add05da4ff5d0d2a6dfcf15303e77757af6c363. Signed-off-by: Brian Barrett --- .github/workflows/backport-command.yaml | 107 ++++++++++++++++-------- .github/workflows/backport.yaml | 12 +-- 2 files changed, 78 insertions(+), 41 deletions(-) diff --git a/.github/workflows/backport-command.yaml b/.github/workflows/backport-command.yaml index 79378b17deb..c5738b2cd69 100644 --- a/.github/workflows/backport-command.yaml +++ b/.github/workflows/backport-command.yaml @@ -29,11 +29,12 @@ jobs: if: github.event.issue.pull_request != null permissions: actions: write # trigger workflow_dispatch - issues: write # post comments + issues: write # post reactions and comments + pull-requests: read # read PR merge status steps: - name: Parse command and validate PR id: parse - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | const body = context.payload.comment.body; @@ -41,22 +42,6 @@ jobs: const issueNumber = context.payload.issue.number; const login = context.payload.comment.user.login; - // Best-effort comment helper — if Issues are disabled on - // the repo (common for forks) the call returns 403 and we - // log a warning rather than aborting the workflow. - async function tryComment(text) { - try { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: text, - }); - } catch (err) { - core.warning(`Could not post comment: ${err.message}`); - } - } - // Detect a bare /backport with no arguments and reply helpfully. const bareMatch = /^\/backport\s*$/m.test(body); // Look for /backport with arguments at the start of any line. @@ -69,20 +54,43 @@ jobs: return; } - // Use author_association from the webhook payload — no extra - // API call required. GITHUB_TOKEN cannot call - // getCollaboratorPermissionLevel on org repos (needs org-level - // "Members" read permission unavailable to GITHUB_TOKEN). - const assoc = context.payload.comment.author_association; - if (!['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc)) { - await tryComment(`âš ī¸ @${login} Backports can only be triggered by repository owners, organization members, or collaborators.`); + // Check actual repository permission level rather than + // author_association: MEMBER alone does not imply write + // access on org-owned public repos. + let permission = 'none'; + try { + const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ + owner: context.repo.owner, + repo: context.repo.repo, + username: login, + }); + // Use role_name rather than permission: the legacy + // permission field collapses 'maintain' into 'write', + // losing the distinction between the two tiers. + permission = data.role_name; // 'admin' | 'maintain' | 'write' | 'triage' | 'read' + } catch (err) { + if (err.status !== 404) throw err; + // 404 = not a collaborator; permission stays 'none' + } + if (!['admin', 'maintain', 'write'].includes(permission)) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `âš ī¸ @${login} Backports can only be triggered by users with write, maintain, or admin access.`, + }); core.setOutput('triggered', 'false'); return; } if (bareMatch && !match) { core.setOutput('triggered', 'false'); - await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', + }); return; } if (!match) { @@ -95,7 +103,12 @@ jobs: if (branches.length === 0) { // e.g. "/backport ,,," — separators only, no real branch names core.setOutput('triggered', 'false'); - await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', + }); return; } @@ -106,21 +119,45 @@ jobs: const invalidBranches = branches.filter(b => !validBranchRe.test(b)); if (invalidBranches.length > 0) { core.setOutput('triggered', 'false'); - await tryComment(`âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`, + }); return; } // Confirm the PR is actually merged. - // merged_at is present in the issue_comment webhook payload - // for PRs, so no extra API call is needed. - if (!context.payload.issue.pull_request.merged_at) { - await tryComment('âš ī¸ Cannot backport: this PR has not been merged yet.'); + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: issueNumber, + }); + + if (!pr.merged) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: 'âš ī¸ Cannot backport: this PR has not been merged yet.', + }); core.setOutput('triggered', 'false'); return; } - // Acknowledge the command with a comment. - await tryComment(`👀 Dispatching backport of this PR to: ${branches.map(b => `\`${b}\``).join(', ')}.`); + // Acknowledge the command with a 👀 reaction. + // Ignore 422 (reaction already exists) so re-runs don't fail. + try { + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId, + content: 'eyes', + }); + } catch (err) { + if (err.status !== 422) throw err; + } core.setOutput('triggered', 'true'); core.setOutput('pr_number', String(issueNumber)); @@ -129,7 +166,7 @@ jobs: - name: Trigger backport workflow if: steps.parse.outputs.triggered == 'true' - uses: actions/github-script@v8 + uses: actions/github-script@v7 env: PR_NUMBER: ${{ steps.parse.outputs.pr_number }} BRANCHES: ${{ steps.parse.outputs.branches }} diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml index 724f678707b..ebff4e66ace 100644 --- a/.github/workflows/backport.yaml +++ b/.github/workflows/backport.yaml @@ -54,7 +54,7 @@ jobs: steps: - name: Determine backport targets id: targets - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | let branches = []; @@ -137,7 +137,7 @@ jobs: # Use paginate() so PRs with more than 100 commits are handled correctly. - name: Fetch PR metadata id: pr_meta - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | const pr = await github.rest.pulls.get({ @@ -163,7 +163,7 @@ jobs: # work. Post a comment and skip if it does not. - name: Validate target branch exists id: validate - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | try { @@ -264,7 +264,7 @@ jobs: # All commits were already present in the target branch — no PR needed. - name: Comment when nothing to backport if: steps.cherry_pick.outputs.nothing_to_backport == 'true' - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | await github.rest.issues.createComment({ @@ -280,7 +280,7 @@ jobs: if: >- steps.cherry_pick.outputs.cherry_pick_failed == 'false' && steps.cherry_pick.outputs.nothing_to_backport == 'false' - uses: actions/github-script@v8 + uses: actions/github-script@v7 env: ORIGINAL_TITLE: ${{ steps.pr_meta.outputs.title }} ORIGINAL_BODY: ${{ steps.pr_meta.outputs.body }} @@ -348,7 +348,7 @@ jobs: # developer knows to create the backport manually. - name: Comment on cherry-pick failure if: steps.cherry_pick.outputs.cherry_pick_failed == 'true' - uses: actions/github-script@v8 + uses: actions/github-script@v7 env: FAILED_SHA: ${{ steps.cherry_pick.outputs.failed_sha }} with: From 2d8342d4dcfcc7a34a6d9bc143e7b2ee05eb7790 Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Mon, 4 May 2026 12:21:36 -0700 Subject: [PATCH 049/230] Revert "GitHub Actions: add backport workflows" GitHub does not trigger actions on triggers that were created by the GITHUB_TOKEN of an action. Meaning that any PR created by this bot won't have any of our GitHub Actions CI run on it. Reverting until we can find a better solution. This reverts commit 910a394363f9c6368727b2d1e5fe57c72161d412. Signed-off-by: Brian Barrett --- .github/workflows/backport-command.yaml | 190 ------------ .github/workflows/backport.yaml | 379 ------------------------ 2 files changed, 569 deletions(-) delete mode 100644 .github/workflows/backport-command.yaml delete mode 100644 .github/workflows/backport.yaml diff --git a/.github/workflows/backport-command.yaml b/.github/workflows/backport-command.yaml deleted file mode 100644 index c5738b2cd69..00000000000 --- a/.github/workflows/backport-command.yaml +++ /dev/null @@ -1,190 +0,0 @@ -# Slash-command handler for /backport. -# -# Posting a comment on a merged PR with: -# -# /backport v5.0.x v4.1.x -# -# is equivalent to manually triggering the "Backport" workflow from the -# GitHub Actions UI with those branch names. Multiple branches may be -# supplied as space- or comma-separated values on the same line. -# -# Only users with write, maintain, or admin access to the repository may -# trigger the command. If an unauthorized user attempts /backport, the bot -# replies with an explanatory comment. For valid commands it acknowledges -# with a 👀 reaction; invalid or unrecognised commands get a usage hint. - -name: Backport slash command - -on: - issue_comment: - types: [created] - -permissions: {} - -jobs: - dispatch: - name: Handle /backport comment - runs-on: ubuntu-latest - # Only act on PR comments (issue_comment fires for both issues and PRs). - if: github.event.issue.pull_request != null - permissions: - actions: write # trigger workflow_dispatch - issues: write # post reactions and comments - pull-requests: read # read PR merge status - steps: - - name: Parse command and validate PR - id: parse - uses: actions/github-script@v7 - with: - script: | - const body = context.payload.comment.body; - const commentId = context.payload.comment.id; - const issueNumber = context.payload.issue.number; - const login = context.payload.comment.user.login; - - // Detect a bare /backport with no arguments and reply helpfully. - const bareMatch = /^\/backport\s*$/m.test(body); - // Look for /backport with arguments at the start of any line. - const match = body.match(/^\/backport\s+([^\r\n]+)/m); - - // If the comment doesn't contain any /backport command at all, - // do nothing — no need to check permissions. - if (!bareMatch && !match) { - core.setOutput('triggered', 'false'); - return; - } - - // Check actual repository permission level rather than - // author_association: MEMBER alone does not imply write - // access on org-owned public repos. - let permission = 'none'; - try { - const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ - owner: context.repo.owner, - repo: context.repo.repo, - username: login, - }); - // Use role_name rather than permission: the legacy - // permission field collapses 'maintain' into 'write', - // losing the distinction between the two tiers. - permission = data.role_name; // 'admin' | 'maintain' | 'write' | 'triage' | 'read' - } catch (err) { - if (err.status !== 404) throw err; - // 404 = not a collaborator; permission stays 'none' - } - if (!['admin', 'maintain', 'write'].includes(permission)) { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `âš ī¸ @${login} Backports can only be triggered by users with write, maintain, or admin access.`, - }); - core.setOutput('triggered', 'false'); - return; - } - - if (bareMatch && !match) { - core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', - }); - return; - } - if (!match) { - core.setOutput('triggered', 'false'); - return; - } - - // Parse branch list (space- or comma-separated). - const branches = match[1].trim().split(/[\s,]+/).filter(Boolean); - if (branches.length === 0) { - // e.g. "/backport ,,," — separators only, no real branch names - core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.', - }); - return; - } - - // Validate branch names with the same allow-list used in - // backport.yaml so the user gets immediate feedback rather - // than a silent dispatch failure. - const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; - const invalidBranches = branches.filter(b => !validBranchRe.test(b)); - if (invalidBranches.length > 0) { - core.setOutput('triggered', 'false'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`, - }); - return; - } - - // Confirm the PR is actually merged. - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: issueNumber, - }); - - if (!pr.merged) { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: 'âš ī¸ Cannot backport: this PR has not been merged yet.', - }); - core.setOutput('triggered', 'false'); - return; - } - - // Acknowledge the command with a 👀 reaction. - // Ignore 422 (reaction already exists) so re-runs don't fail. - try { - await github.rest.reactions.createForIssueComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: commentId, - content: 'eyes', - }); - } catch (err) { - if (err.status !== 422) throw err; - } - - core.setOutput('triggered', 'true'); - core.setOutput('pr_number', String(issueNumber)); - core.setOutput('branches', branches.join(',')); - core.notice(`Dispatching backport of PR #${issueNumber} to: ${branches.join(', ')}`); - - - name: Trigger backport workflow - if: steps.parse.outputs.triggered == 'true' - uses: actions/github-script@v7 - env: - PR_NUMBER: ${{ steps.parse.outputs.pr_number }} - BRANCHES: ${{ steps.parse.outputs.branches }} - with: - script: | - // workflow_dispatch requires a ref; use the default branch. - const { data: repo } = await github.rest.repos.get({ - owner: context.repo.owner, - repo: context.repo.repo, - }); - - await github.rest.actions.createWorkflowDispatch({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: 'backport.yaml', - ref: repo.default_branch, - inputs: { - pr_number: process.env.PR_NUMBER, - branches: process.env.BRANCHES, - }, - }); diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml deleted file mode 100644 index ebff4e66ace..00000000000 --- a/.github/workflows/backport.yaml +++ /dev/null @@ -1,379 +0,0 @@ -# Backport merged PRs to release branches. -# -# This workflow supports two modes: -# -# 1. Automatic (label-based): Apply one or more "backport:vX.Y.z" labels to a -# PR before merging. Once the PR is merged, this workflow fires and creates -# a cherry-pick PR for each labelled target branch. -# -# 2. Manual (workflow_dispatch): After a PR has already been merged, trigger -# this workflow manually via the GitHub Actions UI, providing the PR number -# and a comma-separated list of target branches. -# -# For every successful cherry-pick, a new PR is opened against the target -# branch and tagged with a "target:vX.Y.z" label. If the cherry-pick -# produces conflicts, a comment is posted on the original PR instead so a -# developer can handle it manually. - -name: Backport - -on: - pull_request_target: - types: [closed] - workflow_dispatch: - inputs: - pr_number: - description: 'Number of the merged PR to backport' - required: true - type: number - branches: - description: 'Target release branches (comma-separated, e.g. v5.0.x,v4.1.x)' - required: true - type: string - -permissions: {} - -jobs: - # ------------------------------------------------------------------------- - # Determine which branches need a backport and expose them as a matrix. - # ------------------------------------------------------------------------- - prepare: - name: Prepare backport targets - runs-on: ubuntu-latest - # For pull_request_target: only act when the PR was actually merged AND - # carries at least one "backport:" label (avoids a spurious job run on - # every other merge). For workflow_dispatch: always proceed. - if: > - github.event_name == 'workflow_dispatch' || - (github.event.pull_request.merged == true && - contains(toJson(github.event.pull_request.labels.*.name), '"backport:')) - outputs: - matrix: ${{ steps.targets.outputs.matrix }} - has_targets: ${{ steps.targets.outputs.has_targets }} - pr_number: ${{ steps.targets.outputs.pr_number }} - steps: - - name: Determine backport targets - id: targets - uses: actions/github-script@v7 - with: - script: | - let branches = []; - let prNumber; - - if (context.eventName === 'workflow_dispatch') { - prNumber = Number(context.payload.inputs.pr_number); - if (!Number.isFinite(prNumber) || prNumber <= 0 || !Number.isInteger(prNumber)) { - core.setFailed(`Invalid pr_number: "${context.payload.inputs.pr_number}"`); - return; - } - branches = context.payload.inputs.branches - .split(',') - .map(b => b.trim()) - .filter(Boolean); - } else { - prNumber = context.payload.pull_request.number; - const labels = context.payload.pull_request.labels.map(l => l.name); - for (const label of labels) { - const match = label.match(/^backport:(.+)$/); - if (match) { - branches.push(match[1].trim()); - } - } - } - - // Validate branch names with a strict allow-list: must start - // with alphanumeric and contain only alphanumeric, dot, - // hyphen, underscore, or slash. De-duplicate preserving order. - const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; - const invalid = branches.filter(b => !validBranchRe.test(b)); - if (invalid.length > 0) { - core.setFailed(`Invalid branch name(s): ${invalid.join(', ')}`); - return; - } - branches = [...new Set(branches)]; - - core.setOutput('pr_number', String(prNumber)); - core.setOutput('has_targets', branches.length > 0 ? 'true' : 'false'); - core.setOutput('matrix', JSON.stringify({ branch: branches })); - - if (branches.length === 0) { - core.notice('No backport targets found — nothing to do.'); - } else { - core.notice(`Will backport PR #${prNumber} to: ${branches.join(', ')}`); - } - - # ------------------------------------------------------------------------- - # One job per target branch. All branches run in parallel; a failure on - # one branch does not cancel the others. - # ------------------------------------------------------------------------- - backport: - name: Backport to ${{ matrix.branch }} - needs: prepare - if: needs.prepare.outputs.has_targets == 'true' - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - issues: write - strategy: - matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} - fail-fast: false - env: - PR_NUMBER: ${{ needs.prepare.outputs.pr_number }} - TARGET_BRANCH: ${{ matrix.branch }} - steps: - - name: Checkout repository (full history) - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Configure git identity - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - # Retrieve PR metadata (title, body, commit list) via the API. - # Use paginate() so PRs with more than 100 commits are handled correctly. - - name: Fetch PR metadata - id: pr_meta - uses: actions/github-script@v7 - with: - script: | - const pr = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: Number(process.env.PR_NUMBER), - }); - core.setOutput('title', pr.data.title); - // Body may be empty/null — default to empty string. - core.setOutput('body', pr.data.body ?? ''); - - // Collect all commit SHAs in merge order, paginating as needed. - const commits = await github.paginate(github.rest.pulls.listCommits, { - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: Number(process.env.PR_NUMBER), - per_page: 100, - }); - const shas = commits.map(c => c.sha); - core.setOutput('commits', shas.join(' ')); - - # Verify the target release branch actually exists before doing any - # work. Post a comment and skip if it does not. - - name: Validate target branch exists - id: validate - uses: actions/github-script@v7 - with: - script: | - try { - await github.rest.repos.getBranch({ - owner: context.repo.owner, - repo: context.repo.repo, - branch: process.env.TARGET_BRANCH, - }); - core.setOutput('branch_exists', 'true'); - } catch (err) { - if (err.status !== 404) throw err; - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: Number(process.env.PR_NUMBER), - body: `âš ī¸ Cannot backport to \`${process.env.TARGET_BRANCH}\`: branch does not exist in this repository.`, - }); - core.setOutput('branch_exists', 'false'); - } - - # Cherry-pick every commit from the PR onto a new branch based on - # the target release branch. Push the branch on success; set a - # flag on conflict so the next step can report the failure. - - name: Cherry-pick commits onto backport branch - id: cherry_pick - if: steps.validate.outputs.branch_exists == 'true' - env: - COMMITS: ${{ steps.pr_meta.outputs.commits }} - run: | - set -euo pipefail - - # Resolve a unique branch name. The counter handles the common - # case of re-running a backport; the push-retry below handles the - # rare race where two concurrent runs pick the same name. - git fetch --prune origin - # Fetch the PR's original commits so they are available locally - # regardless of how the PR was merged (squash, rebase, merge commit). - git fetch origin "refs/pull/${PR_NUMBER}/head" - BASE_BRANCH="backport/pr-${PR_NUMBER}-to-${TARGET_BRANCH}" - BACKPORT_BRANCH="${BASE_BRANCH}" - counter=1 - while git ls-remote --exit-code --heads origin "${BACKPORT_BRANCH}" > /dev/null 2>&1; do - counter=$((counter + 1)) - BACKPORT_BRANCH="${BASE_BRANCH}-${counter}" - done - echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" - - git fetch origin "${TARGET_BRANCH}" - git checkout -b "${BACKPORT_BRANCH}" "origin/${TARGET_BRANCH}" - - cherry_pick_failed=false - failed_sha="" - for sha in $COMMITS; do - echo "Cherry-picking ${sha} ..." - - # Detect merge commits (more than one parent) and cherry-pick - # relative to the first parent with -m 1. - parent_count=$(git cat-file -p "${sha}" | grep -c '^parent ' || true) - if [ "${parent_count}" -gt 1 ]; then - echo " Merge commit detected, using -m 1" - cherry_flags="-m 1" - else - cherry_flags="" - fi - - # --empty=drop silently skips commits already applied to the - # target branch rather than recording a no-op empty commit. - if ! git cherry-pick --empty=drop -x ${cherry_flags} "${sha}"; then - cherry_pick_failed=true - failed_sha="${sha}" - git cherry-pick --abort 2>/dev/null || true - break - fi - done - - echo "cherry_pick_failed=${cherry_pick_failed}" >> "$GITHUB_OUTPUT" - echo "failed_sha=${failed_sha}" >> "$GITHUB_OUTPUT" - - if [ "${cherry_pick_failed}" = "false" ]; then - # If every commit was already present in the target branch, - # cherry-pick dropped them all and HEAD hasn't moved. - new_commits=$(git rev-list --count "origin/${TARGET_BRANCH}..HEAD") - if [ "${new_commits}" -eq 0 ]; then - echo "nothing_to_backport=true" >> "$GITHUB_OUTPUT" - else - echo "nothing_to_backport=false" >> "$GITHUB_OUTPUT" - # Push; on a naming collision from a concurrent run, fall back - # to a name that includes the unique run ID. - if ! git push origin "${BACKPORT_BRANCH}" 2>/dev/null; then - BACKPORT_BRANCH="${BASE_BRANCH}-${GITHUB_RUN_ID}" - git branch -m "${BACKPORT_BRANCH}" - git push origin "${BACKPORT_BRANCH}" - echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" - fi - fi - fi - - # All commits were already present in the target branch — no PR needed. - - name: Comment when nothing to backport - if: steps.cherry_pick.outputs.nothing_to_backport == 'true' - uses: actions/github-script@v7 - with: - script: | - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: Number(process.env.PR_NUMBER), - body: `â„šī¸ All commits from this PR are already present in \`${process.env.TARGET_BRANCH}\` — no backport needed.`, - }); - core.notice(`Nothing to backport to ${process.env.TARGET_BRANCH} — all commits already present.`); - - # Open a PR against the target branch and attach the target:* label. - - name: Create backport PR - if: >- - steps.cherry_pick.outputs.cherry_pick_failed == 'false' && - steps.cherry_pick.outputs.nothing_to_backport == 'false' - uses: actions/github-script@v7 - env: - ORIGINAL_TITLE: ${{ steps.pr_meta.outputs.title }} - ORIGINAL_BODY: ${{ steps.pr_meta.outputs.body }} - BACKPORT_BRANCH: ${{ steps.cherry_pick.outputs.backport_branch }} - with: - script: | - const prNumber = Number(process.env.PR_NUMBER); - const targetBranch = process.env.TARGET_BRANCH; - const labelName = `target:${targetBranch}`; - - // Ensure the target:* label exists in this repo. - try { - await github.rest.issues.getLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: labelName, - }); - } catch (err) { - if (err.status === 404) { - try { - await github.rest.issues.createLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: labelName, - color: '0075ca', - description: `Backport targeting the ${targetBranch} branch`, - }); - } catch (createErr) { - // 422 = another concurrent job created the label first; safe to ignore. - if (createErr.status !== 422) throw createErr; - } - } else { - throw err; - } - } - - const title = `[${targetBranch}] ${process.env.ORIGINAL_TITLE}`; - const body = [ - `Backport of #${prNumber} to \`${targetBranch}\`.`, - '', - '---', - '', - process.env.ORIGINAL_BODY, - ].join('\n'); - - const { data: newPR } = await github.rest.pulls.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title, - body, - head: process.env.BACKPORT_BRANCH, - base: targetBranch, - }); - - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: newPR.number, - labels: [labelName], - }); - - core.notice(`Opened backport PR #${newPR.number}: ${newPR.html_url}`); - - # If cherry-pick failed, leave a comment on the original PR so a - # developer knows to create the backport manually. - - name: Comment on cherry-pick failure - if: steps.cherry_pick.outputs.cherry_pick_failed == 'true' - uses: actions/github-script@v7 - env: - FAILED_SHA: ${{ steps.cherry_pick.outputs.failed_sha }} - with: - script: | - const prNumber = Number(process.env.PR_NUMBER); - const targetBranch = process.env.TARGET_BRANCH; - const failedSha = process.env.FAILED_SHA; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: [ - `âš ī¸ **Automatic backport to \`${targetBranch}\` failed.**`, - '', - `Cherry-pick of commit ${failedSha} produced conflicts.`, - 'Please create the backport manually:', - '', - '```bash', - `git fetch origin ${targetBranch}`, - `git checkout -b backport/pr-${prNumber}-to-${targetBranch} origin/${targetBranch}`, - `git cherry-pick -x `, - `git push origin backport/pr-${prNumber}-to-${targetBranch}`, - '```', - ].join('\n'), - }); - - core.warning(`Cherry-pick to ${targetBranch} failed at ${failedSha} — manual backport required.`); From 53cb11b138346ece195f64dddf46c9cc50307940 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Tue, 5 May 2026 01:58:26 -0400 Subject: [PATCH 050/230] config: make m4 type-name sanitization locale-independent The macros OPAL_FIND_TYPE and OMPI_FORTRAN_CHECK constructed autoconf cache-variable and macro names by passing C/Fortran type strings through m4_bpatsubst([type], [[^a-zA-Z0-9_]], [_]) GNU m4's bpatsubst uses the system regex engine, whose bracket expressions honor locale collation. In locales that define multi-character collating elements (e.g. cs_CZ.UTF-8 treats the digraph "ch" as a single element), the negated class [^a-zA-Z0-9_] matches "ch" and replaces it with a single underscore. As a result the generated configure script tested $ac_cv_sizeof__ar instead of $ac_cv_sizeof_char, the lookup always failed, and the C type corresponding to Fortran CHARACTER was reported as not found. Replace the regex-based substitution with AS_TR_SH, whose literal path uses m4_translit and is locale-independent. Keep the inner m4_bpatsubst([$1], [*], []) that strips '*' from Fortran types (it has no ranges and is not affected) so the generated macro names (OMPI_HAVE_FORTRAN_INTEGER4 etc.) are unchanged. The same pattern exists in 3rd-party/prrte/config/prte_find_type.m4 and needs a matching fix upstream in PRRTE. Thanks @albandil for the bug report and initial solution Fixes #13861 Signed-off-by: George Bosilca --- config/ompi_fortran_check.m4 | 39 +++++++++++++++++++----------------- config/opal_find_type.m4 | 6 +++++- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/config/ompi_fortran_check.m4 b/config/ompi_fortran_check.m4 index 7fd2a790353..7646a7e6f06 100644 --- a/config/ompi_fortran_check.m4 +++ b/config/ompi_fortran_check.m4 @@ -161,9 +161,12 @@ AC_DEFUN([OMPI_FORTRAN_CHECK], [ # We always need these defines -- even if we don't have a given # type, there are some places in the code where we have to have - # *something*. Note that the bpatsubst's are the same as used - # above (see comment above), but we added a translit to make them - # uppercase. + # *something*. We strip '*' from the type name (e.g. INTEGER*4 -> + # INTEGER4) and then run AS_TR_SH to map any remaining non-symbol + # characters to '_'. AS_TR_SH is locale-safe; an earlier version + # used m4_bpatsubst with a regex character class, which mis-handled + # locales whose collation defines digraphs (e.g. cs_CZ.UTF-8 treats + # 'ch' as one element and would mangle "char" -> "_ar"). # If we got a pretty name, use that as the basis. If not, use the # first part of the provided fortran type (e.g., @@ -174,38 +177,38 @@ AC_DEFUN([OMPI_FORTRAN_CHECK], [ # the result of the BLUm4E in a shell variable and use that in # AC_DEFINE_UNQUOTED), autoheader won't put them in the # AC_CONFIG_HEADER (or AM_CONFIG_HEADER, in our case). - AC_DEFINE_UNQUOTED([OMPI_HAVE_FORTRAN_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [a-z], [A-Z]), + AC_DEFINE_UNQUOTED([OMPI_HAVE_FORTRAN_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [a-z], [A-Z]), [$ofc_have_type], [Whether we have Fortran $1 or not]) - AC_DEFINE_UNQUOTED([OMPI_SIZEOF_FORTRAN_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [a-z], [A-Z]), + AC_DEFINE_UNQUOTED([OMPI_SIZEOF_FORTRAN_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [a-z], [A-Z]), [$ofc_type_size], [Size of Fortran $1]) - AC_DEFINE_UNQUOTED([OMPI_ALIGNMENT_FORTRAN_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [a-z], [A-Z]), + AC_DEFINE_UNQUOTED([OMPI_ALIGNMENT_FORTRAN_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [a-z], [A-Z]), [$ofc_type_alignment], [Alignment of Fortran $1]) - AC_DEFINE_UNQUOTED([OMPI_KIND_FORTRAN_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [a-z], [A-Z]), + AC_DEFINE_UNQUOTED([OMPI_KIND_FORTRAN_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [a-z], [A-Z]), [$ofc_type_kind], [Fortran KIND number for $1]) if test "$3" != "" && test "$ofc_define_type" = "yes"; then - AC_DEFINE_UNQUOTED([ompi_fortran_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [A-Z], [a-z])[_t], + AC_DEFINE_UNQUOTED([ompi_fortran_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [A-Z], [a-z])[_t], [$ofc_c_type], [C type corresponding to Fortran $1]) fi # Save some in shell variables for later use (e.g., need # OMPI_SIZEOF_FORTRAN_INTEGER in OMPI_FORTRAN_GET_HANDLE_MAX) - [OMPI_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])[_C_TYPE=$ofc_c_type] - [OMPI_KIND_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])[=$ofc_type_kind] - [OMPI_HAVE_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])[=$ofc_have_type] - [OMPI_SIZEOF_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])[=$ofc_type_size] - [OMPI_ALIGNMENT_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])[=$ofc_type_alignment] + [OMPI_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))[_C_TYPE=$ofc_c_type] + [OMPI_KIND_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))[=$ofc_type_kind] + [OMPI_HAVE_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))[=$ofc_have_type] + [OMPI_SIZEOF_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))[=$ofc_type_size] + [OMPI_ALIGNMENT_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))[=$ofc_type_alignment] # Wow, this is sick. But it works! :-) - AC_SUBST([OMPI_HAVE_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])) - AC_SUBST([OMPI_KIND_FORTRAN_]m4_translit(m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_]), [a-z], [A-Z])) - AC_SUBST([OMPI_SIZEOF_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])) - AC_SUBST([OMPI_SIZEOF_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])) - AC_SUBST([OMPI_ALIGNMENT_FORTRAN_]m4_bpatsubst(m4_bpatsubst([$1], [*], []), [[^a-zA-Z0-9_]], [_])) + AC_SUBST([OMPI_HAVE_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))) + AC_SUBST([OMPI_KIND_FORTRAN_]m4_translit(AS_TR_SH(m4_bpatsubst([$1], [*], [])), [a-z], [A-Z])) + AC_SUBST([OMPI_SIZEOF_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))) + AC_SUBST([OMPI_SIZEOF_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))) + AC_SUBST([OMPI_ALIGNMENT_FORTRAN_]AS_TR_SH(m4_bpatsubst([$1], [*], []))) # Clean up OPAL_VAR_SCOPE_POP diff --git a/config/opal_find_type.m4 b/config/opal_find_type.m4 index bc98dd681c5..0fb12be0aea 100644 --- a/config/opal_find_type.m4 +++ b/config/opal_find_type.m4 @@ -34,7 +34,11 @@ AC_DEFUN([OPAL_FIND_TYPE],[ AS_IF([test "$oft_target_size" != ""], [m4_foreach(oft_type, [$2], [if test -z "$oft_real_type"; then - if test "[$ac_cv_sizeof_]m4_bpatsubst(oft_type, [[^a-zA-Z0-9_]], [_])" = "$oft_target_size" ; then + dnl AS_TR_SH expands literals via m4_translit, which is + dnl locale-independent; m4_bpatsubst regex character + dnl classes are not (e.g. cs_CZ.UTF-8 collates "ch" as + dnl one element, mangling "char" -> "_ar"). + if test "[$ac_cv_sizeof_]AS_TR_SH(oft_type)" = "$oft_target_size" ; then oft_real_type="oft_type" fi fi From 6a7c711844a3b970d9d409a4b745029007e1709e Mon Sep 17 00:00:00 2001 From: Brian Barrett Date: Wed, 6 May 2026 08:20:15 -0700 Subject: [PATCH 051/230] ci: Update distro/compiler list Update the distro list to remove EOL (or soon to be EOL) distros in Ubuntu 20 (EOL May 31, 2025) and AL2 (EOL June 30, 2026). Add more recent versions of distros (RHEL 9, RHEL 10, Ubuntu 26.04). Update the compilers list to make sure we explicitly test the newest and oldest versions of GCC and Clang available in the supported Ubuntu distros. Signed-off-by: Brian Barrett --- .ci/community-jenkins/Jenkinsfile | 17 +++++++++++------ .ci/community-jenkins/pr-builder.sh | 7 +++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.ci/community-jenkins/Jenkinsfile b/.ci/community-jenkins/Jenkinsfile index 826c0d95071..603b3a379db 100644 --- a/.ci/community-jenkins/Jenkinsfile +++ b/.ci/community-jenkins/Jenkinsfile @@ -62,20 +62,25 @@ def prepare_check_stages() { "--enable-ipv6", "--enable-mca-dso" ] + // explicitly list the newest and oldest versions of GCC that are included + // in the distros listed below to try and give us good version coverage. def compilers = [ - "gcc14", - "clang18" + "gcc9", + "gcc15", + "clang11", + "clang21" ] def platforms = [ - "amazon_linux_2", - "amazon_linux_2-arm64", "rhel8", + "rhel9", + "rhel10", "amazon_linux_2023-arm64", "amazon_linux_2023-x86_64", "freebsd_15", - "ubuntu_20.04", "ubuntu_24.04-arm64", - "ubuntu_24.04-x86_64" + "ubuntu_24.04-x86_64", + "ubuntu_26.04-arm64", + "ubuntu_26.04-x86_64" ] def check_stages_list = [] diff --git a/.ci/community-jenkins/pr-builder.sh b/.ci/community-jenkins/pr-builder.sh index 526e0ebe1bb..cc43ad40701 100755 --- a/.ci/community-jenkins/pr-builder.sh +++ b/.ci/community-jenkins/pr-builder.sh @@ -145,13 +145,16 @@ if test "${COMPILER}" != "" ; then exit 1 fi + set +u . ${HOME}/ompi-compiler-setup.sh activate_compiler ${COMPILER} + set -u - CONFIGURE_ARGS="${CONFIGURE_ARGS} CC=${CC} CPP=${CPP} CXX=${CXX} FC=${FC}" - if test "$FC" = "" ; then + CONFIGURE_ARGS="${CONFIGURE_ARGS} CC=${CC} CPP=${CPP} CXX=${CXX}" + if [ -z "${FC:-}" ] ; then CONFIGURE_ARGS="${CONFIGURE_ARGS} --disable-mpi-fortran" else + CONFIGURE_ARGS="${CONFIGURE_ARGS} FC=${FC}" # Flang doesn't seem good enough (yet) to compile our Fortran bindings, # so skip for now. case "${COMPILER}" in From 85de788167ad20291b34e3712585f4529d715f22 Mon Sep 17 00:00:00 2001 From: Tomislav Janjusic Date: Thu, 7 May 2026 22:32:07 -0500 Subject: [PATCH 052/230] coll/accelerator: stage full input for MPI_IN_PLACE in reduce_scatter[_block] When sbuf == MPI_IN_PLACE, the input lives entirely in rbuf: * reduce_scatter_block: rbuf holds comm_size * rcount elements * reduce_scatter: rbuf holds sum(rcounts) elements (same on every rank) Both wrappers were sizing the host staging buffer at the local-share size (rbufsize = one rank's output) and copying only that many bytes device->host. The fallback collective then read past the malloc'd region: SIGSEGV inside the convertor pack/copy when the read crossed an unmapped page, or ibv_reg_mr "Bad address" when the read stayed mapped but the peer-side registration walked into invalid pages. For the IN_PLACE path, stage the full input span (sbufsize) device->host before invoking the fallback. The result write-back stays at rbufsize since only the local share is meaningful after the call. The non-IN_PLACE path is unchanged (sbuf is staged separately at sbufsize). Signed-off-by: Tomislav Janjusic --- .../coll/accelerator/coll_accelerator_reduce_scatter.c | 10 +++++++--- .../coll_accelerator_reduce_scatter_block.c | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter.c b/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter.c index 222e9401910..9c4bfeba69c 100644 --- a/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter.c +++ b/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter.c @@ -43,7 +43,7 @@ mca_coll_accelerator_reduce_scatter(const void *sbuf, void *rbuf, ompi_count_arr ptrdiff_t gap; char *rbuf1 = NULL, *sbuf1 = NULL, *rbuf2 = NULL; int sbuf_dev, rbuf_dev; - size_t sbufsize, rbufsize, elemsize; + size_t sbufsize, rbufsize, rbuf_in_size, elemsize; int rc, i; int comm_size = ompi_comm_size(comm); int total_count = 0; @@ -73,13 +73,17 @@ mca_coll_accelerator_reduce_scatter(const void *sbuf, void *rbuf, ompi_count_arr goto exit; } rbufsize = elemsize * ompi_count_array_get(rcounts, ompi_comm_rank(comm)); + /* With MPI_IN_PLACE the input lives entirely in rbuf and spans the full + * sum(rcounts); stage that span device->host so the fallback collective + * doesn't read past the host allocation. */ + rbuf_in_size = (MPI_IN_PLACE == sbuf) ? sbufsize : rbufsize; if (0 < rc) { - rbuf1 = (char*)malloc(rbufsize); + rbuf1 = (char*)malloc(rbuf_in_size); if (NULL == rbuf1) { rc = OMPI_ERR_OUT_OF_RESOURCE; goto exit; } - mca_coll_accelerator_memcpy(rbuf1, MCA_ACCELERATOR_NO_DEVICE_ID, rbuf, rbuf_dev, rbufsize, + mca_coll_accelerator_memcpy(rbuf1, MCA_ACCELERATOR_NO_DEVICE_ID, rbuf, rbuf_dev, rbuf_in_size, MCA_ACCELERATOR_TRANSFER_DTOH); rbuf2 = rbuf; /* save away original buffer */ rbuf = rbuf1 - gap; diff --git a/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter_block.c b/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter_block.c index 5f0fd61914f..7df1881ce00 100644 --- a/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter_block.c +++ b/ompi/mca/coll/accelerator/coll_accelerator_reduce_scatter_block.c @@ -43,12 +43,16 @@ mca_coll_accelerator_reduce_scatter_block(const void *sbuf, void *rbuf, size_t r ptrdiff_t gap; char *rbuf1 = NULL, *sbuf1 = NULL, *rbuf2 = NULL; int sbuf_dev, rbuf_dev; - size_t sbufsize, rbufsize; + size_t sbufsize, rbufsize, rbuf_in_size; int rc; rbufsize = opal_datatype_span(&dtype->super, rcount, &gap); sbufsize = rbufsize * ompi_comm_size(comm); + /* With MPI_IN_PLACE the input lives entirely in rbuf and spans + * comm_size * rcount elements; stage the full span device->host so the + * fallback collective doesn't read past the host allocation. */ + rbuf_in_size = (MPI_IN_PLACE == sbuf) ? sbufsize : rbufsize; rc = mca_coll_accelerator_check_buf((void *)sbuf, &sbuf_dev); if (rc < 0) { return rc; @@ -67,12 +71,12 @@ mca_coll_accelerator_reduce_scatter_block(const void *sbuf, void *rbuf, size_t r return rc; } if (rc > 0) { - rbuf1 = (char*)malloc(rbufsize); + rbuf1 = (char*)malloc(rbuf_in_size); if (NULL == rbuf1) { if (NULL != sbuf1) free(sbuf1); return OMPI_ERR_OUT_OF_RESOURCE; } - mca_coll_accelerator_memcpy(rbuf1, MCA_ACCELERATOR_NO_DEVICE_ID, rbuf, rbuf_dev, rbufsize, + mca_coll_accelerator_memcpy(rbuf1, MCA_ACCELERATOR_NO_DEVICE_ID, rbuf, rbuf_dev, rbuf_in_size, MCA_ACCELERATOR_TRANSFER_DTOH); rbuf2 = rbuf; /* save away original buffer */ rbuf = rbuf1 - gap; From ec19b5af8091f4a901de518c31dc4434a634d5b3 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Mon, 11 May 2026 16:19:46 -0400 Subject: [PATCH 053/230] accelerator/rocm: replace local static variables GCC 7.5.0 complains that rocr_ipc_handle_size us not a constant. There is no reason to have these variables static so just revert to local variables. Signed-off-by: Joseph Schuchart --- opal/mca/accelerator/rocm/accelerator_rocm_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opal/mca/accelerator/rocm/accelerator_rocm_module.c b/opal/mca/accelerator/rocm/accelerator_rocm_module.c index 1419eeedcfe..85902c14927 100644 --- a/opal/mca/accelerator/rocm/accelerator_rocm_module.c +++ b/opal/mca/accelerator/rocm/accelerator_rocm_module.c @@ -652,8 +652,8 @@ static int mca_accelerator_rocm_compare_ipc_handles(uint8_t handle_1[IPC_MAX_HAN * and the process ID for comparison. * We definitily need to exclude the offset component in the comparison. */ - static const int rocr_ipc_handle_size = 32; - static const int pos = rocr_ipc_handle_size + 2*sizeof(size_t); + const int rocr_ipc_handle_size = 32; + const int pos = rocr_ipc_handle_size + 2*sizeof(size_t); int *pid_1 = (int *)&handle_1[pos]; int *pid_2 = (int *)&handle_2[pos]; From 409beffd2b5d45d8f021a848f296489036ab4c5b Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Mon, 11 May 2026 16:20:55 -0400 Subject: [PATCH 054/230] accelerator/rocm: unsigned is never less than zero Squash compiler warning. Signed-off-by: Joseph Schuchart --- opal/mca/accelerator/rocm/accelerator_rocm_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opal/mca/accelerator/rocm/accelerator_rocm_module.c b/opal/mca/accelerator/rocm/accelerator_rocm_module.c index 85902c14927..056b4de3542 100644 --- a/opal/mca/accelerator/rocm/accelerator_rocm_module.c +++ b/opal/mca/accelerator/rocm/accelerator_rocm_module.c @@ -352,7 +352,7 @@ static int mca_accelerator_rocm_memcpy(int dest_dev_id, int src_dev_id, void *de { hipError_t err; - if (NULL == src || NULL == dest || size < 0) { + if (NULL == src || NULL == dest) { return OPAL_ERR_BAD_PARAM; } if (0 == size) { From 57c82b37ba7587a6d3793fd99feb2eb3861a80ee Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Mon, 11 May 2026 17:39:38 -0400 Subject: [PATCH 055/230] HAN: Gracefully handle errors during communicator setup If a process dies before we set up HAN, the split and other collectives will fail. Signed-off-by: Joseph Schuchart --- ompi/mca/coll/han/coll_han_subcomms.c | 115 +++++++++++++++++++++----- 1 file changed, 95 insertions(+), 20 deletions(-) diff --git a/ompi/mca/coll/han/coll_han_subcomms.c b/ompi/mca/coll/han/coll_han_subcomms.c index b1a99ae6e67..ccee0392238 100644 --- a/ompi/mca/coll/han/coll_han_subcomms.c +++ b/ompi/mca/coll/han/coll_han_subcomms.c @@ -8,6 +8,7 @@ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Copyright (c) 2024-2026 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Stony Brook University. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -206,7 +207,7 @@ int mca_coll_han_comm_create_new(struct ompi_communicator_t *comm, HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, scatterv); OBJ_DESTRUCT(&comm_info); - + /* Retain sub-communicators so they survive finalize ordering */ OBJ_RETAIN(*low_comm); OBJ_RETAIN(*up_comm); @@ -236,9 +237,9 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, { int low_rank, low_size, up_rank, w_rank, w_size; mca_coll_han_collectives_fallback_t fallbacks; - ompi_communicator_t **low_comms; - ompi_communicator_t **up_comms; + ompi_communicator_t **low_comms = NULL, **up_comms = NULL; int vrank, *vranks; + int rc; opal_info_t comm_info; /* use cached communicators if possible */ @@ -248,6 +249,8 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, return OMPI_SUCCESS; } + OBJ_CONSTRUCT(&comm_info, opal_info_t); + /* * We cannot use han allreduce and allgather without sub-communicators, * but we are in the creation of the data structures for the HAN, and @@ -281,10 +284,14 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, * all participants. */ int local_procs = ompi_group_count_local_peers(comm->c_local_group); - comm->c_coll->coll_allreduce(MPI_IN_PLACE, &local_procs, 1, MPI_INT, - MPI_MAX, comm, - comm->c_coll->coll_allreduce_module); + rc = comm->c_coll->coll_allreduce(MPI_IN_PLACE, &local_procs, 1, MPI_INT, + MPI_MAX, comm, + comm->c_coll->coll_allreduce_module); + if (OMPI_SUCCESS != rc) { + goto final_agree; + } if( local_procs == 1 ) { + OBJ_DESTRUCT(&comm_info); /* restore saved collectives */ HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, alltoall); HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, alltoallv); @@ -304,20 +311,21 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, /* create communicators if there is no cached communicator */ w_rank = ompi_comm_rank(comm); w_size = ompi_comm_size(comm); - low_comms = (struct ompi_communicator_t **)malloc(COLL_HAN_LOW_MODULES * + low_comms = (struct ompi_communicator_t **)calloc(COLL_HAN_LOW_MODULES, sizeof(struct ompi_communicator_t *)); - up_comms = (struct ompi_communicator_t **)malloc(COLL_HAN_UP_MODULES * + up_comms = (struct ompi_communicator_t **)calloc(COLL_HAN_UP_MODULES, sizeof(struct ompi_communicator_t *)); - OBJ_CONSTRUCT(&comm_info, opal_info_t); - /* * Upgrade sm module priority to set up low_comms[0] with sm module * This sub-communicator contains the ranks that share my node. */ opal_info_set(&comm_info, "ompi_comm_coll_preference", "tuned,^han"); - ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, - &comm_info, &(low_comms[0])); + rc = ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, + &comm_info, &(low_comms[0])); + if (OMPI_SUCCESS != rc) { + goto final_agree; + } assert(OMPI_COMM_IS_DISJOINT_SET(low_comms[0]) && !OMPI_COMM_IS_DISJOINT(low_comms[0])); /* @@ -331,21 +339,30 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, * This sub-communicator contains the ranks that share my node. */ opal_info_set(&comm_info, "ompi_comm_coll_preference", "sm,^han"); - ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, + rc = ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, &comm_info, &(low_comms[1])); + if (OMPI_SUCCESS != rc) { + goto final_agree; + } assert(OMPI_COMM_IS_DISJOINT_SET(low_comms[1]) && !OMPI_COMM_IS_DISJOINT(low_comms[1])); opal_info_set(&comm_info, "ompi_comm_coll_preference", "xhc,^han"); - ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, + rc = ompi_comm_split_type(comm, MPI_COMM_TYPE_SHARED, 0, &comm_info, &(low_comms[2])); - + if (OMPI_SUCCESS != rc) { + goto final_agree; + } + assert(OMPI_COMM_IS_DISJOINT_SET(low_comms[2]) && !OMPI_COMM_IS_DISJOINT(low_comms[2])); /* * Upgrade libnbc module priority to set up up_comms[0] with libnbc module * This sub-communicator contains one process per node: processes with the * same intra-node rank id share such a sub-communicator */ opal_info_set(&comm_info, "ompi_comm_coll_preference", "libnbc,^han"); - ompi_comm_split_with_info(comm, low_rank, w_rank, &comm_info, &(up_comms[0]), false); + rc = ompi_comm_split_with_info(comm, low_rank, w_rank, &comm_info, &(up_comms[0]), false); + if (OMPI_SUCCESS != rc) { + goto final_agree; + } up_rank = ompi_comm_rank(up_comms[0]); assert(OMPI_COMM_IS_DISJOINT_SET(up_comms[0]) && OMPI_COMM_IS_DISJOINT(up_comms[0])); @@ -354,7 +371,10 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, * This sub-communicator contains one process per node. */ opal_info_set(&comm_info, "ompi_comm_coll_preference", "adapt,^han"); - ompi_comm_split_with_info(comm, low_rank, w_rank, &comm_info, &(up_comms[1]), false); + rc = ompi_comm_split_with_info(comm, low_rank, w_rank, &comm_info, &(up_comms[1]), false); + if (OMPI_SUCCESS != rc) { + goto final_agree; + } assert(OMPI_COMM_IS_DISJOINT_SET(up_comms[1]) && OMPI_COMM_IS_DISJOINT(up_comms[1])); /* @@ -371,9 +391,11 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, * gather vrank from each process so every process will know other processes * vrank */ - comm->c_coll->coll_allgather(&vrank, 1, MPI_INT, vranks, 1, MPI_INT, comm, + rc = comm->c_coll->coll_allgather(&vrank, 1, MPI_INT, vranks, 1, MPI_INT, comm, comm->c_coll->coll_allgather_module); - + if (OMPI_SUCCESS != rc) { + goto final_agree; + } /* * Set the cached info */ @@ -389,6 +411,60 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, OBJ_RETAIN(up_comms[i]); } + +final_agree: + + OBJ_DESTRUCT(&comm_info); + + if (OMPI_SUCCESS != rc) { + /** + * Revoke the input communicator to ensure no process is stuck. + */ + ompi_comm_revoke_internal(comm); + } + + /** + * Agree that everyone has successfully created the sub-communicators. + */ + + int agree_flag = (OMPI_SUCCESS == rc) ? 1 : 0; + ompi_group_t *failed_group = &ompi_mpi_group_empty.group; + int agree_rc = comm->c_coll->coll_agree( &agree_flag, + 1, + &ompi_mpi_int.dt, + &ompi_mpi_op_band.op, + &failed_group, false, + comm, + comm->c_coll->coll_agree_module); + + if (OMPI_SUCCESS != agree_rc) { + agree_flag = 0; /* agree failed so make sure to tear everything down */ + rc = agree_rc; + } + + if (!agree_flag) { + han_module->enabled = false; /* entire module set to pass-through from now on */ + if (low_comms != NULL) { + for(int i = 0; i < COLL_HAN_LOW_MODULES; i++) { + if (NULL != low_comms[i]) { + ompi_comm_revoke_internal(low_comms[i]); + ompi_comm_free(&low_comms[i]); + } + } + free(low_comms); + } + if (up_comms != NULL) { + for(int i = 0; i < COLL_HAN_UP_MODULES; i++) { + if (NULL != up_comms[i]) { + ompi_comm_revoke_internal(up_comms[i]); + ompi_comm_free(&up_comms[i]); + } + } + free(up_comms); + } + return rc; /* sub-communicator creation failed on at least one process */ + } + /* Reset the saved collectives to point back to HAN */ HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, alltoall); HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, alltoallv); @@ -402,7 +478,6 @@ int mca_coll_han_comm_create(struct ompi_communicator_t *comm, HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, scatter); HAN_SUBCOM_RESTORE_COLLECTIVE(fallbacks, comm, han_module, scatterv); - OBJ_DESTRUCT(&comm_info); return OMPI_SUCCESS; } From 4a4262e8221c7b3df3155f6783dc9da14caa516c Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Tue, 12 May 2026 10:09:27 -0400 Subject: [PATCH 056/230] comm: add NVLink-domain communicator split support Add OMPI_COMM_TYPE_NVLINK, also available through MPI_COMM_TYPE_HW_GUIDED with mpi_hw_resource_type=nvlink. The CUDA accelerator detects the local NVLink domain after lazy CUDA initialization and caches it in OPAL state instead of publishing it in the PMIx modex. This avoids relying on MPI_Init-time data, since CUDA accelerator initialization may happen later. NVLink domains are detected with NVML. If NVML reports an active NVLink domain with a nonzero clusterUuid, that UUID is used as the split color identifier and the NVML cliqueId is used as the split key. If NVML reports an all-zero clusterUuid for a single-node NVLink domain, generate a nonzero 16-byte host-derived token with an Open MPI signature and use the CUDA device ordinal as the split key. An all-zero token is reserved to mean that the process has no local NVLink domain information. At MPI_Comm_split_type time, collectively allgather only the 16-byte domain token across the communicator. Build a global color map by sorting the unique nonzero tokens, including both local and remote groups for intercommunicators. Processes without local NVLink domain information split with MPI_UNDEFINED. Update the MPI_Comm_split_type documentation for OMPI_COMM_TYPE_NVLINK. Signed-off-by: George Bosilca --- .../man3/MPI_Comm_split_type.3.rst | 6 + ompi/communicator/comm.c | 304 ++++++++++++++- ompi/include/mpi.h.in | 4 +- ompi/include/mpif-values.py | 2 + ompi/mpi/c/comm_split_type.c.in | 2 + opal/mca/accelerator/accelerator.h | 12 + .../cuda/accelerator_cuda_component.c | 352 +++++++++++++++++- 7 files changed, 665 insertions(+), 17 deletions(-) diff --git a/docs/man-openmpi/man3/MPI_Comm_split_type.3.rst b/docs/man-openmpi/man3/MPI_Comm_split_type.3.rst index 74651ea0b47..2f462fffd39 100644 --- a/docs/man-openmpi/man3/MPI_Comm_split_type.3.rst +++ b/docs/man-openmpi/man3/MPI_Comm_split_type.3.rst @@ -103,6 +103,12 @@ OMPI_COMM_TYPE_CLUSTER This type splits the communicator into subcommunicators, each of which belongs to the same cluster. +OMPI_COMM_TYPE_NVLINK + This type splits the communicator into subcommunicators based on + the NVLink domain associated with each process. It may also be + requested via ``MPI_COMM_TYPE_HW_GUIDED`` with + ``mpi_hw_resource_type`` set to ``nvlink``. + NOTES ----- diff --git a/ompi/communicator/comm.c b/ompi/communicator/comm.c index bb08ee2b83a..78d491683d7 100644 --- a/ompi/communicator/comm.c +++ b/ompi/communicator/comm.c @@ -41,6 +41,8 @@ #include #include "ompi/constants.h" +#include "opal/mca/accelerator/accelerator.h" +#include "opal/mca/base/mca_base_var.h" #include "opal/mca/hwloc/base/base.h" #include "opal/mca/pmix/pmix-internal.h" #include "opal/util/string_copy.h" @@ -65,6 +67,7 @@ struct ompi_comm_split_type_hw_guided_t { const char *info_value; int split_type; + bool use_for_unguided; }; typedef struct ompi_comm_split_type_hw_guided_t ompi_comm_split_type_hw_guided_t; @@ -74,18 +77,19 @@ typedef struct ompi_comm_split_type_hw_guided_t ompi_comm_split_type_hw_guided_t * the order in this array must be from largest topology class to smallest. */ static const ompi_comm_split_type_hw_guided_t ompi_comm_split_type_hw_guided_support[] = { - {.info_value = "cluster", .split_type = OMPI_COMM_TYPE_CLUSTER}, - {.info_value = "cu", .split_type = OMPI_COMM_TYPE_CU}, - {.info_value = "host", .split_type = OMPI_COMM_TYPE_HOST}, - {.info_value = "mpi_shared_memory", .split_type = MPI_COMM_TYPE_SHARED}, - {.info_value = "board", .split_type = OMPI_COMM_TYPE_BOARD}, - {.info_value = "numanode", .split_type = OMPI_COMM_TYPE_NUMA}, - {.info_value = "socket", .split_type = OMPI_COMM_TYPE_SOCKET}, - {.info_value = "l3cache", .split_type = OMPI_COMM_TYPE_L3CACHE}, - {.info_value = "l2cache", .split_type = OMPI_COMM_TYPE_L2CACHE}, - {.info_value = "l1cache", .split_type = OMPI_COMM_TYPE_L1CACHE}, - {.info_value = "core", .split_type = OMPI_COMM_TYPE_CORE}, - {.info_value = "hwthread", .split_type = OMPI_COMM_TYPE_HWTHREAD}, + {.info_value = "cluster", .split_type = OMPI_COMM_TYPE_CLUSTER, .use_for_unguided = false}, + {.info_value = "nvlink", .split_type = OMPI_COMM_TYPE_NVLINK, .use_for_unguided = false}, + {.info_value = "cu", .split_type = OMPI_COMM_TYPE_CU, .use_for_unguided = true}, + {.info_value = "host", .split_type = OMPI_COMM_TYPE_HOST, .use_for_unguided = true}, + {.info_value = "mpi_shared_memory", .split_type = MPI_COMM_TYPE_SHARED, .use_for_unguided = true}, + {.info_value = "board", .split_type = OMPI_COMM_TYPE_BOARD, .use_for_unguided = true}, + {.info_value = "numanode", .split_type = OMPI_COMM_TYPE_NUMA, .use_for_unguided = true}, + {.info_value = "socket", .split_type = OMPI_COMM_TYPE_SOCKET, .use_for_unguided = true}, + {.info_value = "l3cache", .split_type = OMPI_COMM_TYPE_L3CACHE, .use_for_unguided = true}, + {.info_value = "l2cache", .split_type = OMPI_COMM_TYPE_L2CACHE, .use_for_unguided = true}, + {.info_value = "l1cache", .split_type = OMPI_COMM_TYPE_L1CACHE, .use_for_unguided = true}, + {.info_value = "core", .split_type = OMPI_COMM_TYPE_CORE, .use_for_unguided = true}, + {.info_value = "hwthread", .split_type = OMPI_COMM_TYPE_HWTHREAD, .use_for_unguided = true}, {.info_value = NULL}, }; @@ -837,6 +841,7 @@ static int ompi_comm_split_type_get_part (ompi_group_t *group, const int split_t case OMPI_COMM_TYPE_CLUSTER: include = OPAL_PROC_ON_LOCAL_CLUSTER(locality); break; + case OMPI_COMM_TYPE_NVLINK: case MPI_COMM_TYPE_HW_GUIDED: case MPI_COMM_TYPE_HW_UNGUIDED: case MPI_COMM_TYPE_RESOURCE_GUIDED: @@ -918,6 +923,270 @@ static int ompi_comm_split_verify (ompi_communicator_t *comm, int split_type, in return OMPI_SUCCESS; } +static int ompi_comm_split_type_nvlink_domain_compare(const void *a, const void *b) +{ + return memcmp(a, b, OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN); +} + +static int ompi_comm_split_type_nvlink_hex_nibble(char digit) +{ + if ('0' <= digit && digit <= '9') { + return digit - '0'; + } + if ('a' <= digit && digit <= 'f') { + return digit - 'a' + 10; + } + if ('A' <= digit && digit <= 'F') { + return digit - 'A' + 10; + } + return -1; +} + +static int ompi_comm_split_type_parse_nvlink_domain( + const char *value, opal_accelerator_cuda_nvlink_domain_t *domain) +{ + char uuid_string[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN + 1] = {0}; + unsigned int clique_id; + int cuda_device; + int end = 0; + + if (NULL == value || + 3 != sscanf(value, "cuda_device=%d,cluster_uuid=%32[0123456789abcdefABCDEF],clique_id=%u%n", + &cuda_device, uuid_string, &clique_id, &end) || + '\0' != value[end] || + 2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN != strlen(uuid_string)) { + return OMPI_ERR_BAD_PARAM; + } + + domain->cuda_device = cuda_device; + domain->clique_id = (uint32_t) clique_id; + for (int i = 0; i < OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN; ++i) { + int high = ompi_comm_split_type_nvlink_hex_nibble(uuid_string[2 * i]); + int low = ompi_comm_split_type_nvlink_hex_nibble(uuid_string[2 * i + 1]); + + if (0 > high || 0 > low) { + return OMPI_ERR_BAD_PARAM; + } + domain->cluster_uuid[i] = (uint8_t) ((high << 4) | low); + } + + return OMPI_SUCCESS; +} + +static int ompi_comm_split_type_get_nvlink_domain( + opal_accelerator_cuda_nvlink_domain_t *domain) +{ + char **value = NULL; + int var_id, rc; + + domain->cuda_device = MCA_ACCELERATOR_NO_DEVICE_ID; + memset(domain->cluster_uuid, 0, sizeof(domain->cluster_uuid)); + domain->clique_id = 0; + + /* The CUDA accelerator owns the cache and exposes it through this + * read-only MCA variable. If CUDA did not register or fill it, the default + * no-device domain above keeps the split color MPI_UNDEFINED. */ + var_id = mca_base_var_find("opal", "accelerator", NULL, "nvlink_domain"); + if (0 > var_id) { + return OMPI_ERR_NOT_FOUND; + } + + rc = mca_base_var_get_value(var_id, &value, NULL, NULL); + if (OMPI_SUCCESS != rc || NULL == value) { + return rc; + } + + return ompi_comm_split_type_parse_nvlink_domain(*value, domain); +} + +#if OPAL_ENABLE_DEBUG +static void ompi_comm_split_type_nvlink_uuid_to_hex( + const uint8_t uuid[OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN], + char hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN + 1]) +{ + static const char hex[] = "0123456789abcdef"; + + for (int i = 0; i < OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN; ++i) { + hex_uuid[2 * i] = hex[uuid[i] >> 4]; + hex_uuid[2 * i + 1] = hex[uuid[i] & 0x0f]; + } + hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN] = '\0'; +} +#endif + +#define OMPI_COMM_SPLIT_TYPE_NVLINK_UUID_WORDS 4 +#define OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS OMPI_COMM_SPLIT_TYPE_NVLINK_UUID_WORDS +#define OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_SIZE \ + (OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS * sizeof(int)) + +static int ompi_comm_split_type_nvlink(ompi_communicator_t *comm, int local_split_type, + opal_info_t *info, ompi_communicator_t **newcomm) +{ + opal_accelerator_cuda_nvlink_domain_t my_domain = { + .cuda_device = MCA_ACCELERATOR_NO_DEVICE_ID, + }; + int my_token[OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS] = {0}; + int *domains = NULL; + int local_size = ompi_comm_size(comm), remote_size = 0, max_domains; + int inter, send_first = 0, local_offset = 0, remote_offset = 0; + int color = MPI_UNDEFINED, rc = OMPI_SUCCESS; + bool have_domain = false; + + /* The allgather payload is only the 16-byte color identifier, carried as + * MPI_INTs through the split-time allgather/broadcast exchange. The + * communicator uses the MCA-backed NVLink domain cache exactly as stored. + * Its default is an all-zero UUID with cuda_device set to + * MCA_ACCELERATOR_NO_DEVICE_ID; ranks in that state still enter the + * collective exchange with a zero token, but keep MPI_UNDEFINED as their + * split color because the default does not imply an NVLink domain. Only the + * CUDA accelerator may replace NVML's active single-node all-zero + * clusterUuid with a hostname-derived token. + */ + inter = OMPI_COMM_IS_INTER(comm); + if (inter) { + remote_size = ompi_comm_remote_size(comm); + send_first = ompi_comm_determine_first_auto(comm); + if (send_first) { + remote_offset = local_size * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + } else { + local_offset = remote_size * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + } + } + + max_domains = local_size + remote_size; + domains = malloc(max_domains * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_SIZE); + /* Do not add a collective allocation check here: all ranks must enter the + * same split-time allgather sequence. For now assume the local allocations + * succeed. */ + + if (MPI_UNDEFINED != local_split_type) { + (void) ompi_comm_split_type_get_nvlink_domain(&my_domain); + if (MCA_ACCELERATOR_NO_DEVICE_ID != my_domain.cuda_device) { + memcpy(my_token, my_domain.cluster_uuid, + OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_SIZE); + have_domain = true; + } + } + + rc = comm->c_coll->coll_allgather(my_token, + OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS, + MPI_INT, domains + remote_offset, + OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS, + MPI_INT, comm, + comm->c_coll->coll_allgather_module); + if (OMPI_SUCCESS != rc) { + goto failure; + } + + if (inter) { + int local_root = 0 == ompi_comm_rank(comm) ? MPI_ROOT : MPI_PROC_NULL; + int *bcast_domains; + int bcast_count, bcast_root; + + /* Intercommunicator allgather gives each group the peer group's tokens. + * Use the deterministic send_first value to establish one global order + * for the domains array on both groups: all ranks from the "first" side + * followed by all ranks from the "second" side. The allgather writes + * the peer block directly into its final global-order position. The two + * broadcasts then send each peer block back to its owning side so every + * process ends with an identical domains[] layout. The conditional + * expressions below pick the block, count, and root for each direction: + * first the second-side block, then the first-side block. This common + * order is what lets the color assignment below avoid sorting. */ + bcast_domains = domains + (send_first ? remote_offset : local_offset); + bcast_count = (send_first ? remote_size : local_size) + * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + bcast_root = send_first ? local_root : 0; + rc = comm->c_coll->coll_bcast(bcast_domains, bcast_count, MPI_INT, + bcast_root, comm, + comm->c_coll->coll_bcast_module); + if (OMPI_SUCCESS != rc) { + goto failure; + } + + bcast_domains = domains + (send_first ? local_offset : remote_offset); + bcast_count = (send_first ? local_size : remote_size) + * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + bcast_root = send_first ? 0 : local_root; + rc = comm->c_coll->coll_bcast(bcast_domains, bcast_count, MPI_INT, + bcast_root, comm, + comm->c_coll->coll_bcast_module); + if (OMPI_SUCCESS != rc) { + goto failure; + } + } + +#if OPAL_ENABLE_DEBUG + for (int i = 0; i < max_domains; ++i) { + int *domain = domains + i * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + char hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN + 1]; + + ompi_comm_split_type_nvlink_uuid_to_hex((const uint8_t *) domain, + hex_uuid); + OPAL_OUTPUT_VERBOSE((10, ompi_comm_output, "rank %d: nvlink domain[%d] uuid=%s", + ompi_comm_rank(comm), i, hex_uuid)); + } +#endif + + if (have_domain) { + int unique_count = 0; + + /* Build the color map in global domain order without sorting. The + * domains array is identical on all processes after the exchange above, + * so the first occurrence of each token is globally deterministic. + * + * As we scan domains[], keep the unique tokens compacted in the prefix + * domains[0..unique_count). A candidate token is unique only if it does + * not match any token already in that prefix. Once a candidate is known + * to be unique, check whether it is the local token before moving it + * into domains[unique_count]; unique_count is then exactly the color for + * that token. Stop as soon as the local token is assigned, because later + * colors do not affect this process. */ + for (int i = 0; MPI_UNDEFINED == color && i < max_domains; ++i) { + int *domain = domains + i * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + int *unique_domain = domains + unique_count * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + bool seen = false; + + for (int j = 0; j < unique_count; ++j) { + int *prior_domain = domains + j * OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_INTS; + + if (0 == ompi_comm_split_type_nvlink_domain_compare(domain, prior_domain)) { + seen = true; + break; + } + } + + if (seen) { + continue; + } + + if (0 == ompi_comm_split_type_nvlink_domain_compare(my_token, domain)) { + color = unique_count; + /* We only need to enumerate colors up to the local process' + * NVLink domain. */ + break; + } + if (domain != unique_domain) { + memcpy(unique_domain, domain, OMPI_COMM_SPLIT_TYPE_NVLINK_TOKEN_SIZE); + } + ++unique_count; + } + } + + free(domains); + + return ompi_comm_split_with_info(comm, color, (int) my_domain.clique_id, info, newcomm, + false); + +failure: + /* Reaching this path means the split-time collective exchange failed, so + * the collective behavior of this function is already compromised. A future + * failure path should revoke the input communicator and return MPI_COMM_NULL + * as the new communicator. */ + free(domains); + return ompi_comm_split_with_info(comm, MPI_UNDEFINED, 0, info, newcomm, false); +} + /** * ompi_comm_split_type_core: Perform common processing for a MPI_Comm_type_split * function call. @@ -1121,13 +1390,16 @@ static int ompi_comm_split_unguided(ompi_communicator_t *comm, int split_type, i * calling ompi_comm_split_type specifying the split type as * MPI_COMM_TYPE_HW_GUIDED using the next lower topology class until a * split results in a smaller size communicator than the input communicator. - * The search starts with OMPI_COMM_TYPE_CU since that is the highest possible - * topology class where the communicator size can be smaller than MPI_COMM_WORLD. */ original_size = ompi_comm_size(unguided_comm); split_info = OBJ_NEW(opal_info_t); - i = 1; + i = 0; while (NULL != ompi_comm_split_type_hw_guided_support[i].info_value) { + if (!ompi_comm_split_type_hw_guided_support[i].use_for_unguided) { + i = i + 1; + continue; + } + /* MPI_COMM_TYPE_HW_GUIDED splits require mpi_hw_resource_type to be set */ opal_info_set(split_info, "mpi_hw_resource_type", ompi_comm_split_type_hw_guided_support[i].info_value); @@ -1310,6 +1582,8 @@ int ompi_comm_split_type (ompi_communicator_t *comm, int split_type, int key, return ompi_comm_split_unguided( comm, split_type, key, need_split, no_reorder, no_undefined, info, newcomm ); + } else if (OMPI_COMM_TYPE_NVLINK == global_split_type) { + return ompi_comm_split_type_nvlink(comm, split_type, info, newcomm); } else { return ompi_comm_split_type_core( comm, global_split_type, split_type, key, need_split, no_reorder, diff --git a/ompi/include/mpi.h.in b/ompi/include/mpi.h.in index e06865b182f..57fe5a33688 100644 --- a/ompi/include/mpi.h.in +++ b/ompi/include/mpi.h.in @@ -30,6 +30,7 @@ * Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * Copyright (c) 2025 UT-Battelle, LLC. All rights reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -868,7 +869,8 @@ enum { OMPI_COMM_TYPE_CLUSTER, MPI_COMM_TYPE_HW_UNGUIDED, MPI_COMM_TYPE_HW_GUIDED, - MPI_COMM_TYPE_RESOURCE_GUIDED + MPI_COMM_TYPE_RESOURCE_GUIDED, + OMPI_COMM_TYPE_NVLINK }; #define OMPI_COMM_TYPE_NODE MPI_COMM_TYPE_SHARED diff --git a/ompi/include/mpif-values.py b/ompi/include/mpif-values.py index 53159d5d8dd..9c521dcea0e 100755 --- a/ompi/include/mpif-values.py +++ b/ompi/include/mpif-values.py @@ -11,6 +11,7 @@ # Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # Copyright (c) 2025 Triad National Security, LLC. All rights # reserved. +# Copyright (c) 2026 NVIDIA Corporation. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -342,6 +343,7 @@ 'MPI_COMM_TYPE_HW_UNGUIDED': 12, 'MPI_COMM_TYPE_HW_GUIDED': 13, 'MPI_COMM_TYPE_RESOURCE_GUIDED': 14, + 'OMPI_COMM_TYPE_NVLINK': 15, } # IO Constants diff --git a/ompi/mpi/c/comm_split_type.c.in b/ompi/mpi/c/comm_split_type.c.in index 0bac2380019..faaa7896e02 100644 --- a/ompi/mpi/c/comm_split_type.c.in +++ b/ompi/mpi/c/comm_split_type.c.in @@ -17,6 +17,7 @@ * Copyright (c) 2017-2022 IBM Corporation. All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -61,6 +62,7 @@ PROTOTYPE ERROR_CLASS comm_split_type(COMM comm, INT split_type, INT key, MPI_COMM_TYPE_HW_GUIDED != split_type && MPI_COMM_TYPE_RESOURCE_GUIDED != split_type && OMPI_COMM_TYPE_CLUSTER != split_type && + OMPI_COMM_TYPE_NVLINK != split_type && OMPI_COMM_TYPE_CU != split_type && OMPI_COMM_TYPE_HOST != split_type && OMPI_COMM_TYPE_BOARD != split_type && diff --git a/opal/mca/accelerator/accelerator.h b/opal/mca/accelerator/accelerator.h index 12f025f53c2..d035f3bc70b 100644 --- a/opal/mca/accelerator/accelerator.h +++ b/opal/mca/accelerator/accelerator.h @@ -8,6 +8,7 @@ * Copyright (c) 2024 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. + * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. * * $COPYRIGHT$ * @@ -147,6 +148,17 @@ struct opal_accelerator_pci_attr_t { }; typedef struct opal_accelerator_pci_attr_t opal_accelerator_pci_attr_t; +#define OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN 16 + +/* + * CUDA NVLink domain information used by OMPI_COMM_TYPE_NVLINK. Only the CUDA + * accelerator fills this structure. + */ +typedef struct { + int cuda_device; + uint8_t cluster_uuid[OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN]; + uint32_t clique_id; +} opal_accelerator_cuda_nvlink_domain_t; struct opal_accelerator_event_t { opal_object_t super; diff --git a/opal/mca/accelerator/cuda/accelerator_cuda_component.c b/opal/mca/accelerator/cuda/accelerator_cuda_component.c index f7ffe8f3228..415aa6d30eb 100644 --- a/opal/mca/accelerator/cuda/accelerator_cuda_component.c +++ b/opal/mca/accelerator/cuda/accelerator_cuda_component.c @@ -6,7 +6,7 @@ * reserved. * Copyright (c) 2017-2022 Amazon.com, Inc. or its affiliates. * All Rights reserved. - * Copyright (c) 2024 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2024-2026 NVIDIA Corporation. All rights reserved. * Copyright (c) 2024 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. @@ -26,9 +26,15 @@ #include "opal_config.h" #include +#include +#include +#include +#include +#include #include "accelerator_cuda.h" #include "opal/mca/accelerator/base/base.h" +#include "opal/mca/base/mca_base_var.h" #include "opal/mca/dl/base/base.h" #include "opal/runtime/opal_params.h" #include "opal/util/argv.h" @@ -47,9 +53,41 @@ bool mca_accelerator_cuda_init_complete = false; float *opal_accelerator_cuda_mem_bw = NULL; +/* + * CUDA owns the NVLink domain cache. The MCA variable below is a read-only + * string mirror used by OMPI_COMM_TYPE_NVLINK, with + * opal_accelerator_nvlink_domain registered as a synonym so the communicator + * does not depend on a CUDA symbol. + */ +static opal_accelerator_cuda_nvlink_domain_t accelerator_cuda_nvlink_domain = { + .cuda_device = MCA_ACCELERATOR_NO_DEVICE_ID, +}; +static char *accelerator_cuda_nvlink_domain_mca_string = + "cuda_device=-1,cluster_uuid=00000000000000000000000000000000,clique_id=0"; +static bool accelerator_cuda_nvlink_domain_mca_string_owned = false; + #define STRINGIFY2(x) #x #define STRINGIFY(x) STRINGIFY2(x) +typedef nvmlReturn_t (*opal_cuda_nvmlInit_v2_fn_t)(void); +typedef nvmlReturn_t (*opal_cuda_nvmlShutdown_fn_t)(void); +typedef nvmlReturn_t (*opal_cuda_nvmlDeviceGetHandleByPciBusId_v2_fn_t)( + const char *pciBusId, nvmlDevice_t *device); +typedef nvmlReturn_t (*opal_cuda_nvmlDeviceGetGpuFabricInfoV_fn_t)( + nvmlDevice_t device, nvmlGpuFabricInfoV_t *gpuFabricInfo); +typedef nvmlReturn_t (*opal_cuda_nvmlDeviceGetNvLinkState_fn_t)( + nvmlDevice_t device, unsigned int link, nvmlEnableState_t *isActive); + +#define OPAL_CUDA_NVML_ASSIGN_FN(type, dst, sym) \ + do { \ + union { \ + void *object; \ + type function; \ + } converter; \ + converter.object = (sym); \ + *(dst) = converter.function; \ + } while (0) + /* Unused variable that we register at init time and unregister at fini time. * This is used to detect if user has done a device reset prior to MPI_Finalize. * This is a workaround to avoid SEGVs. @@ -71,6 +109,7 @@ static int accelerator_cuda_close(void); static int accelerator_cuda_component_register(void); static opal_accelerator_base_module_t* accelerator_cuda_init(void); static void accelerator_cuda_finalize(opal_accelerator_base_module_t* module); +static int accelerator_cuda_cache_nvlink_domain(void); /* * Instantiate the public struct with all of our public information * and pointers to our public functions in it @@ -123,6 +162,316 @@ static int accelerator_cuda_close(void) static int accelerator_cuda_component_register(void) { + int ret; + + ret = mca_base_component_var_register(&mca_accelerator_cuda_component.super.base_version, + "nvlink_domain", + "Cached CUDA NVLink domain used by OMPI_COMM_TYPE_NVLINK", + MCA_BASE_VAR_TYPE_STRING, NULL, 0, + MCA_BASE_VAR_FLAG_DEFAULT_ONLY, OPAL_INFO_LVL_9, + MCA_BASE_VAR_SCOPE_READONLY, + &accelerator_cuda_nvlink_domain_mca_string); + if (0 > ret) { + return ret; + } + (void) mca_base_var_register_synonym(ret, "opal", "accelerator", NULL, + "nvlink_domain", 0); + accelerator_cuda_nvlink_domain_mca_string_owned = true; + + return OPAL_SUCCESS; +} + +static int accelerator_cuda_load_nvml(opal_dl_handle_t **handle, + opal_cuda_nvmlInit_v2_fn_t *dyn_nvml_init, + opal_cuda_nvmlShutdown_fn_t *dyn_nvml_shutdown, + opal_cuda_nvmlDeviceGetHandleByPciBusId_v2_fn_t + *dyn_nvml_device_get_handle_by_pci_bus_id, + opal_cuda_nvmlDeviceGetGpuFabricInfoV_fn_t + *dyn_nvml_device_get_gpu_fabric_info_v, + opal_cuda_nvmlDeviceGetNvLinkState_fn_t + *dyn_nvml_device_get_nvlink_state) +{ + const char *nvml_libraries[] = {"libnvidia-ml.so.1", "libnvidia-ml.so", NULL}; + void *symbol; + char *err_msg = NULL; + int rc = OPAL_ERROR; + + *handle = NULL; + +#if !OPAL_HAVE_DL_SUPPORT + return OPAL_ERR_NOT_AVAILABLE; +#endif + if (NULL == opal_dl) { + return OPAL_ERR_NOT_AVAILABLE; + } + + for (int i = 0; NULL != nvml_libraries[i]; ++i) { + rc = opal_dl_open(nvml_libraries[i], false, true, handle, &err_msg); + if (OPAL_SUCCESS == rc) { + break; + } + } + + if (OPAL_SUCCESS != rc) { + return OPAL_ERR_NOT_AVAILABLE; + } + + rc = opal_dl_lookup(*handle, "nvmlInit_v2", &symbol, NULL); + if (OPAL_SUCCESS != rc) { + goto error; + } + OPAL_CUDA_NVML_ASSIGN_FN(opal_cuda_nvmlInit_v2_fn_t, dyn_nvml_init, symbol); + + rc = opal_dl_lookup(*handle, "nvmlShutdown", &symbol, NULL); + if (OPAL_SUCCESS != rc) { + goto error; + } + OPAL_CUDA_NVML_ASSIGN_FN(opal_cuda_nvmlShutdown_fn_t, dyn_nvml_shutdown, symbol); + + rc = opal_dl_lookup(*handle, "nvmlDeviceGetHandleByPciBusId_v2", &symbol, NULL); + if (OPAL_SUCCESS != rc) { + goto error; + } + OPAL_CUDA_NVML_ASSIGN_FN(opal_cuda_nvmlDeviceGetHandleByPciBusId_v2_fn_t, + dyn_nvml_device_get_handle_by_pci_bus_id, symbol); + + rc = opal_dl_lookup(*handle, "nvmlDeviceGetGpuFabricInfoV", &symbol, NULL); + if (OPAL_SUCCESS != rc) { + goto error; + } + OPAL_CUDA_NVML_ASSIGN_FN(opal_cuda_nvmlDeviceGetGpuFabricInfoV_fn_t, + dyn_nvml_device_get_gpu_fabric_info_v, symbol); + + rc = opal_dl_lookup(*handle, "nvmlDeviceGetNvLinkState", &symbol, NULL); + if (OPAL_SUCCESS != rc) { + goto error; + } + OPAL_CUDA_NVML_ASSIGN_FN(opal_cuda_nvmlDeviceGetNvLinkState_fn_t, + dyn_nvml_device_get_nvlink_state, symbol); + + return OPAL_SUCCESS; + +error: + opal_dl_close(*handle); + *handle = NULL; + return OPAL_ERR_NOT_AVAILABLE; +} + +static bool accelerator_cuda_nvlink_fabric_info_has_domain(const nvmlGpuFabricInfoV_t *fabric_info) +{ + return NVML_GPU_FABRIC_STATE_COMPLETED == fabric_info->state && + NVML_SUCCESS == fabric_info->status; +} + +static bool accelerator_cuda_nvlink_cluster_uuid_is_zero(const unsigned char *cluster_uuid) +{ + for (int i = 0; i < NVML_GPU_FABRIC_UUID_LEN; ++i) { + if (0 != cluster_uuid[i]) { + return false; + } + } + + return true; +} + +static bool accelerator_cuda_nvlink_has_active_link( + opal_cuda_nvmlDeviceGetNvLinkState_fn_t dyn_nvml_device_get_nvlink_state, + nvmlDevice_t nvml_device) +{ + for (unsigned int link = 0; link < NVML_NVLINK_MAX_LINKS; ++link) { + nvmlEnableState_t state; + nvmlReturn_t rc; + + rc = dyn_nvml_device_get_nvlink_state(nvml_device, link, &state); + if (NVML_SUCCESS == rc && NVML_FEATURE_ENABLED == state) { + return true; + } + } + + return false; +} + +static uint64_t accelerator_cuda_nvlink_hash_hostname(const char *hostname) +{ + uint64_t hash = 1469598103934665603ULL; + + if (NULL == hostname) { + hostname = "unknown"; + } + + while ('\0' != *hostname) { + hash ^= (uint8_t) *hostname++; + hash *= 1099511628211ULL; + } + + return hash; +} + +static void accelerator_cuda_nvlink_make_single_node_uuid(unsigned char *uuid, + const char *hostname) +{ + /* Encode an active single-node NVLink domain reported by NVML with an + * all-zero cluster UUID. OMPI_COMM_TYPE_NVLINK does not synthesize this + * token; CUDA is the only producer of the node-local NVLink encoding. */ + static const unsigned char signature[8] = {'O', 'M', 'P', 'I', + 'N', 'V', 'L', '0'}; + uint64_t hash = accelerator_cuda_nvlink_hash_hostname(hostname); + + for (int i = 0; i < 8; ++i) { + uuid[i] = (hash >> (56 - i * 8)) & 0xff; + } + memcpy(uuid + 8, signature, sizeof(signature)); +} + +static void accelerator_cuda_nvlink_domain_uuid_to_hex( + const uint8_t uuid[OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN], + char hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN + 1]) +{ + static const char hex[] = "0123456789abcdef"; + + for (int i = 0; i < OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN; ++i) { + hex_uuid[2 * i] = hex[uuid[i] >> 4]; + hex_uuid[2 * i + 1] = hex[uuid[i] & 0x0f]; + } + hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN] = '\0'; +} + +static int accelerator_cuda_update_nvlink_domain_mca_string(void) +{ + char hex_uuid[2 * OPAL_ACCELERATOR_NVLINK_CLUSTER_UUID_LEN + 1]; + char value[128]; + char *new_value; + int written; + + accelerator_cuda_nvlink_domain_uuid_to_hex(accelerator_cuda_nvlink_domain.cluster_uuid, + hex_uuid); + written = snprintf(value, sizeof(value), "cuda_device=%d,cluster_uuid=%s,clique_id=%u", + accelerator_cuda_nvlink_domain.cuda_device, hex_uuid, + accelerator_cuda_nvlink_domain.clique_id); + if (0 > written || sizeof(value) <= (size_t) written) { + return OPAL_ERROR; + } + + new_value = strdup(value); + if (NULL == new_value) { + return OPAL_ERR_OUT_OF_RESOURCE; + } + + if (accelerator_cuda_nvlink_domain_mca_string_owned) { + free(accelerator_cuda_nvlink_domain_mca_string); + } + accelerator_cuda_nvlink_domain_mca_string = new_value; + accelerator_cuda_nvlink_domain_mca_string_owned = true; + + return OPAL_SUCCESS; +} + +static nvmlReturn_t accelerator_cuda_get_gpu_fabric_info( + opal_cuda_nvmlDeviceGetGpuFabricInfoV_fn_t dyn_nvml_device_get_gpu_fabric_info_v, + nvmlDevice_t nvml_device, nvmlGpuFabricInfoV_t *fabric_info) +{ + nvmlReturn_t rc; + +#if defined(nvmlGpuFabricInfo_v3) + memset(fabric_info, 0, sizeof(*fabric_info)); + fabric_info->version = nvmlGpuFabricInfo_v3; + rc = dyn_nvml_device_get_gpu_fabric_info_v(nvml_device, fabric_info); + if (NVML_SUCCESS == rc && accelerator_cuda_nvlink_fabric_info_has_domain(fabric_info)) { + return NVML_SUCCESS; + } +#endif + + memset(fabric_info, 0, sizeof(*fabric_info)); + fabric_info->version = nvmlGpuFabricInfo_v2; + return dyn_nvml_device_get_gpu_fabric_info_v(nvml_device, fabric_info); +} + +static int accelerator_cuda_cache_nvlink_domain(void) +{ + opal_cuda_nvmlDeviceGetGpuFabricInfoV_fn_t dyn_nvml_device_get_gpu_fabric_info_v; + opal_cuda_nvmlDeviceGetHandleByPciBusId_v2_fn_t dyn_nvml_device_get_handle_by_pci_bus_id; + opal_cuda_nvmlDeviceGetNvLinkState_fn_t dyn_nvml_device_get_nvlink_state; + nvmlGpuFabricInfoV_t fabric_info; + opal_accelerator_cuda_nvlink_domain_t domain = { + .cuda_device = MCA_ACCELERATOR_NO_DEVICE_ID, + }; + opal_cuda_nvmlShutdown_fn_t dyn_nvml_shutdown; + nvmlDevice_t nvml_device; + opal_cuda_nvmlInit_v2_fn_t dyn_nvml_init; + opal_dl_handle_t *nvml_handle = NULL; + char pci_bus_id[16] = {0}; + CUdevice cuDevice; + CUresult cu_rc; + nvmlReturn_t nvml_rc; + int rc; + + accelerator_cuda_nvlink_domain = domain; + (void) accelerator_cuda_update_nvlink_domain_mca_string(); + + cu_rc = cuCtxGetDevice(&cuDevice); + if (CUDA_SUCCESS != cu_rc) { + return OPAL_ERR_NOT_AVAILABLE; + } + + cu_rc = cuDeviceGetPCIBusId(pci_bus_id, sizeof(pci_bus_id), cuDevice); + if (CUDA_SUCCESS != cu_rc) { + return OPAL_ERR_NOT_AVAILABLE; + } + + rc = accelerator_cuda_load_nvml(&nvml_handle, &dyn_nvml_init, &dyn_nvml_shutdown, + &dyn_nvml_device_get_handle_by_pci_bus_id, + &dyn_nvml_device_get_gpu_fabric_info_v, + &dyn_nvml_device_get_nvlink_state); + if (OPAL_SUCCESS != rc) { + return rc; + } + + nvml_rc = dyn_nvml_init(); + if (NVML_SUCCESS != nvml_rc) { + goto out; + } + + nvml_rc = dyn_nvml_device_get_handle_by_pci_bus_id(pci_bus_id, &nvml_device); + if (NVML_SUCCESS != nvml_rc) { + goto shutdown; + } + + if (!accelerator_cuda_nvlink_has_active_link(dyn_nvml_device_get_nvlink_state, + nvml_device)) { + goto shutdown; + } + + nvml_rc = accelerator_cuda_get_gpu_fabric_info(dyn_nvml_device_get_gpu_fabric_info_v, + nvml_device, &fabric_info); + if (NVML_SUCCESS != nvml_rc || + !accelerator_cuda_nvlink_fabric_info_has_domain(&fabric_info)) { + goto shutdown; + } + + domain.cuda_device = (int) cuDevice; + if (accelerator_cuda_nvlink_cluster_uuid_is_zero(fabric_info.clusterUuid)) { + /* NVML reports an all-zero cluster UUID for single-node NVLink domains. + * Store a nonzero hostname-derived token only from the CUDA component, + * so the MCA default can remain all zero without suggesting a + * node-local NVLink domain. In this case, use the CUDA device ordinal + * as the split key. */ + domain.clique_id = (uint32_t) cuDevice; + accelerator_cuda_nvlink_make_single_node_uuid(domain.cluster_uuid, + OPAL_PROC_MY_HOSTNAME); + } else { + /* Multi-node/fabric domains provide a real nonzero clusterUuid and a + * cliqueId, which become the split color token and key respectively. */ + domain.clique_id = fabric_info.cliqueId; + memcpy(domain.cluster_uuid, fabric_info.clusterUuid, sizeof(domain.cluster_uuid)); + } + + accelerator_cuda_nvlink_domain = domain; + (void) accelerator_cuda_update_nvlink_domain_mca_string(); + +shutdown: + dyn_nvml_shutdown(); +out: + opal_dl_close(nvml_handle); return OPAL_SUCCESS; } @@ -187,6 +536,7 @@ int opal_accelerator_cuda_delayed_init() } else { opal_output_verbose(20, opal_accelerator_base_framework.framework_output, "CUDA: cuCtxGetCurrent succeeded"); + (void) accelerator_cuda_cache_nvlink_domain(); } /* Create stream for use in cuMemcpyAsync synchronous copies */ From c454fd408f847347642cf90904947e22ae1d62b9 Mon Sep 17 00:00:00 2001 From: Shi Jin Date: Fri, 15 May 2026 22:10:19 +0000 Subject: [PATCH 057/230] opal/mca/base: fix var group lookup in component repository release mca_base_component_repository_release_internal() passed NULL as the project name to mca_base_var_group_find(). This generates a lookup key without the project prefix (e.g., "framework_component"), but groups are registered with the project prefix (e.g., "opal_framework_component"). The hash lookup fails, skipping var deregistration before dlclose. After the DSO is unloaded, mbv_storage becomes a dangling pointer, and var_destructor segfaults when accessing mbv_storage->stringval during MPI_Finalize. Use "*" wildcard for the project name, which triggers the linear search path designed for cases where the project is unknown. This matches the pattern already used in opal_info_support.c for the same reason. Since the project name is now always available in the component structure and callers that don't know the project should use the "*" wildcard, NULL is never a valid input. Add an assert to catch this programming error early. Signed-off-by: Shi Jin --- opal/mca/base/mca_base_component_repository.c | 2 +- opal/mca/base/mca_base_var_group.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/opal/mca/base/mca_base_component_repository.c b/opal/mca/base/mca_base_component_repository.c index f359cfa9019..b4a8e502b76 100644 --- a/opal/mca/base/mca_base_component_repository.c +++ b/opal/mca/base/mca_base_component_repository.c @@ -296,7 +296,7 @@ static void mca_base_component_repository_release_internal(mca_base_component_re { int group_id; - group_id = mca_base_var_group_find(NULL, ri->ri_type, ri->ri_name); + group_id = mca_base_var_group_find("*", ri->ri_type, ri->ri_name); if (0 <= group_id) { /* ensure all variables are deregistered before we dlclose the component */ mca_base_var_group_deregister(group_id); diff --git a/opal/mca/base/mca_base_var_group.c b/opal/mca/base/mca_base_var_group.c index 732df663e98..559893cf7e4 100644 --- a/opal/mca/base/mca_base_var_group.c +++ b/opal/mca/base/mca_base_var_group.c @@ -28,6 +28,7 @@ #include #include +#include #include #ifdef HAVE_UNISTD_H # include @@ -395,6 +396,7 @@ int mca_base_var_group_deregister(int group_index) int mca_base_var_group_find(const char *project_name, const char *framework_name, const char *component_name) { + assert(NULL != project_name); return group_find(project_name, framework_name, component_name, false); } From 416d64a2b427e8c5dd91c755cde4171dab161062 Mon Sep 17 00:00:00 2001 From: George Katevenis Date: Thu, 21 May 2026 11:51:27 +0300 Subject: [PATCH 058/230] configury: fix --with-knem=PATH Signed-off-by: George Katevenis --- config/opal_check_knem.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/opal_check_knem.m4 b/config/opal_check_knem.m4 index 65ac21b028e..e0168b33a0d 100644 --- a/config/opal_check_knem.m4 +++ b/config/opal_check_knem.m4 @@ -36,7 +36,7 @@ AC_DEFUN([OPAL_CHECK_KNEM],[ [opal_check_knem_happy="yes"]) AS_IF([test "${opal_check_knem_happy}" = "yes"], - [AS_IF([test -a "${with_knem}" != "yes"], + [AS_IF([test -n "${with_knem}" -a "${with_knem}" != "yes"], [$1_CPPFLAGS="-I${with_knem}/include" CPPFLAGS="$CPPFLAGS ${$1_CPPFLAGS}"]) AC_CHECK_HEADER([knem_io.h], [opal_check_knem_happy="yes"], [opal_check_knem_happy="no"])]) From 7990f08e7b9412eb0dbe2e618a3492aa38cafff1 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Tue, 24 Mar 2026 12:28:20 -0400 Subject: [PATCH 059/230] GitHub Actions: add backport workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two workflows to automate backporting merged PRs to release branches: - backport.yaml: cherry-picks PR commits to target branches and opens backport PRs with target:* labels. Triggered automatically via backport:* labels on merge, or manually via workflow_dispatch. - backport-command.yaml: parses /backport ... comments on merged PRs and dispatches backport.yaml, with 👀 acknowledgement reactions. GITHUB_TOKEN-triggered events (push, pull_request) do not fire further workflow runs, so CI never ran on auto-created backport PRs. Switch the backport job to a short-lived GitHub App installation token so that the branch push and PR creation are attributed to the app bot rather than github-actions[bot], which causes CI to trigger normally. APP_ID and APP_PRIVATE_KEY must be set as repository secrets. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Joseph Schuchart --- .github/workflows/backport-command.yaml | 172 +++++++++++ .github/workflows/backport.yaml | 391 ++++++++++++++++++++++++ 2 files changed, 563 insertions(+) create mode 100644 .github/workflows/backport-command.yaml create mode 100644 .github/workflows/backport.yaml diff --git a/.github/workflows/backport-command.yaml b/.github/workflows/backport-command.yaml new file mode 100644 index 00000000000..719c55d62ae --- /dev/null +++ b/.github/workflows/backport-command.yaml @@ -0,0 +1,172 @@ +# Slash-command handler for /backport. +# +# Posting a comment on a merged PR with: +# +# /backport v5.0.x v4.1.x +# +# is equivalent to manually triggering the "Backport" workflow from the +# GitHub Actions UI with those branch names. Multiple branches may be +# supplied as space- or comma-separated values on the same line. +# +# Only repository owners, organisation members, and collaborators may trigger +# the command. If an unauthorised user attempts /backport, the bot replies +# with an explanatory comment. For valid commands it acknowledges with a 👀 +# reaction; invalid or unrecognised commands get a usage hint as a comment. + +name: Backport slash command + +on: + issue_comment: + types: [created] + +permissions: {} + +jobs: + dispatch: + name: Handle /backport comment + runs-on: ubuntu-latest + # Only act on PR comments (issue_comment fires for both issues and PRs). + if: github.event.issue.pull_request != null + permissions: + actions: write # trigger workflow_dispatch + issues: write # post comments + steps: + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Parse command and validate PR + id: parse + uses: actions/github-script@v8 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + const body = context.payload.comment.body; + const commentId = context.payload.comment.id; + const issueNumber = context.payload.issue.number; + const login = context.payload.comment.user.login; + + // Best-effort comment helper — if Issues are disabled on + // the repo (common for forks) the call returns 403 and we + // log a warning rather than aborting the workflow. + async function tryComment(text) { + try { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: text, + }); + } catch (err) { + core.warning(`Could not post comment: ${err.message}`); + } + } + + // Detect a bare /backport with no arguments and reply helpfully. + const bareMatch = /^\/backport\s*$/m.test(body); + // Look for /backport with arguments at the start of any line. + const match = body.match(/^\/backport\s+([^\r\n]+)/m); + + // If the comment doesn't contain any /backport command at all, + // do nothing — no need to check permissions. + if (!bareMatch && !match) { + core.setOutput('triggered', 'false'); + return; + } + + // Use author_association from the webhook payload — no extra + // API call required. getCollaboratorPermissionLevel requires + // org-level "Members" read permission, which is not available + // to either GITHUB_TOKEN or a GitHub App without explicit + // org-level permission grants. + const assoc = context.payload.comment.author_association; + if (!['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc)) { + await tryComment(`âš ī¸ @${login} Backports can only be triggered by repository owners, organization members, or collaborators.`); + core.setOutput('triggered', 'false'); + return; + } + + if (bareMatch && !match) { + core.setOutput('triggered', 'false'); + await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); + return; + } + if (!match) { + core.setOutput('triggered', 'false'); + return; + } + + // Parse branch list (space- or comma-separated). + const branches = match[1].trim().split(/[\s,]+/).filter(Boolean); + if (branches.length === 0) { + // e.g. "/backport ,,," — separators only, no real branch names + core.setOutput('triggered', 'false'); + await tryComment('âš ī¸ `/backport` requires at least one target branch, e.g. `/backport v5.0.x`.'); + return; + } + + // Validate branch names with the same allow-list used in + // backport.yaml so the user gets immediate feedback rather + // than a silent dispatch failure. + const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; + const invalidBranches = branches.filter(b => !validBranchRe.test(b)); + if (invalidBranches.length > 0) { + core.setOutput('triggered', 'false'); + await tryComment(`âš ī¸ Invalid branch name(s): ${invalidBranches.map(b => `\`${b}\``).join(', ')}. Branch names may only contain alphanumeric characters, dots, hyphens, underscores, and slashes.`); + return; + } + + // Confirm the PR is actually merged. + // merged_at is present in the issue_comment webhook payload + // for PRs, so no extra API call is needed. + if (!context.payload.issue.pull_request.merged_at) { + await tryComment('âš ī¸ Cannot backport: this PR has not been merged yet.'); + core.setOutput('triggered', 'false'); + return; + } + + // Acknowledge the command with a 👀 reaction on the triggering comment. + // Ignore 422 (reaction already exists) so re-runs don't fail. + try { + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: commentId, + content: 'eyes', + }); + } catch (err) { + if (err.status !== 422) throw err; + } + + core.setOutput('triggered', 'true'); + core.setOutput('pr_number', String(issueNumber)); + core.setOutput('branches', branches.join(',')); + core.notice(`Dispatching backport of PR #${issueNumber} to: ${branches.join(', ')}`); + + - name: Trigger backport workflow + if: steps.parse.outputs.triggered == 'true' + uses: actions/github-script@v8 + env: + PR_NUMBER: ${{ steps.parse.outputs.pr_number }} + BRANCHES: ${{ steps.parse.outputs.branches }} + with: + script: | + // workflow_dispatch requires a ref; use the default branch. + const { data: repo } = await github.rest.repos.get({ + owner: context.repo.owner, + repo: context.repo.repo, + }); + + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'backport.yaml', + ref: repo.default_branch, + inputs: { + pr_number: process.env.PR_NUMBER, + branches: process.env.BRANCHES, + }, + }); diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml new file mode 100644 index 00000000000..b7216bb46ba --- /dev/null +++ b/.github/workflows/backport.yaml @@ -0,0 +1,391 @@ +# Backport merged PRs to release branches. +# +# This workflow supports two modes: +# +# 1. Automatic (label-based): Apply one or more "backport:vX.Y.z" labels to a +# PR before merging. Once the PR is merged, this workflow fires and creates +# a cherry-pick PR for each labelled target branch. +# +# 2. Manual (workflow_dispatch): After a PR has already been merged, trigger +# this workflow manually via the GitHub Actions UI, providing the PR number +# and a comma-separated list of target branches. +# +# For every successful cherry-pick, a new PR is opened against the target +# branch and tagged with a "target:vX.Y.z" label. If the cherry-pick +# produces conflicts, a comment is posted on the original PR instead so a +# developer can handle it manually. + +name: Backport + +on: + pull_request_target: + types: [closed] + workflow_dispatch: + inputs: + pr_number: + description: 'Number of the merged PR to backport' + required: true + type: number + branches: + description: 'Target release branches (comma-separated, e.g. v5.0.x,v4.1.x)' + required: true + type: string + +permissions: {} + +jobs: + # ------------------------------------------------------------------------- + # Determine which branches need a backport and expose them as a matrix. + # ------------------------------------------------------------------------- + prepare: + name: Prepare backport targets + runs-on: ubuntu-latest + # For pull_request_target: only act when the PR was actually merged AND + # carries at least one "backport:" label (avoids a spurious job run on + # every other merge). For workflow_dispatch: always proceed. + if: > + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.merged == true && + contains(toJson(github.event.pull_request.labels.*.name), '"backport:')) + outputs: + matrix: ${{ steps.targets.outputs.matrix }} + has_targets: ${{ steps.targets.outputs.has_targets }} + pr_number: ${{ steps.targets.outputs.pr_number }} + steps: + - name: Determine backport targets + id: targets + uses: actions/github-script@v8 + with: + script: | + let branches = []; + let prNumber; + + if (context.eventName === 'workflow_dispatch') { + prNumber = Number(context.payload.inputs.pr_number); + if (!Number.isFinite(prNumber) || prNumber <= 0 || !Number.isInteger(prNumber)) { + core.setFailed(`Invalid pr_number: "${context.payload.inputs.pr_number}"`); + return; + } + branches = context.payload.inputs.branches + .split(',') + .map(b => b.trim()) + .filter(Boolean); + } else { + prNumber = context.payload.pull_request.number; + const labels = context.payload.pull_request.labels.map(l => l.name); + for (const label of labels) { + const match = label.match(/^backport:(.+)$/); + if (match) { + branches.push(match[1].trim()); + } + } + } + + // Validate branch names with a strict allow-list: must start + // with alphanumeric and contain only alphanumeric, dot, + // hyphen, underscore, or slash. De-duplicate preserving order. + const validBranchRe = /^[a-zA-Z0-9][a-zA-Z0-9._\-/]*$/; + const invalid = branches.filter(b => !validBranchRe.test(b)); + if (invalid.length > 0) { + core.setFailed(`Invalid branch name(s): ${invalid.join(', ')}`); + return; + } + branches = [...new Set(branches)]; + + core.setOutput('pr_number', String(prNumber)); + core.setOutput('has_targets', branches.length > 0 ? 'true' : 'false'); + core.setOutput('matrix', JSON.stringify({ branch: branches })); + + if (branches.length === 0) { + core.notice('No backport targets found — nothing to do.'); + } else { + core.notice(`Will backport PR #${prNumber} to: ${branches.join(', ')}`); + } + + # ------------------------------------------------------------------------- + # One job per target branch. All branches run in parallel; a failure on + # one branch does not cancel the others. + # ------------------------------------------------------------------------- + backport: + name: Backport to ${{ matrix.branch }} + needs: prepare + if: needs.prepare.outputs.has_targets == 'true' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + strategy: + matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} + fail-fast: false + env: + PR_NUMBER: ${{ needs.prepare.outputs.pr_number }} + TARGET_BRANCH: ${{ matrix.branch }} + steps: + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Checkout repository (full history) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} + + - name: Configure git identity + run: | + git config user.name "${{ steps.app-token.outputs.app-slug }}[bot]" + git config user.email "${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com" + + # Retrieve PR metadata (title, body, commit list) via the API. + # Use paginate() so PRs with more than 100 commits are handled correctly. + - name: Fetch PR metadata + id: pr_meta + uses: actions/github-script@v8 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: Number(process.env.PR_NUMBER), + }); + core.setOutput('title', pr.data.title); + // Body may be empty/null — default to empty string. + core.setOutput('body', pr.data.body ?? ''); + + // Collect all commit SHAs in merge order, paginating as needed. + const commits = await github.paginate(github.rest.pulls.listCommits, { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: Number(process.env.PR_NUMBER), + per_page: 100, + }); + const shas = commits.map(c => c.sha); + core.setOutput('commits', shas.join(' ')); + + # Verify the target release branch actually exists before doing any + # work. Post a comment and skip if it does not. + - name: Validate target branch exists + id: validate + uses: actions/github-script@v8 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + try { + await github.rest.repos.getBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + branch: process.env.TARGET_BRANCH, + }); + core.setOutput('branch_exists', 'true'); + } catch (err) { + if (err.status !== 404) throw err; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body: `âš ī¸ Cannot backport to \`${process.env.TARGET_BRANCH}\`: branch does not exist in this repository.`, + }); + core.setOutput('branch_exists', 'false'); + } + + # Cherry-pick every commit from the PR onto a new branch based on + # the target release branch. Push the branch on success; set a + # flag on conflict so the next step can report the failure. + - name: Cherry-pick commits onto backport branch + id: cherry_pick + if: steps.validate.outputs.branch_exists == 'true' + env: + COMMITS: ${{ steps.pr_meta.outputs.commits }} + run: | + set -euo pipefail + + # Resolve a unique branch name. The counter handles the common + # case of re-running a backport; the push-retry below handles the + # rare race where two concurrent runs pick the same name. + git fetch --prune origin + # Fetch the PR's original commits so they are available locally + # regardless of how the PR was merged (squash, rebase, merge commit). + git fetch origin "refs/pull/${PR_NUMBER}/head" + BASE_BRANCH="backport/pr-${PR_NUMBER}-to-${TARGET_BRANCH}" + BACKPORT_BRANCH="${BASE_BRANCH}" + counter=1 + while git ls-remote --exit-code --heads origin "${BACKPORT_BRANCH}" > /dev/null 2>&1; do + counter=$((counter + 1)) + BACKPORT_BRANCH="${BASE_BRANCH}-${counter}" + done + echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" + + git fetch origin "${TARGET_BRANCH}" + git checkout -b "${BACKPORT_BRANCH}" "origin/${TARGET_BRANCH}" + + cherry_pick_failed=false + failed_sha="" + for sha in $COMMITS; do + echo "Cherry-picking ${sha} ..." + + # Detect merge commits (more than one parent) and cherry-pick + # relative to the first parent with -m 1. + parent_count=$(git cat-file -p "${sha}" | grep -c '^parent ' || true) + if [ "${parent_count}" -gt 1 ]; then + echo " Merge commit detected, using -m 1" + cherry_flags="-m 1" + else + cherry_flags="" + fi + + # --empty=drop silently skips commits already applied to the + # target branch rather than recording a no-op empty commit. + if ! git cherry-pick --empty=drop -x ${cherry_flags} "${sha}"; then + cherry_pick_failed=true + failed_sha="${sha}" + git cherry-pick --abort 2>/dev/null || true + break + fi + done + + echo "cherry_pick_failed=${cherry_pick_failed}" >> "$GITHUB_OUTPUT" + echo "failed_sha=${failed_sha}" >> "$GITHUB_OUTPUT" + + if [ "${cherry_pick_failed}" = "false" ]; then + # If every commit was already present in the target branch, + # cherry-pick dropped them all and HEAD hasn't moved. + new_commits=$(git rev-list --count "origin/${TARGET_BRANCH}..HEAD") + if [ "${new_commits}" -eq 0 ]; then + echo "nothing_to_backport=true" >> "$GITHUB_OUTPUT" + else + echo "nothing_to_backport=false" >> "$GITHUB_OUTPUT" + # Push; on a naming collision from a concurrent run, fall back + # to a name that includes the unique run ID. + if ! git push origin "${BACKPORT_BRANCH}" 2>/dev/null; then + BACKPORT_BRANCH="${BASE_BRANCH}-${GITHUB_RUN_ID}" + git branch -m "${BACKPORT_BRANCH}" + git push origin "${BACKPORT_BRANCH}" + echo "backport_branch=${BACKPORT_BRANCH}" >> "$GITHUB_OUTPUT" + fi + fi + fi + + # All commits were already present in the target branch — no PR needed. + - name: Comment when nothing to backport + if: steps.cherry_pick.outputs.nothing_to_backport == 'true' + uses: actions/github-script@v8 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body: `â„šī¸ All commits from this PR are already present in \`${process.env.TARGET_BRANCH}\` — no backport needed.`, + }); + core.notice(`Nothing to backport to ${process.env.TARGET_BRANCH} — all commits already present.`); + + # Open a PR against the target branch and attach the target:* label. + - name: Create backport PR + if: >- + steps.cherry_pick.outputs.cherry_pick_failed == 'false' && + steps.cherry_pick.outputs.nothing_to_backport == 'false' + uses: actions/github-script@v8 + env: + ORIGINAL_TITLE: ${{ steps.pr_meta.outputs.title }} + ORIGINAL_BODY: ${{ steps.pr_meta.outputs.body }} + BACKPORT_BRANCH: ${{ steps.cherry_pick.outputs.backport_branch }} + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + const prNumber = Number(process.env.PR_NUMBER); + const targetBranch = process.env.TARGET_BRANCH; + const labelName = `target:${targetBranch}`; + + // Ensure the target:* label exists in this repo. + try { + await github.rest.issues.getLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + }); + } catch (err) { + if (err.status === 404) { + try { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: labelName, + color: '0075ca', + description: `Backport targeting the ${targetBranch} branch`, + }); + } catch (createErr) { + // 422 = another concurrent job created the label first; safe to ignore. + if (createErr.status !== 422) throw createErr; + } + } else { + throw err; + } + } + + const title = `[${targetBranch}] ${process.env.ORIGINAL_TITLE}`; + const body = [ + `Backport of #${prNumber} to \`${targetBranch}\`.`, + '', + '---', + '', + process.env.ORIGINAL_BODY, + ].join('\n'); + + const { data: newPR } = await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + head: process.env.BACKPORT_BRANCH, + base: targetBranch, + }); + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: newPR.number, + labels: [labelName], + }); + + core.notice(`Opened backport PR #${newPR.number}: ${newPR.html_url}`); + + # If cherry-pick failed, leave a comment on the original PR so a + # developer knows to create the backport manually. + - name: Comment on cherry-pick failure + if: steps.cherry_pick.outputs.cherry_pick_failed == 'true' + uses: actions/github-script@v8 + env: + FAILED_SHA: ${{ steps.cherry_pick.outputs.failed_sha }} + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + const prNumber = Number(process.env.PR_NUMBER); + const targetBranch = process.env.TARGET_BRANCH; + const failedSha = process.env.FAILED_SHA; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: [ + `âš ī¸ **Automatic backport to \`${targetBranch}\` failed.**`, + '', + `Cherry-pick of commit ${failedSha} produced conflicts.`, + 'Please create the backport manually:', + '', + '```bash', + `git fetch origin ${targetBranch}`, + `git checkout -b backport/pr-${prNumber}-to-${targetBranch} origin/${targetBranch}`, + `git cherry-pick -x `, + `git push origin backport/pr-${prNumber}-to-${targetBranch}`, + '```', + ].join('\n'), + }); + + core.warning(`Cherry-pick to ${targetBranch} failed at ${failedSha} — manual backport required.`); From 744f29c1a16fa74f381a90787bcb69451552f405 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Thu, 21 May 2026 09:05:34 -0600 Subject: [PATCH 060/230] lsf: add note to docs about problems with using most recent release of IBM's LSF product with Open MPI. This problem goes back to the 4.1.x branch at least. related to #13902 Signed-off-by: Howard Pritchard --- docs/launching-apps/lsf.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/launching-apps/lsf.rst b/docs/launching-apps/lsf.rst index 159a85a84a4..988a1a02582 100644 --- a/docs/launching-apps/lsf.rst +++ b/docs/launching-apps/lsf.rst @@ -1,7 +1,12 @@ Launching with LSF ================== -Open MPI supports the LSF resource manager. +Open MPI supports some versions of the LSF resource manager. + +Problems have been reported with using the most recent releases of LSF, in particular +the version supplied with IBM Spectrum LSF Version 10.1 Fix Pack 15. +The suggested workaround is to use an older release of the LSF 10.1 package or to +configure Open MPI without LSF support. Verify LSF support ------------------ From d368fa2c4632b8b00493335cadc9eb399861e307 Mon Sep 17 00:00:00 2001 From: Joseph Schuchart Date: Thu, 21 May 2026 21:25:08 -0400 Subject: [PATCH 061/230] Bump actions/checkout to v6 Node 20 will be deprecated in June, actions/checkout@6 uses Node 24. Signed-off-by: Joseph Schuchart --- .github/workflows/backport.yaml | 2 +- .github/workflows/compile-cuda.yaml | 2 +- .github/workflows/compile-examples.yaml | 2 +- .github/workflows/compile-rocm.yaml | 2 +- .github/workflows/compile-ze.yaml | 2 +- .github/workflows/hdf5-tests.yaml | 2 +- .github/workflows/macos-checks.yaml | 2 +- .github/workflows/ompi_mpi4py.yaml | 4 ++-- .github/workflows/ompi_mpi4py_asan.yaml | 4 ++-- .github/workflows/ompi_nvidia.yaml | 4 ++-- .github/workflows/riscv64-qemu-test.yaml | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml index b7216bb46ba..38fb7917d49 100644 --- a/.github/workflows/backport.yaml +++ b/.github/workflows/backport.yaml @@ -130,7 +130,7 @@ jobs: private-key: ${{ secrets.APP_PRIVATE_KEY }} - name: Checkout repository (full history) - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 token: ${{ steps.app-token.outputs.token }} diff --git a/.github/workflows/compile-cuda.yaml b/.github/workflows/compile-cuda.yaml index 9ba44b4c2b9..a50f637d36c 100644 --- a/.github/workflows/compile-cuda.yaml +++ b/.github/workflows/compile-cuda.yaml @@ -21,7 +21,7 @@ jobs: sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt update sudo apt install -y cuda-toolkit - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Build Open MPI diff --git a/.github/workflows/compile-examples.yaml b/.github/workflows/compile-examples.yaml index aab1ed6e5ef..d7ce1a216f8 100644 --- a/.github/workflows/compile-examples.yaml +++ b/.github/workflows/compile-examples.yaml @@ -9,7 +9,7 @@ jobs: compile-ignored: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Remove .opal_ignore files so that we build all examples diff --git a/.github/workflows/compile-rocm.yaml b/.github/workflows/compile-rocm.yaml index 804f2e4ce48..acba960e870 100644 --- a/.github/workflows/compile-rocm.yaml +++ b/.github/workflows/compile-rocm.yaml @@ -19,7 +19,7 @@ jobs: wget https://repo.radeon.com/amdgpu-install/7.2/ubuntu/jammy/amdgpu-install_7.2.70200-1_all.deb sudo apt install -y ./amdgpu-install_7.2.70200-1_all.deb sudo amdgpu-install --usecase=rocmdev - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Build Open MPI diff --git a/.github/workflows/compile-ze.yaml b/.github/workflows/compile-ze.yaml index b8fb08097e9..87cd105c72a 100644 --- a/.github/workflows/compile-ze.yaml +++ b/.github/workflows/compile-ze.yaml @@ -23,7 +23,7 @@ jobs: cd build cmake ../ -DCMAKE_INSTALL_PREFIX=/opt/ze sudo make -j1 install - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Build Open MPI (VPATH) diff --git a/.github/workflows/hdf5-tests.yaml b/.github/workflows/hdf5-tests.yaml index 5dc7e88cd4c..aee58a9f057 100644 --- a/.github/workflows/hdf5-tests.yaml +++ b/.github/workflows/hdf5-tests.yaml @@ -13,7 +13,7 @@ jobs: run: | sudo apt update sudo apt install -y --no-install-recommends wget - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Build Open MPI diff --git a/.github/workflows/macos-checks.yaml b/.github/workflows/macos-checks.yaml index 8b18c95e4ca..a088a2fed24 100644 --- a/.github/workflows/macos-checks.yaml +++ b/.github/workflows/macos-checks.yaml @@ -22,7 +22,7 @@ jobs: brew install libtool # unlink libevent brew unlink libevent || true - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Build Open MPI diff --git a/.github/workflows/ompi_mpi4py.yaml b/.github/workflows/ompi_mpi4py.yaml index 29abbcaf70d..a6a2574df3a 100644 --- a/.github/workflows/ompi_mpi4py.yaml +++ b/.github/workflows/ompi_mpi4py.yaml @@ -35,7 +35,7 @@ jobs: if: ${{ runner.os == 'Linux' }} - name: Checkout Open MPI - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: path: mpi-build submodules: recursive @@ -105,7 +105,7 @@ jobs: numpy cffi pyyaml - name: Checkout mpi4py - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: ${{ inputs.repository || 'mpi4py/mpi4py' }} ref: ${{ inputs.ref }} diff --git a/.github/workflows/ompi_mpi4py_asan.yaml b/.github/workflows/ompi_mpi4py_asan.yaml index 240e3d2f101..e770514dae7 100644 --- a/.github/workflows/ompi_mpi4py_asan.yaml +++ b/.github/workflows/ompi_mpi4py_asan.yaml @@ -42,7 +42,7 @@ jobs: if: ${{ runner.os == 'Linux' }} - name: Checkout Open MPI - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: path: mpi-build submodules: recursive @@ -106,7 +106,7 @@ jobs: numpy cffi pyyaml - name: Checkout mpi4py - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: ${{ inputs.repository || 'mpi4py/mpi4py' }} ref: ${{ inputs.ref }} diff --git a/.github/workflows/ompi_nvidia.yaml b/.github/workflows/ompi_nvidia.yaml index 8d550fad6cd..b587ea56562 100644 --- a/.github/workflows/ompi_nvidia.yaml +++ b/.github/workflows/ompi_nvidia.yaml @@ -14,11 +14,11 @@ jobs: runs-on: [self-hosted, linux, x64, nvidia] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: recursive - name: Checkout CI scripts - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: Mellanox/jenkins_scripts path: ompi_ci diff --git a/.github/workflows/riscv64-qemu-test.yaml b/.github/workflows/riscv64-qemu-test.yaml index 56a6c741704..4562c6b3541 100644 --- a/.github/workflows/riscv64-qemu-test.yaml +++ b/.github/workflows/riscv64-qemu-test.yaml @@ -20,7 +20,7 @@ jobs: sed -i "s|libdir='/mnt/riscv/riscv64-unknown-linux-gnu/lib'|libdir='/opt/riscv/riscv64-unknown-linux-gnu/lib'|g" /opt/riscv/riscv64-unknown-linux-gnu/lib/libatomic.la - name: Checkout Open MPI - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: recursive From f4a02d8c386cca3be366b3eb4b997a25e8369c0d Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Mon, 20 Oct 2025 13:49:03 +0200 Subject: [PATCH 062/230] [Configure] Common/ubcl uses ubcl CPPFLAGS Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/common/ubcl/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ompi/mca/common/ubcl/Makefile.am b/ompi/mca/common/ubcl/Makefile.am index 0cd4eb083ef..e74470a6f02 100644 --- a/ompi/mca/common/ubcl/Makefile.am +++ b/ompi/mca/common/ubcl/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (c) 2025 Bull SAS. All rights reserved. +# Copyright (c) 2025-2026 Bull SAS. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -35,6 +35,7 @@ libmca_common_ubcl_la_LIBADD = $(common_ubcl_LIBS) \ $(OPAL_TOP_BUILDDIR)/opal/mca/common/ubcl/lib@OPAL_LIB_NAME@mca_common_ubcl.la libmca_common_ubcl_noinst_la_SOURCES = $(common_ubcl_sources) +libmca_common_ubcl_noinst_la_CPPFLAGS = $(common_ubcl_CPPFLAGS) # Conditionally install the header files From a82e065f23f549bc35f05e3f430386a4ab78f3c1 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Tue, 21 Oct 2025 10:42:10 +0200 Subject: [PATCH 063/230] [Configure] Dso Ubcl components ignore ubcl linking Signed-off-by: BRELLE, EMMANUEL --- config/ompi_check_ubcl.m4 | 6 ++++-- ompi/mca/common/ubcl/Makefile.am | 1 + ompi/mca/common/ubcl/configure.m4 | 8 +++++++- ompi/mca/osc/ubcl/configure.m4 | 6 +++++- ompi/mca/pml/ubcl/configure.m4 | 6 +++++- opal/mca/common/ubcl/configure.m4 | 3 ++- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/config/ompi_check_ubcl.m4 b/config/ompi_check_ubcl.m4 index 0957a4fe2ed..0be2bad282f 100644 --- a/config/ompi_check_ubcl.m4 +++ b/config/ompi_check_ubcl.m4 @@ -8,7 +8,7 @@ # reserved. # Copyright (c) 2016 Cisco Systems, Inc. All rights reserved. # Copyright (c) 2022 Amazon.com, Inc. or its affiliates. All Rights reserved. -# Copyright (c) 2024-2025 Bull S.A.S. All rights reserved. +# Copyright (c) 2024-2026 Bull S.A.S. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -43,7 +43,9 @@ AC_DEFUN([OMPI_CHECK_UBCL],[ [ompi_check_ubcl_happy="yes" $1_CPPFLAGS="${$1_CPPFLAGS} -I$with_ubcl/include/" - AC_MSG_NOTICE([$1_CPPFLAGS is set to: ${$1_CPPFLAGS}])]) + AC_MSG_NOTICE([$1_CPPFLAGS is set to: ${$1_CPPFLAGS}]) + $1_LDFLAGS="${$1_LDFLAGS} -lubcl -L$with_ubcl/lib/" + AC_MSG_NOTICE([$1_LDFLAGS is set to: ${$1_LDFLAGS}])]) OPAL_SUMMARY_ADD([Transports],[UBCL],[],[$ompi_check_ubcl_happy]) diff --git a/ompi/mca/common/ubcl/Makefile.am b/ompi/mca/common/ubcl/Makefile.am index e74470a6f02..cb2c0faef39 100644 --- a/ompi/mca/common/ubcl/Makefile.am +++ b/ompi/mca/common/ubcl/Makefile.am @@ -36,6 +36,7 @@ libmca_common_ubcl_la_LIBADD = $(common_ubcl_LIBS) \ libmca_common_ubcl_noinst_la_SOURCES = $(common_ubcl_sources) libmca_common_ubcl_noinst_la_CPPFLAGS = $(common_ubcl_CPPFLAGS) +libmca_common_ubcl_noinst_la_LDFLAGS = $(common_ubcl_LDFLAGS) # Conditionally install the header files diff --git a/ompi/mca/common/ubcl/configure.m4 b/ompi/mca/common/ubcl/configure.m4 index 42ba29cf67a..c45f2d1d5d5 100644 --- a/ompi/mca/common/ubcl/configure.m4 +++ b/ompi/mca/common/ubcl/configure.m4 @@ -1,6 +1,6 @@ # -*- shell-script -*- # -# Copyright (c) 2025 Bull S.A.S. All rights reserved. +# Copyright (c) 2025-2026 Bull S.A.S. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -15,6 +15,12 @@ AC_DEFUN([MCA_ompi_common_ubcl_CONFIG],[ [common_ubcl_happy="yes"], [common_ubcl_happy="no"]) + # common/ubcl let endusers provide a more recent version of UBCL + # An mca parameter is exposed to select a specific UBCL path that is dlopen + # at runtime. We don't want any previous linking on DSO files. + AS_IF([test "$compile_mode" = "dso"], + [common_ubcl_LDFLAGS=""], + [AC_MSG_WARN([Only DSO mode of common/ubcl is tested])]) AC_REQUIRE([MCA_opal_common_ubcl_CONFIG]) diff --git a/ompi/mca/osc/ubcl/configure.m4 b/ompi/mca/osc/ubcl/configure.m4 index add1db7c94b..8e4a6fa543c 100644 --- a/ompi/mca/osc/ubcl/configure.m4 +++ b/ompi/mca/osc/ubcl/configure.m4 @@ -1,4 +1,4 @@ -# Copyright (c) 2025 Bull SAS. All rights reserved. +# Copyright (c) 2025-2026 Bull SAS. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -21,6 +21,10 @@ AC_DEFUN([MCA_ompi_osc_ubcl_CONFIG], [ [osc_ubcl_happy="yes"], [osc_ubcl_happy="no"]) + AS_IF([test "$compile_mode" = "dso"], + [osc_ubcl_LDFLAGS=""], + [AC_MSG_WARN([Only DSO mode of osc/ubcl is tested (see --enable-mca-dso)])]) + AS_IF([test "$osc_ubcl_happy" = "yes"], [$1], [$2]) diff --git a/ompi/mca/pml/ubcl/configure.m4 b/ompi/mca/pml/ubcl/configure.m4 index 262de492c19..4d85aa67722 100644 --- a/ompi/mca/pml/ubcl/configure.m4 +++ b/ompi/mca/pml/ubcl/configure.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2024 Bull SAS. All rights reserved. +# Copyright (c) 2024-2026 Bull SAS. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -19,6 +19,10 @@ AC_DEFUN([MCA_ompi_pml_ubcl_CONFIG], [ [pml_ubcl_happy="yes"], [pml_ubcl_happy="no"]) + AS_IF([test "$compile_mode" = "dso"], + [pml_ubcl_LDFLAGS=""], + [AC_MSG_WARN([Only DSO mode of pml/ubcl is tested (see --enable-mca-dso)])]) + AC_REQUIRE([MCA_ompi_common_ubcl_CONFIG]) AC_REQUIRE([MCA_opal_common_ubcl_CONFIG]) diff --git a/opal/mca/common/ubcl/configure.m4 b/opal/mca/common/ubcl/configure.m4 index d98ebf43103..fbaeaf7fb0a 100644 --- a/opal/mca/common/ubcl/configure.m4 +++ b/opal/mca/common/ubcl/configure.m4 @@ -1,6 +1,6 @@ # -*- shell-script -*- # -# Copyright (c) 2024 Bull S.A.S. All rights reserved. +# Copyright (c) 2024-2026 Bull S.A.S. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -15,6 +15,7 @@ AC_DEFUN([MCA_opal_common_ubcl_CONFIG],[ [common_ubcl_happy="yes"], [common_ubcl_happy="no"]) + common_ubcl_LDFLAGS="" AS_IF([test "$common_ubcl_happy" = "yes"], [$1], From ffae3eb4878664edd1774f672efc134febddd016 Mon Sep 17 00:00:00 2001 From: "BRELLE, EMMANUEL" Date: Tue, 14 Apr 2026 11:30:01 +0200 Subject: [PATCH 064/230] [UBCL][COMPILATION] Do not mix up opal and ompi common components flags Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/common/ubcl/Makefile.am | 18 +++++++++--------- ompi/mca/common/ubcl/configure.m4 | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ompi/mca/common/ubcl/Makefile.am b/ompi/mca/common/ubcl/Makefile.am index cb2c0faef39..8e97d16ccdc 100644 --- a/ompi/mca/common/ubcl/Makefile.am +++ b/ompi/mca/common/ubcl/Makefile.am @@ -8,7 +8,7 @@ #AM_CPPFLAGS = $(common_ubcl_CPPFLAGS) -common_ubcl_sources = \ +ompi_common_ubcl_sources = \ common_ubcl.c \ common_ubcl.h @@ -27,16 +27,16 @@ else noinst_LTLIBRARIES += $(comp_noinst) endif -libmca_common_ubcl_la_SOURCES = $(common_ubcl_sources) -libmca_common_ubcl_la_CFLAGS = $(common_ubcl_CFLAGS) -libmca_common_ubcl_la_CPPFLAGS = $(common_ubcl_CPPFLAGS) -libmca_common_ubcl_la_LDFLAGS = $(common_ubcl_LDFLAGS) -libmca_common_ubcl_la_LIBADD = $(common_ubcl_LIBS) \ +libmca_common_ubcl_la_SOURCES = $(ompi_common_ubcl_sources) +libmca_common_ubcl_la_CFLAGS = $(ompi_common_ubcl_CFLAGS) +libmca_common_ubcl_la_CPPFLAGS = $(ompi_common_ubcl_CPPFLAGS) +libmca_common_ubcl_la_LDFLAGS = $(ompi_common_ubcl_LDFLAGS) +libmca_common_ubcl_la_LIBADD = $(ompi_common_ubcl_LIBS) \ $(OPAL_TOP_BUILDDIR)/opal/mca/common/ubcl/lib@OPAL_LIB_NAME@mca_common_ubcl.la -libmca_common_ubcl_noinst_la_SOURCES = $(common_ubcl_sources) -libmca_common_ubcl_noinst_la_CPPFLAGS = $(common_ubcl_CPPFLAGS) -libmca_common_ubcl_noinst_la_LDFLAGS = $(common_ubcl_LDFLAGS) +libmca_common_ubcl_noinst_la_SOURCES = $(ompi_common_ubcl_sources) +libmca_common_ubcl_noinst_la_CPPFLAGS = $(ompi_common_ubcl_CPPFLAGS) +libmca_common_ubcl_noinst_la_LDFLAGS = $(ompi_common_ubcl_LDFLAGS) # Conditionally install the header files diff --git a/ompi/mca/common/ubcl/configure.m4 b/ompi/mca/common/ubcl/configure.m4 index c45f2d1d5d5..9ff2ff7b026 100644 --- a/ompi/mca/common/ubcl/configure.m4 +++ b/ompi/mca/common/ubcl/configure.m4 @@ -29,7 +29,7 @@ AC_DEFUN([MCA_ompi_common_ubcl_CONFIG],[ [$2]) # substitute in the things needed to build ubcl - AC_SUBST([common_ubcl_CPPFLAGS]) - AC_SUBST([common_ubcl_LDFLAGS]) - AC_SUBST([common_ubcl_LIBS]) + AC_SUBST([ompi_common_ubcl_CPPFLAGS]) + AC_SUBST([ompi_common_ubcl_LDFLAGS]) + AC_SUBST([ompi_common_ubcl_LIBS]) ])dnl From b528c40fccafe58694ba77285afab1a8740e9990 Mon Sep 17 00:00:00 2001 From: "GERMAIN, FLORENT" Date: Wed, 14 Jan 2026 12:04:14 +0100 Subject: [PATCH 065/230] [PML/UBCL] Check iprobe and improbe return value Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/pml/ubcl/pml_ubcl_iprobe.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ompi/mca/pml/ubcl/pml_ubcl_iprobe.c b/ompi/mca/pml/ubcl/pml_ubcl_iprobe.c index 6b6dbad0cee..b8e87fe6813 100644 --- a/ompi/mca/pml/ubcl/pml_ubcl_iprobe.c +++ b/ompi/mca/pml/ubcl/pml_ubcl_iprobe.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2019-2025 Bull SAS. All rights reserved. + * Copyright (c) 2019-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -32,6 +32,7 @@ int mca_pml_ubcl_iprobe(int src, int tag, struct ompi_communicator_t *comm, OPAL_OUTPUT_VERBOSE((75, mca_pml_ubcl_component.output, "UBCL_MODULE_IPROBE\n")); ubcl_status_t ubcl_status; + ubcl_error_t err; uint64_t cid; uint64_t rank; @@ -45,10 +46,13 @@ int mca_pml_ubcl_iprobe(int src, int tag, struct ompi_communicator_t *comm, } cid = ompi_comm_get_local_cid(comm); - ubcl_cid_t ubcl_cid= mca_pml_ubcl_compute_ubcl_cid(tag, cid); + ubcl_cid_t ubcl_cid = mca_pml_ubcl_compute_ubcl_cid(tag, cid); /* Call the UBCL api for iprobe */ - ubcl_iprobe(rank, tag, ubcl_cid, matched, &ubcl_status); + err = ubcl_iprobe(rank, tag, ubcl_cid, matched, &ubcl_status); + if (UBCL_SUCCESS != err) { + return ubcl_error_to_ompi(err); + } if (*matched) { mca_common_ubcl_status_to_ompi(status, ubcl_status, comm, src); } @@ -78,6 +82,7 @@ int mca_pml_ubcl_improbe(int src, int tag, struct ompi_communicator_t *comm, OPAL_OUTPUT_VERBOSE((75, mca_pml_ubcl_component.output, "UBCL_MODULE_IMPROBE\n")); ubcl_status_t ubcl_status; + ubcl_error_t err; uint64_t rank; uint64_t cid; if (OMPI_ANY_SOURCE == src) { @@ -95,7 +100,10 @@ int mca_pml_ubcl_improbe(int src, int tag, struct ompi_communicator_t *comm, ubcl_message_t *ubcl_message; /* Call the UBCL api for improbe */ - ubcl_improbe(rank, tag, ubcl_cid, matched, &ubcl_message, &ubcl_status); + err = ubcl_improbe(rank, tag, ubcl_cid, matched, &ubcl_message, &ubcl_status); + if (UBCL_SUCCESS != err) { + return ubcl_error_to_ompi(err); + } if (*matched) { mca_common_ubcl_status_to_ompi(status, ubcl_status, comm, src); *message = ompi_message_alloc(); From e81cdf7da2155efcec7e463ff0753b1a052e16c0 Mon Sep 17 00:00:00 2001 From: "GERMAIN, FLORENT" Date: Wed, 21 Jan 2026 16:18:13 +0100 Subject: [PATCH 066/230] [PML/UBCL] Call ubcl_memory_descriptor_destruct when needed Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/pml/ubcl/pml_ubcl_irecv.c | 29 ++++++++++++---------------- ompi/mca/pml/ubcl/pml_ubcl_isend.c | 23 ++++++++++------------ ompi/mca/pml/ubcl/pml_ubcl_request.c | 6 ++++-- ompi/mca/pml/ubcl/pml_ubcl_request.h | 3 ++- 4 files changed, 28 insertions(+), 33 deletions(-) diff --git a/ompi/mca/pml/ubcl/pml_ubcl_irecv.c b/ompi/mca/pml/ubcl/pml_ubcl_irecv.c index 9ea74d9e428..0f46cec2f4d 100644 --- a/ompi/mca/pml/ubcl/pml_ubcl_irecv.c +++ b/ompi/mca/pml/ubcl/pml_ubcl_irecv.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2019-2025 Bull SAS. All rights reserved. + * Copyright (c) 2019-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -91,17 +91,16 @@ void mca_pml_ubcl_irecv_start(struct ompi_request_t **request) mca_pml_ubcl_request_t, ompi_req); void *output_buf = (void *) req->buf; - ubcl_memory_descriptor_t rbuf_md; ubcl_error_t err = 0; size_t size; /* Init UBCL MD */ - err = ubcl_memory_descriptor_init(&rbuf_md); + err = ubcl_memory_descriptor_init(&req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to initialize ubcl MD"); } if (pml_ubcl_request_is_cuda_buf(req)) { - err = ubcl_memory_descriptor_set_properties(UBCL_BUF_IS_CUDA, &rbuf_md); + err = ubcl_memory_descriptor_set_properties(UBCL_BUF_IS_CUDA, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to set MD properties, got error: %d", err); @@ -113,7 +112,7 @@ void mca_pml_ubcl_irecv_start(struct ompi_request_t **request) ompi_datatype_type_size(req->datatype, &size); size *= req->count; - err = ubcl_memory_descriptor_build_contiguous(output_buf, size, &rbuf_md); + err = ubcl_memory_descriptor_build_contiguous(output_buf, size, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to build memory descriptor for output buffer"); @@ -121,12 +120,9 @@ void mca_pml_ubcl_irecv_start(struct ompi_request_t **request) } /* Always build a custom MD representation so that we have a fallback */ - err = ubcl_memory_descriptor_build_custom((void *) &req->convertor, - pml_ubcl_datatype_pack, - pml_ubcl_datatype_unpack, - pml_ubcl_datatype_mem_size, - pml_ubcl_datatype_finish, - &rbuf_md); + err = ubcl_memory_descriptor_build_custom((void *) &req->convertor, pml_ubcl_datatype_pack, + pml_ubcl_datatype_unpack, pml_ubcl_datatype_mem_size, + pml_ubcl_datatype_finish, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to build custom memory descriptor for input buffer"); @@ -136,9 +132,8 @@ void mca_pml_ubcl_irecv_start(struct ompi_request_t **request) MCA_PML_UBCL_REQUEST_ACTIVATE(req); if (req->message != NULL) { - err = ubcl_imrecv(rbuf_md, (ubcl_message_t **) &req->message, - (ubcl_completion_callback_fct) &ubcl_request_recv_complete_cb, - *request); + err = ubcl_imrecv(req->md, (ubcl_message_t **) &req->message, + (ubcl_completion_callback_fct) ubcl_request_recv_complete_cb, *request); } else { uint64_t rank; uint64_t cid; @@ -158,9 +153,9 @@ void mca_pml_ubcl_irecv_start(struct ompi_request_t **request) OPAL_OUTPUT_VERBOSE( (50, mca_pml_ubcl_component.output, "PML/UBCL IRECV: recv from rank=%zu\n", rank)); - err = ubcl_irecv(rbuf_md, tag, ubcl_cid, rank, - (ubcl_completion_callback_fct) &ubcl_request_recv_complete_cb, - *request, &req->ubcl_operation_handle); + err = ubcl_irecv(req->md, tag, ubcl_cid, rank, + (ubcl_completion_callback_fct) &ubcl_request_recv_complete_cb, *request, + &req->ubcl_operation_handle); } if (UBCL_ERROR == err) { diff --git a/ompi/mca/pml/ubcl/pml_ubcl_isend.c b/ompi/mca/pml/ubcl/pml_ubcl_isend.c index 3bd19f0852c..8dcfbc8ffe4 100644 --- a/ompi/mca/pml/ubcl/pml_ubcl_isend.c +++ b/ompi/mca/pml/ubcl/pml_ubcl_isend.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2019-2025 Bull SAS. All rights reserved. + * Copyright (c) 2019-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -106,7 +106,6 @@ void mca_pml_ubcl_isend_start(struct ompi_request_t **request) char *input_buf = NULL; mca_common_ubcl_endpoint_t *endpoint = NULL; - ubcl_memory_descriptor_t sbuf_md; ubcl_error_t err = 0; ubcl_send_mode_t send_mode; uint64_t cid; @@ -127,12 +126,12 @@ void mca_pml_ubcl_isend_start(struct ompi_request_t **request) endpoint = (mca_common_ubcl_endpoint_t *) req->proc->proc_endpoints[OMPI_PROC_ENDPOINT_TAG_PML]; /* Init UBCL MD */ - err = ubcl_memory_descriptor_init(&sbuf_md); + err = ubcl_memory_descriptor_init(&req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to initialize ubcl MD"); } if (pml_ubcl_request_is_cuda_buf(req)) { - err = ubcl_memory_descriptor_set_properties(UBCL_BUF_IS_CUDA, &sbuf_md); + err = ubcl_memory_descriptor_set_properties(UBCL_BUF_IS_CUDA, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to set MD properties, got error: %d", err); @@ -143,7 +142,7 @@ void mca_pml_ubcl_isend_start(struct ompi_request_t **request) if (! MCA_PML_UBCL_REQUEST_NEED_XPACK(req)) { ptrdiff_t gap = 0; size_t span = opal_datatype_span(&req->datatype->super, req->count, &gap); - err = ubcl_memory_descriptor_build_contiguous(input_buf+gap, span, &sbuf_md); + err = ubcl_memory_descriptor_build_contiguous(input_buf + gap, span, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to build contiguous memory descriptor for input buffer"); @@ -151,11 +150,9 @@ void mca_pml_ubcl_isend_start(struct ompi_request_t **request) } /* Always build a custom MD representation so that we have a fallback */ - err = ubcl_memory_descriptor_build_custom((void *) &req->convertor, - pml_ubcl_datatype_pack, - pml_ubcl_datatype_unpack, - pml_ubcl_datatype_mem_size, - pml_ubcl_datatype_finish, &sbuf_md); + err = ubcl_memory_descriptor_build_custom((void *) &req->convertor, pml_ubcl_datatype_pack, + pml_ubcl_datatype_unpack, pml_ubcl_datatype_mem_size, + pml_ubcl_datatype_finish, &req->md); if (UBCL_SUCCESS != err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to build custom memory descriptor for input buffer"); @@ -171,9 +168,9 @@ void mca_pml_ubcl_isend_start(struct ompi_request_t **request) OPAL_OUTPUT_VERBOSE( (50, mca_pml_ubcl_component.output, "PML/UBCL ISEND: sending to rank=%zu\n", endpoint->rank)); - err = ubcl_isend(sbuf_md, tag, ubcl_cid, endpoint->rank, send_mode, - (ubcl_completion_callback_fct) &ubcl_request_send_complete_cb, - *request, &req->ubcl_operation_handle); + err = ubcl_isend(req->md, tag, ubcl_cid, endpoint->rank, send_mode, + (ubcl_completion_callback_fct) ubcl_request_send_complete_cb, *request, + &req->ubcl_operation_handle); if (UBCL_ERROR == err) { mca_pml_ubcl_error(ubcl_error_to_ompi(err), "Failed to send data"); } diff --git a/ompi/mca/pml/ubcl/pml_ubcl_request.c b/ompi/mca/pml/ubcl/pml_ubcl_request.c index b5a206f504c..85699e3f803 100644 --- a/ompi/mca/pml/ubcl/pml_ubcl_request.c +++ b/ompi/mca/pml/ubcl/pml_ubcl_request.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2019-2025 Bull SAS. All rights reserved. + * Copyright (c) 2019-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -216,7 +216,6 @@ int mca_pml_ubcl_request_complete_cb(struct ompi_request_t *request) return mca_pml_ubcl_request_complete(request); } -/* TODO: Get a pointer to status and not a cpy ? */ void ubcl_request_send_complete_cb(ubcl_status_t status, void *cb_data) { if (UBCL_SUCCESS != status.status) { @@ -232,7 +231,9 @@ void ubcl_request_send_complete_cb(ubcl_status_t status, void *cb_data) /* This lock cannot be removed, even in thread single mode */ opal_atomic_lock(&req->req_lock); req->completed = 1; + ubcl_memory_descriptor_destruct(&req->md); opal_atomic_unlock(&req->req_lock); + if (req->is_buffered) { mca_pml_base_bsend_request_free(req->comm, (void*)req->buf); /* Bsend started completed, but could not be freed, now that UBCL is @@ -280,6 +281,7 @@ void ubcl_request_recv_complete_cb(ubcl_status_t status, void *cb_data) /* This lock cannot be removed, even in thread single mode */ opal_atomic_lock(&req->req_lock); req->completed = 1; + ubcl_memory_descriptor_destruct(&req->md); opal_atomic_unlock(&req->req_lock); ompi_request_complete(&(req->ompi_req), true); diff --git a/ompi/mca/pml/ubcl/pml_ubcl_request.h b/ompi/mca/pml/ubcl/pml_ubcl_request.h index d47fa598af8..256f276e39c 100644 --- a/ompi/mca/pml/ubcl/pml_ubcl_request.h +++ b/ompi/mca/pml/ubcl/pml_ubcl_request.h @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2019-2025 Bull SAS. All rights reserved. + * Copyright (c) 2019-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -85,6 +85,7 @@ struct mca_pml_ubcl_request_t { struct ompi_communicator_t *comm; /**< Communicator */ struct ompi_proc_t *proc; /**< Remote ompi proc */ opal_convertor_t convertor; /**< Data convertor */ + ubcl_memory_descriptor_t md; ompi_request_complete_fn_t saved_complete_cb; /**< Saved callback from another component (e.g OSC pt2pt) */ void *saved_complete_cb_data; /**< Saved callback data from another component (e.g OSC pt2pt) */ From fb6ebd30ae109608c4188387cab72edb9aec5fed Mon Sep 17 00:00:00 2001 From: "BRELLE, EMMANUEL" Date: Mon, 27 Apr 2026 17:38:04 +0200 Subject: [PATCH 067/230] [OSC/UBCL] Be more explicit on the failure log when using GPU buffer on osc/ubcl Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/osc/ubcl/osc_ubcl.c | 13 +++++++++---- ompi/mca/osc/ubcl/osc_ubcl_get.c | 7 +++++-- ompi/mca/osc/ubcl/osc_ubcl_put.c | 7 +++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/ompi/mca/osc/ubcl/osc_ubcl.c b/ompi/mca/osc/ubcl/osc_ubcl.c index 5e81ed1add3..5a81d0a763d 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl.c +++ b/ompi/mca/osc/ubcl/osc_ubcl.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2025 Bull SAS. All rights reserved. + * Copyright (c) 2025-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -250,7 +250,9 @@ static int component_query(struct ompi_win_t *win, void **base, size_t size, ptr if (MPI_WIN_FLAVOR_ALLOCATE != flavor && MPI_WIN_FLAVOR_DYNAMIC != flavor && 0 < size && NULL != base && NULL != *base && opal_accelerator.check_addr(*base, &dev_id, &flags) > 0) { - mca_osc_ubcl_log(20, "GPU buffer not supported by osc/ubcl"); + mca_osc_ubcl_warn( + OPAL_ERR_NOT_SUPPORTED, + "GPU buffer not supported by osc/ubcl: disqualifying UBCL for this window creation"); return OPAL_ERR_NOT_SUPPORTED; } @@ -478,8 +480,11 @@ static int win_attach(struct ompi_win_t *win, void *base, size_t size) wid = (ubcl_wid_t) module->wid; /* Accelerator buffer is not supported as attached buffer */ - if (opal_accelerator.check_addr(base, &dev_id, &flags)) { - mca_osc_ubcl_warn(OPAL_ERR_NOT_SUPPORTED, "GPU buffer not supported by osc/ubcl"); + if (0 < size && NULL != base && opal_accelerator.check_addr(base, &dev_id, &flags)) { + mca_osc_ubcl_error( + OPAL_ERR_NOT_SUPPORTED, + "GPU buffer not supported by osc/ubcl: UBCL fail to attach %zu B starting at %p", size, + base); return OPAL_ERR_NOT_SUPPORTED; } diff --git a/ompi/mca/osc/ubcl/osc_ubcl_get.c b/ompi/mca/osc/ubcl/osc_ubcl_get.c index f0fb8ad7706..5254c71d609 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_get.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_get.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2025 Bull SAS. All rights reserved. + * Copyright (c) 2025-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -112,7 +112,10 @@ int ompi_osc_ubcl_rget(void *origin_addr, size_t origin_count, if (opal_convertor_on_device(&osc_req->origin_convertor)) { opal_free_list_return(&mca_osc_ubcl_component.req_free_list, &(osc_req->super)); - mca_osc_ubcl_warn(OPAL_ERR_NOT_SUPPORTED, "GPU buffer not supported by osc/ubcl"); + mca_osc_ubcl_error( + OPAL_ERR_NOT_SUPPORTED, + "GPU buffer not supported by osc/ubcl: cannot cannot perform MPI_Get of buffer %p", + origin_addr); ret = OPAL_ERR_NOT_SUPPORTED; goto exit; } diff --git a/ompi/mca/osc/ubcl/osc_ubcl_put.c b/ompi/mca/osc/ubcl/osc_ubcl_put.c index ae45c45d511..f4d300091cd 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_put.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_put.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2025 Bull SAS. All rights reserved. + * Copyright (c) 2025-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -120,7 +120,10 @@ int ompi_osc_ubcl_rput(const void *origin_addr, size_t origin_count, if (opal_convertor_on_device(&osc_req->origin_convertor)) { opal_free_list_return(&mca_osc_ubcl_component.req_free_list, &(osc_req->super)); - mca_osc_ubcl_warn(OPAL_ERR_NOT_SUPPORTED, "GPU buffer not supported by osc/ubcl"); + mca_osc_ubcl_error( + OPAL_ERR_NOT_SUPPORTED, + "GPU buffer not supported by osc/ubcl: cannot perform MPI_Put of buffer %p", + origin_addr); ret = OPAL_ERR_NOT_SUPPORTED; goto exit; } From c3a9c0a20c783518d238d195ea62a4e69dc8e109 Mon Sep 17 00:00:00 2001 From: "BRELLE, EMMANUEL" Date: Tue, 5 May 2026 14:33:09 +0200 Subject: [PATCH 068/230] [OSC/UBCL] Removed invalid type (LOGICAL16) support for accumulate Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/osc/ubcl/osc_ubcl_accumulate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c index 58756665ee1..2a9f03c75b5 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* - * Copyright (c) 2025 Bull SAS. All rights reserved. + * Copyright (c) 2025-2026 Bull SAS. All rights reserved. * * $COPYRIGHT$ * @@ -25,6 +25,7 @@ #include "ompi/mca/osc/ubcl/osc_ubcl_sync.h" #include "ompi/mca/osc/ubcl/osc_ubcl_request.h" #include "ompi/mca/common/ubcl/common_ubcl.h" +#include "opal/include/opal_config.h" static int get_ubcl_int_type(size_t size, bool is_signed, ubcl_win_atomic_datatype_t *ubcl_type) { @@ -210,9 +211,6 @@ static int get_logical_ubcl_type(struct ompi_datatype_t *origin_dt, #endif #if OMPI_HAVE_FORTRAN_LOGICAL8 || MPI_LOGICAL8 == origin_dt -#endif -#if OMPI_HAVE_FORTRAN_LOGICAL16 - || MPI_LOGICAL16 == origin_dt #endif ) { ret = OMPI_ERR_NOT_IMPLEMENTED; From 9016dab37db58ae9b9d36a585e72997e2ef370af Mon Sep 17 00:00:00 2001 From: "BRELLE, EMMANUEL" Date: Wed, 29 Apr 2026 17:58:05 +0200 Subject: [PATCH 069/230] [OSC/UBCL] Fixed void* arithmetic Signed-off-by: BRELLE, EMMANUEL --- ompi/mca/osc/ubcl/osc_ubcl_get.c | 2 +- ompi/mca/osc/ubcl/osc_ubcl_put.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_get.c b/ompi/mca/osc/ubcl/osc_ubcl_get.c index 5254c71d609..9efa4c72aaa 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_get.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_get.c @@ -41,7 +41,7 @@ int ompi_osc_ubcl_rget(void *origin_addr, size_t origin_count, size_t target_span; size_t target_iov_count; struct iovec *target_iov; - void *target_addr; + char *target_addr; mca_common_ubcl_endpoint_t *endpoint; ubcl_memory_descriptor_t sbuf_md; mca_osc_ubcl_module_t *module; diff --git a/ompi/mca/osc/ubcl/osc_ubcl_put.c b/ompi/mca/osc/ubcl/osc_ubcl_put.c index f4d300091cd..17a7479e6a2 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_put.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_put.c @@ -50,7 +50,7 @@ int ompi_osc_ubcl_rput(const void *origin_addr, size_t origin_count, size_t span; size_t target_iov_count; struct iovec *target_iov; - void *target_addr; + char *target_addr; mca_common_ubcl_endpoint_t *endpoint; ubcl_memory_descriptor_t sbuf_md; mca_osc_ubcl_module_t *module = (mca_osc_ubcl_module_t *) win->w_osc_module; From bc127b2098092a1d45057e9a0de40cf8bd982583 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Wed, 27 May 2026 16:09:52 +0200 Subject: [PATCH 070/230] mailmap: Add alternate email address for Brelle Emmanuel Signed-off-by: Brelle Emmanuel --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index 0b2e1684f6d..86031b5c04d 100644 --- a/.mailmap +++ b/.mailmap @@ -139,3 +139,6 @@ Brian Barrett Andrii Bilokur B-a-S Kento Hasegawa hasegawa.kento + +Brelle Emmanuel Brelle Emmanuel +Brelle Emmanuel Brelle Emmanuel From 94bc7141a07fe07beaa4ee965f1bb2184b89044d Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Thu, 28 May 2026 10:55:32 +0200 Subject: [PATCH 071/230] Revert "[OSC/UBCL] Removed invalid type (LOGICAL16) support for accumulate" This reverts commit 43c29a01dbbe44c35dfba315f5bbc56b8d34d63d. Type has just been introduced by recent versions Signed-off-by: Brelle Emmanuel --- ompi/mca/osc/ubcl/osc_ubcl_accumulate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c index 2a9f03c75b5..1796ab5c7bf 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c @@ -25,7 +25,6 @@ #include "ompi/mca/osc/ubcl/osc_ubcl_sync.h" #include "ompi/mca/osc/ubcl/osc_ubcl_request.h" #include "ompi/mca/common/ubcl/common_ubcl.h" -#include "opal/include/opal_config.h" static int get_ubcl_int_type(size_t size, bool is_signed, ubcl_win_atomic_datatype_t *ubcl_type) { @@ -211,6 +210,9 @@ static int get_logical_ubcl_type(struct ompi_datatype_t *origin_dt, #endif #if OMPI_HAVE_FORTRAN_LOGICAL8 || MPI_LOGICAL8 == origin_dt +#endif +#if OMPI_HAVE_FORTRAN_LOGICAL16 + || MPI_LOGICAL16 == origin_dt #endif ) { ret = OMPI_ERR_NOT_IMPLEMENTED; From 536b395a127129e59456aa1e4f3fada39ba607b8 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Thu, 28 May 2026 12:11:14 +0200 Subject: [PATCH 072/230] [OSC/UBCL] Include opal/include/opal_config.h for datatype supports defines Signed-off-by: Brelle Emmanuel --- ompi/mca/osc/ubcl/osc_ubcl_accumulate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c index 1796ab5c7bf..32957fc1cec 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c @@ -18,6 +18,7 @@ * of these functions, refer to ompi/mca/osc/osc.h. */ +#include "opal/include/opal_config.h" #include "ompi/mca/osc/ubcl/osc_ubcl.h" #include "opal/mca/common/ubcl/common_ubcl.h" #include "ompi/mca/osc/ubcl/osc_ubcl_info.h" From 11a619cb5a42357d6b93ef49809cb6b7e6e2186e Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Thu, 28 May 2026 11:49:52 +0200 Subject: [PATCH 073/230] [OSC/UBCL] Fixed typo in a log Signed-off-by: Brelle Emmanuel --- ompi/mca/osc/ubcl/osc_ubcl_get.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_get.c b/ompi/mca/osc/ubcl/osc_ubcl_get.c index 9efa4c72aaa..20824deac62 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_get.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_get.c @@ -114,7 +114,7 @@ int ompi_osc_ubcl_rget(void *origin_addr, size_t origin_count, opal_free_list_return(&mca_osc_ubcl_component.req_free_list, &(osc_req->super)); mca_osc_ubcl_error( OPAL_ERR_NOT_SUPPORTED, - "GPU buffer not supported by osc/ubcl: cannot cannot perform MPI_Get of buffer %p", + "GPU buffer not supported by osc/ubcl: cannot perform MPI_Get of buffer %p", origin_addr); ret = OPAL_ERR_NOT_SUPPORTED; goto exit; From 72fdc07481a7ccd4b07ce605f3ff7f44defc23b9 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Thu, 28 May 2026 11:49:06 +0200 Subject: [PATCH 074/230] [CONFIG] Added comments why dynamic mode is better for UBCL and why linking flags become optional Signed-off-by: Brelle Emmanuel --- config/ompi_check_ubcl.m4 | 4 ++++ ompi/mca/common/ubcl/configure.m4 | 18 +++++++++++++++--- ompi/mca/osc/ubcl/configure.m4 | 2 ++ ompi/mca/pml/ubcl/configure.m4 | 3 +++ opal/mca/common/ubcl/configure.m4 | 1 + 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/config/ompi_check_ubcl.m4 b/config/ompi_check_ubcl.m4 index 0be2bad282f..cf556cb7ee5 100644 --- a/config/ompi_check_ubcl.m4 +++ b/config/ompi_check_ubcl.m4 @@ -44,6 +44,10 @@ AC_DEFUN([OMPI_CHECK_UBCL],[ [ompi_check_ubcl_happy="yes" $1_CPPFLAGS="${$1_CPPFLAGS} -I$with_ubcl/include/" AC_MSG_NOTICE([$1_CPPFLAGS is set to: ${$1_CPPFLAGS}]) + # Let define UBCL linking flags even if they will be ignored afterwards + # as ubcl components are very likely compiled in dynamic mode + # See ompi/mca/common/ubcl/configure.m4 comment explaining why UBCL linking + # flags are removed only in dynamic mode $1_LDFLAGS="${$1_LDFLAGS} -lubcl -L$with_ubcl/lib/" AC_MSG_NOTICE([$1_LDFLAGS is set to: ${$1_LDFLAGS}])]) diff --git a/ompi/mca/common/ubcl/configure.m4 b/ompi/mca/common/ubcl/configure.m4 index 9ff2ff7b026..76000dbc7e3 100644 --- a/ompi/mca/common/ubcl/configure.m4 +++ b/ompi/mca/common/ubcl/configure.m4 @@ -15,12 +15,24 @@ AC_DEFUN([MCA_ompi_common_ubcl_CONFIG],[ [common_ubcl_happy="yes"], [common_ubcl_happy="no"]) - # common/ubcl let endusers provide a more recent version of UBCL + # By default the tarball build goes through a 'make dist check' step. + # It runs first a configure without any options and OMPI_CHECK_UBCL may find UBCL. + # In that case, UBCL symbols will be included inside binaries such as ompi_info, + # therefore UBCL linking flags are needed in static mode to resolve symbols. + # + # In dynamic mode, UBCL symbols are resolved at runtime: ompi components + # are dlopen-ed lazily and UBCL components initialization starts with a dlopen + # of libubcl.so to load symbols. If it fails UBCL components init returns an error and + # Open MPI will search for other components. UBCL linking flags become optional. + # + # In dynamic mode, linking to the UBCL library is delayed. So common/ubcl can let + # endusers provide a more recent version of UBCL. + # This mode should be preferably selected for UBCL components. # An mca parameter is exposed to select a specific UBCL path that is dlopen - # at runtime. We don't want any previous linking on DSO files. + # at runtime. AS_IF([test "$compile_mode" = "dso"], [common_ubcl_LDFLAGS=""], - [AC_MSG_WARN([Only DSO mode of common/ubcl is tested])]) + [AC_MSG_WARN([Only DSO mode of common/ubcl is tested (see --enable-mca-dso)])]) AC_REQUIRE([MCA_opal_common_ubcl_CONFIG]) diff --git a/ompi/mca/osc/ubcl/configure.m4 b/ompi/mca/osc/ubcl/configure.m4 index 8e4a6fa543c..1677000c469 100644 --- a/ompi/mca/osc/ubcl/configure.m4 +++ b/ompi/mca/osc/ubcl/configure.m4 @@ -21,6 +21,8 @@ AC_DEFUN([MCA_ompi_osc_ubcl_CONFIG], [ [osc_ubcl_happy="yes"], [osc_ubcl_happy="no"]) + # See ompi/mca/common/ubcl/configure.m4 comment explaining why UBCL linking + # flags are removed only in dynamic mode AS_IF([test "$compile_mode" = "dso"], [osc_ubcl_LDFLAGS=""], [AC_MSG_WARN([Only DSO mode of osc/ubcl is tested (see --enable-mca-dso)])]) diff --git a/ompi/mca/pml/ubcl/configure.m4 b/ompi/mca/pml/ubcl/configure.m4 index 4d85aa67722..ac3b17efb6d 100644 --- a/ompi/mca/pml/ubcl/configure.m4 +++ b/ompi/mca/pml/ubcl/configure.m4 @@ -19,8 +19,11 @@ AC_DEFUN([MCA_ompi_pml_ubcl_CONFIG], [ [pml_ubcl_happy="yes"], [pml_ubcl_happy="no"]) + # See ompi/mca/common/ubcl/configure.m4 comment explaining why UBCL linking + # flags are removed only in dynamic mode AS_IF([test "$compile_mode" = "dso"], [pml_ubcl_LDFLAGS=""], + # Static mode should work, but Bull provides support only for dynamic components [AC_MSG_WARN([Only DSO mode of pml/ubcl is tested (see --enable-mca-dso)])]) AC_REQUIRE([MCA_ompi_common_ubcl_CONFIG]) diff --git a/opal/mca/common/ubcl/configure.m4 b/opal/mca/common/ubcl/configure.m4 index fbaeaf7fb0a..fa4af35cb7d 100644 --- a/opal/mca/common/ubcl/configure.m4 +++ b/opal/mca/common/ubcl/configure.m4 @@ -15,6 +15,7 @@ AC_DEFUN([MCA_opal_common_ubcl_CONFIG],[ [common_ubcl_happy="yes"], [common_ubcl_happy="no"]) + # opal/mca/common/ubcl does not handle any UBCL symbols common_ubcl_LDFLAGS="" AS_IF([test "$common_ubcl_happy" = "yes"], From ba8a23d79d2df69a5f29dbeb79d004de832a6780 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Fri, 17 Oct 2025 14:20:21 +0200 Subject: [PATCH 075/230] [Configure] UBCL path is guessed with --with-ubcl=yes Signed-off-by: Brelle Emmanuel --- config/ompi_check_ubcl.m4 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/config/ompi_check_ubcl.m4 b/config/ompi_check_ubcl.m4 index cf556cb7ee5..0b6bf689458 100644 --- a/config/ompi_check_ubcl.m4 +++ b/config/ompi_check_ubcl.m4 @@ -32,6 +32,18 @@ AC_DEFUN([OMPI_CHECK_UBCL],[ # UBCL is dlopen'd to avoid direct link to libubcl.so. # OAC_CHECK_PACKAGE would add this explicit link, so it cannot be used. + + # No option means no dso and with-ubcl="" + AS_IF([test "$with_ubcl" = "yes" || test "x$with_ubcl" = "x"], + [AC_MSG_NOTICE([Unspecified UBCL path]) + guessed_path="`find /opt/ubcl -name ubcl_api.h 2>/dev/null \ + | sort | tail -n1 \ + | cut -d "/" -f1-4`" + AS_IF([test "x$guessed_path" != "x"], + [with_ubcl=$guessed_path + AC_MSG_NOTICE([Guessed that UBCL is $guessed_path])]) + ]) + # OPAL_CHECK_WITHDIR prints an error if the given path is invalid OPAL_CHECK_WITHDIR([ubcl], [$with_ubcl], [include/ubcl_api.h]) From e9de5ea9008da8baa82149ea297edbdc5c755699 Mon Sep 17 00:00:00 2001 From: Brelle Emmanuel Date: Mon, 1 Jun 2026 10:24:51 +0200 Subject: [PATCH 076/230] [OSC/UBCL] Fixed cherry-picking for older versions without OMPI_HAVE_FORTRAN_LOGICAL16 Signed-off-by: Brelle Emmanuel --- ompi/mca/osc/ubcl/osc_ubcl_accumulate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c index 32957fc1cec..c3082188537 100644 --- a/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c +++ b/ompi/mca/osc/ubcl/osc_ubcl_accumulate.c @@ -212,8 +212,11 @@ static int get_logical_ubcl_type(struct ompi_datatype_t *origin_dt, #if OMPI_HAVE_FORTRAN_LOGICAL8 || MPI_LOGICAL8 == origin_dt #endif +/* To ease backport to older ompi versions */ +#if defined OMPI_HAVE_FORTRAN_LOGICAL16 #if OMPI_HAVE_FORTRAN_LOGICAL16 || MPI_LOGICAL16 == origin_dt +#endif #endif ) { ret = OMPI_ERR_NOT_IMPLEMENTED; From 495304d9e4d0df1f15d61db9f04034a5786cda0d Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 1 Jun 2026 17:25:09 -0400 Subject: [PATCH 077/230] Add AGENTS.md to orient AI coding agents Provide a concise entry point for AI coding agents (and the humans driving them) working in the Open MPI source tree. It captures the mental model -- the OPAL/OMPI/OSHMEM projects and their linker boundaries, the MCA architecture -- and the handful of conventions agents most often get wrong (prefix rule, config.h-first, no back-end MPI_*() calls, copyright headers, warning-free builds). It also covers build/smoke-test flow, generated/do-not-edit trees, performance discipline, and the sign-off / commit / branch process. Rather than duplicate the authoritative developer docs, it links into docs/developers/ and docs/contributing.rst so it stays a thin, low-drift orientation map. Signed-off-by: Jeff Squyres --- AGENTS.md | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..805ce2dbb9b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,262 @@ + + +# AGENTS.md + +Guidance for AI coding agents (and the humans driving them) working in +the Open MPI source tree. This file is an *orientation map*, not the +full rulebook: the authoritative, human-maintained documentation lives +under [`docs/developers/`](docs/developers/) and +[`docs/contributing.rst`](docs/contributing.rst) (rendered at +). When this file and those docs disagree, +**the docs win** — and please fix this file. + +AI-assisted contributions are welcome. But Open MPI runs on the largest +supercomputers in the world and across a huge range of operating +systems and hardware. We want careful, portable, performant code — not +plausible-looking code that solves one problem in one environment at the +expense of others. Hold yourself to the same bar as a thoughtful human +contributor. + +## What Open MPI is + +Open MPI is an open source implementation of the [Message Passing +Interface (MPI) specification](https://www.mpi-forum.org/docs/) — a +high-level library for sending discrete, typed messages between +processes, independent of the underlying network or OS. It also +includes a run-time system that launches and manages the lifecycle of +many processes across many hosts as a single MPI "job". + +## The mental model: three projects + +The code base is divided into three *projects*, which are strict +abstraction barriers — each compiles to its own library with a one-way +dependency order: + +``` +OSHMEM (liboshmem) OpenSHMEM API layer + │ depends on +OMPI (libmpi) MPI API layer + language bindings + │ depends on +OPAL (libopen-pal) portability layer (OS/arch abstractions) +``` + +- **OPAL** — portability primitives. Symbols prefixed `opal_` / `OPAL_`. + This is where most OS/arch `#if` blocks belong. +- **OMPI** — everything the MPI standard mandates: the language bindings + (C, several Fortran flavors, non-standard Java) on top, MCA frameworks + underneath. Symbols prefixed `ompi_` / `OMPI_`; only *official* MPI + symbols get `MPI_` / `mpi_`. +- **OSHMEM** — the OpenSHMEM API layer; sibling to OMPI, changes slowly. + Symbols prefixed `oshmem_` / `OSHMEM_`. + +**Linker boundary (a real, hard error if you violate it):** code in a +lower layer *cannot* directly call functions in a higher layer. OPAL +cannot call OMPI or OSHMEM; OMPI cannot call OSHMEM. The legal way for a +lower layer to reach upward is a **callback function pointer** handed +down from the higher layer. Direct upward calls fail to resolve at link +time. + +## MCA: the Modular Component Architecture + +OPAL, OMPI, and OSHMEM are built almost entirely out of MCA plugins. +Read [`docs/developers/terminology.rst`](docs/developers/terminology.rst) +and the MCA section it points to before doing real work. The hierarchy: + +- **Project** → **Framework** → **Component** → **Module** (runtime + instance, like a C++ object). Each level is isolated from its + siblings; a framework exposes a top-level header for its public API. +- Example: `opal/mca/btl/` is the BTL framework in OPAL; + `opal/mca/btl/tcp/` is one component within it. +- **MCA parameters** let users change behavior at run time (env var, + file, CLI). **Prefer adding an MCA parameter over hard-coding a + constant** — this is idiomatic and expected here. + +## Golden rules (the things agents most often get wrong) + +From [`docs/developers/source-code.rst`](docs/developers/source-code.rst) +and [`docs/contributing.rst`](docs/contributing.rst): + +- **Prefix rule.** Filenames are prefixed `_`. + Public symbols in a component are prefixed + `__` (`` ∈ `mca`, `opal`, + `ompi`, `oshmem`). Non-public symbols must be `static` or otherwise + kept out of global scope. When in doubt, add the prefix. +- **Include `_config.h` first** — `opal_config.h`, + `ompi_config.h`, or `oshmem_config.h` for the layer you're in — as the + very first `#include`, before any system header. +- **MPI back-end code must never call public `MPI_*()` APIs.** The + bindings are thin wrappers; call the internal `ompi_*` routines, not + the user-facing entry points. +- **New files need the standard copyright/license header.** Copy the + multi-institution BSD header block — including the `$COPYRIGHT$` and + `$HEADER$` tokens — from a neighboring file. If you substantially + change an existing file, add your copyright line to its block. +- **`#define` logical macros to `0` or `1`; never `#undef` them.** Test + with `#if FOO`, not `#ifdef FOO`, so a misspelling is a compiler + error, not a silent false. +- **Put constants on the left** of equality tests: `if (NULL == ptr)`. +- **Always brace blocks**, even one-liners. **4-space indents, never a + literal tab character**, in any language. +- C11 is required (Open MPI â‰Ĩ 6.0): C++-style `//` comments and C99 + mixed declarations are allowed and preferred. Fortran has no formal + style — match the surrounding code. +- **Stay compiler-warning-free.** Open MPI strives to build with zero + compiler warnings. Do not introduce code that adds new warnings. + +## Generated code: edit the source, not the output + +The MPI C/Fortran bindings are **generated at build time** by the Python +generator under [`ompi/mpi/bindings/`](ompi/mpi/bindings/) +(`bindings.py` + `ompi_bindings/`), driven in part by official MPI +symbol/signature data pulled from the MPI Forum's `pympistandard`. If +you need to change a binding's behavior, change the **generator, +templates, or the back-end implementation** — never the emitted `.c`/`.h` +files. + +## Do NOT hand-edit + +- **`3rd-party/` and the git submodules** (embedded OpenPMIx, and the + Open MPI *fork* of PRRTE). Fixes belong upstream, not patched in here. +- **Autotools-generated output** — `configure`, `Makefile.in`, + `config.status`, anything produced by `./autogen.pl`. Edit + `configure.ac`, `Makefile.am`, or the m4 in [`config/`](config/) + instead. +- **Generated MPI bindings** — see the section above. +- **Pre-rendered docs** — shipped HTML and generated man pages. Edit the + RST sources under [`docs/`](docs/). + +## Build and test + +Open MPI uses the GNU Autotools (Autoconf / Automake / Libtool). From a +Git clone: + +```sh +./autogen.pl # regenerate the build system (one-time / after build-system changes) +./configure --prefix=/path/to/install +make -j # full builds are SLOW +make install +``` + +Out-of-tree (VPATH) builds are not required, but they are often helpful +for sanity checks because they avoid perturbing the source tree: + +```sh +mkdir build && cd build +../configure --prefix=/path/to/install +make -j +``` + +See [`docs/developers/building-open-mpi.rst`](docs/developers/building-open-mpi.rst) +and the [install docs](docs/installing-open-mpi/) for options. + +**"Did I break it?" — layered:** + +1. **Build cleanly.** A clean `make` after your change is the baseline. + Open MPI is highly configurable at build time: many components, + source files, directories, and generated artifacts are selected or + omitted by `configure` and Automake based on the local environment. + For any change to code or documentation that might be conditionally + built, verify that your configured build is actually compiling or + generating the thing you changed; do not assume this can be checked + only by looking for `#if` blocks. +2. **Documentation-only changes can be narrower.** If the change is + wholly under [`docs/`](docs/), it is often enough to configure with + Sphinx support and run `make` in the `docs/` build directory instead + of doing a full build, install, smoke test, or `make check`. Make + sure Sphinx was really enabled by `configure`; one practical check is + that `SPHINX_BUILD` in `config.status` names a valid executable. +3. **Quick smoke test.** After `make install`, put your `--prefix`'s + `bin/` on your `PATH`, then build and run an example on the local + host: + + ```sh + cd examples && make # compiles against the installed mpicc/mpifort wrappers + mpirun --np 2 ./hello_c # smallest launch + MPI_Init/Finalize sanity check + mpirun --np 2 ./ring_c # adds real point-to-point messaging + ``` +4. **Deeper validation** when your environment supports it: `make check` + and the programs under [`test/`](test/). Be aware that the full suite + and realistic MPI jobs frequently need a proper launcher and/or + multiple hosts/specialized hardware — **do not assume you can run all + of it locally, and don't report untested code as verified.** + +**Add tests for new code.** Whenever practical, add unit tests under +[`test/`](test/) that are wired into `make check` (and therefore run in +CI). Prefer a `make check`-able test over a manual one-off so the +coverage sticks and regressions are caught automatically. + +## Performance discipline + +Performance is paramount: short-message **latency** and large-message +**bandwidth** are headline metrics, along with the ability to offload +work to networking/GPU hardware so the CPU can make progress +elsewhere. Microseconds — sometimes nanoseconds — matter, and much of +the hot path uses OS-bypass techniques talking directly to network, +CUDA, and ROCm hardware. + +Concrete rules for hot paths: + +- **Don't add allocations, locks, or branches to the critical + send/receive path** without a clear, measured justification. +- **Guard debug output and expensive assertions behind + `OPAL_ENABLE_DEBUG`** so release builds pay nothing for them. +- **Prefer an MCA parameter** to a hard-coded constant when a value + might need tuning per environment. +- Keep environment-specific optimization where it belongs — generally in + OPAL or in the hardware-specific component — not smeared across + portable MPI logic. + +## Contributing + +Authoritative process: +[`docs/contributing.rst`](docs/contributing.rst). Highlights agents must +honor: + +- **Sign off every commit.** Each commit needs a `Signed-off-by:` line + per the Contributor's Declaration — use `git commit -s`. Commits + without it are not accepted. This applies to AI-assisted work too: the + human submitter certifies the contribution. +- **Commit messages:** a short first line saying *what* changed, then a + body explaining *why*. Open MPI does **not** use Conventional Commits + (`feat:`/`fix:` prefixes) — write prose. Don't add AI tooling + attribution. +- **Branch flow:** land on `main` first via a GitHub pull request, then + cherry-pick to the relevant release branch(es) `vMAJOR.MINOR.x` with a + `(cherry picked from commit ...)` line. Never commit features directly + to a release branch. See + [`docs/developers/git-github.rst`](docs/developers/git-github.rst). +- **Update the docs and the changelog** when user-visible behavior + changes: RST under [`docs/`](docs/), and a release-notes entry under + [`docs/release-notes/changelog/`](docs/release-notes/changelog/) + (`vMAJOR.MINOR.x.rst`). + +## Repository map + +| Path | What's there | +|------|--------------| +| `opal/` | OPAL portability layer (`opal/mca/` = its frameworks) | +| `ompi/` | OMPI / MPI layer; `ompi/mpi/` = language bindings, `ompi/mca/` = frameworks | +| `oshmem/` | OpenSHMEM layer | +| `3rd-party/` | embedded upstreams + submodules (OpenPMIx, PRRTE fork) — don't hand-edit | +| `config/` | m4 macros for Autoconf / Automake / Libtool | +| `docs/` | all RST documentation (Sphinx); `docs/developers/` is the dev guide | +| `examples/` | small MPI example programs (good smoke tests) | +| `test/` | unit / functional tests | +| `contrib/` | unsupported contributed scripts and tools | + +## When in doubt + +- Match the surrounding code's style and conventions — this is an old, + multi-author code base with established patterns. +- Read the relevant [`docs/developers/`](docs/developers/) page before + inventing a new pattern. +- Ask on the developer mailing list / a GitHub issue for anything large + before writing it; see [`docs/contributing.rst`](docs/contributing.rst). From e8253197d93bd6bc5e39de650c3b263f01409ed7 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 2 Jun 2026 19:01:17 -0400 Subject: [PATCH 078/230] docs: fix spelling and grammar throughout RST docs Correct clear spelling mistakes, repeated words, and grammatical issues across the RST documentation tree. This includes developer and user guides, tuning and installation docs, release notes, and MPI/OpenSHMEM man-page sources. Also fix misspelled RST labels and update their references so the documentation links continue to resolve correctly. Validation performed: - aspell scan over docs/**/*.rst with false positives manually filtered - targeted rg sweeps for common misspellings, repeated words, and grammar patterns - git diff --cached --check Signed-off-by: Jeff Squyres --- docs/app-debug/index.rst | 2 +- docs/app-debug/lost-output.rst | 2 +- docs/building-apps/abi-compatibility.rst | 2 +- docs/building-apps/deprecation-warnings.rst | 4 +- docs/building-apps/removed-mpi-constructs.rst | 2 +- docs/developers/autogen.rst | 2 +- docs/developers/rst-for-markdown-expats.rst | 2 +- docs/developers/sphinx.rst | 2 +- docs/features/extensions.rst | 2 +- docs/features/profiling.rst | 10 ++--- docs/features/ulfm.rst | 8 ++-- .../configure-cli-options/installation.rst | 2 +- .../configure-cli-options/mpi.rst | 2 +- .../installation-location.rst | 4 +- docs/installing-open-mpi/packagers.rst | 4 +- .../required-support-libraries.rst | 10 ++--- .../installing-open-mpi/supported-systems.rst | 2 +- docs/launching-apps/pmix-and-prrte.rst | 4 +- docs/launching-apps/prerequisites.rst | 2 +- docs/launching-apps/ssh.rst | 8 ++-- docs/launching-apps/troubleshooting.rst | 12 +++--- docs/man-openmpi/man1/mpirun.1.rst | 8 ++-- .../man1/ompi-wrapper-compiler.1.rst | 2 +- .../man3/MPIX_Comm_ack_failed.3.rst | 2 +- docs/man-openmpi/man3/MPIX_Comm_shrink.3.rst | 2 +- .../man3/MPIX_Query_cuda_support.3.rst | 2 +- .../man3/MPIX_Query_rocm_support.3.rst | 2 +- docs/man-openmpi/man3/MPI_Allgather.3.rst | 2 +- docs/man-openmpi/man3/MPI_Buffer_flush.3.rst | 2 +- docs/man-openmpi/man3/MPI_Comm_set_info.3.rst | 2 +- .../man3/MPI_Dist_graph_create.3.rst | 2 +- docs/man-openmpi/man3/MPI_Fetch_and_op.3.rst | 2 +- docs/man-openmpi/man3/MPI_Finalize.3.rst | 2 +- .../man-openmpi/man3/MPI_Get_accumulate.3.rst | 2 +- docs/man-openmpi/man3/MPI_Init.3.rst | 2 +- docs/man-openmpi/man3/MPI_Init_thread.3.rst | 4 +- .../man3/MPI_Reduce_scatter_block.3.rst | 2 +- .../man3/MPI_Session_get_num_psets.3.rst | 2 +- .../man3/MPI_T_source_get_timestamp.3.rst | 2 +- docs/man-openmpi/man3/MPI_Win_fence.3.rst | 2 +- docs/man-openmpi/man3/MPI_Win_post.3.rst | 2 +- docs/man-openmpi/man3/MPI_Win_set_info.3.rst | 2 +- docs/man-openmpi/man3/MPI_Wtime.3.rst | 2 +- docs/man-openshmem/man3/shmem_int_fetch.3.rst | 2 +- docs/man-openshmem/man3/shmem_wait.3.rst | 2 +- docs/mca.rst | 2 +- docs/release-notes/changelog/v1.x.rst | 40 +++++++++---------- docs/release-notes/changelog/v2.x.rst | 18 ++++----- docs/release-notes/changelog/v3.0.x.rst | 10 ++--- docs/release-notes/changelog/v3.1.x.rst | 6 +-- docs/release-notes/changelog/v4.0.x.rst | 6 +-- docs/release-notes/changelog/v4.1.x.rst | 6 +-- docs/release-notes/networks.rst | 2 +- docs/tuning-apps/accelerators/cuda.rst | 2 +- docs/tuning-apps/accelerators/memkind.rst | 2 +- docs/tuning-apps/accelerators/rocm.rst | 2 +- docs/tuning-apps/benchmarking.rst | 5 +-- docs/tuning-apps/collectives/components.rst | 6 +-- docs/tuning-apps/collectives/index.rst | 2 +- docs/tuning-apps/collectives/xhc.rst | 2 +- .../fault-tolerance/checkpoint-restart.rst | 2 +- docs/tuning-apps/large-clusters/libraries.rst | 2 +- docs/tuning-apps/mpi-io.rst | 2 +- docs/tuning-apps/networking/iwarp.rst | 2 +- docs/tuning-apps/networking/ofi.rst | 2 +- docs/tuning-apps/networking/tcp.rst | 2 +- docs/version-numbering.rst | 2 +- 67 files changed, 134 insertions(+), 135 deletions(-) diff --git a/docs/app-debug/index.rst b/docs/app-debug/index.rst index 91bf934b6c4..b3b18faa3bd 100644 --- a/docs/app-debug/index.rst +++ b/docs/app-debug/index.rst @@ -8,7 +8,7 @@ logic errors, uninitialized variables, storage overlays and timing problems. Debugging a parallel application can be further complicated -by problems that can include additional race conditions and aysynchronous +by problems that can include additional race conditions and asynchronous events, as well as understanding execution of multiple application processes running simultaneously. diff --git a/docs/app-debug/lost-output.rst b/docs/app-debug/lost-output.rst index 57af5cd5f25..9093d9f4dd0 100644 --- a/docs/app-debug/lost-output.rst +++ b/docs/app-debug/lost-output.rst @@ -18,7 +18,7 @@ MPI process when it displays the error message. If the process's memory is already corrupted, Open MPI's attempt to allocate memory may fail and the process will simply terminate, possibly silently. When Open MPI does not attempt to aggregate error messages, most of its setup -work is done when the MPI library is initiaized and no memory is allocated +work is done when the MPI library is initialized and no memory is allocated during the "print the error" routine. It therefore almost always successfully outputs error messages in real time |mdash| but at the expense that you'll potentially see the same error message for *each* MPI process that diff --git a/docs/building-apps/abi-compatibility.rst b/docs/building-apps/abi-compatibility.rst index 458362ca0ef..325379d97bf 100644 --- a/docs/building-apps/abi-compatibility.rst +++ b/docs/building-apps/abi-compatibility.rst @@ -34,7 +34,7 @@ Open MPI v4.x might not execute correctly with Open MPI |ompi_series|. compilers (e.g., GNU Fortran >= v4.9), Open MPI v5.0.0 removed the names from the MPI interfaces when there is only a single subroutine in the interface, and that subroutine name exactly - matches the iterface name. This change is likely to make Open MPI + matches the interface name. This change is likely to make Open MPI |ompi_series|'s ``mpi`` module bindings *less* restrictive than Open MPI v4.x, but it *may* also have ABI implications, depending on your Fortran compiler. diff --git a/docs/building-apps/deprecation-warnings.rst b/docs/building-apps/deprecation-warnings.rst index dabf456978d..0a0da77ea78 100644 --- a/docs/building-apps/deprecation-warnings.rst +++ b/docs/building-apps/deprecation-warnings.rst @@ -217,7 +217,7 @@ but the usage differs slightly. See the example below. // Create an info object using MPI_Info_create() ... - // Retrieve the the value of a provided key later in the code + // Retrieve the value of a provided key later in the code char key[] = "my_key"; char value[64]; int valuelen=64; @@ -248,7 +248,7 @@ Please refer to the example shown in :ref:`MPI_INFO_GET `. MPI_Sizeof ---------- -The ``MPI_SIZEOF`` construct in Fortran has been deprected since there +The ``MPI_SIZEOF`` construct in Fortran has been deprecated since there are standard Fortran language constructs such as ``c_sizeof`` and ``storage_size`` that can be used instead. diff --git a/docs/building-apps/removed-mpi-constructs.rst b/docs/building-apps/removed-mpi-constructs.rst index 4dfa5b77293..d64f7a66780 100644 --- a/docs/building-apps/removed-mpi-constructs.rst +++ b/docs/building-apps/removed-mpi-constructs.rst @@ -448,7 +448,7 @@ If we run the above, we get an output of: The ``MPI_TYPE_RESIZED`` function allows us to take any arbitrary datatype and set the lower bound and extent directly (which indirectly -sets the upper bound), without needing to setup the arrays and +sets the upper bound), without needing to set up the arrays and computing the displacements necessary to invoke ``MPI_TYPE_CREATE_STRUCT``. diff --git a/docs/developers/autogen.rst b/docs/developers/autogen.rst index 8239719623e..a740be9ddd1 100644 --- a/docs/developers/autogen.rst +++ b/docs/developers/autogen.rst @@ -4,7 +4,7 @@ Running ``autogen.pl`` You can now run OMPI's top-level ``autogen.pl`` script. This script will invoke the GNU Autoconf, Automake, and Libtool commands in the proper order and do a bunch of component discovery and housekeeping to -setup to run OMPI's top-level ``configure`` script. +set up to run OMPI's top-level ``configure`` script. Running ``autogen.pl`` may take a few minutes, depending on your system. It's not very exciting to watch. diff --git a/docs/developers/rst-for-markdown-expats.rst b/docs/developers/rst-for-markdown-expats.rst index af09f7dee33..839ca59fe98 100644 --- a/docs/developers/rst-for-markdown-expats.rst +++ b/docs/developers/rst-for-markdown-expats.rst @@ -152,7 +152,7 @@ Multi-line code/fixed-width font case, the example code block will be rendered in the bulleted item. -Whereas this parargraph and code block will be outside of the +Whereas this paragraph and code block will be outside of the above bulleted list: .. code-block:: sh diff --git a/docs/developers/sphinx.rst b/docs/developers/sphinx.rst index 0e0b2c7231e..74a53b9625b 100644 --- a/docs/developers/sphinx.rst +++ b/docs/developers/sphinx.rst @@ -131,7 +131,7 @@ under ``$HOME/Library/Python/PYTHON_VERSION/bin/sphinx-build``). Running Sphinx -------------- -Open MPI's build environment is setup to invoke Sphinx automatically; +Open MPI's build environment is set up to invoke Sphinx automatically; you should not need to invoke Sphinx manually. .. important:: You will need to ensure that Sphinx is in your ``PATH`` diff --git a/docs/features/extensions.rst b/docs/features/extensions.rst index 592d56e7687..30783693a73 100644 --- a/docs/features/extensions.rst +++ b/docs/features/extensions.rst @@ -1,4 +1,4 @@ -.. _ompi-features-extentions-label: +.. _ompi-features-extensions-label: Open MPI extensions =================== diff --git a/docs/features/profiling.rst b/docs/features/profiling.rst index e0de0597cad..626007d2f9c 100644 --- a/docs/features/profiling.rst +++ b/docs/features/profiling.rst @@ -1,10 +1,10 @@ -.. _open-mpi-profileing-label: +.. _open-mpi-profiling-label: Open MPI profiling interface ============================ -Open MPI |ompi_ver| supportings the "PMPI" profiling interface as -perscribed by the MPI standard for the C and Fortran bindings (*not* +Open MPI |ompi_ver| supports the "PMPI" profiling interface as +prescribed by the MPI standard for the C and Fortran bindings (*not* the :ref:`Open MPI Java binding extensions `). Per MPI-4.0 section 15.2.1, MPI implementations must document which @@ -15,7 +15,7 @@ level routines. In general, Open MPI's Fortran bindings are implemented on top of the C bindings. Hence, a profile developer who implements ``MPI_Init()`` -in C will also intecept all Fortran calls to ``MPI_INIT`` regardless +in C will also intercept all Fortran calls to ``MPI_INIT`` regardless of whether the user is utilizing the ``mpif.h``, ``use mpi``, or ``use mpi_f08`` Fortran interfaces. @@ -78,4 +78,4 @@ interfaces. Indeed, that is the most portable way to implement a profiling interface. Since Open MPI's Fortran bindings are |mdash| for the most part |mdash| implemented on top of its C bindings, profile developers can ignore all Fortran interfaces except for the -ones enumated above. +ones enumerated above. diff --git a/docs/features/ulfm.rst b/docs/features/ulfm.rst index 0ec3570c927..cbf8c1201a5 100644 --- a/docs/features/ulfm.rst +++ b/docs/features/ulfm.rst @@ -190,7 +190,7 @@ mpi_ft_foo `` for Open MPI options, and with ``--prtemca errmgr_detector_bar `` for PRTE options. .. important:: The main control for enabling/disabling fault tolerance - at runtime is the ``--with-ft ulfm`` (or its synomym ``--with-ft mpi``) + at runtime is the ``--with-ft ulfm`` (or its synonym ``--with-ft mpi``) ``mpirun`` CLI option. This option sets up multiple subsystems in Open MPI to enable fault tolerance. The options described below are best used to override the default behavior after the ``--with-ft ulfm`` @@ -305,7 +305,7 @@ three classifications: after a failure. 3. **Disabled:** This framework/component will cause unspecified behavior when fault tolerance is enabled. As a consequence, it will be disabled when the - ``--with-ft ulfm`` option is used (see above for defails about implicit + ``--with-ft ulfm`` option is used (see above for details about implicit parameters loaded from the ``ft-mpi`` aggregate param file). Any framework or component not listed below are categorized as **Unmodified**, @@ -371,7 +371,7 @@ ULFM Integrated in Open MPI As of |ompi_ver|, ULFM is now integrated directly in to the community release of Open MPI. The following sections describe previous ULFM -standlone releases. +standalone releases. ULFM Standalone Release 4.0.2u1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -434,7 +434,7 @@ main (November 2018). * Bugfixes: * Correct the behavior of process placement during an MPI_COMM_SPAWN - when some slots were occcupied by failed processes. + when some slots were occupied by failed processes. * MPI_COMM_SPAWN accepts process placement directives in the Info object. * Fixed deadlocks in some NBC collective operations. * Crashes and deadlocks in MPI_FINALIZE have been resolved. diff --git a/docs/installing-open-mpi/configure-cli-options/installation.rst b/docs/installing-open-mpi/configure-cli-options/installation.rst index c23877adb6b..69bd05186d4 100644 --- a/docs/installing-open-mpi/configure-cli-options/installation.rst +++ b/docs/installing-open-mpi/configure-cli-options/installation.rst @@ -147,7 +147,7 @@ be used with ``configure``: ` to build Open MPI/OpenSHMEM applications. -.. _building-ompi-cli-options-diable-dlopen-label: +.. _building-ompi-cli-options-disable-dlopen-label: * ``--enable-dlopen``: Enable Open MPI to load components as standalone Dynamic Shared Objects (DSOs) at run-time. This option diff --git a/docs/installing-open-mpi/configure-cli-options/mpi.rst b/docs/installing-open-mpi/configure-cli-options/mpi.rst index dcc35670e72..430f5c987ce 100644 --- a/docs/installing-open-mpi/configure-cli-options/mpi.rst +++ b/docs/installing-open-mpi/configure-cli-options/mpi.rst @@ -67,7 +67,7 @@ MPI API behaviors that can be used with ``configure``: * ``--enable-mpi-ext[=LIST]``: Enable Open MPI's non-portable API extensions. ``LIST`` is a - comma-delmited list of extensions. If no ``LIST`` is specified, all + comma-delimited list of extensions. If no ``LIST`` is specified, all of the extensions are enabled. See the "Open MPI API Extensions" section for more details. diff --git a/docs/installing-open-mpi/installation-location.rst b/docs/installing-open-mpi/installation-location.rst index ee90b5bb432..528a1fa713b 100644 --- a/docs/installing-open-mpi/installation-location.rst +++ b/docs/installing-open-mpi/installation-location.rst @@ -322,14 +322,14 @@ the end): #. The C constants ``MPI_F_STATUS_IGNORE`` and ``MPI_F_STATUSES_IGNORE`` will only compare properly to Fortran applications that were - created with Fortran compilers that that use the same + created with Fortran compilers that use the same name-mangling scheme as the Fortran compiler with which Open MPI was configured. #. Fortran compilers may have different values for the logical ``.TRUE.`` constant. As such, any MPI function that uses the Fortran ``LOGICAL`` type may only get ``.TRUE.`` values back that - correspond to the the ``.TRUE.`` value of the Fortran compiler with which + correspond to the ``.TRUE.`` value of the Fortran compiler with which Open MPI was configured. #. Similar to C++, linking object files that Fortran language features such diff --git a/docs/installing-open-mpi/packagers.rst b/docs/installing-open-mpi/packagers.rst index c0fb13ea23a..d0ad8e9defe 100644 --- a/docs/installing-open-mpi/packagers.rst +++ b/docs/installing-open-mpi/packagers.rst @@ -25,7 +25,7 @@ the following: # Install Sphinx so that Open MPI can re-build its docs with the # installed PRRTE's docs - virtualalenv venv + virtualenv venv . ./venv/bin/activate pip install docs/requirements.txt @@ -145,7 +145,7 @@ performance savings. .. note:: If not using a networked filesystem, or if not launching at scale, loading a large number of DSO files may not consume a noticeable amount of time during MPI process launch. Put - simply: loading DSOs as indvidual files generally only + simply: loading DSOs as individual files generally only matters when using a networked filesystem while launching at scale. diff --git a/docs/installing-open-mpi/required-support-libraries.rst b/docs/installing-open-mpi/required-support-libraries.rst index 983608a3fb9..2e8944bc51f 100644 --- a/docs/installing-open-mpi/required-support-libraries.rst +++ b/docs/installing-open-mpi/required-support-libraries.rst @@ -29,7 +29,7 @@ system. compared to later versions. Other than the Hwloc restriction about v3.0.0 and beyond - (see below), the Open MPI community generally recomends + (see below), the Open MPI community generally recommends using the latest available version of Hwloc unless there is a specific reason not to. @@ -88,7 +88,7 @@ system. may still have bugs and/or have less functionality as compared to later versions. - The Open MPI community generally recomends using the + The Open MPI community generally recommends using the latest available version of OpenPMIx unless there is a specific reason not to. @@ -114,7 +114,7 @@ system. and run with |prte_min_version|, you will not get a fully-populated ``mpirun(1)`` man page. - The Open MPI community generally recomends using the + The Open MPI community generally recommends using the latest available version of PRRTE unless there is a specific reason not to. @@ -277,7 +277,7 @@ Build example 1 * If ``configure`` is unable to find header files and libraries for PMIx, Hwloc, and Libevent elsewhere on the build machine (i.e., - assumedly the same PMIx, Hwloc, and Libevent than the PRRTE in + presumably the same PMIx, Hwloc, and Libevent as the PRRTE in ``/usr/local`` is using), this is an error: ``configure`` will abort, and therefore refuse to build Open MPI. @@ -298,7 +298,7 @@ will cause the following to occur: * If ``configure`` is unable to find header files and libraries for Hwloc and Libevent elsewhere on the build machine (i.e., - assumedly the same Hwloc and Libevent than the PMIx in + presumably the same Hwloc and Libevent as the PMIx in ``/opt/local`` is using), this is an error: ``configure`` will abort, and therefore refuse to build Open MPI. diff --git a/docs/installing-open-mpi/supported-systems.rst b/docs/installing-open-mpi/supported-systems.rst index 45b4ecd821b..76b6ef39930 100644 --- a/docs/installing-open-mpi/supported-systems.rst +++ b/docs/installing-open-mpi/supported-systems.rst @@ -14,7 +14,7 @@ operating systems supported has changed over time (e.g., native Microsoft Windows support was added in v1.3.3, and although it was removed prior to v1.8, is still supported through Cygwin). :ref:`See the Platform Notes section ` for a -listing of the OSes that that version supports. +listing of the OSes that version supports. Open MPI is fairly POSIX-neutral, so it will run without *too* many modifications on most POSIX-like systems. Hence, if we haven't listed diff --git a/docs/launching-apps/pmix-and-prrte.rst b/docs/launching-apps/pmix-and-prrte.rst index 11183f57925..61dcb96766b 100644 --- a/docs/launching-apps/pmix-and-prrte.rst +++ b/docs/launching-apps/pmix-and-prrte.rst @@ -28,7 +28,7 @@ abstractions and configuration options belong to Open MPI vs. PMIx vs. PRRTE. Advanced users can peek into the PMIx and PRRTE internals and tweak -additional configuration settings if necessary, but we hope that that +additional configuration settings if necessary, but we hope that will rarely be necessary. PMIx @@ -48,7 +48,7 @@ PMIx presents a unified API that hides many of the complexities of communication with these back-end run-time environments. Open MPI uses the PMIx API to discover, communicate, and coordinate with any supported back-end run-time system without needing to know the -intimiate details of that system. +intimate details of that system. PRRTE ----- diff --git a/docs/launching-apps/prerequisites.rst b/docs/launching-apps/prerequisites.rst index 036ba915a64..582c27e9c54 100644 --- a/docs/launching-apps/prerequisites.rst +++ b/docs/launching-apps/prerequisites.rst @@ -66,7 +66,7 @@ For example: Additionally, Open MPI requires that jobs can be started on remote nodes without any input from the keyboard. For example, if using -``ssh`` as the remote agent, you must have your environment setup to +``ssh`` as the remote agent, you must have your environment set up to allow execution on remote nodes without entering a password or passphrase. diff --git a/docs/launching-apps/ssh.rst b/docs/launching-apps/ssh.rst index 39bd04a2732..3251bfd9f74 100644 --- a/docs/launching-apps/ssh.rst +++ b/docs/launching-apps/ssh.rst @@ -50,7 +50,7 @@ There are three mechanisms for specifying the hosts that an MPI job will run on: Non-interactive ``ssh`` logins ------------------------------ -SSH keys must be setup such that the following can be executed without +SSH keys must be set up such that the following can be executed without being prompted for password or passphrase: .. code-block:: sh @@ -60,7 +60,7 @@ being prompted for password or passphrase: shell$ Consult instructions and tutorials from around the internet to learn -how to setup SSH keys. Try Google search terms like "passwordless +how to set up SSH keys. Try Google search terms like "passwordless SSH" or "SSH key authentication". For simplicity, it may be desirable to configure your SSH keys @@ -75,12 +75,12 @@ comfortable with. or passphrase |mdash| *to any node* in the host list *from any node* in the host list. - It may *not* be sufficient to only setup an SSH key from the node + It may *not* be sufficient to only set up an SSH key from the node where you are invoking :ref:`mpirun(1) ` to all other nodes. If you have a shared ``$HOME`` filesystem between your nodes, you can -setup a single SSH key that is used to login to all nodes. +set up a single SSH key that is used to login to all nodes. Finding Open MPI executables and libraries ------------------------------------------ diff --git a/docs/launching-apps/troubleshooting.rst b/docs/launching-apps/troubleshooting.rst index e5ed1618a48..629f1b90d9d 100644 --- a/docs/launching-apps/troubleshooting.rst +++ b/docs/launching-apps/troubleshooting.rst @@ -77,7 +77,7 @@ Errors about missing libraries When building Open MPI with the compilers that have libraries in non-default search path locations, you may see errors about those compiler's support libraries when trying to launch MPI applications if -their corresponding environments were not setup properly. +their corresponding environments were not set up properly. For example, you may see warnings similar to the following: @@ -107,13 +107,13 @@ Specifically, Open MPI first attempts to launch a "helper" daemon libraries shown above (``libimf.so``, ``libpgcc.so``, and ``libmv.so``) are specific to their compiler suites (Intel, PGI, and PathScale, respectively). As such, it is likely that the user did not -setup the compiler library in their environment properly on this node. +set up the compiler library in their environment properly on this node. -Double check that you have setup the appropriate compiler environment +Double check that you have set up the appropriate compiler environment on the target node, for both interactive and non-interactive logins. .. note:: It is a common error to ensure that the compiler environment - is setup properly for *interactive* logins, but not for + is set up properly for *interactive* logins, but not for *non-interactive* logins. Here's an example of a user-compiled MPI application working fine @@ -142,7 +142,7 @@ locally, but failing when invoked non-interactively on a remote node: mpi_hello: error while loading shared libraries: libimf.so: cannot open shared object file: No such file or directory In cases like this, check your shell script startup files and verify -that the appropriate compiler environment is setup properly for +that the appropriate compiler environment is set up properly for non-interactive logins. Problems when running across multiple hosts @@ -162,7 +162,7 @@ them across multiple hosts, try the following: remotehost If you are unable to launch across multiple hosts, check that your - SSH keys are setup properly. Or, if you are running in a managed + SSH keys are set up properly. Or, if you are running in a managed environment, such as in a Slurm, Torque, or other job launcher, check that you have reserved enough hosts, are running in an allocated job, etc. diff --git a/docs/man-openmpi/man1/mpirun.1.rst b/docs/man-openmpi/man1/mpirun.1.rst index 33412896104..b970e2d5d6d 100644 --- a/docs/man-openmpi/man1/mpirun.1.rst +++ b/docs/man-openmpi/man1/mpirun.1.rst @@ -1157,7 +1157,7 @@ If only ``--bind-to OBJ`` is specified, then ``--map-by`` is determined by the n R2 hostA [../../../../../../../..][BB/../../../../../../..] R3 hostA [../../../../../../../..][../BB/../../../../../..] -The mapping pattern might be better seen if we change the default ``--rank-by`` from ``fill`` to ``span``. First, the processes are mapped by package iterating between the two marking a core at a time. Next, the processes are ranked in a spanning manner that load balances them across the object they were mapped against. Finally, the processes are bound to the core that they were mapped againast. +The mapping pattern might be better seen if we change the default ``--rank-by`` from ``fill`` to ``span``. First, the processes are mapped by package iterating between the two marking a core at a time. Next, the processes are ranked in a spanning manner that load balances them across the object they were mapped against. Finally, the processes are bound to the core that they were mapped against. .. code:: @@ -1206,12 +1206,12 @@ Means that: * Rank 1 runs on node bb, bound to logical package 0, cores 0 and 1. * Rank 2 runs on node cc, bound to logical cores 2 and 3. -Note that only logicical processor locations are supported. By default, the values specified are assumed to be cores. If you intend to specify specific hardware threads then you must add the ``:hwtcpus`` qualifier to the ``--map-by`` command line option (e.g., ``--map-by rankfile:file=myrankfile:hwtcpus``). +Note that only logical processor locations are supported. By default, the values specified are assumed to be cores. If you intend to specify specific hardware threads then you must add the ``:hwtcpus`` qualifier to the ``--map-by`` command line option (e.g., ``--map-by rankfile:file=myrankfile:hwtcpus``). If the binding specification overlaps between any two ranks then an error occurs. If you intend to allow processes to share the same logical processing unit then you must pass the ``--bind-to :overload-allowed`` command line option to tell the runtime to ignore this check. The hostnames listed above are "absolute," meaning that actual -resolveable hostnames are specified. However, hostnames can also be +resolvable hostnames are specified. However, hostnames can also be specified as "relative," meaning that they are specified in relation to an externally-specified list of hostnames (e.g., by ``mpirun``'s ``--host`` argument, a hostfile, or a job scheduler). @@ -1230,7 +1230,7 @@ hostnames, indexed from 0. For example: All package/core slot locations are specified as logical indexes. -.. note:: The Open MPI v1.6 series used physical indexes. Starting in Open MPI v5.0 only logicial indexes are supported and the ``rmaps_rank_file_physical`` MCA parameter is no longer recognized. +.. note:: The Open MPI v1.6 series used physical indexes. Starting in Open MPI v5.0 only logical indexes are supported and the ``rmaps_rank_file_physical`` MCA parameter is no longer recognized. You can use tools such as Hwloc's `lstopo(1)` to find the logical indexes of package and cores. diff --git a/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst b/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst index 249de903ad2..4f60cbfbd8b 100644 --- a/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst +++ b/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst @@ -117,7 +117,7 @@ Open MPI provides wrapper compilers for several languages: underlying C++ compiler with the same options. All are provided as compatibility with other MPI implementations. -* ``mpifort`` (and its legacy/deprecated aliaes ``mpif77`` and +* ``mpifort`` (and its legacy/deprecated aliases ``mpif77`` and ``mpif90``): Fortran * ``mpijavac``: Java diff --git a/docs/man-openmpi/man3/MPIX_Comm_ack_failed.3.rst b/docs/man-openmpi/man3/MPIX_Comm_ack_failed.3.rst index 0302b889a5b..b02e3de4dcd 100644 --- a/docs/man-openmpi/man3/MPIX_Comm_ack_failed.3.rst +++ b/docs/man-openmpi/man3/MPIX_Comm_ack_failed.3.rst @@ -90,7 +90,7 @@ class MPI_ERR_PROC_FAILED due to this acknowledged failure. USAGE PATTERNS -------------- -One may query, without side effect, for the number of currently aknowledged +One may query, without side effect, for the number of currently acknowledged process failures *comm* by supplying 0 in *num_to_ack*. Conversely, one may unconditionally acknowledge all currently known process diff --git a/docs/man-openmpi/man3/MPIX_Comm_shrink.3.rst b/docs/man-openmpi/man3/MPIX_Comm_shrink.3.rst index 1bbf94ba44c..0b7ad568177 100644 --- a/docs/man-openmpi/man3/MPIX_Comm_shrink.3.rst +++ b/docs/man-openmpi/man3/MPIX_Comm_shrink.3.rst @@ -104,7 +104,7 @@ group of *comm* contains failed MPI processes. In particular, even when *comm* is revoked. The implementation will strive to detect all failures during the shrink -operation, but in certain circumpstances, the group of *newcomm* may still +operation, but in certain circumstances, the group of *newcomm* may still contain failed MPI processes, whose failure will be detected in subsequent MPI operations on *newcomm*. diff --git a/docs/man-openmpi/man3/MPIX_Query_cuda_support.3.rst b/docs/man-openmpi/man3/MPIX_Query_cuda_support.3.rst index 302c478b60b..9635f3f6edf 100644 --- a/docs/man-openmpi/man3/MPIX_Query_cuda_support.3.rst +++ b/docs/man-openmpi/man3/MPIX_Query_cuda_support.3.rst @@ -41,7 +41,7 @@ DESCRIPTION ----------- This function is part of an :ref:`Open MPI extension -`; it is not part of standard MPI. +`; it is not part of standard MPI. This routine returns 1 if both the MPI library was built with the NVIDIA CUDA library and the runtime supports CUDA buffers. Otherwise, diff --git a/docs/man-openmpi/man3/MPIX_Query_rocm_support.3.rst b/docs/man-openmpi/man3/MPIX_Query_rocm_support.3.rst index 59f6148079a..005a4176e50 100644 --- a/docs/man-openmpi/man3/MPIX_Query_rocm_support.3.rst +++ b/docs/man-openmpi/man3/MPIX_Query_rocm_support.3.rst @@ -41,7 +41,7 @@ DESCRIPTION ----------- This function is part of an :ref:`Open MPI extension -`; it is not part of standard MPI. +`; it is not part of standard MPI. This routine returns 1 if both the MPI library was built with the AMD ROCm library and the runtime supports ROCm buffers. Otherwise, it diff --git a/docs/man-openmpi/man3/MPI_Allgather.3.rst b/docs/man-openmpi/man3/MPI_Allgather.3.rst index 2d7926bb5cb..9013adae7ff 100644 --- a/docs/man-openmpi/man3/MPI_Allgather.3.rst +++ b/docs/man-openmpi/man3/MPI_Allgather.3.rst @@ -112,7 +112,7 @@ first group and received by all the members of the second group. Then the data is gathered from all the members of the second group and received by all the members of the first. The operation, however, need not be symmetric. The number of items sent by the processes in first -group need not be equal to the number of items sent by the the processes +group need not be equal to the number of items sent by the processes in the second group. You can move data in only one direction by giving *sendcount* a value of 0 for communication in the reverse direction. diff --git a/docs/man-openmpi/man3/MPI_Buffer_flush.3.rst b/docs/man-openmpi/man3/MPI_Buffer_flush.3.rst index e712479baac..5446825e827 100644 --- a/docs/man-openmpi/man3/MPI_Buffer_flush.3.rst +++ b/docs/man-openmpi/man3/MPI_Buffer_flush.3.rst @@ -6,7 +6,7 @@ MPI_Buffer_flush .. include_body :ref:`MPI_Buffer_flush`, :ref:`MPI_Buffer_iflush` |mdash| Wait till all messages currently in -the the MPI process specific buffer of the calling MPI process have been transmitted. +the MPI process specific buffer of the calling MPI process have been transmitted. .. The following directive tells the man page generation script to generate multiple bindings for this file. diff --git a/docs/man-openmpi/man3/MPI_Comm_set_info.3.rst b/docs/man-openmpi/man3/MPI_Comm_set_info.3.rst index e94d51e83e4..7f1892760af 100644 --- a/docs/man-openmpi/man3/MPI_Comm_set_info.3.rst +++ b/docs/man-openmpi/man3/MPI_Comm_set_info.3.rst @@ -26,7 +26,7 @@ DESCRIPTION :ref:`MPI_Comm_set_info` sets new values for the hints of the communicator associated with *comm*. :ref:`MPI_Comm_set_info` is a collective routine. The info object may be different on each process, but any info entries that -an implementation requires to be the same on all processes must appear +an implementation requires to have identical values on all processes must appear with the same value in each process's *info* object. The following info key assertions may be accepted by Open MPI: diff --git a/docs/man-openmpi/man3/MPI_Dist_graph_create.3.rst b/docs/man-openmpi/man3/MPI_Dist_graph_create.3.rst index 51c98bc3fd2..6452255d2e8 100644 --- a/docs/man-openmpi/man3/MPI_Dist_graph_create.3.rst +++ b/docs/man-openmpi/man3/MPI_Dist_graph_create.3.rst @@ -48,7 +48,7 @@ this edge is stored in *weights*\ [*degrees*\ [0]+...+\ *degrees*\ [i-1]+j]. Both the *sources* and the *destinations* arrays may contain the same node more than once, and the order in which nodes are listed as destinations or sources is -not signicant. Similarly, different processes may specify edges with the +not significant. Similarly, different processes may specify edges with the same source and destination nodes. Source and destination nodes must be process ranks of comm_old. Different processes may specify different numbers of source and destination nodes, as well as different source to diff --git a/docs/man-openmpi/man3/MPI_Fetch_and_op.3.rst b/docs/man-openmpi/man3/MPI_Fetch_and_op.3.rst index 48b163f0eee..f2f5e884ca8 100644 --- a/docs/man-openmpi/man3/MPI_Fetch_and_op.3.rst +++ b/docs/man-openmpi/man3/MPI_Fetch_and_op.3.rst @@ -46,7 +46,7 @@ the associative function f(a, b) =b; that is, the current value in the target memory is replaced by the value supplied by the origin. A new predefined operation, MPI_NO_OP, is defined. It corresponds to the -assiciative function f(a, b) = a; that is the current value in the +associative function f(a, b) = a; that is the current value in the target memory is returned in the result buffer at the origin and no operation is performed on the target buffer. diff --git a/docs/man-openmpi/man3/MPI_Finalize.3.rst b/docs/man-openmpi/man3/MPI_Finalize.3.rst index bf52247e205..faad83e83dc 100644 --- a/docs/man-openmpi/man3/MPI_Finalize.3.rst +++ b/docs/man-openmpi/man3/MPI_Finalize.3.rst @@ -65,7 +65,7 @@ some other verification of completion. For example, a successful return from a blocking communication operation or from one of the :ref:`MPI_Wait` or :ref:`MPI_Test` -varients means that the communication is completed by the user and the +variants means that the communication is completed by the user and the buffer can be reused, but does not guarantee that the local process has no more work to do. Similarly, a successful return from :ref:`MPI_Request_free` with a request handle generated by an diff --git a/docs/man-openmpi/man3/MPI_Get_accumulate.3.rst b/docs/man-openmpi/man3/MPI_Get_accumulate.3.rst index 5a717ef5836..68e47135c71 100644 --- a/docs/man-openmpi/man3/MPI_Get_accumulate.3.rst +++ b/docs/man-openmpi/man3/MPI_Get_accumulate.3.rst @@ -70,7 +70,7 @@ the associative function f(a, b) =b; that is, the current value in the target memory is replaced by the value supplied by the origin. A new predefined operation, MPI_NO_OP, is defined. It corresponds to the -assiciative function f(a, b) = a; that is the current value in the +associative function f(a, b) = a; that is the current value in the target memory is returned in the result buffer at the origin and no operation is performed on the target buffer. diff --git a/docs/man-openmpi/man3/MPI_Init.3.rst b/docs/man-openmpi/man3/MPI_Init.3.rst index 6df7d039cc2..b3bd1182c89 100644 --- a/docs/man-openmpi/man3/MPI_Init.3.rst +++ b/docs/man-openmpi/man3/MPI_Init.3.rst @@ -45,7 +45,7 @@ interprets, nor distributes them: int main(int argv, char *argv[]) { MPI_Init(&argc, &argv); - /* ...body of main MPI pogram... */ + /* ...body of main MPI program... */ MPI_Finalize(); return 0; } diff --git a/docs/man-openmpi/man3/MPI_Init_thread.3.rst b/docs/man-openmpi/man3/MPI_Init_thread.3.rst index 8d77ba17d50..e9068b0c20d 100644 --- a/docs/man-openmpi/man3/MPI_Init_thread.3.rst +++ b/docs/man-openmpi/man3/MPI_Init_thread.3.rst @@ -58,7 +58,7 @@ neither modifies, interprets, nor distributes them: int main(int argv, char *argv[]) { int provided; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); - /* ...body of main MPI pogram... */ + /* ...body of main MPI program... */ MPI_Finalize(); return 0; } @@ -142,7 +142,7 @@ of the values listed below. environment variable. Starting with Open MPI v6.0.0, the Open MPI community - recomends using one of the string name variants so that it + recommends using one of the string name variants so that it can be correctly mapped to the corresponding Open MPI ABI value or the MPI Standard ABI value, as relevant. diff --git a/docs/man-openmpi/man3/MPI_Reduce_scatter_block.3.rst b/docs/man-openmpi/man3/MPI_Reduce_scatter_block.3.rst index 0d4ab22de09..ee1188af231 100644 --- a/docs/man-openmpi/man3/MPI_Reduce_scatter_block.3.rst +++ b/docs/man-openmpi/man3/MPI_Reduce_scatter_block.3.rst @@ -20,7 +20,7 @@ results in blocks. INPUT PARAMETERS ---------------- * ``sendbuf``: Starting address of send buffer (choice). -* ``recvcount``: lement count per block (non-negative integer). +* ``recvcount``: Element count per block (non-negative integer). * ``datatype``: Datatype of elements of input buffer (handle). * ``op``: Operation (handle). * ``comm``: Communicator (handle). diff --git a/docs/man-openmpi/man3/MPI_Session_get_num_psets.3.rst b/docs/man-openmpi/man3/MPI_Session_get_num_psets.3.rst index 032080dd172..839da2ea922 100644 --- a/docs/man-openmpi/man3/MPI_Session_get_num_psets.3.rst +++ b/docs/man-openmpi/man3/MPI_Session_get_num_psets.3.rst @@ -20,7 +20,7 @@ INPUT PARAMETERS OUTPUT PARAMETERS ----------------- -* ``npset_names`` : number of available process sets (non-negtive integer) +* ``npset_names`` : number of available process sets (non-negative integer) * ``ierror`` : Fortran only: Error status (integer). DESCRIPTION diff --git a/docs/man-openmpi/man3/MPI_T_source_get_timestamp.3.rst b/docs/man-openmpi/man3/MPI_T_source_get_timestamp.3.rst index d7d67bc32da..96c7d7a0b1a 100644 --- a/docs/man-openmpi/man3/MPI_T_source_get_timestamp.3.rst +++ b/docs/man-openmpi/man3/MPI_T_source_get_timestamp.3.rst @@ -22,7 +22,7 @@ OUTPUT PARAMETERS DESCRIPTION ----------- -:ref:`MPI_T_source_get_timestamp` returns the current timestamp from the specificed source. +:ref:`MPI_T_source_get_timestamp` returns the current timestamp from the specified source. ERRORS diff --git a/docs/man-openmpi/man3/MPI_Win_fence.3.rst b/docs/man-openmpi/man3/MPI_Win_fence.3.rst index c37aa7433d8..90eb3a4fe06 100644 --- a/docs/man-openmpi/man3/MPI_Win_fence.3.rst +++ b/docs/man-openmpi/man3/MPI_Win_fence.3.rst @@ -60,7 +60,7 @@ MPI_MODE_NOSTORE MPI_MODE_NOPUT Informs that the local window will not be updated by any put or - accummulate calls in the ensuing epoch (until next fence call). + accumulate calls in the ensuing epoch (until next fence call). MPI_MODE_NOSUCCEED No local RMA calls will be issued after this fence. This assertion diff --git a/docs/man-openmpi/man3/MPI_Win_post.3.rst b/docs/man-openmpi/man3/MPI_Win_post.3.rst index fbbf122588a..53212ef02c6 100644 --- a/docs/man-openmpi/man3/MPI_Win_post.3.rst +++ b/docs/man-openmpi/man3/MPI_Win_post.3.rst @@ -46,7 +46,7 @@ MPI_MODE_NOSTORE MPI_MODE_NOPUT Informs that the local window will not be updated by put or - accummulate calls until the ensuing wait synchronization. + accumulate calls until the ensuing wait synchronization. ERRORS diff --git a/docs/man-openmpi/man3/MPI_Win_set_info.3.rst b/docs/man-openmpi/man3/MPI_Win_set_info.3.rst index 69de8bf2894..30aabb87f62 100644 --- a/docs/man-openmpi/man3/MPI_Win_set_info.3.rst +++ b/docs/man-openmpi/man3/MPI_Win_set_info.3.rst @@ -26,7 +26,7 @@ DESCRIPTION :ref:`MPI_WIN_SET_INFO` sets new values for the hints of the window associated with *win.* :ref:`MPI_WIN_SET_INFO` is a collective routine. The info object may be different on each process, but any info entries that an -implementation requires to be the same on all processes must appear with +implementation requires to have identical values on all processes must appear with the same value in each process's *info* object. diff --git a/docs/man-openmpi/man3/MPI_Wtime.3.rst b/docs/man-openmpi/man3/MPI_Wtime.3.rst index 9baeef4c46d..70edf333f3d 100644 --- a/docs/man-openmpi/man3/MPI_Wtime.3.rst +++ b/docs/man-openmpi/man3/MPI_Wtime.3.rst @@ -70,7 +70,7 @@ function will be used to obtain a monotonic clock value with whatever precision is supported on that platform (e.g., nanoseconds). Note, too, that the MCA parameter opal_timer_require_monotonic can -influcence this behavior. It defaults to true, but if set to false, Open +influence this behavior. It defaults to true, but if set to false, Open MPI may use a finer-grained timing mechanism (e.g., the RDTSC/RDTSCP clock ticks on x86_64 platforms), but is not guaranteed to be monotonic in some cases (e.g., if the MPI process is not bound to a single diff --git a/docs/man-openshmem/man3/shmem_int_fetch.3.rst b/docs/man-openshmem/man3/shmem_int_fetch.3.rst index 29f8d0aaf31..ddb254b0bf8 100644 --- a/docs/man-openshmem/man3/shmem_int_fetch.3.rst +++ b/docs/man-openshmem/man3/shmem_int_fetch.3.rst @@ -75,7 +75,7 @@ RETURN VALUES ------------- The contents at the *target* address on the remote PE. The data type of -the return value is the same as the the type of the remote data object. +the return value is the same as the type of the remote data object. .. seealso:: diff --git a/docs/man-openshmem/man3/shmem_wait.3.rst b/docs/man-openshmem/man3/shmem_wait.3.rst index 5b5fd861e65..881c8d1e512 100644 --- a/docs/man-openshmem/man3/shmem_wait.3.rst +++ b/docs/man-openshmem/man3/shmem_wait.3.rst @@ -139,7 +139,7 @@ cmp cmp_value cmp_value must be of type integer. If you are using C/C++, the type - of cmp_value should match thatimplied in the SYNOPSIS section. If you + of cmp_value should match that implied in the SYNOPSIS section. If you are using Fortran, cmp_value must be an integer of the same size and kind as ivar. The :ref:`shmem_wait` routines return when ivar is no longer equal to cmp_value. The :ref:`shmem_wait_until` routines return when the diff --git a/docs/mca.rst b/docs/mca.rst index 0c8256a4e55..5a4f2b4b1e4 100644 --- a/docs/mca.rst +++ b/docs/mca.rst @@ -138,7 +138,7 @@ thumb that the developers use are: #. Instead of using a constant for an important value, make it an MCA parameter. #. If a task can be implemented in multiple, user-discernible ways, - implement as many as possible, and use an an MCA parameter to + implement as many as possible, and use an MCA parameter to choose between them at run-time. For example, an easy MCA parameter to describe is the boundary between diff --git a/docs/release-notes/changelog/v1.x.rst b/docs/release-notes/changelog/v1.x.rst index b945177598c..a6180d0a1d3 100644 --- a/docs/release-notes/changelog/v1.x.rst +++ b/docs/release-notes/changelog/v1.x.rst @@ -14,7 +14,7 @@ Open MPI version 1.10.7 - Fix bug in TCP BTL that impacted performance on 10GbE (and faster) networks by not adjusting the TCP send/recv buffer sizes and using system default values -- Add missing MPI_AINT_ADD and MPI_AINT_DIFF function delcarations in +- Add missing MPI_AINT_ADD and MPI_AINT_DIFF function declarations in mpif.h - Fixed time reported by MPI_WTIME; it was previously reported as dependent upon the CPU frequency. @@ -340,7 +340,7 @@ Open MPI version 1.10.0 - Fixed a variety of small bugs in OpenSHMEM. - Fixed MXM configure with additional CPPFLAGS and LDFLAGS. Thanks to David Shrader for the patch. -- Fixed incorrect memalign threshhold in the openib BTL. Thanks to +- Fixed incorrect memalign threshold in the openib BTL. Thanks to Xavier Besseron for pointing out the issue. @@ -503,7 +503,7 @@ Open MPI version 1.8.4 - Fix MPI_SIZEOF; now available in mpif.h for modern Fortran compilers (see README for more details). Also fixed various compiler/linker errors. -- Fixed inadvertant Fortran ABI break between v1.8.1 and v1.8.2 in the +- Fixed inadvertent Fortran ABI break between v1.8.1 and v1.8.2 in the mpi interface module when compiled with gfortran >= v4.9. - Fix various MPI_THREAD_MULTIPLE issues in the TCP BTL. - mpirun no longer requires the ``--hetero-nodes`` switch; it will @@ -694,7 +694,7 @@ Open MPI version 1.7.5 - Fix MPI_GRAPH_CREATE when nnodes is smaller than the size of the old communicator. - usnic BTL now supports underlying UDP transport. -- usnic BTL now checks for common connectivty errors at first send to +- usnic BTL now checks for common connectivity errors at first send to a remote server. - Minor scalability improvements in the usnic BTL. - ompi_info now lists whether the Java MPI bindings are available or not. @@ -782,7 +782,7 @@ Open MPI version 1.7.4 - Prevent integer overflow when creating datatypes. Thanks to original patch from Gilles Gouaillardet. - Port some upstream hwloc fixes to Open MPI's embedded copy for - working around buggy NUMA node cpusets and including mising header + working around buggy NUMA node cpusets and including missing header files. Thanks to Jeff Becker and Paul Hargrove for reporting the issues. - Fix recursive invocation issues in the MXM MTL. @@ -1060,7 +1060,7 @@ Open MPI version 1.7.0 MCA params). - Upgraded to hwloc v1.5.1. - Added performance improvements to the OpenIB (OpenFabrics) BTL. -- Made malloc hooks more friendly to IO interprosers. Thanks to the +- Made malloc hooks more friendly to IO interposers. Thanks to the bug report and suggested fix from Darshan maintainer Phil Carns. - Added support for the DMTCP checkpoint/restart system. - Added support for the Cray uGNI interconnect. @@ -1217,7 +1217,7 @@ Open MPI version 1.6.4 - Improved error message when process affinity fails. - Fixed MPI_MINLOC on man pages for MPI_REDUCE(_LOCAL). Thanks to Jed Brown for noticing the problem and supplying a fix. -- Made malloc hooks more friendly to IO interprosers. Thanks to the +- Made malloc hooks more friendly to IO interposers. Thanks to the bug report and suggested fix from Darshan maintainer Phil Carns. - Restored ability to direct launch under SLURM without PMI support. - Fixed MPI datatype issues on OpenBSD. @@ -1296,7 +1296,7 @@ Open MPI version 1.6.1 https://www.open-mpi.org/faq/?category=openfabrics#ib-low-reg-mem - Fall back to send/receive semantics if registered memory is - unavilable for RDMA. + unavailable for RDMA. - Fix two fragment leaks when registered memory is exhausted. - Hueristically determine how much registered memory is available and warn if it's significantly less than all of RAM. @@ -1317,7 +1317,7 @@ Open MPI version 1.6.1 OpenFabrics devices. - Lots of VampirTrace fixes; upgrade to v5.13.0.4. - Map MPI_2INTEGER to underlying MPI_INTEGERs, not MPI_INTs. -- Ensure that the OMPI version number is toleant of handling spaces. +- Ensure that the OMPI version number is tolerant of handling spaces. Thanks to dragonboy for identifying the issue. - Fixed IN parameter marking on Fortran "mpi" module MPI_COMM_TEST_INTER interface. @@ -1810,7 +1810,7 @@ Open MPI version 1.4.4 to Avinash Malik for reporting the issue. - Fix for correctly handling multi-token args when using debuggers. - Eliminated the unneeded ``u_int*_t`` datatype definitions. -- Change in ORTE DPM to get around gcc 4.[45].x compiler wanrings +- Change in ORTE DPM to get around gcc 4.[45].x compiler warnings about possibly calling free() on a non-heap variable, even though it will never happen because the refcount will never go to zero. - Fixed incorrect text in MPI_File_set_view man page. @@ -1889,7 +1889,7 @@ Open MPI version 1.4.3 - Change to ensure TotalView works properly on Darwin. - Added support for Visual Studio 2010. - Fix to ensure proper placement of VampirTrace header files. -- Needed to add volatile keyword to a varialbe used in debugging +- Needed to add volatile keyword to a variable used in debugging (MPIR_being_debugged). - Fixed a bug in inter-allgather. - Fixed malloc(0) warnings. @@ -2275,7 +2275,7 @@ Open MPI version 1.3.0 - Added ``btl_openib_if_[in|ex]clude`` MCA parameters for including/excluding comma-delimited lists of HCAs and ports. - - Added RDMA CM support, includng ``btl_openib_cpc_[in|ex]clude`` + - Added RDMA CM support, including ``btl_openib_cpc_[in|ex]clude`` MCA parameters - Added NUMA support to only use "near" network adapters - Added "Bucket SRQ" (BSRQ) support to better utilize registered @@ -2283,7 +2283,7 @@ Open MPI version 1.3.0 - Added ConnectX XRC support (and integrated with BSRQ) - Added btl_openib_ib_max_inline_data MCA parameter - Added iWARP support - - Revamped flow control mechansisms to be more efficient + - Revamped flow control mechanisms to be more efficient - ``mpi_leave_pinned=1`` is now the default when possible, automatically improving performance for large messages when application buffers are re-used @@ -2305,7 +2305,7 @@ Open MPI version 1.3.0 predefined datatypes in the fortran header files, there will not be any compatibility issues. - Added Portable Linux Processor Affinity (PLPA) for Linux. -- Addition of a finer symbols export control via the visibiliy feature +- Addition of a finer symbols export control via the visibility feature offered by some compilers. - Added checkpoint/restart process fault tolerance support. Initially support a LAM/MPI-like protocol. @@ -2318,7 +2318,7 @@ Open MPI version 1.3.0 use leave_pinned with ptmalloc2 will now need to link the library into their application explicitly. All other users will use the libc-provided allocator instead of Open MPI's ptmalloc2. This change - may be overriden with the configure option enable-ptmalloc2-internal + may be overridden with the configure option enable-ptmalloc2-internal - The leave_pinned options will now default to using mallopt on Linux in the cases where ptmalloc2 was not linked in. mallopt will also only be available if munmap can be intercepted (the @@ -2355,7 +2355,7 @@ Open MPI version 1.2.9 - Fix the ``--enable-cxx-exceptions`` configure option. See ticket #1607. - Properly handle when the MX BTL cannot open an endpoint. See ticket #1621. - Fix a double free of events on the tcp_events list. See ticket #1631. -- Fix a buffer overun in opal_free_list_grow (called by MPI_Init). +- Fix a buffer overrun in opal_free_list_grow (called by MPI_Init). Thanks to Patrick Farrell for the bugreport and Stephan Kramer for the bugfix. See ticket #1583. - Fix a problem setting OPAL_PREFIX for remote sh-based shells. @@ -2824,7 +2824,7 @@ Open MPI version 1.1.2 - Fix receiving messages to buffers allocated by MPI_ALLOC_MEM. - Fix a number of race conditions with the MPI-2 Onesided interface. -- Fix the "tuned" collective componenete where some cases where +- Fix the "tuned" collective component where some cases where MPI_BCAST could hang. - Update TCP support to support non-uniform TCP environments. - Allow the "poe" RAS component to be built on AIX or Linux. @@ -2841,7 +2841,7 @@ Open MPI version 1.1.1 - Fix for Fortran string handling in various MPI API functions. - Fix for Fortran status handling in MPI_WAITSOME and MPI_TESTSOME. - Various fixes for the XL compilers. -- Automatically disable using mallot() on AIX. +- Automatically disable using mallopt() on AIX. - Memory fixes for 64 bit platforms with registering MCA parameters in the self and MX BTL components. - Fixes for BProc to support oversubscription and changes to the @@ -2919,7 +2919,7 @@ Open MPI version 1.1.0 match. Thanks to Michael Kluskens for pointing out the problems to us. -- Allow short messagees to use RDMA (vs. send/receive semantics) to a +- Allow short messages to use RDMA (vs. send/receive semantics) to a limited number peers in both the mvapi and openib BTL components. This reduces communication latency over IB channels. - Numerous performance improvements throughout the entire code base. @@ -3143,7 +3143,7 @@ Open MPI version 1.0.1 MPI_SCATTERV implementation. - Fix EOF handling on stdin. - Fix missing MPI_F_STATUS_IGNORE and MPI_F_STATUSES_IGNORE - instanatiations. Thanks to Anthony Chan for pointing this out. + instantiations. Thanks to Anthony Chan for pointing this out. - Add a missing value for MPI_WIN_NULL in mpif.h. - Bring over some fixes for the sm btl that somehow didn't make it over from the trunk before v1.0. Thanks to Beth Tibbitts and Bill diff --git a/docs/release-notes/changelog/v2.x.rst b/docs/release-notes/changelog/v2.x.rst index 896055a43b6..13995071739 100644 --- a/docs/release-notes/changelog/v2.x.rst +++ b/docs/release-notes/changelog/v2.x.rst @@ -220,8 +220,8 @@ Open MPI version 2.1.0 .. attention:: Removed legacy support: - The ptmalloc2 hooks have been removed from the Open MPI code base. - This is not really a user-noticable change; it is only mentioned - here because there was much rejoycing in the Open MPI developer + This is not really a user-noticeable change; it is only mentioned + here because there was much rejoicing in the Open MPI developer community. - New MCA parameters: @@ -240,7 +240,7 @@ Open MPI version 2.1.0 libfabric progress model to be used for control and data. - Fix MPI_WTICK regression where the time reported may be inaccurate - on systems with processor frequency scalaing enabled. + on systems with processor frequency scaling enabled. - Fix regression that lowered the memory maximum message bandwidth for large messages on some BTL network transports, such as openib, sm, and vader. @@ -305,7 +305,7 @@ Open MPI version 2.1.0 "test". Thanks to Kevin Buckley for pointing out the issue. - Fix bug when using darrays with lib and extent of darray datatypes. - Updates to make Open MPI binary builds more bit-for-bit - reproducable. Thanks to Alastair McKinstry for the suggestion. + reproducible. Thanks to Alastair McKinstry for the suggestion. - Fix issues regarding persistent request handling. - Ensure that shmemx.h is a standalone OpenSHMEM header file. Thanks to Nick Park (@nspark) for the report. @@ -527,11 +527,11 @@ Open MPI version 2.0.1 all transports. - Fix shared memory performance when using RDMA-capable networks. Thanks to Tetsuya Mishima and Christoph Niethammer for reporting. -- Fix bandwith performance degredation in the yalla (MXM) PML. Thanks +- Fix bandwidth performance degradation in the yalla (MXM) PML. Thanks to Andreas Kempf for reporting the issue. - Fix OpenSHMEM crash when running on non-Mellanox MXM-based networks. Thanks to Debendra Das for reporting the issue. -- Fix a crash occuring after repeated calls to MPI_FILE_SET_VIEW with +- Fix a crash occurring after repeated calls to MPI_FILE_SET_VIEW with predefined datatypes. Thanks to Eric Chamberland and Matthew Knepley for reporting and helping chase down this issue. - Fix stdin propagation to MPI processes. Thanks to Jingchao Zhang @@ -540,7 +540,7 @@ Open MPI version 2.0.1 internal component to v1.1.5. - Fix process startup failures on Intel MIC platforms due to very large entries in ``/proc/mounts``. -- Fix a problem with use of relative path for specifing executables to +- Fix a problem with use of relative path for specifying executables to mpirun / oshrun. Thanks to David Schneider for reporting. - Various improvements when running over portals-based networks. - Fix thread-based race conditions with GNI-based networks. @@ -641,7 +641,7 @@ Open MPI version 2.0.0 - ompi-release#1081: Support MPI_IN_PLACE in MPI_(I)ALLTOALLW and MPI_(I)EXSCAN - ompi-release#1107: Allow future PMIx support for RM spawn limits - ompi-release#1108: Fix sparse group process reference counting - - ompi-release#1109: If specified to be oversubcribed, disable binding + - ompi-release#1109: If specified to be oversubscribed, disable binding - ompi-release#1122: Allow NULL arrays for empty datatypes - ompi-release#1123: Fix signed vs. unsigned compiler warnings - ompi-release#1123: Make max hostname length uniform across code base @@ -748,7 +748,7 @@ Open MPI version 2.0.0 - Allow NULL arrays when creating empty MPI datatypes. - Replace use of alloca with malloc for certain datatype creation functions. Thanks to Bogdan Sataric for reporting this. -- Fix use of MPI_LB and MPI_UB in creation of of certain MPI datatypes. +- Fix use of MPI_LB and MPI_UB in creation of certain MPI datatypes. Thanks to Gus Correa for helping to fix this. - Implement a workaround for a GNU Libtool problem. Thanks to Eric Schnetter for reporting and fixing. diff --git a/docs/release-notes/changelog/v3.0.x.rst b/docs/release-notes/changelog/v3.0.x.rst index 27578071121..f76b4c97b42 100644 --- a/docs/release-notes/changelog/v3.0.x.rst +++ b/docs/release-notes/changelog/v3.0.x.rst @@ -63,7 +63,7 @@ Open MPI version 3.0.5 - Add support for unwinding info to all files that are present in the stack starting from ``MPI_Init``, which is helpful with parallel debuggers. Thanks to James Clark for the report and initial fix. -- Fixed inadvertant use of bitwise operators in the MPI C++ bindings +- Fixed inadvertent use of bitwise operators in the MPI C++ bindings header files. Thanks to Bert Wesarg for the report and the fix. - Added configure option ``--disable-wrappers-runpath`` (alongside the already-existing ``--disable-wrappers-rpath`` option) to prevent Open @@ -79,7 +79,7 @@ Open MPI version 3.0.4 ``--with-devel-headers``. Thanks to @g-raffy for reporting the issue. - Fix possible floating point rounding and division issues in OMPIO which led to crashes and/or data corruption with very large data. - Thanks to Axel Huebl and RenÊ Widera for identifing the issue, + Thanks to Axel Huebl and RenÊ Widera for identifying the issue, supplying and testing the fix (** also appeared: v3.0.4). - Use ``static_cast<>`` in ``mpi.h`` where appropriate. Thanks to @shadow-fx for identifying the issue. @@ -152,7 +152,7 @@ Open MPI version 3.0.2 rather than those documented in the MPI standard. - Fixed ``MPI_SIZEOF`` in the "mpi" Fortran module for the NAG compiler. - Fix RMA function signatures for ``use-mpi-f08`` bindings to have the - asynchonous property on all buffers. + asynchronous property on all buffers. - Fix Fortran ``MPI_COMM_SPAWN_MULTIPLE`` to properly follow the count length argument when parsing the array_of_commands variable. - Revamp Java detection to properly handle new Java versions which do @@ -197,9 +197,9 @@ Open MPI version 3.0.1 propagation tools. By default it is set to false, except for Cray XC systems. - Fix a problem reported on the mailing separately by Kevin McGrattan and Stephen Guzik about consistency issues on NFS file systems when using OMPIO. This fix - also introduces a new mca parameter ``fs_ufs_lock_algorithm`` which allows to + also introduces a new mca parameter ``fs_ufs_lock_algorithm`` which allows users to control the locking algorithm used by ompio for read/write operations. By - default, ompio does not perfom locking on local UNIX file systems, locks the + default, ompio does not perform locking on local UNIX file systems, locks the entire file per operation on NFS file systems, and selective byte-range locking on other distributed file systems. - Add an mca parameter ``pmix_server_usock_connections`` to allow mpirun to diff --git a/docs/release-notes/changelog/v3.1.x.rst b/docs/release-notes/changelog/v3.1.x.rst index 68502fce637..6a6e5371b32 100644 --- a/docs/release-notes/changelog/v3.1.x.rst +++ b/docs/release-notes/changelog/v3.1.x.rst @@ -78,7 +78,7 @@ Open MPI version 3.1.5 - Add support for unwinding info to all files that are present in the stack starting from MPI_Init, which is helpful with parallel debuggers. Thanks to James Clark for the report and initial fix. -- Fixed inadvertant use of bitwise operators in the MPI C++ bindings +- Fixed inadvertent use of bitwise operators in the MPI C++ bindings header files. Thanks to Bert Wesarg for the report and the fix. @@ -93,7 +93,7 @@ Open MPI version 3.1.4 Easterday for the fix. - Fix possible floating point rounding and division issues in OMPIO which led to crashes and/or data corruption with very large data. - Thanks to Axel Huebl and RenÊ Widera for identifing the issue, + Thanks to Axel Huebl and RenÊ Widera for identifying the issue, supplying and testing the fix (** also appeared: v3.0.4). - Use ``static_cast<>`` in ``mpi.h`` where appropriate. Thanks to @shadow-fx for identifying the issue (** also appeared: v3.0.4). @@ -193,7 +193,7 @@ Open MPI version 3.1.1 - Revamp Java detection to properly handle new Java versions which do not provide a javah wrapper. - Fix RMA function signatures for use-mpi-f08 bindings to have the - asynchonous property on all buffers. + asynchronous property on all buffers. - Improved configure logic for finding the UCX library. diff --git a/docs/release-notes/changelog/v4.0.x.rst b/docs/release-notes/changelog/v4.0.x.rst index 70d452c0619..e7db8a26ac0 100644 --- a/docs/release-notes/changelog/v4.0.x.rst +++ b/docs/release-notes/changelog/v4.0.x.rst @@ -153,7 +153,7 @@ Open MPI version 4.0.2 Thanks to Orivej Desh for reporting and providing a fix. - Fix divide by zero segfault in ompio. Thanks to @haraldkl for reporting and providing a fix. -- Fix finalize of flux compnents. +- Fix finalize of flux components. Thanks to Stephen Herbein and Jim Garlick for providing a fix. - Fix osc_rdma_acc_single_intrinsic regression. Thanks to Joseph Schuchart for reporting and providing a fix. @@ -231,7 +231,7 @@ Open MPI version 4.0.1 Thanks to Igor Andriyash and Axel Huebl for reporting. - Fix two memory leaks encountered for certain MPI-RMA usage patterns. Thanks to Joseph Schuchart for reporting and fixing. -- Fix a problem with the ORTE ``rmaps_base_oversubscribe`` MCA paramater. +- Fix a problem with the ORTE ``rmaps_base_oversubscribe`` MCA parameter. Thanks to @iassiour for reporting. - Fix a problem with UCX PML default error handler for MPI communicators. Thanks to Marcin Krotkiewski for reporting. @@ -277,7 +277,7 @@ Open MPI version 4.0.0 - Fix problems with use of newer map-by mpirun options. Thanks to Tony Reina for reporting. - Fix rank-by algorithms to properly rank by object and span -- Allow for running as root of two environment variables are set. +- Allow for running as root if two environment variables are set. Requested by Axel Huebl. - Fix a problem with building the Java bindings when using Java 10. Thanks to Bryce Glover for reporting. diff --git a/docs/release-notes/changelog/v4.1.x.rst b/docs/release-notes/changelog/v4.1.x.rst index f5540505189..f8d35dd0bee 100644 --- a/docs/release-notes/changelog/v4.1.x.rst +++ b/docs/release-notes/changelog/v4.1.x.rst @@ -31,7 +31,7 @@ Open MPI version 4.1.6 - Fix minor issues and add some minor performance optimizations with OFI support. - Support the ``striping_factor`` and ``striping_unit`` MPI_Info names - recomended by the MPI standard for parallel IO. + recommended by the MPI standard for parallel IO. - Fixed some minor issues with UCX support. - Minor optimization for 0-byte MPI_Alltoallw (i.e., make it a no-op). @@ -119,7 +119,7 @@ Open MPI version 4.1.3 based on float precision. - Fix compile failure for ``--enable-heterogeneous``. Also updated the README to clarify that ``--enable-heterogeneous`` is functional, - but still not recomended for most environments. + but still not recommended for most environments. - Minor fixes to OMPIO, including: - Fixing the open behavior of shared memory shared file pointers. @@ -154,7 +154,7 @@ Open MPI version 4.1.2 - Correctly process 0 slots with the ``mpirun --host`` option. - Ensure to unlink and rebind socket when the Open MPI session directory already exists. -- Fix a segv in ``mpirun --disable-dissable-map``. +- Fix a segv in ``mpirun --disable-display-map``. - Fix a potential hang in the memory hook handling. - Slight performance improvement in ``MPI_WAITALL`` when running in ``MPI_THREAD_MULTIPLE``. diff --git a/docs/release-notes/networks.rst b/docs/release-notes/networks.rst index 400bf21f9cd..d0521a013d8 100644 --- a/docs/release-notes/networks.rst +++ b/docs/release-notes/networks.rst @@ -60,7 +60,7 @@ run-time: .. code-block:: sh - shell$ mpirun --mca pml ob1 --mca btl [comma-delimted-BTLs] ... + shell$ mpirun --mca pml ob1 --mca btl [comma-delimited-BTLs] ... # or shell$ mpirun --mca pml cm --mca mtl [MTL] ... # or diff --git a/docs/tuning-apps/accelerators/cuda.rst b/docs/tuning-apps/accelerators/cuda.rst index 8a393b3f32f..68190d9bf75 100644 --- a/docs/tuning-apps/accelerators/cuda.rst +++ b/docs/tuning-apps/accelerators/cuda.rst @@ -198,7 +198,7 @@ Libfabric's API. Can I get additional CUDA debug-level information at run-time? -------------------------------------------------------------- -Yes, by enabling some vebosity flags. +Yes, by enabling some verbosity flags. * The ``opal_cuda_verbose`` parameter has only one level of verbosity: diff --git a/docs/tuning-apps/accelerators/memkind.rst b/docs/tuning-apps/accelerators/memkind.rst index 7567d9f7e82..e414af4eacc 100644 --- a/docs/tuning-apps/accelerators/memkind.rst +++ b/docs/tuning-apps/accelerators/memkind.rst @@ -48,7 +48,7 @@ information to Open MPI at application launch: Asserting usage of memory kind when creating a Communicator =========================================================== -The following code-snipplet demonstrates how to assert that a +The following code snippet demonstrates how to assert that a communicator will only be used for ROCm device buffers: .. code:: c diff --git a/docs/tuning-apps/accelerators/rocm.rst b/docs/tuning-apps/accelerators/rocm.rst index b19ad98bb6d..5c78f78ef78 100644 --- a/docs/tuning-apps/accelerators/rocm.rst +++ b/docs/tuning-apps/accelerators/rocm.rst @@ -255,7 +255,7 @@ An example for configure UCC and Open MPI with ROCm is shown below: --with-ucx=/path/to/ucx-rocm-install \ --with-ucc=/path/to/ucc-rocm-install -To use the UCC component in an application requires setting some +Using the UCC component in an application requires setting some additional parameters: .. code-block:: diff --git a/docs/tuning-apps/benchmarking.rst b/docs/tuning-apps/benchmarking.rst index 0a555a2fdbb..caff1d79340 100644 --- a/docs/tuning-apps/benchmarking.rst +++ b/docs/tuning-apps/benchmarking.rst @@ -8,7 +8,7 @@ This documentation is by no means a definitive guide, but it does try to offer some suggestions for generating accurate, meaningful benchmarks. -#. Decide *exactly* what you are benchmarking and setup your system +#. Decide *exactly* what you are benchmarking and set up your system accordingly. For example, if you are trying to benchmark maximum performance, then many of the suggestions listed below are extremely relevant (be the only user on the systems and network in @@ -82,7 +82,7 @@ benchmarks. * Perform some "warmup" events first. Many MPI implementations (including Open MPI) |mdash| and other subsystems upon which the - MPI uses |mdash| may use "lazy" semantics to setup and maintain + MPI uses |mdash| may use "lazy" semantics to set up and maintain streams of communications. Hence, the first event (or first few events) may well take significantly longer than subsequent events. @@ -108,4 +108,3 @@ benchmarks. system configuration that you are benchmarking. Note, for example, all hardware and software characteristics (to include hardware, firmware, and software versions as appropriate). - diff --git a/docs/tuning-apps/collectives/components.rst b/docs/tuning-apps/collectives/components.rst index 382c7febbf8..b828d9861ad 100644 --- a/docs/tuning-apps/collectives/components.rst +++ b/docs/tuning-apps/collectives/components.rst @@ -2,7 +2,7 @@ Available Collective Components =============================== Open MPI's ``coll`` framework provides a number of components -implementing collective communication, each of which target a +implementing collective communication, each of which targets a different environment or scenario. Some of these components may not be available depending on how Open MPI was compiled and what hardware is available on the system. A run-time decision based on each @@ -36,13 +36,13 @@ The following provides a list of components and their primary target scenario: - ``accelerator``: component providing host-proxy algorithms for some collective operations using device buffers. - ``ftagree``: component providing fault-tolerant collective operations. - - ``inter``: component providing collective operaitons for inter-communicators. + - ``inter``: component providing collective operations for inter-communicators. - ``basic``: component providing basic algorithms, used as a fall-back component. - ``sync``: component used in scenarios where some nodes can be overrun with messages. This component can be used to insert synchronization points every *n-th* execution of a collective operations. - - ``portals4``: component targetting portals4 networks. + - ``portals4``: component targeting portals4 networks. Different component can and will be used for different collective operations, since no component is providing implementations for all diff --git a/docs/tuning-apps/collectives/index.rst b/docs/tuning-apps/collectives/index.rst index d4c8871335b..be30b5a574c 100644 --- a/docs/tuning-apps/collectives/index.rst +++ b/docs/tuning-apps/collectives/index.rst @@ -2,7 +2,7 @@ Collective operations ===================== Open MPI provides a number of components implementing collective -operations and significant flexbility to tune collective operations. +operations and significant flexibility to tune collective operations. This section documents the available components and gives for some components additional information on how to utilize them. diff --git a/docs/tuning-apps/collectives/xhc.rst b/docs/tuning-apps/collectives/xhc.rst index 8ac345649c5..a74d81698f0 100644 --- a/docs/tuning-apps/collectives/xhc.rst +++ b/docs/tuning-apps/collectives/xhc.rst @@ -167,7 +167,7 @@ Main * - coll_xhc__hierarchy - bcast/barrier: ``numa,socket`` (all)reduce: ``l3,numa,socket`` - - Topological features to consider for XHC's hierarchy, specifially for + - Topological features to consider for XHC's hierarchy, specifically for this primitive. Mutually exclusive with the respective non-specific parameter. diff --git a/docs/tuning-apps/fault-tolerance/checkpoint-restart.rst b/docs/tuning-apps/fault-tolerance/checkpoint-restart.rst index d904c7b1efa..248be721a80 100644 --- a/docs/tuning-apps/fault-tolerance/checkpoint-restart.rst +++ b/docs/tuning-apps/fault-tolerance/checkpoint-restart.rst @@ -7,7 +7,7 @@ Old versions of Open MPI (starting from v1.3 series) had support for the transparent, coordinated checkpointing and restarting of MPI processes (similar to LAM/MPI). -Open MPI supported both the the `BLCR `_ +Open MPI supported both the `BLCR `_ checkpoint/restart system and a "self" checkpointer that allows applications to perform their own checkpoint/restart functionality while taking advantage of the Open MPI checkpoint/restart infrastructure. diff --git a/docs/tuning-apps/large-clusters/libraries.rst b/docs/tuning-apps/large-clusters/libraries.rst index 8673c45de14..8e53e9d04d0 100644 --- a/docs/tuning-apps/large-clusters/libraries.rst +++ b/docs/tuning-apps/large-clusters/libraries.rst @@ -24,7 +24,7 @@ place the Open MPI libraries on networked file systems: cluster! Doing so will lead to significant network traffic and delayed start times, especially on clusters with a large number of nodes. Instead, be sure to :ref:`configure your build - ` with + ` with ``--disable-dlopen``. This will include the DSO's in the main libraries, resulting in much faster startup times. diff --git a/docs/tuning-apps/mpi-io.rst b/docs/tuning-apps/mpi-io.rst index cf6327f9efd..7b1a04d7aaf 100644 --- a/docs/tuning-apps/mpi-io.rst +++ b/docs/tuning-apps/mpi-io.rst @@ -207,7 +207,7 @@ individual files are merged into the actual output file, using the time stamps as the main criteria. The component has certain limitations and restrictions, such as its -relience on the synchronization clocks on the individual cluster nodes +reliance on the synchronization clocks on the individual cluster nodes to determine the order between entries in the final file, which might lead to some deviations compared to the actual calling sequence. diff --git a/docs/tuning-apps/networking/iwarp.rst b/docs/tuning-apps/networking/iwarp.rst index a24b3c73fbb..79293fa58e9 100644 --- a/docs/tuning-apps/networking/iwarp.rst +++ b/docs/tuning-apps/networking/iwarp.rst @@ -6,7 +6,7 @@ Open MPI's support for iWARP devices has changed over time. In the Open MPI |ompi_series| series, iWARP devices are supported via the OFI (``ofi``) MTL via the CM (``cm``) PML. -.. note:: Prior versions of Open MPI supported iWARP devies via the +.. note:: Prior versions of Open MPI supported iWARP devices via the ``openib`` BTL. Open MPI |ompi_series| no longer includes the ``openib`` BTL. diff --git a/docs/tuning-apps/networking/ofi.rst b/docs/tuning-apps/networking/ofi.rst index 3f7563985d1..e5e0f4f1f9c 100644 --- a/docs/tuning-apps/networking/ofi.rst +++ b/docs/tuning-apps/networking/ofi.rst @@ -58,7 +58,7 @@ communications: See each Lifabric provider man page (e.g., fi_sockets(7)) to understand which provider will work for each of the above-listed Open MPI components. Some -providers may require to be used with one of the Libfabric utility providers; +providers may require use with one of the Libfabric utility providers; for example, the verbs provider needs to be paired with utility provider ``ofi_rxm`` to provide reliable datagram endpoint support (``verbs;ofi_rxm``). diff --git a/docs/tuning-apps/networking/tcp.rst b/docs/tuning-apps/networking/tcp.rst index 7b87546596c..4b81ebbddc3 100644 --- a/docs/tuning-apps/networking/tcp.rst +++ b/docs/tuning-apps/networking/tcp.rst @@ -200,7 +200,7 @@ not use specific IP networks |mdash| or not use any IP networks at all This interface was automatically given an IP address in the 192.168.1.0/24 subnet and marked as "up". Since Open MPI saw this 192.168.1.0/24 "up" interface in all MPI - processes on all nodes, it assumed that that network was + processes on all nodes, it assumed that network was usable for MPI communications. This is obviously incorrect, and it led to MPI applications hanging when they tried to send or receive MPI messages. diff --git a/docs/version-numbering.rst b/docs/version-numbering.rst index b96da23de91..3788cdae40f 100644 --- a/docs/version-numbering.rst +++ b/docs/version-numbering.rst @@ -67,7 +67,7 @@ format. Each of the three numbers has a specific meaning: change in the code base and/or end-user functionality, and also indicate a break from backward compatibility. Specifically: Open MPI releases with different major version numbers are not - backward compatibale with each other. + backward compatible with each other. .. important:: This rule does not extend to versions prior to v1.10.0. Specifically: v1.10.x is not guaranteed to be backward From 80231f65cca1aeeb06f5642de6be02ceb2d3e1e2 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 2 Jun 2026 19:35:52 -0400 Subject: [PATCH 079/230] AGENTS: document commit message conventions Add guidance for agents to wrap commit-message lines at around 75 characters. Also clarify that release-branch cherry-picks must leave the cherry-pick tagline at the end of the commit message. Point agents at git cherry-pick -x as the preferred way to add it. Signed-off-by: Jeff Squyres --- AGENTS.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 805ce2dbb9b..40df5279977 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -227,11 +227,12 @@ honor: - **Commit messages:** a short first line saying *what* changed, then a body explaining *why*. Open MPI does **not** use Conventional Commits (`feat:`/`fix:` prefixes) — write prose. Don't add AI tooling - attribution. + attribution. Wrap commit-message lines at around 75 characters. - **Branch flow:** land on `main` first via a GitHub pull request, then cherry-pick to the relevant release branch(es) `vMAJOR.MINOR.x` with a - `(cherry picked from commit ...)` line. Never commit features directly - to a release branch. See + `(cherry picked from commit ...)` line at the end of the commit + message; use `git cherry-pick -x` to add it. Never commit features + directly to a release branch. See [`docs/developers/git-github.rst`](docs/developers/git-github.rst). - **Update the docs and the changelog** when user-visible behavior changes: RST under [`docs/`](docs/), and a release-notes entry under From 786804a6fd04dd745a8ff1e3f5a722ebf40611f5 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Tue, 2 Jun 2026 09:51:00 -0600 Subject: [PATCH 080/230] docs: add code of conduct file may need to use a different email address Signed-off-by: Howard Pritchard --- .github/CODE_OF_CONDUCT.md | 46 +++++++++++ .gitignore | 3 + .readthedocs-pre-create-environment.sh | 2 + docs/Makefile.am | 19 ++++- docs/generate-code-of-conduct-rst.py | 102 +++++++++++++++++++++++++ docs/index.rst | 1 + 6 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100755 docs/generate-code-of-conduct-rst.py diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..b002ea3373b --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Open MPI Community Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the Open MPI project or its community. Examples of representing the project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of the project may be further defined and clarified by Open MPI maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at maintainers@open-mpi.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.gitignore b/.gitignore index b30321da7ca..578ab99149e 100644 --- a/.gitignore +++ b/.gitignore @@ -533,6 +533,9 @@ docs/schizo-ompi-rst-content docs/html docs/man +# other doc RST files to ignore as they are generated +docs/code-of-conduct.rst + # Generated C Bindings ompi/mpi/c/*_generated*.c diff --git a/.readthedocs-pre-create-environment.sh b/.readthedocs-pre-create-environment.sh index cc461ac2b13..34cf3496bf1 100755 --- a/.readthedocs-pre-create-environment.sh +++ b/.readthedocs-pre-create-environment.sh @@ -29,3 +29,5 @@ cp -rp $PRRTE_RST_SRC_DIR $PRRTE_RST_TARGET_DIR cd docs python3 ./generate-mpi-man3-bindings.py --srcdir . --builddir . +python3 ./generate-code-of-conduct-rst.py --input ../.github/CODE_OF_CONDUCT.md --output code-of-conduct.rst + diff --git a/docs/Makefile.am b/docs/Makefile.am index a6edc6ae045..24a6d17740d 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -36,6 +36,8 @@ SPHINX_OPTS ?= -W --keep-going -j auto # However, it is necessary to list $(srcdir) when using wildcards. TEXT_SOURCE_FILES = \ $(srcdir)/license/*.txt +MARKDOWN_SOURCE_FILES = \ + $(top_srcdir)/.github/CODE_OF_CONDUCT.md IMAGE_SOURCE_FILES = \ $(srcdir)/openmpi_logo.png \ $(srcdir)/installing-open-mpi/required-support-libraries-dependency-graph.png \ @@ -62,12 +64,14 @@ RST_SOURCE_FILES = \ EXTRA_DIST = \ requirements.txt \ no-prrte-content.rst.txt \ + generate-code-of-conduct-rst.py \ generate-mpi-man3-bindings.py \ mpi-standard-apis.json \ html \ man \ $(SPHINX_CONFIG) \ $(TEXT_SOURCE_FILES) \ + $(MARKDOWN_SOURCE_FILES) \ $(IMAGE_SOURCE_FILES) \ $(RST_SOURCE_FILES) @@ -868,6 +872,10 @@ OMPI_MAN3_RST = $(OMPI_MAN3:%.3=man-openmpi/man3/%.3.rst) OMPI_MAN3_BUILT = $(OMPI_MAN3:%.3=$(MAN_OUTDIR)/%.3) OMPI_MAN3_INSTALL_FROM = $(OMPI_MAN3:%.3=$(MAN_INSTALL_FROM)/%.3) +# Generate this file from CODE_OF_CONDUCT.md as part of the Sphinx +# docs build. +CODE_OF_CONDUCT_RST = $(builddir)/code-of-conduct.rst + # Use this one file as a sentinel for building all the Open MPI man # page API bindings files SENTINEL_OMPI_MAN3_BINDING = $(builddir)/man-openmpi/man3/bindings/mpi_init.rst @@ -950,7 +958,7 @@ man: $(ALL_MAN_BUILT) # Remove the copies of the built HTML and man pages to get back to a # clean git clone. maintainer-clean-local: - rm -rf html man man-openmpi/man3/bindings + rm -rf html man man-openmpi/man3/bindings $(CODE_OF_CONDUCT_RST) # If we're doing a VPATH build, we may have "html" and "man" # directories in the build tree (e.g., if we did "make dist"). Remove @@ -1036,10 +1044,16 @@ $(SENTINEL_OMPI_MAN3_BINDING): mpi-standard-apis.json $(OMPI_V_GEN) $(PYTHON3) $(srcdir)/generate-mpi-man3-bindings.py \ --srcdir $(srcdir) --builddir $(builddir) +$(CODE_OF_CONDUCT_RST): $(top_srcdir)/.github/CODE_OF_CONDUCT.md +$(CODE_OF_CONDUCT_RST): generate-code-of-conduct-rst.py + $(OMPI_V_GEN) $(PYTHON3) $(srcdir)/generate-code-of-conduct-rst.py \ + --input $(top_srcdir)/.github/CODE_OF_CONDUCT.md --output $@ + $(ALL_MAN_BUILT): $(builddir)/prrte-rst-content $(ALL_MAN_BUILT): $(builddir)/schizo-ompi-rst-content/schizo-ompi-cli.rstxt $(ALL_MAN_BUILT): $(RST_SOURCE_FILES) $(IMAGE_SOURCE_FILES) $(ALL_MAN_BUILT): $(TEXT_SOURCE_FILES) $(SPHINX_CONFIG) +$(ALL_MAN_BUILT): $(CODE_OF_CONDUCT_RST) $(ALL_MAN_BUILT): $(SENTINEL_OMPI_MAN3_BINDING) # Render the RST source into both 1) full HTML docs and 2) nroff man @@ -1131,6 +1145,7 @@ linkcheck: # RST source files to the build tree. So delete all of those, too. clean-local: rm -rf $(OUTDIR) + rm -f $(CODE_OF_CONDUCT_RST) rm -rf prrte-rst-content schizo-ompi-rst-content rm -rf ompi-prrte-objects.inv opal-pmix-objects.inv if test "$(srcdir)" != "$(builddir)"; then \ @@ -1150,7 +1165,7 @@ clean-local: # macro. This hooks into the normal Automake build mechanisms, and # will ultimately cause the invocation of the above rule that runs # Sphinx to build the HTML and man pages. -BUILT_SOURCES = $(ALL_MAN_BUILT) +BUILT_SOURCES = $(CODE_OF_CONDUCT_RST) $(ALL_MAN_BUILT) endif OPAL_BUILD_DOCS diff --git a/docs/generate-code-of-conduct-rst.py b/docs/generate-code-of-conduct-rst.py new file mode 100755 index 00000000000..a0f12316664 --- /dev/null +++ b/docs/generate-code-of-conduct-rst.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +"""Convert Open MPI's Markdown CODE_OF_CONDUCT.md to reStructuredText.""" + +import argparse +import re +from pathlib import Path + +HEADING_RE = re.compile(r"^(#{1,6})\s+(.+?)\s*#*\s*$") +REF_DEF_RE = re.compile(r"^\[([^\]]+)\]:\s*(\S+)\s*$") +REF_LINK_RE = re.compile(r"\[([^\]]+)\]\[([^\]]+)\]") +INLINE_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+)\)") +BULLET_RE = re.compile(r"^\s*[*+-]\s+") +UNDERLINES = ["=", "-", "~", "^", '"', "'"] + + +def _rst_link(text, url): + return "`{} <{}>`_".format(text, url) + + +def _convert_links(line, refs): + def repl_ref(match): + text = match.group(1) + ref = match.group(2) + return _rst_link(text, refs.get(ref, ref)) + + def repl_inline(match): + return _rst_link(match.group(1), match.group(2)) + + line = REF_LINK_RE.sub(repl_ref, line) + line = INLINE_LINK_RE.sub(repl_inline, line) + return line + + +def convert(lines): + refs = {} + for line in lines: + match = REF_DEF_RE.match(line.strip()) + if match: + refs[match.group(1)] = match.group(2) + + out = [ + "..", + " This file was generated from CODE_OF_CONDUCT.md by docs/Makefile.am.", + " Do not edit directly.", + "", + ] + + skip_next_blank = False + prev_bullet = False + for line in lines: + if REF_DEF_RE.match(line.strip()): + continue + if skip_next_blank and not line.strip(): + skip_next_blank = False + continue + skip_next_blank = False + + match = HEADING_RE.match(line) + if match: + if out and out[-1] != "": + out.append("") + title = _convert_links(match.group(2), refs) + level = min(len(match.group(1)) - 1, len(UNDERLINES) - 1) + out.extend([title, UNDERLINES[level] * len(title), ""]) + skip_next_blank = True + prev_bullet = False + else: + is_bullet = bool(BULLET_RE.match(line)) + if is_bullet and out and out[-1] != "" and not prev_bullet: + out.append("") + out.append(_convert_links(line, refs)) + prev_bullet = is_bullet + + while out and out[-1] == "": + out.pop() + return "\n".join(out) + "\n" + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--input", required=True) + parser.add_argument("--output", required=True) + args = parser.parse_args() + + input_path = Path(args.input) + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text( + convert(input_path.read_text(encoding="utf-8").splitlines()), + encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/docs/index.rst b/docs/index.rst index 50bd1c412e4..2148491e729 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -78,6 +78,7 @@ Table of contents app-debug/index developers/index contributing + code-of-conduct license/index history man-openmpi/index From 9b71f5593128cac7730e9aea377b797dae5093ee Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Wed, 3 Jun 2026 14:55:28 -0400 Subject: [PATCH 081/230] Reserve dist graph tags outside the libnbc tag range MPI_Dist_graph_create exchanges distributed-graph edge metadata with PML sends and receives on the parent communicator before the new communicator is fully created. The topo base code used hard-coded internal tags -50 and -51 for this exchange. Those tags are reachable by the dynamic nonblocking collective tag allocator. In repeated communicator creation, comm->c_nbc_tag can count down into -50/-51. This creates a race where some ranks may still be matching distributed-graph edge traffic while other ranks have already entered ompi_comm_nextcid and started its nonblocking allreduce on the same parent communicator. The resulting tag collision can leave the CID allocation request waiting forever. Reserve the distributed-graph edge tags in coll_tags.h as static internal tags, before MCA_COLL_BASE_TAG_STATIC_END, so the libnbc nonblocking collective range starts below them. Use those central tag definitions in topo_base_dist_graph_create instead of local hard-coded values. This keeps distributed-graph construction traffic disjoint from nonblocking collective traffic on the parent communicator and avoids the loop-triggered deadlock in MPI_Dist_graph_create. Fixes #13918 Signed-off-by: George Bosilca --- ompi/mca/coll/base/coll_tags.h | 8 ++++++-- ompi/mca/topo/base/topo_base_dist_graph_create.c | 11 +++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ompi/mca/coll/base/coll_tags.h b/ompi/mca/coll/base/coll_tags.h index 5d3da7eafe5..fe9e1ce9424 100644 --- a/ompi/mca/coll/base/coll_tags.h +++ b/ompi/mca/coll/base/coll_tags.h @@ -61,9 +61,13 @@ #define MCA_COLL_BASE_TAG_UCC (MCA_COLL_BASE_TAG_FT_END - 1) -#define MCA_COLL_BASE_TAG_STATIC_END (MCA_COLL_BASE_TAG_UCC - 1) - +/* Distributed graph construction uses PML messages before the new + * communicator is fully created. Keep these tags out of the nonblocking + * collective tag range. */ +#define MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_IN (MCA_COLL_BASE_TAG_UCC - 1) +#define MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_OUT (MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_IN - 1) +#define MCA_COLL_BASE_TAG_STATIC_END (MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_OUT) #define MCA_COLL_BASE_TAG_NONBLOCKING_BASE (MCA_COLL_BASE_TAG_STATIC_END - 1) #define MCA_COLL_BASE_TAG_NONBLOCKING_END ((-1 * INT_MAX/2) + 1) diff --git a/ompi/mca/topo/base/topo_base_dist_graph_create.c b/ompi/mca/topo/base/topo_base_dist_graph_create.c index 66e2976deb5..43c899cb4b8 100644 --- a/ompi/mca/topo/base/topo_base_dist_graph_create.c +++ b/ompi/mca/topo/base/topo_base_dist_graph_create.c @@ -19,6 +19,7 @@ #include "ompi_config.h" #include "ompi/communicator/communicator.h" +#include "ompi/mca/coll/base/coll_tags.h" #include "ompi/info/info.h" #include "ompi/mca/topo/base/base.h" #include "ompi/datatype/ompi_datatype.h" @@ -27,8 +28,6 @@ #define IN_INDEX 0 #define OUT_INDEX 1 -#define MCA_TOPO_BASE_TAG_DIST_EDGE_IN -50 -#define MCA_TOPO_BASE_TAG_DIST_EDGE_OUT -51 typedef struct _dist_graph_elem { int in; @@ -172,7 +171,7 @@ int mca_topo_base_dist_graph_distribute(mca_topo_base_module_t* module, position *= 2; } err = MCA_PML_CALL(isend( &rin[position], count, (ompi_datatype_t*)&ompi_mpi_int, - i, MCA_TOPO_BASE_TAG_DIST_EDGE_IN, MCA_PML_BASE_SEND_STANDARD, + i, MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_IN, MCA_PML_BASE_SEND_STANDARD, comm, &reqs[pending_reqs])); pending_reqs++; } @@ -183,7 +182,7 @@ int mca_topo_base_dist_graph_distribute(mca_topo_base_module_t* module, position *= 2; } err = MCA_PML_CALL(isend(&rout[position], count, (ompi_datatype_t*)&ompi_mpi_int, - i, MCA_TOPO_BASE_TAG_DIST_EDGE_OUT, MCA_PML_BASE_SEND_STANDARD, + i, MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_OUT, MCA_PML_BASE_SEND_STANDARD, comm, &reqs[pending_reqs])); pending_reqs++; } @@ -210,7 +209,7 @@ int mca_topo_base_dist_graph_distribute(mca_topo_base_module_t* module, for( left_over = count, current_pos = i = 0; left_over > 0; i++ ) { MCA_PML_CALL(recv( &temp[count - left_over], left_over, (ompi_datatype_t*)&ompi_mpi_int, /* keep receiving in the same buffer */ - MPI_ANY_SOURCE, MCA_TOPO_BASE_TAG_DIST_EDGE_IN, + MPI_ANY_SOURCE, MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_IN, comm, &status )); how_much = status._ucount / int_size; if (MPI_UNWEIGHTED != weights) { @@ -246,7 +245,7 @@ int mca_topo_base_dist_graph_distribute(mca_topo_base_module_t* module, for( left_over = count, current_pos = i = 0; left_over > 0; i++ ) { MCA_PML_CALL(recv( &temp[count - left_over], left_over, (ompi_datatype_t*)&ompi_mpi_int, /* keep receiving in the same buffer */ - MPI_ANY_SOURCE, MCA_TOPO_BASE_TAG_DIST_EDGE_OUT, + MPI_ANY_SOURCE, MCA_COLL_BASE_TAG_TOPO_DIST_EDGE_OUT, comm, &status )); how_much = status._ucount / int_size; From 964719c5c5b8e2d12f7b30d8c21564742e4aec4d Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Thu, 4 Jun 2026 09:48:54 -0600 Subject: [PATCH 082/230] pmix: advance to v6.1.1rc2 Signed-off-by: Howard Pritchard --- 3rd-party/openpmix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rd-party/openpmix b/3rd-party/openpmix index dbe39f0ecd5..cb89026c747 160000 --- a/3rd-party/openpmix +++ b/3rd-party/openpmix @@ -1 +1 @@ -Subproject commit dbe39f0ecd5d21ead734ed65d01b4cf81158af68 +Subproject commit cb89026c747e8540692eed29b3880e67b7ba9aa2 From 598fda43cc89fd9d0184c57acfe63dbb568bcaff Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Thu, 4 Jun 2026 11:54:20 -0400 Subject: [PATCH 083/230] Update installation and runtime documentation Add a configure-options page that helps experienced site administrators decide which Open MPI components to build on stable HPC systems. The new page explains when avoiding unused components can reduce installation footprint and component selection overhead, and gives a current Open MPI v6.0.0 example for building only the OB1 PML. Link this guidance from the large-cluster tuning chapter so deployment-focused readers can find the build-time considerations without moving configure-specific material out of the installation chapter. Refresh nearby user-facing documentation at the same time: correct the Homebrew package name to open-mpi, keep the MacPorts command, add package-manager reference URLs, and improve the mpirun man page wording for hwloc logical IDs and lstopo(1). Signed-off-by: Jeff Squyres --- .../configure-cli-options/index.rst | 1 + .../configure-cli-options/what-to-install.rst | 68 +++++++++++++++++++ docs/installing-open-mpi/quickstart.rst | 4 +- docs/man-openmpi/man1/mpirun.1.rst | 14 ++-- docs/tuning-apps/large-clusters/index.rst | 4 ++ 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 docs/installing-open-mpi/configure-cli-options/what-to-install.rst diff --git a/docs/installing-open-mpi/configure-cli-options/index.rst b/docs/installing-open-mpi/configure-cli-options/index.rst index e80812e4799..90c974f2909 100644 --- a/docs/installing-open-mpi/configure-cli-options/index.rst +++ b/docs/installing-open-mpi/configure-cli-options/index.rst @@ -11,6 +11,7 @@ below. .. toctree:: :maxdepth: 1 + what-to-install conventions installation networking diff --git a/docs/installing-open-mpi/configure-cli-options/what-to-install.rst b/docs/installing-open-mpi/configure-cli-options/what-to-install.rst new file mode 100644 index 00000000000..2e6f3563094 --- /dev/null +++ b/docs/installing-open-mpi/configure-cli-options/what-to-install.rst @@ -0,0 +1,68 @@ +Deciding what to install +======================== + +Open MPI's ``configure`` script will, by default, search for support +and build every component that it can. This is convenient, and +helpful for a good out-of-the-box experience for many HPC +environments. + +However, HPC clusters rarely change from day-to-day, and large +clusters rarely change at all. If you know your cluster's +configuration, there are several steps you can take to reduce the +Open MPI installation footprint and component selection overhead. +These steps use a combination of build-time configuration options to +eliminate components |mdash| thus eliminating their libraries and +avoiding unnecessary component open/close operations |mdash| as well +as run-time MCA parameters to specify what modules to use by default +for most users. + +.. caution:: This is somewhat advanced functionality, and is only + recommended for users who are deeply familiar with what + components are actually used by Open MPI in their + environments. + + Most users should just allow building whatever components + Open MPI's ``configure`` script finds. + +Build/install-time choices +-------------------------- + +One way to save memory is to avoid building components that will +actually never be selected by the system. Unless MCA parameters +specify which components to open, installed components are *always* +opened and tested as to whether or not they should be selected for +use. If you know that a component can build on your system, but due to +your cluster's configuration will never actually be selected, then it +is best to simply configure Open MPI to not build that component by +using the ``--enable-mca-no-build`` CLI option to ``configure``. + +For example, if you know that your system will only utilize the +``ob1`` component of the PML framework, then you can "no build" all +the others: + +.. code:: sh + + # See what directories (i.e., components) exist in the PML + # framework + shell$ ls -1 ompi/mca/pml + + # Do not list "base", but list all other undesired components + # (i.e., directories). For example, in Open MPI v6.0.0, to build + # *only* the OB1 PML: + shell$ ./configure --enable-mca-no-build=pml-cm,pml-monitoring,pml-ubcl,pml-ucx,pml-v + + +This not only reduces the size of the Open MPI libraries, but can also +avoid unnecessary component open/selection work at run time. + +Run-time choices +---------------- + +The ``$sysconfdir/openmpi-mca-params.conf`` file in the installation +tree (which defaults to ``$prefix/etc/openmpi-mca-params.conf``) is +where a system administrator can set system-wide defaults for Open MPI +:ref:`run-time MCA parameters `. + +These values can still be overridden by end users, but the values in +this file allow the hiding of any system-specific defaults that an +administrator may want the majority of users to utilize. diff --git a/docs/installing-open-mpi/quickstart.rst b/docs/installing-open-mpi/quickstart.rst index 3ecc172e826..412f78593e5 100644 --- a/docs/installing-open-mpi/quickstart.rst +++ b/docs/installing-open-mpi/quickstart.rst @@ -37,9 +37,11 @@ packages: .. code-block:: sh # For Homebrew - shell$ brew install openmpi + # https://formulae.brew.sh/formula/open-mpi + shell$ brew install open-mpi # For MacPorts + # https://ports.macports.org/search/?q=openmpi shell$ port install openmpi .. important:: Binary packages may or may not include support for diff --git a/docs/man-openmpi/man1/mpirun.1.rst b/docs/man-openmpi/man1/mpirun.1.rst index b970e2d5d6d..5eec1816613 100644 --- a/docs/man-openmpi/man1/mpirun.1.rst +++ b/docs/man-openmpi/man1/mpirun.1.rst @@ -267,10 +267,13 @@ To map processes: * ``--cpu-list ``: Comma-delimited list of processor IDs to which to bind processes [default=``NULL``]. Processor IDs are - interpreted as hwloc logical core IDs. + interpreted as `Hwloc `_ + logical core IDs. - .. note:: You can run Run the hwloc ``lstopo(1)`` command to see a - list of available cores and their logical IDs. + .. note:: You can run the `Hwloc + `_ ``lstopo(1)`` + command to see a list of available cores and their logical + IDs. To order processes' ranks in ``MPI_COMM_WORLD``: @@ -1232,8 +1235,9 @@ All package/core slot locations are specified as logical indexes. .. note:: The Open MPI v1.6 series used physical indexes. Starting in Open MPI v5.0 only logical indexes are supported and the ``rmaps_rank_file_physical`` MCA parameter is no longer recognized. -You can use tools such as Hwloc's `lstopo(1)` to find the logical -indexes of package and cores. +You can use tools such as `Hwloc's +`_ ``lstopo(1)`` command to +find the logical indexes of package and cores. Application Context or Executable Program? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/tuning-apps/large-clusters/index.rst b/docs/tuning-apps/large-clusters/index.rst index ff58b2b7e13..8ed80bb842b 100644 --- a/docs/tuning-apps/large-clusters/index.rst +++ b/docs/tuning-apps/large-clusters/index.rst @@ -5,6 +5,10 @@ Setting up a large cluster to run MPI applications can be challenging and full of many decisions. The following sections include guidance for installing and tuning Open MPI on large clusters. +Also see :doc:`Deciding what to install +` for +build-time considerations that can affect large-cluster deployments. + .. toctree:: :maxdepth: 1 From a22012ef07d186e0bf11a66eb90074b3f74c7214 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sat, 30 Nov 2024 10:03:36 -0500 Subject: [PATCH 084/230] developers: Doc how to build against external PMIx/PRTE Signed-off-by: Jeff Squyres --- docs/developers/building-open-mpi.rst | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/docs/developers/building-open-mpi.rst b/docs/developers/building-open-mpi.rst index ee09d294e20..d21bcc74e45 100644 --- a/docs/developers/building-open-mpi.rst +++ b/docs/developers/building-open-mpi.rst @@ -1,9 +1,87 @@ Building Open MPI ================= +General +------- + Once you have run ``autogen.pl`` successfully, you can configure and build Open MPI just like end users do with official distribution Open MPI tarballs. See the :doc:`general "Install Open MPI" documentation for more details. ` + +Building Against External OpenPMIx / PRRTE +------------------------------------------ + +One thing that developers and/or packagers may need to do is to build +Open MPI against an external OpenPMIx and/or PRRTE source tree (i.e., +an OpenPMIx and/or PRRTE installation that was not built from the +embedded copies inside the Open MPI source tree / Git submodules). + +With regards to :doc:`Open MPI's required dependent libraries +` (Hwloc, Libevent, +OpenPMIx, and PRRTE), it generally is simplest to build Open MPI in +one of two ways: + +#. Build and use all the **internal** copies of Open MPI's required + dependent libraries. + + * Specifically: use the Hwloc, Libevent, OpenPMIx, and PRRTE source + trees that are bundled in with Open MPI's source code. + +#. Build and use all **external** copies of Open MPI's required + dependent libraries. + + * Specifically: ignore the Hwloc, Libevent, OpenPMIx, and PRRTE source + trees that are bundled in with Open MPI's source code, and, + instead, compile and link Open MPI against already-installed + versions of these libraries. + +Other variations are possible, but can get tricky and complicated with +subtle linker consequences, and are therefore not recommended. + +Some facts that are relevant to know when building against an external +OpenPMIx / PRRTE: + +1. Open MPI, OpenPMIx, and PRRTE must all be built against the + **same** installation of Hwloc and Libevent. Meaning: + + * Assumedly the external OpenPMIx and PRRTE were built against + external Hwloc and Libevent. Open MPI **must** compile and link + against the **same** Hwloc and Libevent that the external + OpenPMIx and PRRTE were built against. + + .. admonition:: Critical + :class: Danger + + Open MPI, OpenPMIx, and PRRTE must all use the same Hwloc and + Libevent libraries at run time (e.g., they must all resolve to + the same run-time loadable libraries at run time). + + .. important:: This statement applies regardless of whether + Open MPI -- and/or the other libraries -- are + built as static or dynamically-loadable + libraries. + + * Unless you really know what you are doing, this usually means + building and installing Open MPI against the same installation + tree(s) of Hwloc and Libevent that OpenPMIx and PRRTE used to + build themselves. + + For example, consider an environment where you install Hwloc, + Libevent, OpenPMIx, and PRRTE via the operating system's package + manager. Assuming that the package-manager installs of OpenPMIx + and PRRTE were built against the package-manager-provider Hwloc + and Libevent, then Open MPI will *also* need to be built against + the package-manager-provided Hwloc and Libevent. To build Open + MPI this way, you may need to install the package manager's + "developer" Hwloc, Libevent, OpenPMIx, and/or PRRTE packages. + +1. Open MPI and PRRTE must be built against the **same** installation + of OpenPMIx. + + .. important:: Similar to how OpenPMIx, PRRTE, and Open MPI, must + be built against the same Hwloc and Libevent, PRRTE + and Open MPI must be built against the same + OpenPMIx. From ea1627ff257162616de2bed3487a10120c110918 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Thu, 4 Jun 2026 15:04:19 -0400 Subject: [PATCH 085/230] TO BE SQUASHED Separated out into a separate commit just for reviewing purposes. Signed-off-by: Jeff Squyres --- docs/developers/building-open-mpi.rst | 82 +++++++++++++++++---------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/docs/developers/building-open-mpi.rst b/docs/developers/building-open-mpi.rst index d21bcc74e45..e53b5a2d767 100644 --- a/docs/developers/building-open-mpi.rst +++ b/docs/developers/building-open-mpi.rst @@ -15,8 +15,9 @@ Building Against External OpenPMIx / PRRTE ------------------------------------------ One thing that developers and/or packagers may need to do is to build -Open MPI against an external OpenPMIx and/or PRRTE source tree (i.e., -an OpenPMIx and/or PRRTE installation that was not built from the +Open MPI against an external OpenPMIx installation, and/or configure +Open MPI's ``mpirun`` / ``mpiexec`` launchers to use an external PRRTE +installation (i.e., installations that were not built from the embedded copies inside the Open MPI source tree / Git submodules). With regards to :doc:`Open MPI's required dependent libraries @@ -35,29 +36,34 @@ one of two ways: * Specifically: ignore the Hwloc, Libevent, OpenPMIx, and PRRTE source trees that are bundled in with Open MPI's source code, and, - instead, compile and link Open MPI against already-installed - versions of these libraries. + instead, build Open MPI against already-installed Hwloc, + Libevent, and OpenPMIx libraries, and configure Open MPI's + launchers to use an already-installed PRRTE. -Other variations are possible, but can get tricky and complicated with -subtle linker consequences, and are therefore not recommended. +Other variations are possible, but can get tricky and complicated +because Open MPI, the OpenPMIx library that it uses, Hwloc, and +Libevent can be loaded into the same process. They are therefore not +recommended unless you understand the run-time linker consequences. Some facts that are relevant to know when building against an external OpenPMIx / PRRTE: -1. Open MPI, OpenPMIx, and PRRTE must all be built against the - **same** installation of Hwloc and Libevent. Meaning: +1. Open MPI and the OpenPMIx library that Open MPI links against must + be built against the **same** installation of Hwloc and Libevent. + Meaning: - * Assumedly the external OpenPMIx and PRRTE were built against - external Hwloc and Libevent. Open MPI **must** compile and link - against the **same** Hwloc and Libevent that the external - OpenPMIx and PRRTE were built against. + * Assumedly the external OpenPMIx was built against external Hwloc + and Libevent. Open MPI **must** compile and link against the + **same** Hwloc and Libevent that the external OpenPMIx was built + against. .. admonition:: Critical :class: Danger - Open MPI, OpenPMIx, and PRRTE must all use the same Hwloc and - Libevent libraries at run time (e.g., they must all resolve to - the same run-time loadable libraries at run time). + Open MPI and the OpenPMIx library that it links against must + use the same Hwloc and Libevent libraries at run time (e.g., + they must resolve to the same run-time loadable libraries at + run time). .. important:: This statement applies regardless of whether Open MPI -- and/or the other libraries -- are @@ -66,22 +72,36 @@ OpenPMIx / PRRTE: * Unless you really know what you are doing, this usually means building and installing Open MPI against the same installation - tree(s) of Hwloc and Libevent that OpenPMIx and PRRTE used to - build themselves. + tree(s) of Hwloc and Libevent that OpenPMIx used to build itself. For example, consider an environment where you install Hwloc, Libevent, OpenPMIx, and PRRTE via the operating system's package - manager. Assuming that the package-manager installs of OpenPMIx - and PRRTE were built against the package-manager-provider Hwloc - and Libevent, then Open MPI will *also* need to be built against - the package-manager-provided Hwloc and Libevent. To build Open - MPI this way, you may need to install the package manager's - "developer" Hwloc, Libevent, OpenPMIx, and/or PRRTE packages. - -1. Open MPI and PRRTE must be built against the **same** installation - of OpenPMIx. - - .. important:: Similar to how OpenPMIx, PRRTE, and Open MPI, must - be built against the same Hwloc and Libevent, PRRTE - and Open MPI must be built against the same - OpenPMIx. + manager. Assuming that the package-manager install of OpenPMIx + was built against the package-manager-provided Hwloc and + Libevent, then Open MPI will *also* need to be built against the + package-manager-provided Hwloc and Libevent. To build Open MPI + this way, you may need to install the package manager's + "developer" Hwloc, Libevent, and OpenPMIx packages. + +1. PRRTE and the OpenPMIx library that PRRTE uses must be built + against the **same** installation of Hwloc and Libevent. + + This is a separate requirement from Open MPI's requirement above: + Open MPI does not link against PRRTE, and MPI applications do not + load ``libprrte``. Therefore, PRRTE's Hwloc, Libevent, and + OpenPMIx dependencies do not have to match Open MPI's dependencies + merely because Open MPI uses PRRTE as a launcher. + +1. Open MPI and PRRTE do **not** have to use the same OpenPMIx + installation. + + PMIx supports cross-version operations, so Open MPI and PRRTE can + use different OpenPMIx installations, and those installations do + not need to be the same OpenPMIx version. + + If Open MPI and PRRTE do use the **same** OpenPMIx installation, + then the requirements above mean that Open MPI, PRRTE, OpenPMIx, + Hwloc, and Libevent will all use the same Hwloc and Libevent + installations. However, this is a consequence of sharing one + OpenPMIx installation; it is not a requirement that Open MPI and + PRRTE share one OpenPMIx installation. From 8849c0121dd92b1476b602499f3a9f3f2b76d605 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Thu, 4 Jun 2026 18:34:54 -0400 Subject: [PATCH 086/230] pml/ob1: drain pckt_pending from mca_pml_ob1_progress to avoid orphaned FINs The FIN/ACK control-packet retry queue (mca_pml_ob1.pckt_pending) was drained only as a side effect of BTL completion callbacks, via MCA_PML_OB1_PROGRESS_PENDING(). A FIN whose btl_sendi() fails with OPAL_ERR_OUT_OF_RESOURCE is parked on pckt_pending and retried the next time a send/recv/control fragment completes on some bml_btl. That assumption breaks at the tail of an incast. When a receiver has consumed all incoming data the BTL goes idle: no fragments remain in flight, no completion callback fires, and MCA_PML_OB1_PROGRESS_PENDING() is never invoked again. Any FINs still queued on pckt_pending are orphaned. The senders' RGET requests stay ACTIVE forever (req_pending NONE, req_bytes_delivered 0) and block in MPI_Waitall, while the receiver spins in opal_progress() with a non-empty pckt_pending and an otherwise idle PML/BTL. Treat a queued control packet like any other pending PML work instead of relying on BTL completions. mca_pml_ob1_add_to_pending() now calls mca_pml_ob1_enable_progress(1), reusing the existing progress counter and the already-registered mca_pml_ob1_progress() callback, which is extended to drain pckt_pending alongside send_pending and to fold the drained packets into its completed-request accounting. No second progress function and no second atomic are introduced; the callback unregisters itself once all pending work (sends and control packets) is gone, so there is no steady-state overhead. Because the BTL is idle when this path matters, fragments are available and the queued FINs are sent, completing the peers' sends. Reproduced with an all-to-one incast of 80KB rendezvous (RGET) messages over the sm BTL on a single node; aggravated by btl_sm_fbox_max=0, which increases btl_sendi() resource-exhaustion failures. Switching to another BTL hid the issue because their completion/async-progress patterns kept firing MCA_PML_OB1_PROGRESS_PENDING(). Fixes #12979 Signed-off-by: George Bosilca --- ompi/mca/pml/ob1/pml_ob1.h | 16 ++++++++++------ ompi/mca/pml/ob1/pml_ob1_progress.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ompi/mca/pml/ob1/pml_ob1.h b/ompi/mca/pml/ob1/pml_ob1.h index a0091793ab4..29a57d02f51 100644 --- a/ompi/mca/pml/ob1/pml_ob1.h +++ b/ompi/mca/pml/ob1/pml_ob1.h @@ -255,6 +255,12 @@ do { \ (opal_free_list_item_t*)pckt); \ } while(0) +/** + * A thread-safe function that should be called every time we need the OB1 + * progress to be turned (or kept) on. + */ +int mca_pml_ob1_enable_progress(int32_t count); + static inline void mca_pml_ob1_add_to_pending (ompi_proc_t *proc, mca_bml_base_btl_t *bml_btl, int order, mca_pml_ob1_hdr_t *hdr, size_t hdr_size) { @@ -270,6 +276,10 @@ static inline void mca_pml_ob1_add_to_pending (ompi_proc_t *proc, mca_bml_base_b OPAL_THREAD_SCOPED_LOCK(&mca_pml_ob1.lock, { opal_list_append(&mca_pml_ob1.pckt_pending, &pckt->super.super); }); + /* Drive mca_pml_ob1_progress() so the queue is retried from opal_progress() + * even if no further BTL completion fires to call + * MCA_PML_OB1_PROGRESS_PENDING. */ + mca_pml_ob1_enable_progress(1); } #define OB1_MATCHING_LOCK(lock) \ @@ -411,12 +421,6 @@ mca_pml_ob1_calc_weighted_length( mca_pml_ob1_com_btl_t *btls, int num_btls, siz btls[0].length += length_left; } -/** - * A thread-safe function that should be called every time we need the OB1 - * progress to be turned (or kept) on. - */ -int mca_pml_ob1_enable_progress(int32_t count); - int mca_pml_ob1_send_control_any (ompi_proc_t *proc, int order, mca_pml_ob1_hdr_t *hdr, size_t hdr_size, bool add_to_pending); int mca_pml_ob1_send_control_btl (mca_bml_base_btl_t *bml_btl, int order, mca_pml_ob1_hdr_t *hdr, size_t hdr_size, diff --git a/ompi/mca/pml/ob1/pml_ob1_progress.c b/ompi/mca/pml/ob1/pml_ob1_progress.c index 930d5b7311e..935d5bf1357 100644 --- a/ompi/mca/pml/ob1/pml_ob1_progress.c +++ b/ompi/mca/pml/ob1/pml_ob1_progress.c @@ -71,6 +71,21 @@ int mca_pml_ob1_progress(void) completed_requests += mca_pml_ob1_process_pending_accelerator_async_copies(); + /* Drain the FIN/ACK control-packet retry queue. It is otherwise drained + * only as a side effect of BTL completion callbacks (see + * MCA_PML_OB1_PROGRESS_PENDING). If the BTL goes idle while packets are + * still queued -- e.g. the tail of an incast where btl_sendi() repeatedly + * returned OPAL_ERR_OUT_OF_RESOURCE -- no further completion fires, the + * queue is never revisited, and every peer waiting on those FINs hangs + * forever. Retrying it here, driven by mca_pml_ob1_progress_needed (which + * mca_pml_ob1_add_to_pending() bumps via mca_pml_ob1_enable_progress()), + * guarantees the queue makes progress even with no BTL traffic in flight. */ + if( opal_list_get_size(&mca_pml_ob1.pckt_pending) ) { + int pckt_before = (int) opal_list_get_size(&mca_pml_ob1.pckt_pending); + mca_pml_ob1_process_pending_packets(NULL); + completed_requests += pckt_before - (int) opal_list_get_size(&mca_pml_ob1.pckt_pending); + } + for( i = 0; i < queue_length; i++ ) { mca_pml_ob1_send_pending_t pending_type = MCA_PML_OB1_SEND_PENDING_NONE; mca_pml_ob1_send_request_t* sendreq; From a1eee3b880ac1801516b1e000bc024e3ba59d195 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sat, 27 Dec 2025 14:28:41 -0500 Subject: [PATCH 087/230] Add a CodeQL code scanning (static analysis) workflow Run GitHub code scanning over the actions, c-cpp, and python languages. The c-cpp analysis uses CodeQL's manual build mode and builds the tree with the standard autogen.pl / configure / make flow. Analysis is configured by .github/codeql/codeql-config.yml, referenced by both jobs. It keeps CodeQL's default (high-precision security) query suite and uses paths-ignore to drop alerts from the vendored third-party packages under 3rd-party/ and from the test trees. Like this workflow, the config file is read from the checked-out tree, so it must be committed alongside it on each scanned branch. Coverage has two parts: - Event-driven: every pull request and every push (merge) to main and the supported release branches is analyzed, catching problems at the moment code changes. - Periodic: a weekly Monday scan re-analyzes main and the active release branches. CodeQL's query packs and engine are updated continually as new vulnerability classes and CVEs are discovered, so the weekly run can flag issues in code that has not changed since it was merged (and would otherwise never be re-examined). Release branches in particular tend to go quiet between point releases. Because the schedule event only ever fires from the default branch, the scheduled job explicitly checks out each branch and attributes results via the analyze action's ref/sha inputs. To get PR and merge analysis on a release branch, this file must also be committed on that branch; the scheduled job is inert there. A third job (check-scheduled-coverage) runs on the default branch and fails the build if a release branch matched by the push/pull_request globs is missing from the scheduled branch list, so new release branches are not silently left out of the weekly scan. It derives its matcher from the on.push.branches globs, and the push and pull_request filters share a single YAML-anchored list, so the branch pattern has a single definition that cannot drift. A concurrency group cancels superseded pull-request runs to avoid stacking up expensive C/C++ builds, while letting scheduled scans and branch pushes run to completion. All jobs are guarded with github.repository == 'open-mpi/ompi', so forks do not run scans on their own pushes or schedules. Pull requests opened against open-mpi/ompi are still analyzed, since they run in the base-repository context. Signed-off-by: Jeff Squyres --- .github/codeql/codeql-config.yml | 16 ++ .github/workflows/codeql.yml | 290 +++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 .github/codeql/codeql-config.yml create mode 100644 .github/workflows/codeql.yml diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 00000000000..a0f72e5cf60 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# CodeQL configuration for Open MPI, referenced by both analysis jobs +# in .github/workflows/codeql.yml via their `config-file:` input. + +name: "Open MPI CodeQL config" + +paths-ignore: + - '3rd-party' + - '**/test' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..e3244d3f902 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,290 @@ +# +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# +# CodeQL (GitHub code scanning / static analysis) configuration for +# Open MPI. +# +# What this workflow does: +# +# 1. Runs CodeQL analysis on every pull request and on every push +# (i.e., merge) to main and the supported release branches. This +# catches newly-introduced problems at the moment code changes. +# +# 2. Runs a periodic (weekly, Monday morning UTC) CodeQL scan of main +# *and* the active release branches. +# +# Why run periodic scans in addition to the per-PR / per-merge scans? +# +# The PR/merge scans only ever examine code at the moment it changes. +# But CodeQL's query packs and analysis engine are continually +# updated as new classes of vulnerabilities (and new CVEs) are +# discovered. The weekly scan re-analyzes the *existing* code base +# with the latest queries, so a vulnerability pattern that was +# unknown when a piece of code was merged can still be found later -- +# even though that code has not changed and therefore would never be +# re-examined by a push/PR scan. Release branches in particular tend +# to go quiet between point releases, so the periodic scan is often +# the only thing that keeps their results current. +# +# A note on branches and where this file must live: +# +# - push and pull_request workflows always run from the copy of this +# file on the branch receiving the push / targeted by the PR (not +# from main). So to get PR and merge analysis on a release branch +# (e.g., v5.0.x, v6.0.x), this file must also be committed on that +# branch. +# +# - The schedule (cron) event is special: it only ever fires from the +# default branch (main). To periodically scan the release branches +# as well, the scheduled job below explicitly checks out each +# branch and tells the analyze action which ref/sha to attribute +# the results to. The scheduled job is therefore inert on the +# release branches (it never fires there); only the copy on main +# drives the weekly scans. +# +# Why inline (and not a composite action or reusable workflow): the two +# jobs below intentionally duplicate the init / build / analyze steps. +# Because per-branch CI requires this file to be cherry-picked onto each +# release branch anyway, a single self-contained file (one file per +# branch, with nothing else to keep in sync) is simpler than factoring +# the shared steps out. Sharing them would not buy a cross-branch single +# source of truth, and a local composite action would actually break the +# weekly scan, since `uses: ./...` resolves from the checked-out branch +# rather than from main. +# +# We started running CodeQL on the main, v5.0.x, and v6.0.x branches in +# June 2026. Subsequent release branches are matched by the branch +# globs below (for PR/merge scans) and should be added to the scheduled +# job's branch list on main (for the weekly scans). + +name: "CodeQL Advanced" + +on: + push: + # Defined once here (&scan_branches) and reused by pull_request + # below via a YAML alias, so the two trigger lists cannot drift. + branches: &scan_branches + - main + - 'v[5-9].*.x' # Matches v5.0.x through v9.9.x + - 'v[1-9][0-9]+.*.x' # Matches v10.0.x and higher (double digits+) + pull_request: + branches: *scan_branches + schedule: + # Monday morning (UTC). The off-the-hour minute avoids GitHub's + # top-of-the-hour scheduling congestion. + - cron: '32 5 * * 1' + +permissions: + # required for all workflows + security-events: write + # required to fetch internal or private CodeQL packs + packages: read + # only required for workflows in private repositories + actions: read + contents: read + +# Cancel a superseded in-progress run when a newer commit is pushed to +# the same pull request, to avoid stacking up expensive C/C++ builds. +# The group includes the event name so push/schedule runs live in +# separate groups, and cancellation is enabled only for pull_request +# runs -- never the weekly scheduled scan or pushes to a branch. +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + # ------------------------------------------------------------------- + # Event-driven analysis: scans the ref that triggered the push / PR. + # ------------------------------------------------------------------- + analyze: + if: github.event_name != 'schedule' && github.repository == 'open-mpi/ompi' + name: Analyze ${{ matrix.language }} (${{ github.ref_name }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: c-cpp + build-mode: manual + - language: python + build-mode: none + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: recursive + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + ./autogen.pl + ./configure + make -j $(nproc) + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + + # ------------------------------------------------------------------- + # Scheduled analysis: explicitly scans main and each release branch. + # Only fires from the default branch (main); see the header comment. + # ------------------------------------------------------------------- + analyze-scheduled: + if: github.event_name == 'schedule' && github.repository == 'open-mpi/ompi' + name: Analyze ${{ matrix.language }} (${{ matrix.branch }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Concrete branch names only: this matrix drives + # 'actions/checkout', so (unlike the on.push.branches globs) + # these cannot be globs or regexes. New release branches must be + # added here, too; the check-scheduled-coverage job enforces it. + branch: + - main + - v5.0.x + - v6.0.x + language: + - actions + - c-cpp + - python + include: + - language: actions + build-mode: none + - language: c-cpp + build-mode: manual + - language: python + build-mode: none + steps: + - name: Checkout ${{ matrix.branch }} + uses: actions/checkout@v6 + with: + ref: ${{ matrix.branch }} + submodules: recursive + persist-credentials: false + + - name: Resolve commit SHA + id: commit + shell: bash + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + config-file: ./.github/codeql/codeql-config.yml + + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + ./autogen.pl + ./configure + make -j $(nproc) + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + # Attribute results to the checked-out branch rather than to + # main (which is what a schedule event would otherwise report + # against). The category is keyed on language only -- NOT on + # branch -- so each branch's results update in place and the + # weekly main scan stays consistent with its push/PR scans. + ref: refs/heads/${{ matrix.branch }} + sha: ${{ steps.commit.outputs.sha }} + + # ------------------------------------------------------------------- + # Guard: fail if a release branch that the push/pull_request globs + # cover is missing from the analyze-scheduled 'branch:' list, so new + # release branches don't silently drop out of the weekly scan. + # + # Runs only in the default-branch (main) context, where the scheduled + # matrix is authoritative. On a release branch the matrix is inert + # (the schedule fires only from the default branch) and its copy can + # lag main's, so running there would block CI for drift it can't fix. + # ------------------------------------------------------------------- + check-scheduled-coverage: + if: >- + github.event_name != 'schedule' && + github.ref_name == github.event.repository.default_branch && + github.repository == 'open-mpi/ompi' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Verify periodic-scan branch coverage + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + # The push/PR trigger globs in on.push.branches (above) are the + # single definition of which branches get scanned. This guard + # reads them from this file and converts each GitHub filter-glob + # to a regex (. -> \., * -> .*; +, ?, and [..] mean the same in + # both), so it matches exactly what the triggers match -- there + # is no second copy of the pattern to keep in sync. It then + # checks that every such branch is also listed in the + # analyze-scheduled matrix. python3 is always present on the + # runner, so (unlike yq) a runner image change cannot break it. + gh api --paginate "repos/${{ github.repository }}/branches" \ + -q '.[].name' > "$RUNNER_TEMP/branches.txt" + + python3 - .github/workflows/codeql.yml "$RUNNER_TEMP/branches.txt" <<'PY' + import sys, re + + wf = open(sys.argv[1]).read() + branches = [b.strip() for b in open(sys.argv[2]) if b.strip()] + + # on.push.branches globs -> anchored ERE regexes. Capture the + # whole push block (tolerates comments and the &scan_branches + # anchor on the branches: line) and pull out its list items. + push = re.search(r"(?ms)^ push:\n(.*?)^ \S", wf) + raw = re.findall(r"(?m)^ - (\S.*?) *(?:#.*)?$", push.group(1)) if push else [] + globs = [x.strip().strip("'") for x in raw] + triggers = [re.compile("^" + g.replace(".", r"\.").replace("*", ".*") + "$") + for g in globs] + if not triggers: + sys.exit("::error::could not parse on.push.branches; " + "coverage guard cannot run") + + # analyze-scheduled matrix branch list. + sched = re.search(r"(?ms)^ branch:\n(.*?)^ \S", wf) + scheduled = set(re.findall(r"^ - (\S+)", sched.group(1), re.M)) if sched else set() + + missing = [b for b in branches + if any(rx.match(b) for rx in triggers) and b not in scheduled] + + if missing: + print("::error::Branch(es) get push/PR CodeQL scans but are missing " + "from the weekly scan list: " + " ".join(missing)) + print("Add them to jobs.analyze-scheduled.strategy.matrix.branch " + "in .github/workflows/codeql.yml.") + sys.exit(1) + print("OK: every push/PR-scanned branch is covered by the weekly scan.") + PY From b86379cbcfabe1e09723c5f13385d6d9d28e3fe0 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 8 Jun 2026 10:11:08 -0400 Subject: [PATCH 088/230] Document proper build system regeneration workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new "Modifying the configure / build system" section to AGENTS.md that details the correct process for rebuilding the Autotools-generated build system after changes to configure.ac or config/*.m4 files. This addresses a critical and frequently misunderstood aspect of Open MPI development: the build system cannot be safely regenerated with a plain `make` command. Open MPI builds in maintainer mode, which auto-triggers partial in-tree Autotools regeneration that frequently fails (e.g., unexpanded OAC_* macros, config.status errors) and can leave the tree half-regenerated and unbuildable. This section provides: 1. An explicit, step-by-step regeneration workflow (autogen.pl + configure) 2. An explanation of why plain `make` is unsafe and what can go wrong 3. Guidance on recovering the original configure invocation options from the existing tree using ./config.status --config 4. A clarification that Makefile.am edits do NOT require the full regeneration process — a plain `make` suffices for those This guidance is particularly important for AI coding agents, which easily fall into the trap of using `make` as a shortcut, resulting in broken trees. The section is positioned after the basic build instructions to minimize confusion and provide just-in-time documentation for developers who need to modify the build system. Signed-off-by: Jeff Squyres --- AGENTS.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 40df5279977..b0ec197c541 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -157,6 +157,34 @@ make -j See [`docs/developers/building-open-mpi.rst`](docs/developers/building-open-mpi.rst) and the [install docs](docs/installing-open-mpi/) for options. +## Modifying the configure / build system + +Editing the build system means regenerating it — `make` alone can't, +and trying will wedge the tree. If you change `configure.ac` or any +`config/*.m4` file (including the embedded oac/Autotools macros), the +change does not take effect until the build system is regenerated. Do +not rely on a plain `make`: Open MPI builds in maintainer mode, so +`make` auto-triggers a partial in-tree Autotools regeneration that +frequently fails (e.g., unexpanded `OAC_*` macros, `config.status` +errors) and can leave the tree half-regenerated and +unbuildable. Instead, regenerate and reconfigure explicitly: + +```sh +./autogen.pl +./configure +make -j +``` + +Recover the original configure invocation options from the existing +tree with `./config.status --config` (or read the header of +`config.log`). This process is slow but mandatory after any +build-system source change — there is no safe shortcut. + +Note that editing `Makefile.am` files do *not* require the full +`autogen.pl` + `./configure` process. A simple `make` will regenerate +the relevant `Makefile[.in]` files and then complete the build +successfully. + **"Did I break it?" — layered:** 1. **Build cleanly.** A clean `make` after your change is the baseline. From 4ef1d030ea66b30020ece145a4422dea02d87a42 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 8 Jun 2026 16:05:15 -0400 Subject: [PATCH 089/230] .gitignore: Add new "make check" executables Add a few more executables that were created by "make check". Signed-off-by: Jeff Squyres --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 578ab99149e..5e6d4a12728 100644 --- a/.gitignore +++ b/.gitignore @@ -456,8 +456,12 @@ test/datatype/to_self test/datatype/checksum test/datatype/position test/datatype/ddt_raw +test/datatype/ddt_raw2 +test/datatype/large_data test/datatype/opal_datatype_test +test/datatype/partial test/datatype/position_noncontig +test/datatype/reduce_local test/datatype/unpack_ooo test/datatype/unpack_hetero @@ -471,6 +475,8 @@ test/monitoring/example_reduce_count test/monitoring/test_overhead test/monitoring/test_pvar_access +test/mpool/mpool_memkind + test/mpi/environment/chello test/runtime/parse_context @@ -483,6 +489,7 @@ test/spc/spc_test test/threads/opal_condition test/threads/opal_thread +test/threads/opal_atomic_thread_bench test/util/aaa test/util/test_session_dir_out @@ -506,6 +513,7 @@ test/util/opal_path_nfs.out test/util/opal_bit_ops test/util/bipartite_graph test/util/opal_sha256 +test/util/opal_json opal/test/reachable/reachable_netlink opal/test/reachable/reachable_weighted From ffe1423116d7c2878e1403fd989786a4bdbf6de4 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 9 Jun 2026 07:39:36 -0400 Subject: [PATCH 090/230] Allow manual CodeQL scheduled scans Add workflow_dispatch to the CodeQL workflow and route manual runs through the scheduled cross-branch matrix. This lets maintainers test the scheduled scan path without waiting for the next weekly cron event. Signed-off-by: Jeff Squyres --- .github/workflows/codeql.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e3244d3f902..e6d64bfae72 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -78,6 +78,7 @@ on: # Monday morning (UTC). The off-the-hour minute avoids GitHub's # top-of-the-hour scheduling congestion. - cron: '32 5 * * 1' + workflow_dispatch: permissions: # required for all workflows @@ -102,7 +103,10 @@ jobs: # Event-driven analysis: scans the ref that triggered the push / PR. # ------------------------------------------------------------------- analyze: - if: github.event_name != 'schedule' && github.repository == 'open-mpi/ompi' + if: >- + github.event_name != 'schedule' && + github.event_name != 'workflow_dispatch' && + github.repository == 'open-mpi/ompi' name: Analyze ${{ matrix.language }} (${{ github.ref_name }}) runs-on: ubuntu-latest strategy: @@ -143,11 +147,17 @@ jobs: category: "/language:${{ matrix.language }}" # ------------------------------------------------------------------- - # Scheduled analysis: explicitly scans main and each release branch. - # Only fires from the default branch (main); see the header comment. + # Scheduled/manual analysis: explicitly scans main and each release + # branch. The schedule only fires from the default branch (main); see + # the header comment. workflow_dispatch intentionally runs this same + # matrix so the scheduled path can be tested without waiting for the + # next cron event. # ------------------------------------------------------------------- analyze-scheduled: - if: github.event_name == 'schedule' && github.repository == 'open-mpi/ompi' + if: >- + (github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch') && + github.repository == 'open-mpi/ompi' name: Analyze ${{ matrix.language }} (${{ matrix.branch }}) runs-on: ubuntu-latest strategy: @@ -224,7 +234,7 @@ jobs: # ------------------------------------------------------------------- check-scheduled-coverage: if: >- - github.event_name != 'schedule' && + github.event_name == 'push' && github.ref_name == github.event.repository.default_branch && github.repository == 'open-mpi/ompi' runs-on: ubuntu-latest From e3783d56ca3d363d4238f2316066e6a0e880326b Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 9 Jun 2026 07:50:53 -0400 Subject: [PATCH 091/230] Load CodeQL config from main for scheduled scans Scheduled CodeQL jobs check out each branch before initializing CodeQL. Release branches may not yet contain the shared sidecar config file, so local config-file paths can fail during init. Use CodeQL remote config-file syntax for the scheduled job so it loads the default branch copy while analyzing each release branch. Signed-off-by: Jeff Squyres --- .github/codeql/codeql-config.yml | 7 +++++-- .github/workflows/codeql.yml | 22 +++++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index a0f72e5cf60..af9a473663f 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -6,8 +6,11 @@ # # $HEADER$ # -# CodeQL configuration for Open MPI, referenced by both analysis jobs -# in .github/workflows/codeql.yml via their `config-file:` input. +# CodeQL configuration for Open MPI. Push / PR scans load this file +# locally from the checked-out branch. The scheduled cross-branch scan +# loads this same file from the default branch via CodeQL's remote +# config-file syntax, so the release-branch scans do not require a local +# copy of this file to already exist. name: "Open MPI CodeQL config" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e6d64bfae72..367ee8ad65a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -47,15 +47,18 @@ # release branches (it never fires there); only the copy on main # drives the weekly scans. # -# Why inline (and not a composite action or reusable workflow): the two -# jobs below intentionally duplicate the init / build / analyze steps. +# Why mostly inline (and not a composite action or reusable workflow): +# the two jobs below intentionally duplicate the init / build / analyze +# steps. # Because per-branch CI requires this file to be cherry-picked onto each -# release branch anyway, a single self-contained file (one file per -# branch, with nothing else to keep in sync) is simpler than factoring -# the shared steps out. Sharing them would not buy a cross-branch single -# source of truth, and a local composite action would actually break the -# weekly scan, since `uses: ./...` resolves from the checked-out branch -# rather than from main. +# release branch anyway, keeping the workflow logic here is simpler than +# factoring the shared steps out. Sharing them would not buy a +# cross-branch single source of truth, and local workflow/action paths +# would actually break the weekly scan, since they resolve from the +# checked-out branch rather than from main. The CodeQL config sidecar is +# the exception: the scheduled job uses CodeQL's remote config-file +# syntax to load the sidecar file from main, so the config stays +# single-sourced while the analyzed worktree is a release branch. # # We started running CodeQL on the main, v5.0.x, and v6.0.x branches in # June 2026. Subsequent release branches are matched by the branch @@ -200,7 +203,8 @@ jobs: with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - config-file: ./.github/codeql/codeql-config.yml + config-file: >- + ${{ github.repository }}/.github/codeql/codeql-config.yml@${{ github.event.repository.default_branch }} - name: Run manual build steps if: matrix.build-mode == 'manual' From 18982ebb9d601a7df99783ffc42e748e20df1124 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 9 Jun 2026 09:28:53 -0400 Subject: [PATCH 092/230] Filter third-party C/C++ CodeQL alerts CodeQL path filters do not apply to C/C++ code compiled by a manual build. Open MPI still needs the normal full build for context, but alerts from bundled third-party source should not be reported as Open MPI findings. Write the C/C++ SARIF locally, filter results under 3rd-party, and upload the filtered SARIF for both event-driven and scheduled scans. Signed-off-by: Jeff Squyres --- .github/workflows/codeql.yml | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 367ee8ad65a..0d1d91cec51 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -145,10 +145,56 @@ jobs: make -j $(nproc) - name: Perform CodeQL Analysis + if: matrix.language != 'c-cpp' uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" + # CodeQL's paths-ignore setting does not filter C/C++ code that is + # compiled by a manual build. Open MPI's normal build compiles + # bundled third-party projects, which gives CodeQL complete build + # context but can also produce alerts in code we do not maintain. + # For C/C++ only, write SARIF locally, remove alerts whose primary + # locations are under 3rd-party/, and then upload the filtered SARIF. + - name: Perform CodeQL Analysis + if: matrix.language == 'c-cpp' + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + output: c-cpp-sarif-results + upload: failure-only + + - name: Locate C/C++ SARIF + if: matrix.language == 'c-cpp' + id: cpp_sarif + shell: bash + run: | + set -euo pipefail + shopt -s nullglob + sarif_files=(c-cpp-sarif-results/*.sarif) + if test ${#sarif_files[@]} -ne 1; then + echo "::error::Expected one C/C++ SARIF file, found ${#sarif_files[@]}" + exit 1 + fi + echo "file=${sarif_files[0]}" >> "$GITHUB_OUTPUT" + + - name: Filter third-party C/C++ SARIF results + if: matrix.language == 'c-cpp' + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -3rd-party/** + -**/3rd-party/** + input: ${{ steps.cpp_sarif.outputs.file }} + output: ${{ steps.cpp_sarif.outputs.file }} + + - name: Upload filtered C/C++ SARIF + if: matrix.language == 'c-cpp' + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: ${{ steps.cpp_sarif.outputs.file }} + category: "/language:${{ matrix.language }}" + # ------------------------------------------------------------------- # Scheduled/manual analysis: explicitly scans main and each release # branch. The schedule only fires from the default branch (main); see @@ -215,6 +261,7 @@ jobs: make -j $(nproc) - name: Perform CodeQL Analysis + if: matrix.language != 'c-cpp' uses: github/codeql-action/analyze@v4 with: category: "/language:${{ matrix.language }}" @@ -226,6 +273,62 @@ jobs: ref: refs/heads/${{ matrix.branch }} sha: ${{ steps.commit.outputs.sha }} + # CodeQL's paths-ignore setting does not filter C/C++ code that is + # compiled by a manual build. Open MPI's normal build compiles + # bundled third-party projects, which gives CodeQL complete build + # context but can also produce alerts in code we do not maintain. + # For C/C++ only, write SARIF locally, remove alerts whose primary + # locations are under 3rd-party/, and then upload the filtered SARIF. + - name: Perform CodeQL Analysis + if: matrix.language == 'c-cpp' + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + output: c-cpp-sarif-results + upload: failure-only + # Attribute results to the checked-out branch rather than to + # main (which is what a schedule event would otherwise report + # against). The category is keyed on language only -- NOT on + # branch -- so each branch's results update in place and the + # weekly main scan stays consistent with its push/PR scans. + ref: refs/heads/${{ matrix.branch }} + sha: ${{ steps.commit.outputs.sha }} + + - name: Locate C/C++ SARIF + if: matrix.language == 'c-cpp' + id: cpp_sarif + shell: bash + run: | + set -euo pipefail + shopt -s nullglob + sarif_files=(c-cpp-sarif-results/*.sarif) + if test ${#sarif_files[@]} -ne 1; then + echo "::error::Expected one C/C++ SARIF file, found ${#sarif_files[@]}" + exit 1 + fi + echo "file=${sarif_files[0]}" >> "$GITHUB_OUTPUT" + + - name: Filter third-party C/C++ SARIF results + if: matrix.language == 'c-cpp' + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -3rd-party/** + -**/3rd-party/** + input: ${{ steps.cpp_sarif.outputs.file }} + output: ${{ steps.cpp_sarif.outputs.file }} + + - name: Upload filtered C/C++ SARIF + if: matrix.language == 'c-cpp' + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: ${{ steps.cpp_sarif.outputs.file }} + category: "/language:${{ matrix.language }}" + # Match the scheduled analyze attribution above when uploading + # the filtered SARIF. + ref: refs/heads/${{ matrix.branch }} + sha: ${{ steps.commit.outputs.sha }} + # ------------------------------------------------------------------- # Guard: fail if a release branch that the push/pull_request globs # cover is missing from the analyze-scheduled 'branch:' list, so new From ef9993e0d1de7233060c7c5c1652de33dae2922e Mon Sep 17 00:00:00 2001 From: FranCDoc Date: Thu, 11 Jun 2026 00:06:20 -0300 Subject: [PATCH 093/230] docs: fix shmem_wait argument descriptions The shmem_wait man page documents target, value, and pe arguments that are not part of the shmem_wait or shmem_wait_until interfaces. Remove those copied argument descriptions and keep the documentation focused on ivar, cmp, and cmp_value. Fixes #7148. Signed-off-by: FranCDoc --- docs/man-openshmem/man3/shmem_wait.3.rst | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/docs/man-openshmem/man3/shmem_wait.3.rst b/docs/man-openshmem/man3/shmem_wait.3.rst index 881c8d1e512..c30326bda2a 100644 --- a/docs/man-openshmem/man3/shmem_wait.3.rst +++ b/docs/man-openshmem/man3/shmem_wait.3.rst @@ -81,24 +81,6 @@ processor that it has completed some action. The arguments are as follows: -target - The remotely accessible integer data object to be updated on the - remote PE. If you are using C/C++, the type of target should match - that implied in the SYNOPSIS section. If you are using the Fortran - compiler, it must be of type integer with an element size of 4 bytes - for SHMEM_INT4_ADD and 8 bytes for SHMEM_INT8_ADD. - -value - The value to be atomically added to target. If you are using C/C++, - the type of value should match that implied in the SYNOPSIS section. - If you are using Fortran, it must be of type integer with an element - size of target. - -pe - An integer that indicates the PE number upon which target is to be - updated. If you are using Fortran, it must be a default integer - value. - ivar A remotely accessible integer variable that is being updated by another PE. If you are using C/C++, the type of ivar should match From 57803b2d5b5d56b838cccbbe56fa2f0854da7550 Mon Sep 17 00:00:00 2001 From: Matthew Whitlock Date: Thu, 11 Jun 2026 10:23:12 -0700 Subject: [PATCH 094/230] Make yield_when_idle a modifyable MPI_T_cvar Signed-off-by: Matthew Whitlock --- ompi/runtime/ompi_mpi_params.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ompi/runtime/ompi_mpi_params.c b/ompi/runtime/ompi_mpi_params.c index 7b5d1f3c55e..d33a75efa55 100644 --- a/ompi/runtime/ompi_mpi_params.c +++ b/ompi/runtime/ompi_mpi_params.c @@ -24,6 +24,7 @@ * reserved. * Copyright (c) 2021 Nanook Consulting. All rights reserved. * Copyright (c) 2022 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Sandia National Laboratories. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -157,9 +158,9 @@ int ompi_mpi_register_params(void) /* yield if the node is oversubscribed and allow users to override */ (void) mca_base_var_register("ompi", "mpi", NULL, "yield_when_idle", "Yield the processor when waiting for MPI communication (for MPI processes, will default to 1 when oversubscribing nodes)", - MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0, - OPAL_INFO_LVL_5, - MCA_BASE_VAR_SCOPE_READONLY, + MCA_BASE_VAR_TYPE_BOOL, NULL, 0, + MCA_BASE_VAR_FLAG_SETTABLE, OPAL_INFO_LVL_5, + MCA_BASE_VAR_SCOPE_LOCAL, &ompi_mpi_yield_when_idle); ompi_mpi_event_tick_rate = -1; From e57aec4272c2661a210ac29e3039a3122e391f71 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Fri, 12 Jun 2026 21:55:42 -0400 Subject: [PATCH 095/230] docs: on the front page, link back to the v4.1.x FAQ Because we don't have all of that content here on the docs site, and that's now the only surviving link to https://www.open-mpi.org/faq/ (all other links on www.open-mpi.org now point out to docs.open-mpi.org). Signed-off-by: Jeff Squyres --- docs/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 2148491e729..c6b08b4b226 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -42,7 +42,8 @@ Documentation for Open MPI can be found in the following locations: For example: - * `v4.1.x README file `_ + * `v4.1.x README file `_, + `v4.1.x FAQ `_ * `v4.0.x README file `_ Release announcements From f22bc9de8ba23b2ad003dc40f326f76488b07fc3 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sat, 13 Jun 2026 17:45:46 -0400 Subject: [PATCH 096/230] request: fix MPI_Testall spuriously returning MPI_ERR_IN_STATUS MPI_Testall (ompi_request_default_test_all) had an inverted success/error test in the branch taken when the caller passes a real array_of_statuses (i.e. not MPI_STATUSES_IGNORE). The guard read: if (MPI_SUCCESS == request->req_status.MPI_ERROR) { rc = MPI_ERR_IN_STATUS; ... } so the aggregate return code was set to MPI_ERR_IN_STATUS exactly when a request had *no* error, and was left untouched when a request *did* carry an error. The net effect: * A fully successful MPI_Testall (all requests complete, none in error) returned MPI_ERR_IN_STATUS instead of MPI_SUCCESS. Under the default MPI_ERRORS_ARE_FATAL handler this aborts the application; under MPI_ERRORS_RETURN it surfaces as a bogus error. * Conversely, a genuine per-request error was *masked*: the condition is false when MPI_ERROR != MPI_SUCCESS, so rc was never set to MPI_ERR_IN_STATUS, and the fault-tolerance MPI_ERR_PROC_FAILED / MPI_ERR_REVOKED sub-branch became dead code. The fix flips the comparison to "!=", matching the three sibling code paths that were already correct: the MPI_STATUSES_IGNORE branch of the same function (a few lines below), MPI_Waitall (req_wait.c, ompi_request_default_wait_all), and MPI_Testsome (ompi_request_default_test_some). The adjacent persistent/free logic, which legitimately frees a request only on success, is unchanged. Provenance: this inverted condition was introduced by commit 38a7fbb837 (PR #13437, "MPI_ERR_IN_STATUS for persistent requests"), which was addressing issue #13432. That PR refactored both req_test.c and req_wait.c; the req_wait.c change is correct, but the req_test.c rewrite landed with the comparison reversed. The regression is present on main, v5.0.x, and v6.0.x (PR #13437 was backported to the release branches), at the same location and with the same one-line fix on each. Only MPI_Testall is affected -- MPI_Waitall, MPI_Wait, MPI_Test, MPI_Testany, MPI_Testsome, and the MPI_STATUSES_IGNORE path of MPI_Testall all use the correct test. The bug is deterministic, not a race: any MPI_Testall call that completes one or more active requests while a real status array is supplied reproduces it every time. Found during a systematic MPI-5.0 conformance review of main (PR #13954); a standalone reproducer is attached to the issue. Closes #13967 Signed-off-by: Jeff Squyres --- ompi/request/req_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ompi/request/req_test.c b/ompi/request/req_test.c index 8eaa37e0d29..0da69b09142 100644 --- a/ompi/request/req_test.c +++ b/ompi/request/req_test.c @@ -14,6 +14,7 @@ * Copyright (c) 2010-2012 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2025 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -249,7 +250,7 @@ int ompi_request_default_test_all( ompi_grequest_invoke_query(request, &request->req_status); } OMPI_COPY_STATUS(&statuses[i], request->req_status, true); - if (MPI_SUCCESS == request->req_status.MPI_ERROR) { + if (MPI_SUCCESS != request->req_status.MPI_ERROR) { rc = MPI_ERR_IN_STATUS; #if OPAL_ENABLE_FT_MPI if (MPI_ERR_PROC_FAILED == request->req_status.MPI_ERROR From 3fe74515102134dc18a78f3ebccdce66a9e6d9e6 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 17:41:45 -0400 Subject: [PATCH 097/230] Remove the Open MPI Java MPI bindings The Java MPI bindings were always experimental, were never part of the MPI standard, and are no longer maintained. Remove them in their entirety. Deleted: - the ompi/mpi/java tree (Java sources and the JNI C glue) - the mpijavac wrapper compiler (mpijavac.pl.in) - the Java example programs (Hello/Ring/Connectivity.java) - the LANL macosx-dynamic-java contrib platform files, whose sole purpose was building the Java bindings Removed the Java build machinery: the --enable-mpi-java configure option, the ompi_setup_java / ompi_setup_mpi_java m4 macros, the OMPI_WANT_JAVA_BINDINGS automake conditional and preprocessor define, the libmpi_java shared-library versioning, and the related Makefile.am hooks. Removed the now-dead Java op-callback infrastructure from ompi/op (the java_data union member, the OMPI_OP_FLAGS_JAVA_FUNC flag, the ompi_op_set_java_callback() setter, and the reduction dispatch branch). The "Java bindings" line in ompi_info is retained but hard-coded to "no" so anything parsing that field keeps working. Updated all documentation to drop references to the Java bindings, and added a v6.0.0 changelog entry recording the removal. Signed-off-by: Jeff Squyres --- .gitignore | 6 - AGENTS.md | 2 +- VERSION | 1 - config/ompi_config_files.m4 | 2 +- config/ompi_setup_java.m4 | 234 -- config/ompi_setup_mpi_java.m4 | 85 - config/opal_summary.m4 | 7 +- configure.ac | 10 +- contrib/platform/hadoop/cisco | 3 - contrib/platform/hadoop/linux | 1 - contrib/platform/hadoop/mac | 3 - contrib/platform/intel/bend/ext | 1 - contrib/platform/intel/bend/gadget | 1 - contrib/platform/intel/bend/gadget-optimized | 1 - contrib/platform/intel/bend/linux-optimized | 1 - contrib/platform/intel/bend/mac-optimized | 3 - contrib/platform/intel/bend/ubuntu | 1 - contrib/platform/lanl/macosx-dynamic-java | 21 - .../platform/lanl/macosx-dynamic-java.conf | 60 - docs/Makefile.am | 11 +- docs/developers/prerequisites.rst | 3 +- docs/developers/rst-for-markdown-expats.rst | 5 +- docs/developers/source-code.rst | 3 +- docs/features/index.rst | 1 - docs/features/java.rst | 350 -- docs/features/profiling.rst | 3 +- .../configure-cli-options/mpi.rst | 13 - docs/man-openmpi/man1/mpijavac.1 | 1 - .../man1/ompi-wrapper-compiler.1.rst | 7 +- docs/release-notes/changelog/v6.0.x.rst | 4 + docs/version-numbering.rst | 1 - examples/Connectivity.java | 78 - examples/Hello.java | 39 - examples/Makefile | 15 +- examples/Makefile.include | 3 +- examples/README.md | 2 - examples/Ring.java | 75 - ompi/Makefile.am | 8 +- ompi/mpi/java/Makefile.am | 14 - ompi/mpi/java/README.md | 55 - ompi/mpi/java/c/Makefile.am | 53 - ompi/mpi/java/c/mpiJava.h | 201 - ompi/mpi/java/c/mpi_CartComm.c | 194 - ompi/mpi/java/c/mpi_Comm.c | 2294 ----------- ompi/mpi/java/c/mpi_Constant.c | 180 - ompi/mpi/java/c/mpi_Count.c | 52 - ompi/mpi/java/c/mpi_Datatype.c | 367 -- ompi/mpi/java/c/mpi_Errhandler.c | 70 - ompi/mpi/java/c/mpi_File.c | 745 ---- ompi/mpi/java/c/mpi_GraphComm.c | 169 - ompi/mpi/java/c/mpi_Group.c | 239 -- ompi/mpi/java/c/mpi_Info.c | 147 - ompi/mpi/java/c/mpi_Intercomm.c | 124 - ompi/mpi/java/c/mpi_Intracomm.c | 584 --- ompi/mpi/java/c/mpi_MPI.c | 1352 ------- ompi/mpi/java/c/mpi_Message.c | 103 - ompi/mpi/java/c/mpi_Op.c | 173 - ompi/mpi/java/c/mpi_Prequest.c | 49 - ompi/mpi/java/c/mpi_Request.c | 425 -- ompi/mpi/java/c/mpi_Status.c | 206 - ompi/mpi/java/c/mpi_Win.c | 508 --- ompi/mpi/java/java/CartComm.java | 246 -- ompi/mpi/java/java/CartParms.java | 117 - ompi/mpi/java/java/Comm.java | 3469 ----------------- ompi/mpi/java/java/Constant.java | 122 - ompi/mpi/java/java/Count.java | 97 - ompi/mpi/java/java/Datatype.java | 581 --- ompi/mpi/java/java/DistGraphNeighbors.java | 110 - ompi/mpi/java/java/DoubleComplex.java | 150 - ompi/mpi/java/java/DoubleInt.java | 115 - ompi/mpi/java/java/Errhandler.java | 67 - ompi/mpi/java/java/File.java | 1389 ------- ompi/mpi/java/java/FileView.java | 83 - ompi/mpi/java/java/FloatComplex.java | 150 - ompi/mpi/java/java/FloatInt.java | 115 - ompi/mpi/java/java/Freeable.java | 60 - ompi/mpi/java/java/GraphComm.java | 198 - ompi/mpi/java/java/GraphParms.java | 118 - ompi/mpi/java/java/Group.java | 275 -- ompi/mpi/java/java/Info.java | 180 - ompi/mpi/java/java/Int2.java | 127 - ompi/mpi/java/java/Intercomm.java | 182 - ompi/mpi/java/java/Intracomm.java | 887 ----- ompi/mpi/java/java/LongInt.java | 134 - ompi/mpi/java/java/MPI.java | 1014 ----- ompi/mpi/java/java/MPIException.java | 107 - ompi/mpi/java/java/Makefile.am | 220 -- ompi/mpi/java/java/Message.java | 163 - ompi/mpi/java/java/Op.java | 135 - ompi/mpi/java/java/Prequest.java | 97 - ompi/mpi/java/java/Request.java | 522 --- ompi/mpi/java/java/ShiftParms.java | 83 - ompi/mpi/java/java/ShortInt.java | 137 - ompi/mpi/java/java/Status.java | 278 -- ompi/mpi/java/java/Struct.java | 802 ---- ompi/mpi/java/java/UserFunction.java | 212 - ompi/mpi/java/java/Version.java | 69 - ompi/mpi/java/java/Win.java | 921 ----- ompi/op/op.c | 20 +- ompi/op/op.h | 33 +- ompi/tools/ompi_info/param.c | 6 +- ompi/tools/wrappers/Makefile.am | 23 +- ompi/tools/wrappers/mpijavac.pl.in | 145 - 103 files changed, 29 insertions(+), 23299 deletions(-) delete mode 100644 config/ompi_setup_java.m4 delete mode 100644 config/ompi_setup_mpi_java.m4 delete mode 100644 contrib/platform/lanl/macosx-dynamic-java delete mode 100644 contrib/platform/lanl/macosx-dynamic-java.conf delete mode 100644 docs/features/java.rst delete mode 100644 docs/man-openmpi/man1/mpijavac.1 delete mode 100644 examples/Connectivity.java delete mode 100644 examples/Hello.java delete mode 100644 examples/Ring.java delete mode 100644 ompi/mpi/java/Makefile.am delete mode 100644 ompi/mpi/java/README.md delete mode 100644 ompi/mpi/java/c/Makefile.am delete mode 100644 ompi/mpi/java/c/mpiJava.h delete mode 100644 ompi/mpi/java/c/mpi_CartComm.c delete mode 100644 ompi/mpi/java/c/mpi_Comm.c delete mode 100644 ompi/mpi/java/c/mpi_Constant.c delete mode 100644 ompi/mpi/java/c/mpi_Count.c delete mode 100644 ompi/mpi/java/c/mpi_Datatype.c delete mode 100644 ompi/mpi/java/c/mpi_Errhandler.c delete mode 100644 ompi/mpi/java/c/mpi_File.c delete mode 100644 ompi/mpi/java/c/mpi_GraphComm.c delete mode 100644 ompi/mpi/java/c/mpi_Group.c delete mode 100644 ompi/mpi/java/c/mpi_Info.c delete mode 100644 ompi/mpi/java/c/mpi_Intercomm.c delete mode 100644 ompi/mpi/java/c/mpi_Intracomm.c delete mode 100644 ompi/mpi/java/c/mpi_MPI.c delete mode 100644 ompi/mpi/java/c/mpi_Message.c delete mode 100644 ompi/mpi/java/c/mpi_Op.c delete mode 100644 ompi/mpi/java/c/mpi_Prequest.c delete mode 100644 ompi/mpi/java/c/mpi_Request.c delete mode 100644 ompi/mpi/java/c/mpi_Status.c delete mode 100644 ompi/mpi/java/c/mpi_Win.c delete mode 100644 ompi/mpi/java/java/CartComm.java delete mode 100644 ompi/mpi/java/java/CartParms.java delete mode 100644 ompi/mpi/java/java/Comm.java delete mode 100644 ompi/mpi/java/java/Constant.java delete mode 100644 ompi/mpi/java/java/Count.java delete mode 100644 ompi/mpi/java/java/Datatype.java delete mode 100644 ompi/mpi/java/java/DistGraphNeighbors.java delete mode 100644 ompi/mpi/java/java/DoubleComplex.java delete mode 100644 ompi/mpi/java/java/DoubleInt.java delete mode 100644 ompi/mpi/java/java/Errhandler.java delete mode 100644 ompi/mpi/java/java/File.java delete mode 100644 ompi/mpi/java/java/FileView.java delete mode 100644 ompi/mpi/java/java/FloatComplex.java delete mode 100644 ompi/mpi/java/java/FloatInt.java delete mode 100644 ompi/mpi/java/java/Freeable.java delete mode 100644 ompi/mpi/java/java/GraphComm.java delete mode 100644 ompi/mpi/java/java/GraphParms.java delete mode 100644 ompi/mpi/java/java/Group.java delete mode 100644 ompi/mpi/java/java/Info.java delete mode 100644 ompi/mpi/java/java/Int2.java delete mode 100644 ompi/mpi/java/java/Intercomm.java delete mode 100644 ompi/mpi/java/java/Intracomm.java delete mode 100644 ompi/mpi/java/java/LongInt.java delete mode 100644 ompi/mpi/java/java/MPI.java delete mode 100644 ompi/mpi/java/java/MPIException.java delete mode 100644 ompi/mpi/java/java/Makefile.am delete mode 100644 ompi/mpi/java/java/Message.java delete mode 100644 ompi/mpi/java/java/Op.java delete mode 100644 ompi/mpi/java/java/Prequest.java delete mode 100644 ompi/mpi/java/java/Request.java delete mode 100644 ompi/mpi/java/java/ShiftParms.java delete mode 100644 ompi/mpi/java/java/ShortInt.java delete mode 100644 ompi/mpi/java/java/Status.java delete mode 100644 ompi/mpi/java/java/Struct.java delete mode 100644 ompi/mpi/java/java/UserFunction.java delete mode 100644 ompi/mpi/java/java/Version.java delete mode 100644 ompi/mpi/java/java/Win.java delete mode 100644 ompi/tools/wrappers/mpijavac.pl.in diff --git a/.gitignore b/.gitignore index 5e6d4a12728..244687824e6 100644 --- a/.gitignore +++ b/.gitignore @@ -228,11 +228,6 @@ ompi/mpi/fortran/use-mpi-tkr/mpi_kinds.ompi_module ompi/mpi/fortran/use-mpi-tkr/mpi-tkr-sizeof.f90 ompi/mpi/fortran/use-mpi-tkr/mpi-tkr-sizeof.h -ompi/mpi/java/java/mpi -ompi/mpi/java/java/*.jar -ompi/mpi/java/java/*.h -ompi/mpi/java/java/doc - ompi/mpi/tool/profile/*.c ompi/mpiext/affinity/c/example @@ -277,7 +272,6 @@ ompi/tools/wrappers/ompi.pc ompi/tools/wrappers/ompi-c.pc ompi/tools/wrappers/ompi-cxx.pc ompi/tools/wrappers/ompi-fort.pc -ompi/tools/wrappers/mpijavac.pl ompi/tools/wrappers/mpicxx-wrapper-data.txt ompi/tools/wrappers/mpif77-wrapper-data.txt ompi/tools/wrappers/mpif90-wrapper-data.txt diff --git a/AGENTS.md b/AGENTS.md index b0ec197c541..d02a3f7cc9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,7 +51,7 @@ OPAL (libopen-pal) portability layer (OS/arch abstractions) - **OPAL** — portability primitives. Symbols prefixed `opal_` / `OPAL_`. This is where most OS/arch `#if` blocks belong. - **OMPI** — everything the MPI standard mandates: the language bindings - (C, several Fortran flavors, non-standard Java) on top, MCA frameworks + (C and several Fortran flavors) on top, MCA frameworks underneath. Symbols prefixed `ompi_` / `OMPI_`; only *official* MPI symbols get `MPI_` / `mpi_`. - **OSHMEM** — the OpenSHMEM API layer; sibling to OMPI, changes slowly. diff --git a/VERSION b/VERSION index 20ae1c819c6..c82de41b70f 100644 --- a/VERSION +++ b/VERSION @@ -101,7 +101,6 @@ libmpi_usempi_tkr_so_version=0:0:0 libmpi_usempi_ignore_tkr_so_version=0:0:0 libmpi_usempif08_so_version=0:0:0 libopen_pal_so_version=0:0:0 -libmpi_java_so_version=0:0:0 liboshmem_so_version=0:0:0 libompitrace_so_version=0:0:0 diff --git a/config/ompi_config_files.m4 b/config/ompi_config_files.m4 index 21d1e3eb791..7e574165fd8 100644 --- a/config/ompi_config_files.m4 +++ b/config/ompi_config_files.m4 @@ -8,6 +8,7 @@ # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights # reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -54,7 +55,6 @@ AC_DEFUN([OMPI_CONFIG_FILES],[ ompi/tools/wrappers/ompi-c.pc ompi/tools/wrappers/ompi-cxx.pc ompi/tools/wrappers/ompi-fort.pc - ompi/tools/wrappers/mpijavac.pl ompi/tools/mpisync/Makefile ompi/tools/mpirun/Makefile ]) diff --git a/config/ompi_setup_java.m4 b/config/ompi_setup_java.m4 deleted file mode 100644 index 596df8be9b7..00000000000 --- a/config/ompi_setup_java.m4 +++ /dev/null @@ -1,234 +0,0 @@ -dnl -*- shell-script -*- -dnl -dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -dnl University Research and Technology -dnl Corporation. All rights reserved. -dnl Copyright (c) 2004-2006 The University of Tennessee and The University -dnl of Tennessee Research Foundation. All rights -dnl reserved. -dnl Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, -dnl University of Stuttgart. All rights reserved. -dnl Copyright (c) 2004-2006 The Regents of the University of California. -dnl All rights reserved. -dnl Copyright (c) 2006-2012 Los Alamos National Security, LLC. All rights -dnl reserved. -dnl Copyright (c) 2007-2012 Oracle and/or its affiliates. All rights reserved. -dnl Copyright (c) 2008-2018 Cisco Systems, Inc. All rights reserved -dnl Copyright (c) 2013 Intel, Inc. All rights reserved. -dnl Copyright (c) 2015-2018 Research Organization for Information Science -dnl and Technology (RIST). All rights reserved. -dnl Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. -dnl Copyright (c) 2025 Nanook Consulting All rights reserved. -dnl $COPYRIGHT$ -dnl -dnl Additional copyrights may follow -dnl -dnl $HEADER$ -dnl - -dnl _OMPI_SETUP_JAVA() -dnl ---------------- -dnl Invoked by OMPI_SETUP_JAVA only if --enable-mpi-java was specified. -AC_DEFUN([_OMPI_SETUP_JAVA],[ - OPAL_VAR_SCOPE_PUSH([ompi_java_bad ompi_java_found ompi_java_dir ompi_java_jnih ompi_java_PATH_save ompi_java_CPPFLAGS_save]) - - # Check for bozo case: ensure a directory was specified - AS_IF([test "$with_jdk_dir" = "yes" || test "$with_jdk_dir" = "no"], - [AC_MSG_WARN([Must specify a directory name for --with-jdk-dir]) - AC_MSG_ERROR([Cannot continue])]) - AS_IF([test "$with_jdk_bindir" = "yes" || test "$with_jdk_bindir" = "no"], - [AC_MSG_WARN([Must specify a directory name for --with-jdk-bindir]) - AC_MSG_ERROR([Cannot continue])]) - AS_IF([test "$with_jdk_headers" = "yes" || test "$with_jdk_headers" = "no"], - [AC_MSG_WARN([Must specify a directory name for --with-jdk-headers]) - AC_MSG_ERROR([Cannot continue])]) - - # Check for bozo case: either specify --with-jdk-dir or - # (--with-jdk-bindir, --with-jdk-headers) -- not both. - ompi_java_bad=0 - AS_IF([test -n "$with_jdk_dir" && \ - (test -n "$with_jdk_bindir" || test -n "$with_jdk_headers")], - [ompi_java_bad=1]) - AS_IF([(test -z "$with_jdk_bindir" && test -n "$with_jdk_headers") || \ - (test -n "$with_jdk_bindir" && test -z "$with_jdk_headers")], - [ompi_java_bad=1]) - AS_IF([test $ompi_java_bad -eq 1], - [AC_MSG_WARN([Either specify --with-jdk-dir or both of (--with-jdk_bindir, --with-jdk-headers) -- not both.]) - AC_MSG_ERROR([Cannot continue])]) - - AS_IF([test -n "$with_jdk_dir"], - [with_jdk_bindir=$with_jdk_dir/bin - with_jdk_headers=$with_jdk_dir/include]) - - ################################################################## - # with_jdk_dir can now be ignored; with_jdk_bindir and - # with_jdk_headers will be either empty or have valid values. - ################################################################## - - # Some java installations are in obscure places. So let's - # hard-code a few of the common ones so that users don't have to - # specify --with-java-=LONG_ANNOYING_DIRECTORY. - AS_IF([test -z "$with_jdk_bindir"], - [ # OS X/macOS - ompi_java_found=0 - # The following logic was deliberately decided upon in - # https://github.com/open-mpi/ompi/pull/5015 specifically - # to prevent this script and the rest of Open MPI's build - # system from getting confused by the somewhat unorthodox - # Java toolchain layout present on OS X/macOS systems, - # described in depth by - # https://github.com/open-mpi/ompi/pull/5015#issuecomment-379324639, - # and mishandling OS X/macOS Java toolchain path detection - # as a result. - AS_IF([test -x /usr/libexec/java_home], - [ompi_java_dir=`/usr/libexec/java_home`], - [ompi_java_dir=/System/Library/Frameworks/JavaVM.framework/Versions/Current]) - AC_MSG_CHECKING([for Java in OS X/macOS locations]) - AS_IF([test -d "$ompi_java_dir"], - [AC_MSG_RESULT([found ($ompi_java_dir)]) - ompi_java_found=1 - if test -d "$ompi_java_dir/Headers" && test -d "$ompi_java_dir/Commands"; then - with_jdk_headers=$ompi_java_dir/Headers - with_jdk_bindir=$ompi_java_dir/Commands - elif test -d "$ompi_java_dir/include" && test -d "$ompi_java_dir/bin"; then - with_jdk_headers=$ompi_java_dir/include - with_jdk_bindir=$ompi_java_dir/bin - else - AC_MSG_WARN([No recognized OS X/macOS JDK directory structure found under $ompi_java_dir]) - ompi_java_found=0 - fi], - [AC_MSG_RESULT([not found])]) - - if test "$ompi_java_found" = "0"; then - # Various Linux - if test -z "$JAVA_HOME"; then - ompi_java_dir='/usr/lib/jvm/java-*-openjdk*/include/' - else - ompi_java_dir=$JAVA_HOME/include - fi - ompi_java_jnih=`ls $ompi_java_dir/jni.h 2>/dev/null | head -n 1` - AC_MSG_CHECKING([for Java in Linux locations]) - AS_IF([test -r "$ompi_java_jnih"], - [with_jdk_headers=`dirname $ompi_java_jnih` - OPAL_WHICH([javac], [with_jdk_bindir]) - AS_IF([test -n "$with_jdk_bindir"], - [AC_MSG_RESULT([found ($with_jdk_headers)]) - ompi_java_found=1 - with_jdk_bindir=`dirname $with_jdk_bindir`], - [with_jdk_headers=])], - [ompi_java_dir='/usr/lib/jvm/default-java/include/' - ompi_java_jnih=`ls $ompi_java_dir/jni.h 2>/dev/null | head -n 1` - AS_IF([test -r "$ompi_java_jnih"], - [with_jdk_headers=`dirname $ompi_java_jnih` - OPAL_WHICH([javac], [with_jdk_bindir]) - AS_IF([test -n "$with_jdk_bindir"], - [AC_MSG_RESULT([found ($with_jdk_headers)]) - ompi_java_found=1 - with_jdk_bindir=`dirname $with_jdk_bindir`], - [with_jdk_headers=])], - [AC_MSG_RESULT([not found])])]) - fi - - ], - [ompi_java_found=1]) - - if test "$ompi_java_found" = "1"; then - OPAL_CHECK_WITHDIR([jdk-bindir], [$with_jdk_bindir], [javac]) - OPAL_CHECK_WITHDIR([jdk-headers], [$with_jdk_headers], [jni.h]) - - # Look for various Java-related programs - ompi_java_happy=no - ompi_java_PATH_save=$PATH - AS_IF([test -n "$with_jdk_bindir" && test "$with_jdk_bindir" != "yes" && test "$with_jdk_bindir" != "no"], - [PATH="$with_jdk_bindir:$PATH"]) - AC_PATH_PROG(JAVAC, javac) - AC_PATH_PROG(JAR, jar) - AC_PATH_PROG(JAVADOC, javadoc) - AC_PATH_PROG(JAVAH, javah) - PATH=$ompi_java_PATH_save - - # Check to see if we have all 3 programs. - AS_IF([test -z "$JAVAC" || test -z "$JAR" || test -z "$JAVADOC"], - [ompi_java_happy=no], - [ompi_java_happy=yes]) - - # Look for jni.h - AS_IF([test "$ompi_java_happy" = "yes"], - [ompi_java_CPPFLAGS_save=$CPPFLAGS - # silence a stupid Mac warning - CPPFLAGS="$CPPFLAGS -DTARGET_RT_MAC_CFM=0" - AC_MSG_CHECKING([javac -h]) - cat > Conftest.java << EOF -public final class Conftest { - public native void conftest(); -} -EOF - AS_IF([$JAVAC -d . -h . Conftest.java > /dev/null 2>&1], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AS_IF([test -n "$JAVAH"], - [ompi_javah_happy=yes], - [ompi_java_happy=no])]) - rm -f Conftest.java Conftest.class Conftest.h - - AS_IF([test -n "$with_jdk_headers" && test "$with_jdk_headers" != "yes" && test "$with_jdk_headers" != "no"], - [OMPI_JDK_CPPFLAGS="-I$with_jdk_headers" - # Some flavors of JDK also require -I/linux. - # See if that's there, and if so, add a -I for that, - # too. Ugh. - AS_IF([test -d "$with_jdk_headers/linux"], - [OMPI_JDK_CPPFLAGS="$OMPI_JDK_CPPFLAGS -I$with_jdk_headers/linux"]) - # Darwin JDK also require -I/darwin. - # See if that's there, and if so, add a -I for that, - # too. Ugh. - AS_IF([test -d "$with_jdk_headers/darwin"], - [OMPI_JDK_CPPFLAGS="$OMPI_JDK_CPPFLAGS -I$with_jdk_headers/darwin"]) - - CPPFLAGS="$CPPFLAGS $OMPI_JDK_CPPFLAGS"]) - AC_CHECK_HEADER([jni.h], [], - [ompi_java_happy=no]) - CPPFLAGS=$ompi_java_CPPFLAGS_save - ]) - else - ompi_java_happy=no - fi - AC_SUBST(OMPI_JDK_CPPFLAGS) - - # Are we happy? - AC_MSG_CHECKING([if Java support available]) - AS_IF([test "$ompi_java_happy" = "yes"], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_MSG_WARN([Java support requested but not found.]) - AC_MSG_ERROR([Cannot continue])]) - - OPAL_VAR_SCOPE_POP -]) - -dnl OMPI_SETUP_JAVA() -dnl ---------------- -dnl Do everything required to setup the Java compiler. -AC_DEFUN([OMPI_SETUP_JAVA],[ - OPAL_VAR_SCOPE_PUSH([ompi_java_happy ompi_javah_happy]) - - ompi_java_happy=no - ompi_javah_happy=no - - AC_ARG_WITH([jdk-dir], - [AS_HELP_STRING([--with-jdk-dir(=DIR)], - [Location of the JDK header directory. If you use this option, do not specify --with-jdk-bindir or --with-jdk-headers.])]) - AC_ARG_WITH([jdk-bindir], - [AS_HELP_STRING([--with-jdk-bindir(=DIR)], - [Location of the JDK bin directory. If you use this option, you must also use --with-jdk-headers (and you must NOT use --with-jdk-dir)])]) - AC_ARG_WITH([jdk-headers], - [AS_HELP_STRING([--with-jdk-headers(=DIR)], - [Location of the JDK header directory. If you use this option, you must also use --with-jdk-bindir (and you must NOT use --with-jdk-dir)])]) - - # Only setup the compiler if we were requested to - AS_IF([test "$1" = "yes"], - [_OMPI_SETUP_JAVA]) - - AM_CONDITIONAL(OMPI_HAVE_JAVAH_SUPPORT, test "$ompi_javah_happy" = "yes") - - OPAL_VAR_SCOPE_POP -]) diff --git a/config/ompi_setup_mpi_java.m4 b/config/ompi_setup_mpi_java.m4 deleted file mode 100644 index 3f8f76c580f..00000000000 --- a/config/ompi_setup_mpi_java.m4 +++ /dev/null @@ -1,85 +0,0 @@ -dnl -*- shell-script -*- -dnl -dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -dnl University Research and Technology -dnl Corporation. All rights reserved. -dnl Copyright (c) 2004-2006 The University of Tennessee and The University -dnl of Tennessee Research Foundation. All rights -dnl reserved. -dnl Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, -dnl University of Stuttgart. All rights reserved. -dnl Copyright (c) 2004-2006 The Regents of the University of California. -dnl All rights reserved. -dnl Copyright (c) 2006-2012 Los Alamos National Security, LLC. All rights -dnl reserved. -dnl Copyright (c) 2007-2012 Oracle and/or its affiliates. All rights reserved. -dnl Copyright (c) 2008-2018 Cisco Systems, Inc. All rights reserved -dnl Copyright (c) 2015 Research Organization for Information Science -dnl and Technology (RIST). All rights reserved. -dnl $COPYRIGHT$ -dnl -dnl Additional copyrights may follow -dnl -dnl $HEADER$ -dnl - -dnl OMPI_SETUP_JAVA_BINDINGS() -dnl ---------------- -dnl Do everything required to setup the Java MPI bindings. -AC_DEFUN([OMPI_SETUP_JAVA_BINDINGS],[ - opal_show_subtitle "Java MPI bindings" - - AC_ARG_ENABLE([mpi-java], - [AS_HELP_STRING([--enable-mpi-java], - [enable Java MPI bindings (default: disabled)])]) - - # Find the Java compiler and whatnot. - # It knows to do very little if $enable_mpi_java!="yes". - OMPI_SETUP_JAVA([$enable_mpi_java]) - - # Only build the Java bindings if requested - AC_MSG_CHECKING([if want Java bindings]) - if test "$enable_mpi_java" = "yes"; then - AC_MSG_RESULT([yes]) - WANT_MPI_JAVA_BINDINGS=1 - AC_MSG_CHECKING([if shared libraries are enabled]) - AS_IF([test "$enable_shared" != "yes"], - [AC_MSG_RESULT([no]) - AC_MSG_WARN([Java bindings cannot be built without shared libraries]) - AC_MSG_WARN([Please reconfigure with --enable-shared]) - AC_MSG_ERROR([Cannot continue])], - [AC_MSG_RESULT([yes])]) - - # Mac Java requires this file (i.e., some other Java-related - # header file needs this file, so we need to check for - # it/include it in our sources when compiling on Mac). - AC_CHECK_HEADERS([TargetConditionals.h]) - - # dladdr and Dl_info are required to build the full path to - # libmpi on OS X 10.11 (a.k.a. El Capitan) - AC_CHECK_TYPES([Dl_info], [], [], [[#include ]]) - else - AC_MSG_RESULT([no]) - WANT_MPI_JAVA_BINDINGS=0 - fi - AC_DEFINE_UNQUOTED([OMPI_WANT_JAVA_BINDINGS], [$WANT_MPI_JAVA_BINDINGS], - [do we want java mpi bindings]) - AM_CONDITIONAL(OMPI_WANT_JAVA_BINDINGS, test "$WANT_MPI_JAVA_BINDINGS" = "1") - - # Are we happy? - AS_IF([test $WANT_MPI_JAVA_BINDINGS -eq 1], - [AC_MSG_WARN([******************************************************]) - AC_MSG_WARN([*** Java MPI bindings are provided on a provisional]) - AC_MSG_WARN([*** basis. They are NOT part of the current or]) - AC_MSG_WARN([*** proposed MPI standard. Continued inclusion of]) - AC_MSG_WARN([*** the Java MPI bindings in Open MPI is contingent]) - AC_MSG_WARN([*** upon user interest and developer support.]) - AC_MSG_WARN([******************************************************]) - ]) - - AC_CONFIG_FILES([ - ompi/mpi/java/Makefile - ompi/mpi/java/java/Makefile - ompi/mpi/java/c/Makefile - ]) -]) diff --git a/config/opal_summary.m4 b/config/opal_summary.m4 index a922a836a17..67e6e959d5c 100644 --- a/config/opal_summary.m4 +++ b/config/opal_summary.m4 @@ -7,6 +7,7 @@ dnl Copyright (c) 2016 Research Organization for Information Science dnl and Technology (RIST). All rights reserved. dnl Copyright (c) 2022 Amazon.com, Inc. or its affiliates. All Rights reserved. dnl Copyright (c) 2022 IBM Corporation. All rights reserved. +dnl Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. dnl $COPYRIGHT$ dnl dnl Additional copyrights may follow @@ -57,12 +58,6 @@ EOF else echo "Build MPI Fortran bindings: no" >&AS_MESSAGE_FD fi - - if test $WANT_MPI_JAVA_BINDINGS -eq 1 ; then - echo "Build MPI Java bindings (experimental): yes" >&AS_MESSAGE_FD - else - echo "Build MPI Java bindings (experimental): no" >&AS_MESSAGE_FD - fi fi if test "$project_oshmem_amc" = "true" ; then diff --git a/configure.ac b/configure.ac index d4276b23284..34246b170d5 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2019 Triad National Security, LLC. All rights # reserved. -# Copyright (c) 2023 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2023-2026 Jeffrey M. Squyres. All rights reserved. # Copyright (c) 2025 Nanook Consulting All rights reserved. # $COPYRIGHT$ # @@ -151,7 +151,6 @@ m4_ifdef([project_ompi], AC_SUBST(libmpi_usempi_tkr_so_version) AC_SUBST(libmpi_usempi_ignore_tkr_so_version) AC_SUBST(libmpi_usempif08_so_version) - AC_SUBST(libmpi_java_so_version) AC_SUBST(libompitrace_so_version)]) m4_ifdef([project_oshmem], [AC_SUBST(liboshmem_so_version)]) @@ -641,13 +640,6 @@ AS_IF([test "$opal_cv_compiler_FAMILYNAME" = "GNU" && \ AC_MSG_ERROR([Cannot continue]) ]) -################################## -# Java MPI Binding request -################################## -# Only needed for OMPI -m4_ifdef([project_ompi], [OMPI_SETUP_JAVA_BINDINGS]) - - ################################## # MPI / OpenSHMEM API profiling layer ################################## diff --git a/contrib/platform/hadoop/cisco b/contrib/platform/hadoop/cisco index ac506c30365..25a5e4f64e9 100644 --- a/contrib/platform/hadoop/cisco +++ b/contrib/platform/hadoop/cisco @@ -14,7 +14,6 @@ enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no -enable_mpi_java=yes enable_per_user_config_files=no enable_script_wrapper_compilers=no enable_orterun_prefix_by_default=yes @@ -27,5 +26,3 @@ with_portals=no with_valgrind=no with_slurm=/opt/slurm/2.1.0 with_openib=no -with_jdk_bindir=/usr/lib/jvm/java-1.6.0/bin -with_jdk_headers=/usr/lib/jvm/java-1.6.0/include diff --git a/contrib/platform/hadoop/linux b/contrib/platform/hadoop/linux index 4cd76ed4db0..fd5be6316ec 100644 --- a/contrib/platform/hadoop/linux +++ b/contrib/platform/hadoop/linux @@ -15,7 +15,6 @@ enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no -enable_mpi_java=yes enable_io_romio=no enable_mca_no_build=memchecker with_memory_manager=no diff --git a/contrib/platform/hadoop/mac b/contrib/platform/hadoop/mac index 844e1d4ec6c..31238c40483 100644 --- a/contrib/platform/hadoop/mac +++ b/contrib/platform/hadoop/mac @@ -13,12 +13,9 @@ enable_ipv6=no enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no -enable_mpi_java=yes enable_memchecker=no enable_mca_no_build=memchecker with_memory_manager=no with_devel_headers=yes with_xgrid=no with_slurm=no -with_jdk_bindir=/usr/bin -with_jdk_headers=/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers diff --git a/contrib/platform/intel/bend/ext b/contrib/platform/intel/bend/ext index 127e61f9e80..46467051dc6 100644 --- a/contrib/platform/intel/bend/ext +++ b/contrib/platform/intel/bend/ext @@ -15,7 +15,6 @@ enable_mpi_fortran=yes enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no -enable_mpi_java=no enable_io_romio=no enable_contrib_no_build=libnbc with_memory_manager=no diff --git a/contrib/platform/intel/bend/gadget b/contrib/platform/intel/bend/gadget index 152f17f8191..87dc62ff358 100644 --- a/contrib/platform/intel/bend/gadget +++ b/contrib/platform/intel/bend/gadget @@ -16,7 +16,6 @@ enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no enable_oshmem=no -enable_mpi_java=no enable_io_romio=no enable_builtin_atomics=no enable_contrib_no_build=libnbc diff --git a/contrib/platform/intel/bend/gadget-optimized b/contrib/platform/intel/bend/gadget-optimized index 99f459f31eb..365623c9f68 100644 --- a/contrib/platform/intel/bend/gadget-optimized +++ b/contrib/platform/intel/bend/gadget-optimized @@ -16,7 +16,6 @@ enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no enable_oshmem=no -enable_mpi_java=no enable_io_romio=no enable_contrib_no_build=libnbc with_memory_manager=no diff --git a/contrib/platform/intel/bend/linux-optimized b/contrib/platform/intel/bend/linux-optimized index fa9350f4703..efffa66c26b 100644 --- a/contrib/platform/intel/bend/linux-optimized +++ b/contrib/platform/intel/bend/linux-optimized @@ -15,7 +15,6 @@ enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no -enable_mpi_java=yes enable_io_romio=no enable_mca_no_build=memchecker enable_contrib_no_build=libnbc diff --git a/contrib/platform/intel/bend/mac-optimized b/contrib/platform/intel/bend/mac-optimized index d5e239ad73a..c1747db2cdf 100644 --- a/contrib/platform/intel/bend/mac-optimized +++ b/contrib/platform/intel/bend/mac-optimized @@ -14,7 +14,6 @@ enable_ipv6=no enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no -enable_mpi_java=yes enable_memchecker=no enable_mca_no_build=memchecker enable_contrib_no_build=libnbc @@ -22,6 +21,4 @@ with_memory_manager=no with_devel_headers=yes with_xgrid=no with_slurm=no -with_jdk_bindir=/usr/bin -with_jdk_headers=/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers with_mpi_param_check=no diff --git a/contrib/platform/intel/bend/ubuntu b/contrib/platform/intel/bend/ubuntu index 98df8b25777..49d3da0d813 100644 --- a/contrib/platform/intel/bend/ubuntu +++ b/contrib/platform/intel/bend/ubuntu @@ -15,7 +15,6 @@ enable_mpi_fortran=no enable_mpi_cxx=no enable_mpi_cxx_seek=no enable_cxx_exceptions=no -enable_mpi_java=no enable_io_romio=no enable_contrib_no_build=libnbc enable_install_libpmix=yes diff --git a/contrib/platform/lanl/macosx-dynamic-java b/contrib/platform/lanl/macosx-dynamic-java deleted file mode 100644 index 2cb0976cde5..00000000000 --- a/contrib/platform/lanl/macosx-dynamic-java +++ /dev/null @@ -1,21 +0,0 @@ -with_memory_manager=no -enable_mem_debug=yes -enable_mem_profile=no -enable_debug_symbols=yes -enable_binaries=yes -with_devel_headers=yes -enable_heterogeneous=no -enable_picky=yes -enable_debug=yes -enable_shared=yes -enable_static=no -enable_contrib_no_build=libnbc -with_xgrid=no -enable_io_romio=no -enable_ipv6=no -enable_mpi_fortran=no -enable_mpi_cxx=no -enable_mpi_cxx_seek=no -enable_mpi_java=yes -enable_memchecker=no -enable_mca_no_build=pml-cm,filem,pml-v diff --git a/contrib/platform/lanl/macosx-dynamic-java.conf b/contrib/platform/lanl/macosx-dynamic-java.conf deleted file mode 100644 index c888e678047..00000000000 --- a/contrib/platform/lanl/macosx-dynamic-java.conf +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# This is the default system-wide MCA parameters defaults file. -# Specifically, the MCA parameter "mca_param_files" defaults to a -# value of -# "$HOME/.openmpi/mca-params.conf:$sysconf/openmpi-mca-params.conf" -# (this file is the latter of the two). So if the default value of -# mca_param_files is not changed, this file is used to set system-wide -# MCA parameters. This file can therefore be used to set system-wide -# default MCA parameters for all users. Of course, users can override -# these values if they want, but this file is an excellent location -# for setting system-specific MCA parameters for those users who don't -# know / care enough to investigate the proper values for them. - -# Note that this file is only applicable where it is visible (in a -# filesystem sense). Specifically, MPI processes each read this file -# during their startup to determine what default values for MCA -# parameters should be used. mpirun does not bundle up the values in -# this file from the node where it was run and send them to all nodes; -# the default value decisions are effectively distributed. Hence, -# these values are only applicable on nodes that "see" this file. If -# $sysconf is a directory on a local disk, it is likely that changes -# to this file will need to be propagated to other nodes. If $sysconf -# is a directory that is shared via a networked filesystem, changes to -# this file will be visible to all nodes that share this $sysconf. - -# The format is straightforward: one per line, mca_param_name = -# rvalue. Quoting is ignored (so if you use quotes or escape -# characters, they'll be included as part of the value). For example: - -# Disable run-time MPI parameter checking -# mpi_param_check = 0 - -# Note that the value "~/" will be expanded to the current user's home -# directory. For example: - -# Change component loading path -# component_path = /usr/local/lib/openmpi:~/my_openmpi_components - -# See "ompi_info --param all all" for a full listing of Open MPI MCA -# parameters available and their default values. -# - diff --git a/docs/Makefile.am b/docs/Makefile.am index 24a6d17740d..69248573202 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (c) 2022 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2023-2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2023-2026 Jeffrey M. Squyres. All rights reserved. # Copyright (c) 2025 Triad National Security, LLC. All rights reserved. # # $COPYRIGHT$ @@ -898,8 +898,8 @@ OSHMEM_MAN3_INSTALL_FROM = $(OSHMEM_MAN3:%.3=$(MAN_INSTALL_FROM)/%.3) # Sphinx-generated man pages) -- they exist directly in Git. We # *always* want these files to be in EXTRA_DIST (so that they're in # distribution tarballs). We'll decide later whether we install each -# of these (e.g., if configure disabled the Java bindings, we won't -# install mpijavac.1). +# of these (e.g., if configure did not find a C++ compiler, we won't +# install mpic++.1). OMPI_MAN1_C_REDIRECTS = man-openmpi/man1/mpicc.1 OMPI_MAN1_CXX_REDIRECTS = \ man-openmpi/man1/mpicxx.1 \ @@ -908,7 +908,6 @@ OMPI_MAN1_FORTRAN_REDIRECTS = \ man-openmpi/man1/mpifort.1 \ man-openmpi/man1/mpif77.1 \ man-openmpi/man1/mpif90.1 -OMPI_MAN1_JAVA_REDIRECTS = man-openmpi/man1/mpijavac.1 OSHMEM_MAN1_C_REDIRECTS = \ man-openshmem/man1/oshcc.1 \ @@ -926,7 +925,6 @@ EXTRA_DIST += \ $(OMPI_MAN1_C_REDIRECTS) \ $(OMPI_MAN1_CXX_REDIRECTS) \ $(OMPI_MAN1_FORTRAN_REDIRECTS) \ - $(OMPI_MAN1_JAVA_REDIRECTS) \ $(OSHMEM_MAN1_C_REDIRECTS) \ $(OSHMEM_MAN1_CXX_REDIRECTS) \ $(OSHMEM_MAN1_FORTRAN_REDIRECTS) @@ -1181,9 +1179,6 @@ endif if OMPI_BUILD_ANY_FORTRAN_BINDINGS man1_MANS += $(OMPI_MAN1_FORTRAN_REDIRECTS) endif -if OMPI_WANT_JAVA_BINDINGS -man1_MANS += $(OMPI_MAN1_JAVA_REDIRECTS) -endif man3_MANS = $(OMPI_MAN3_INSTALL_FROM) man7_MANS = $(OMPI_MAN7_INSTALL_FROM) diff --git a/docs/developers/prerequisites.rst b/docs/developers/prerequisites.rst index b4971635b52..18d4ab531a4 100644 --- a/docs/developers/prerequisites.rst +++ b/docs/developers/prerequisites.rst @@ -8,8 +8,7 @@ Although it should probably be assumed, you'll need a C compiler that supports C11. You'll also need a Fortran compiler if you want to build the Fortran -MPI bindings (the more recent the Fortran compiler, the better), and a -Java compiler if you want to build the (unofficial) Java MPI bindings. +MPI bindings (the more recent the Fortran compiler, the better). GNU Autotools ------------- diff --git a/docs/developers/rst-for-markdown-expats.rst b/docs/developers/rst-for-markdown-expats.rst index 839ca59fe98..e4531f62822 100644 --- a/docs/developers/rst-for-markdown-expats.rst +++ b/docs/developers/rst-for-markdown-expats.rst @@ -243,12 +243,11 @@ Including files .. code-block:: rst .. include:: features-extensions.rst - .. include:: features-java.rst - Those directives include those 2 files right here in this RST file. + That directive includes that file right here in this RST file. .. important:: Chapter/section/subsection delimiters will be - continued in those files as part of rendering this + continued in that file as part of rendering this file. Hyperlinks to URLs diff --git a/docs/developers/source-code.rst b/docs/developers/source-code.rst index a2108e62446..484cd88a183 100644 --- a/docs/developers/source-code.rst +++ b/docs/developers/source-code.rst @@ -226,8 +226,7 @@ identical) directory structures under them: There are other top-level directories in each of the sub-projects, each having to do with specific logic and code for that project. For example, the MPI API implementations can be found under -``ompi/mpi/LANGUAGE``, where ``LANGUAGE`` is ``c``, ``fortran``, or -``java``. +``ompi/mpi/LANGUAGE``, where ``LANGUAGE`` is ``c`` or ``fortran``. The layout of the ``mca`` trees are strictly defined. They are of the form: diff --git a/docs/features/index.rst b/docs/features/index.rst index 3afb117dabb..0662a60cf20 100644 --- a/docs/features/index.rst +++ b/docs/features/index.rst @@ -14,4 +14,3 @@ categories of Open MPI-specific features. profiling extensions ulfm - java diff --git a/docs/features/java.rst b/docs/features/java.rst deleted file mode 100644 index 81fedd72bb7..00000000000 --- a/docs/features/java.rst +++ /dev/null @@ -1,350 +0,0 @@ -.. _open-mpi-java-label: - -Open MPI Java bindings -====================== - -Open MPI |ompi_ver| provides support for Java-based MPI applications. - -.. warning:: The Open MPI Java bindings are provided on a - "provisional" basis |mdash| i.e., they are not part of the current or - proposed MPI standards. Thus, inclusion of Java support is not - required by the standard. Continued inclusion of the Java bindings - is contingent upon active user interest and continued developer - support. - -The rest of this document provides step-by-step instructions on -building OMPI with Java bindings, and compiling and running Java-based -MPI applications. Also, part of the functionality is explained with -examples. Further details about the design, implementation and usage -of Java bindings in Open MPI can be found in its canonical reference -paper [#ompijava]_. The bindings follow a JNI approach, that is, we do -not provide a pure Java implementation of MPI primitives, but a thin -layer on top of the C implementation. This is the same approach as in -mpiJava [#mpijava]_; in fact, mpiJava was taken as a starting point -for Open MPI Java bindings, but they were later totally rewritten. - -Building the Java bindings --------------------------- - -Java support requires that Open MPI be built at least with shared -libraries (i.e., ``--enable-shared``). Note that this is the default -for Open MPI, so you don't have to explicitly add the option. The Java -bindings will build only if ``--enable-mpi-java`` is specified, and a -JDK is found in a typical system default location. - -If the JDK is not in a place where we automatically find it, you can -specify the location. For example, this is required on the Mac -platform as the JDK headers are located in a non-typical location. Two -options are available for this purpose: - -#. ``--with-jdk-bindir=``: the location of ``javac`` and ``javah`` -#. ``--with-jdk-headers=``: the directory containing ``jni.h`` - -Some example configurations are provided in Open MPI configuration -platform files under ``contrib/platform/hadoop``. These examples can -provide a starting point for your own custom configuration. - -In summary, therefore, you can configure the system using the -following Java-related options:: - - $ ./configure --with-platform=contrib/platform/hadoop/ ... - -or:: - - $ ./configure --enable-mpi-java --with-jdk-bindir= --with-jdk-headers= ... - -or simply:: - - $ ./configure --enable-mpi-java ... - -if JDK is in a "standard" place that ``configure`` can automatically -find. - -Building Java MPI applications ------------------------------- - -The ``mpijavac`` wrapper compiler is available for compiling -Java-based MPI applications. It ensures that all required Open MPI -libraries and classpaths are defined. For example: - -.. code-block:: - - $ mpijavac Hello.java - -You can use the ``--showme`` option to see the full command line of -the Java compiler that is invoked: - -.. code-block:: - - $ mpijavac Hello.java --showme - /usr/bin/javac -cp /opt/openmpi/lib/mpi.jar Hello.java - -Note that if you are specifying a ``-cp`` argument on the command line -to pass your application-specific classpaths, Open MPI will *extend* -that argument to include the ``mpi.jar``: - -.. code-block:: - - $ mpijavac -cp /path/to/my/app.jar Hello.java --showme - /usr/bin/javac -cp /path/to/my/app.jar:/opt/openmpi/lib/mpi.jar Hello.java - -Similarly, if you have a ``CLASSPATH`` environment variable defined, -``mpijavac`` will convert that into a ``-cp`` argument and extend it -to include the ``mpi.jar``: - -.. code-block:: - - $ export CLASSPATH=/path/to/my/app.jar - $ mpijavac Hello.java --showme - /usr/bin/javac -cp /path/to/my/app.jar:/opt/openmpi/lib/mpi.jar Hello.java - - -Running Java MPI applications ------------------------------ - -Once your application has been compiled, you can run it with the -standard ``mpirun`` command line:: - - $ mpirun java - -``mpirun`` will detect the ``java`` token and ensure that the required -MPI libraries and class paths are defined to support execution. You -therefore do **not** need to specify the Java library path to the MPI -installation, nor the MPI classpath. Any classpath definitions -required for your application should be specified either on the -command line or via the ``CLASSPATH`` environment variable. Note that -the local directory will be added to the classpath if nothing is -specified. - -.. note:: The ``java`` executable, all required libraries, and your - application classes must be available on all nodes. - -Basic usage of the Java bindings --------------------------------- - -There is an MPI package that contains all classes of the MPI Java -bindings: ``Comm``, ``Datatype``, ``Request``, etc. These classes have a -direct correspondence with handle types defined by the MPI standard. MPI -primitives are just methods included in these classes. The convention -used for naming Java methods and classes is the usual camel-case -convention, e.g., the equivalent of ``MPI_File_set_info(fh,info)`` is -``fh.setInfo(info)``, where ``fh`` is an object of the class ``File``. - -Apart from classes, the MPI package contains predefined public -attributes under a convenience class ``MPI``. Examples are the -predefined communicator ``MPI.COMM_WORLD`` and predefined datatypes such -as ``MPI.DOUBLE``. Also, MPI initialization and finalization are methods -of the ``MPI`` class and must be invoked by all MPI Java -applications. The following example illustrates these concepts: - -.. code-block:: java - - import mpi.*; - - class ComputePi { - - public static void main(String args[]) throws MPIException { - - MPI.Init(args); - - int rank = MPI.COMM_WORLD.getRank(), - size = MPI.COMM_WORLD.getSize(), - nint = 100; // Intervals. - double h = 1.0/(double)nint, sum = 0.0; - - for (int i=rank+1; i<=nint; i+=size) { - double x = h * ((double)i - 0.5); - sum += (4.0 / (1.0 + x * x)); - } - - double sBuf[] = { h * sum }, - rBuf[] = new double[1]; - - MPI.COMM_WORLD.reduce(sBuf, rBuf, 1, MPI.DOUBLE, MPI.SUM, 0); - - if (rank == 0) { - System.out.println("PI: " + rBuf[0]); - } - MPI.Finalize(); - } - } - -Exception handling ------------------- - -The Java bindings in Open MPI support exception handling. By default, -errors are fatal, but this behavior can be changed. The Java API will -throw exceptions if the ``MPI.ERRORS_RETURN`` error handler is set: - -.. code-block:: java - - MPI.COMM_WORLD.setErrhandler(MPI.ERRORS_RETURN); - -If you add this statement to your program, it will show the line -where it breaks, instead of just crashing in case of an error. -Error-handling code can be separated from main application code by -means of try-catch blocks, for instance: - -.. code-block:: java - - try - { - File file = new File(MPI.COMM_SELF, "filename", MPI.MODE_RDONLY); - } - catch(MPIException ex) - { - System.err.println("Error Message: "+ ex.getMessage()); - System.err.println(" Error Class: "+ ex.getErrorClass()); - ex.printStackTrace(); - System.exit(-1); - } - -How to specify buffers ----------------------- - -In MPI primitives that require a buffer (either send or receive), the -Java API admits a Java array. Since Java arrays can be relocated by -the Java runtime environment, the MPI Java bindings need to make a -copy of the contents of the array to a temporary buffer, then pass the -pointer to this buffer to the underlying C implementation. From the -practical point of view, this implies an overhead associated to all -buffers that are represented by Java arrays. The overhead is small for -small buffers but increases for large arrays. - -There is a pool of temporary buffers with a default capacity of 64K. -If a temporary buffer of 64K or less is needed, then the buffer will -be obtained from the pool. But if the buffer is larger, then it will -be necessary to allocate the buffer and free it later. - -The default capacity of pool buffers can be modified with an Open MPI -MCA parameter:: - - $ mpirun --mca ompi_mpi_java_eager SIZE ... - -The value of ``SIZE`` can be: - -* ``N``: An integer number of bytes -* ``Nk``: An integer number (suffixed with ``k``) of kilobytes -* ``Nm``: An integer number (suffixed with ``m``) of megabytes - -An alternative is to use "direct buffers" provided by standard classes -available in the Java SDK such as ``ByteBuffer``. For convenience, -Open MPI provides a few static methods ``new[Type]Buffer`` in the -``MPI`` class to create direct buffers for a number of basic -datatypes. Elements of the direct buffer can be accessed with methods -``put()`` and ``get()``, and the number of elements in the buffer can -be obtained with the method ``capacity()``. This example illustrates -its use: - -.. code-block:: java - - int myself = MPI.COMM_WORLD.getRank(); - int tasks = MPI.COMM_WORLD.getSize(); - - IntBuffer in = MPI.newIntBuffer(MAXLEN * tasks), - out = MPI.newIntBuffer(MAXLEN); - - for (int i = 0; i < MAXLEN; i++) - out.put(i, myself); // fill the buffer with the rank - - Request request = MPI.COMM_WORLD.iAllGather( - out, MAXLEN, MPI.INT, in, MAXLEN, MPI.INT); - request.waitFor(); - request.free(); - - for (int i = 0; i < tasks; i++) { - for (int k = 0; k < MAXLEN; k++) { - if (in.get(k + i * MAXLEN) != i) - throw new AssertionError("Unexpected value"); - } - } - -Direct buffers are available for: ``BYTE``, ``CHAR``, ``SHORT``, -``INT``, ``LONG``, ``FLOAT``, and ``DOUBLE``. - -.. note:: There is no direct buffer for booleans. - -Direct buffers are not a replacement for arrays, because they have -higher allocation and deallocation costs than arrays. In some cases -arrays will be a better choice. You can easily convert a buffer into -an array and vice versa. - -.. important:: All non-blocking methods *must* use direct buffers. - Only blocking methods can choose between arrays and - direct buffers. - -The above example also illustrates that it is necessary to call the -``free()`` method on objects whose class implements the ``Freeable`` -interface. Otherwise, a memory leak will occur. - -Specifying offsets in buffers ------------------------------ - -In a C program, it is common to specify an offset in a array with -``&array[i]`` or ``array+i`` to send data starting from a given -position in the array. The equivalent form in the Java bindings is to -``slice()`` the buffer to start at an offset. Making a ``slice()`` on -a buffer is only necessary, when the offset is not zero. Slices work -for both arrays and direct buffers. - -.. code-block:: java - - import static mpi.MPI.slice; - // ... - int numbers[] = new int[SIZE]; - // ... - MPI.COMM_WORLD.send(slice(numbers, offset), count, MPI.INT, 1, 0); - - -Supported APIs --------------- - -Complete MPI-3.1 coverage is provided in the Open MPI Java bindings, -with a few exceptions: - -* The bindings for the ``MPI_Neighbor_alltoallw`` and - ``MPI_Ineighbor_alltoallw`` functions are not implemented. - -* Also excluded are functions that incorporate the concepts of - explicit virtual memory addressing, such as - ``MPI_Win_shared_query``. - - -Known issues ------------- - -There exist issues with the Omnipath (PSM2) interconnect involving -Java. The problems definitely exist in PSM2 v10.2; we have not tested -previous versions. - -As of November 2016, there is not yet a PSM2 release that completely -fixes the issue. - -The following ``mpirun`` command options will disable PSM2:: - - shell$ mpirun ... --mca mtl ^psm2 java ...your-java-options... your-app-class - - -Questions? Problems? ---------------------- - -The Java API documentation is generated at build time in -``$prefix/share/doc/openmpi/javadoc``. - -Additionally, `this Cisco blog post -`_ has -quite a bit of information about the Open MPI Java bindings. - -If you have any problems, or find any bugs, please feel free to report -them to `Open MPI user's mailing list -`_. - -.. rubric:: Footnotes - -.. [#ompijava] O. Vega-Gisbert, J. E. Roman, and J. M. Squyres. "Design - and implementation of Java bindings in Open MPI". Parallel Comput. - 59: 1-20 (2016). - -.. [#mpijava] M. Baker et al. "mpiJava: An object-oriented Java - interface to MPI". In Parallel and Distributed Processing, LNCS - vol. 1586, pp. 748-762, Springer (1999). diff --git a/docs/features/profiling.rst b/docs/features/profiling.rst index 626007d2f9c..8b6001d11cf 100644 --- a/docs/features/profiling.rst +++ b/docs/features/profiling.rst @@ -4,8 +4,7 @@ Open MPI profiling interface ============================ Open MPI |ompi_ver| supports the "PMPI" profiling interface as -prescribed by the MPI standard for the C and Fortran bindings (*not* -the :ref:`Open MPI Java binding extensions `). +prescribed by the MPI standard for the C and Fortran bindings. Per MPI-4.0 section 15.2.1, MPI implementations must document which bindings layer on top of each other, so that profile developers know diff --git a/docs/installing-open-mpi/configure-cli-options/mpi.rst b/docs/installing-open-mpi/configure-cli-options/mpi.rst index 430f5c987ce..8db0baf593d 100644 --- a/docs/installing-open-mpi/configure-cli-options/mpi.rst +++ b/docs/installing-open-mpi/configure-cli-options/mpi.rst @@ -29,19 +29,6 @@ MPI API behaviors that can be used with ``configure``: :ref:`See the ULFM section ` for more information. -* ``--enable-mpi-java``: - Enable building of an **EXPERIMENTAL** Java MPI interface (disabled - by default). You may also need to specify ``--with-jdk-dir``, - ``--with-jdk-bindir``, and/or ``--with-jdk-headers``. - - .. warning:: Note that this Java interface is **INCOMPLETE** - (meaning: it does not support all MPI functionality) and **LIKELY - TO CHANGE**. The Open MPI developers would very much like to - hear your feedback about this interface. - - :ref:`See the Java section ` for many more - details. - * ``--enable-mpi-fortran[=VALUE]``: By default, Open MPI will attempt to build all 3 Fortran bindings: ``mpif.h``, the ``mpi`` module, and the ``mpi_f08`` module. The following diff --git a/docs/man-openmpi/man1/mpijavac.1 b/docs/man-openmpi/man1/mpijavac.1 deleted file mode 100644 index 7b464ffa102..00000000000 --- a/docs/man-openmpi/man1/mpijavac.1 +++ /dev/null @@ -1 +0,0 @@ -.so man1/ompi-wrapper-compiler.1 diff --git a/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst b/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst index 4f60cbfbd8b..ff27686f80d 100644 --- a/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst +++ b/docs/man-openmpi/man1/ompi-wrapper-compiler.1.rst @@ -2,14 +2,13 @@ .. _man1-mpic++: .. _man1-mpicxx: .. _man1-mpifort: -.. _man1-mpijavac: Open MPI Wrapper Compilers ========================== .. include_body -mpicc, mpic++, mpicxx, mpifort, mpijavac |mdash| Open MPI wrapper compilers +mpicc, mpic++, mpicxx, mpifort |mdash| Open MPI wrapper compilers SYNTAX ------ @@ -22,8 +21,6 @@ SYNTAX ``mpifort [--showme | --showme:compile | --showme:link] ...`` -``mpijavac [--showme | --showme:compile | --showme:link] ...`` - The following deprecated commands are also available |mdash| but ``mpifort`` should be used instead: @@ -120,8 +117,6 @@ Open MPI provides wrapper compilers for several languages: * ``mpifort`` (and its legacy/deprecated aliases ``mpif77`` and ``mpif90``): Fortran -* ``mpijavac``: Java - The wrapper compilers for each of the languages are identical; they can be use interchangeably. The different names are provided solely for backwards compatibility. diff --git a/docs/release-notes/changelog/v6.0.x.rst b/docs/release-notes/changelog/v6.0.x.rst index 6b3038ee6bc..70fd5e00802 100644 --- a/docs/release-notes/changelog/v6.0.x.rst +++ b/docs/release-notes/changelog/v6.0.x.rst @@ -29,6 +29,10 @@ Open MPI version v6.0.0 delivered through the Open MPI internal "OMPIO" implementation (which has been the default for quite a while, anyway). +- Removed the Java MPI bindings and the ``--enable-mpi-java`` + configure option. These bindings were experimental, were never part + of the MPI standard, and are no longer supported. + - Added support for MPI-4.1 functions to access and update ``MPI_Status`` fields. diff --git a/docs/version-numbering.rst b/docs/version-numbering.rst index 3788cdae40f..00fbdd426bc 100644 --- a/docs/version-numbering.rst +++ b/docs/version-numbering.rst @@ -163,7 +163,6 @@ Here's how we apply those rules specifically to Open MPI: * ``libmpi_usempi_ignore_tkr`` * ``libmpi_usempif08`` * ``libmpi_cxx`` - * ``libmpi_java`` * ``liboshmem`` API and ABI Compatibility diff --git a/examples/Connectivity.java b/examples/Connectivity.java deleted file mode 100644 index 551a56ad188..00000000000 --- a/examples/Connectivity.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Test the connectivity between all processes - */ - -import mpi.*; -import java.nio.IntBuffer; - -class Connectivity { - public static void main(String args[]) throws MPIException { - MPI.Init(args); - - /* - * MPI.COMM_WORLD is the communicator provided when MPI is - * initialized. It contains all the processes that are created - * upon program execution. - */ - int myRank = MPI.COMM_WORLD.getRank(); - int numProcesses = MPI.COMM_WORLD.getSize(); - boolean verbose = false; - String processorName = MPI.getProcessorName(); - - for (String arg : args) { - if (arg.equals("-v") || arg.equals("--verbose")) { - verbose = true; - break; - } - } - - for (int i = 0; i < numProcesses; i++) { - /* Find current process */ - if (myRank == i) { - /* send to and receive from all higher ranked processes */ - for (int j = i + 1; j < numProcesses; j++) { - if (verbose) - System.out.printf("Checking connection between rank %d on %s and rank %d\n", i, processorName, - j); - - /* - * rank is the Buffer passed into sendRecv to send to rank j. - * rank is populated with myRank, which is the data to send off - * peer is the Buffer received from rank j to current rank - */ - IntBuffer rank = MPI.newIntBuffer(1); - IntBuffer peer = MPI.newIntBuffer(1); - rank.put(0, myRank); - - /* - * To avoid deadlocks, use combined sendRecv operation. - * This performs a send and recv as a combined atomic operation - * and allow MPI to efficiently handle the requests internally. - */ - MPI.COMM_WORLD.sendRecv(rank, 1, MPI.INT, j, myRank, peer, 1, MPI.INT, j, j); - } - } else if (myRank > i) { - IntBuffer rank = MPI.newIntBuffer(1); - IntBuffer peer = MPI.newIntBuffer(1); - rank.put(0, myRank); - - /* receive from and reply to rank i */ - MPI.COMM_WORLD.sendRecv(rank, 1, MPI.INT, i, myRank, peer, 1, MPI.INT, i, i); - } - } - - /* Wait for all processes to reach barrier before proceeding */ - MPI.COMM_WORLD.barrier(); - - /* - * Once all ranks have reached the barrier, - * have only one process print out the confirmation message. - * In this case, we are having the "master" process print the message. - */ - if (myRank == 0) { - System.out.printf("Connectivity test on %d processes PASSED.\n", numProcesses); - } - - MPI.Finalize(); - } -} \ No newline at end of file diff --git a/examples/Hello.java b/examples/Hello.java deleted file mode 100644 index cd7c5268fa2..00000000000 --- a/examples/Hello.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * Author of revised version: Franklyn Pinedo - * - * Adapted from Source Code in C of Tutorial/User's Guide for MPI by - * Peter Pacheco. - */ -/* - * Copyright (c) 2011 Cisco Systems, Inc. All rights reserved. - * - */ - -import mpi.*; - -class Hello { - static public void main(String[] args) throws MPIException { - - - MPI.Init(args); - - int myrank = MPI.COMM_WORLD.getRank(); - int size = MPI.COMM_WORLD.getSize() ; - System.out.println("Hello world from rank " + myrank + " of " + size); - - MPI.Finalize(); - } -} diff --git a/examples/Makefile b/examples/Makefile index a92ff5400b7..3616a617400 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -15,6 +15,7 @@ # Copyright (c) 2013 Mellanox Technologies, Inc. All rights reserved. # Copyright (c) 2017-2018 Research Organization for Information Science # and Technology (RIST). All rights reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -26,7 +27,6 @@ MPICC = mpicc MPIFC = mpifort -MPIJAVAC = mpijavac SHMEMCC = shmemcc SHMEMCXX = shmemc++ SHMEMFC = shmemfort @@ -51,16 +51,13 @@ EXAMPLES = \ hello_oshmem \ hello_oshmemcxx \ hello_oshmemfh \ - Hello.class \ ring_c \ ring_mpifh \ ring_usempi \ ring_usempif08 \ ring_oshmem \ ring_oshmemfh \ - Ring.class \ connectivity_c \ - Connectivity.class \ oshmem_shmalloc \ oshmem_circular_shift \ oshmem_max_reduction \ @@ -94,9 +91,6 @@ mpi: @ if ompi_info --parsable | grep -q bindings:use_mpi_f08:yes >/dev/null; then \ $(MAKE) hello_usempif08 ring_usempif08; \ fi - @ if ompi_info --parsable | grep -q bindings:java:yes >/dev/null; then \ - $(MAKE) Hello.class Ring.class; \ - fi @ if ompi_info --parsable | grep -q enable-spc >/dev/null; then \ $(MAKE) spc_example; \ fi @@ -124,7 +118,7 @@ oshmem: clean: rm -f $(EXAMPLES) *~ *.o -# Don't rely on default rules for the Fortran and Java examples +# Don't rely on default rules for the Fortran examples hello_c: hello_c.c $(MPICC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ @@ -152,11 +146,6 @@ hello_usempif08: hello_usempif08.f90 ring_usempif08: ring_usempif08.f90 $(MPIFC) $(FCFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ -Hello.class: Hello.java - $(MPIJAVAC) Hello.java -Ring.class: Ring.java - $(MPIJAVAC) Ring.java - hello_oshmem: hello_oshmem_c.c $(SHMEMCC) $(CFLAGS) $(LDFLAGS) $? $(LDLIBS) -o $@ hello_oshmemcxx: hello_oshmem_cxx.cc diff --git a/examples/Makefile.include b/examples/Makefile.include index 8da106cb507..1fe536d669b 100644 --- a/examples/Makefile.include +++ b/examples/Makefile.include @@ -16,6 +16,7 @@ # Copyright (c) 2013 Mellanox Technologies, Inc. All rights reserved. # Copyright (c) 2017 Research Organization for Information Science # and Technology (RIST). All rights reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -54,7 +55,5 @@ EXTRA_DIST += \ examples/oshmem_max_reduction.c \ examples/oshmem_strided_puts.c \ examples/oshmem_symmetric_data.c \ - examples/Hello.java \ - examples/Ring.java \ examples/spc_example.c \ examples/hello_sessions_c.c diff --git a/examples/README.md b/examples/README.md index 6a1ab9528cb..ec6e2e23e2e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -21,7 +21,6 @@ The MPI version of the canonical "hello world" program: * Fortran mpif.h: `hello_mpifh.f` * Fortran use mpi: `hello_usempi.f90` * Fortran use mpi_f08: `hello_usempif08.f90` -* Java: `Hello.java` * C shmem.h: `hello_oshmem_c.c` * Fortran shmem.fh: `hello_oshmemfh.f90` @@ -34,7 +33,6 @@ Send a trivial message around in a ring: * Fortran mpif.h: `ring_mpifh.f` * Fortran use mpi: `ring_usempi.f90` * Fortran use mpi_f08: `ring_usempif08.f90` -* Java: `Ring.java` * C shmem.h: `ring_oshmem_c.c` * Fortran shmem.fh: `ring_oshmemfh.f90` diff --git a/examples/Ring.java b/examples/Ring.java deleted file mode 100644 index 6aa3770e21b..00000000000 --- a/examples/Ring.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Cisco Systems, Inc. All rights reserved. - * - * Simple ring test program - */ - -import mpi.* ; - -class Ring { - static public void main(String[] args) throws MPIException { - - - MPI.Init(args) ; - - int source; // Rank of sender - int dest; // Rank of receiver - int tag=50; // Tag for messages - int next; - int prev; - int message[] = new int [1]; - - int myrank = MPI.COMM_WORLD.getRank() ; - int size = MPI.COMM_WORLD.getSize() ; - - /* Calculate the rank of the next process in the ring. Use the - modulus operator so that the last process "wraps around" to - rank zero. */ - - next = (myrank + 1) % size; - prev = (myrank + size - 1) % size; - - /* If we are the "manager" process (i.e., MPI_COMM_WORLD rank 0), - put the number of times to go around the ring in the - message. */ - - if (0 == myrank) { - message[0] = 10; - - System.out.println("Process 0 sending " + message[0] + " to rank " + next + " (" + size + " processes in ring)"); - MPI.COMM_WORLD.send(message, 1, MPI.INT, next, tag); - } - - /* Pass the message around the ring. The exit mechanism works as - follows: the message (a positive integer) is passed around the - ring. Each time it passes rank 0, it is decremented. When - each processes receives a message containing a 0 value, it - passes the message on to the next process and then quits. By - passing the 0 message first, every process gets the 0 message - and can quit normally. */ - - while (true) { - MPI.COMM_WORLD.recv(message, 1, MPI.INT, prev, tag); - - if (0 == myrank) { - --message[0]; - System.out.println("Process 0 decremented value: " + message[0]); - } - - MPI.COMM_WORLD.send(message, 1, MPI.INT, next, tag); - if (0 == message[0]) { - System.out.println("Process " + myrank + " exiting"); - break; - } - } - - /* The last process does one extra send to process 0, which needs - to be received before the program can exit */ - - if (0 == myrank) { - MPI.COMM_WORLD.recv(message, 1, MPI.INT, prev, tag); - } - - MPI.Finalize(); - } -} diff --git a/ompi/Makefile.am b/ompi/Makefile.am index f855492ef15..47b8b8aaffc 100644 --- a/ompi/Makefile.am +++ b/ompi/Makefile.am @@ -21,7 +21,7 @@ # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2021 Amazon.com, Inc. or its affiliates. All Rights # reserved. -# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2025-2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -94,11 +94,6 @@ SUBDIRS = \ mpi/fortran/mpiext-use-mpi-f08 \ $(MCA_ompi_FRAMEWORK_COMPONENT_DSO_SUBDIRS) -if OMPI_WANT_JAVA_BINDINGS -SUBDIRS += \ - mpi/java -endif - # The ordering of the DIST_SUBDIRS isn't as important, but note that # its contents *are* different than SUBDIRS. In particular, the # MPIEXT subdirs has a different value that is *not* equivalent to the @@ -121,7 +116,6 @@ DIST_SUBDIRS = \ mpi/fortran/use-mpi-f08/mod \ mpi/fortran/use-mpi-f08/bindings \ mpi/fortran/mpiext-use-mpi-f08 \ - mpi/java \ $(OMPI_MPIEXT_ALL_SUBDIRS) \ $(MCA_ompi_FRAMEWORKS_SUBDIRS) \ $(MCA_ompi_FRAMEWORK_COMPONENT_ALL_SUBDIRS) diff --git a/ompi/mpi/java/Makefile.am b/ompi/mpi/java/Makefile.am deleted file mode 100644 index 943f3ecc757..00000000000 --- a/ompi/mpi/java/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -# -*- makefile -*- -# -# Copyright (c) 2011 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2014 Intel, Inc. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -SUBDIRS = java c - -EXTRA_DIST = README.md diff --git a/ompi/mpi/java/README.md b/ompi/mpi/java/README.md deleted file mode 100644 index 93b43d3521a..00000000000 --- a/ompi/mpi/java/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Open MPI Java bindings - -Note about the Open MPI Java bindings - -The Java bindings in this directory are not part of the MPI -specification, as noted in the README.JAVA.md file in the root -directory. That file also contains some information regarding the -installation and use of the Java bindings. Further details can be -found in the paper [1]. - -We originally took the code from the mpiJava project [2] as starting point -for our developments, but we have pretty much rewritten 100% of it. The -original copyrights and license terms of mpiJava are listed below. - -1. O. Vega-Gisbert, J. E. Roman, and J. M. Squyres. "Design and - implementation of Java bindings in Open MPI". Parallel Comput. - 59: 1-20 (2016). -1. M. Baker et al. "mpiJava: An object-oriented Java interface to - MPI". In Parallel and Distributed Processing, LNCS vol. 1586, - pp. 748-762, Springer (1999). - -## Original citation - -``` - mpiJava - A Java Interface to MPI - --------------------------------- - Copyright 2003 - - Bryan Carpenter, Sung Hoon Ko, Sang Boem Lim - Pervasive Technology Labs, Indiana University - email {shko,slim,dbc}@grids.ucs.indiana.edu - - Xinying Li - Syracuse University - - Mark Baker - CSM, University of Portsmouth - email mark.baker@computer.org - - (Bugfixes/Additions, CMake based configure/build) - Blasius Czink - HLRS, University of Stuttgart -``` - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/ompi/mpi/java/c/Makefile.am b/ompi/mpi/java/c/Makefile.am deleted file mode 100644 index 96552eb93e0..00000000000 --- a/ompi/mpi/java/c/Makefile.am +++ /dev/null @@ -1,53 +0,0 @@ -# -*- makefile -*- -# -# Copyright (c) 2011-2018 Cisco Systems, Inc. All rights reserved -# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2015 Los Alamos National Security, LLC. All rights -# reserved. -# Copyright (c) 2015 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2016 IBM Corporation. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -if OMPI_WANT_JAVA_BINDINGS - -# Get the include files that were generated from the .java source files -AM_CPPFLAGS = -I$(top_builddir)/ompi/mpi/java/java $(OMPI_JDK_CPPFLAGS) -DOMPI_LIBMPI_NAME=\"$(OMPI_LIBMPI_NAME)\" -DOPAL_DYN_LIB_SUFFIX=\"$(OPAL_DYN_LIB_SUFFIX)\" - -headers = \ - mpiJava.h -ompidir = $(ompiincludedir)/ompi/mpi/java -ompi_HEADERS = \ - $(headers) - -lib_LTLIBRARIES = lib@OMPI_LIBMPI_NAME@_java.la -lib@OMPI_LIBMPI_NAME@_java_la_SOURCES = \ - mpi_CartComm.c \ - mpi_Comm.c \ - mpi_Constant.c \ - mpi_Count.c \ - mpi_Datatype.c \ - mpi_Errhandler.c \ - mpi_File.c \ - mpi_GraphComm.c \ - mpi_Group.c \ - mpi_Info.c \ - mpi_Intercomm.c \ - mpi_Intracomm.c \ - mpi_Message.c \ - mpi_MPI.c \ - mpi_Op.c \ - mpi_Request.c \ - mpi_Prequest.c \ - mpi_Status.c \ - mpi_Win.c - -lib@OMPI_LIBMPI_NAME@_java_la_LIBADD = -ldl $(top_builddir)/ompi/lib@OMPI_LIBMPI_NAME@.la -lib@OMPI_LIBMPI_NAME@_java_la_LDFLAGS = -version-info $(libmpi_java_so_version) - -endif diff --git a/ompi/mpi/java/c/mpiJava.h b/ompi/mpi/java/c/mpiJava.h deleted file mode 100644 index 319536e22d4..00000000000 --- a/ompi/mpi/java/c/mpiJava.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#ifndef _MPIJAVA_H_ -#define _MPIJAVA_H_ - -#include "mpi.h" -#include "opal/class/opal_free_list.h" - -typedef struct { - jfieldID CommHandle; - jfieldID GroupHandle; - jclass CartParmsClass; - jmethodID CartParmsInit; - jclass ShiftParmsClass; - jmethodID ShiftParmsInit; - jclass VersionClass; - jmethodID VersionInit; - jclass CountClass; - jmethodID CountInit; - jclass GraphParmsClass; - jmethodID GraphParmsInit; - jclass DistGraphNeighborsClass; - jmethodID DistGraphNeighborsInit; - jfieldID DatatypeHandle; - jfieldID DatatypeBaseType; - jfieldID DatatypeBaseSize; - jfieldID MessageHandle; - jfieldID OpHandle; - jfieldID OpCommute; - jmethodID OpCall; - jfieldID ReqHandle; - jclass StatusClass; - jfieldID StatusData; - jclass ExceptionClass; - jmethodID ExceptionInit; - jclass IntegerClass; - jmethodID IntegerValueOf; - jclass LongClass; - jmethodID LongValueOf; -} ompi_java_globals_t; - -extern ompi_java_globals_t ompi_java; - -typedef struct ompi_java_buffer_t -{ - opal_free_list_item_t super; - void *buffer; -} ompi_java_buffer_t; - -OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_java_buffer_t); - -void* ompi_java_getArrayCritical(void** bufBase, JNIEnv *env, - jobject buf, int offset); - -void* ompi_java_getDirectBufferAddress(JNIEnv *env, jobject buf); - -/* Gets a buffer pointer for reading (copy from Java). */ -void ompi_java_getReadPtr( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int offset, int count, MPI_Datatype type, int baseType); - -/* Gets a buffer pointer for reading. - * It only copies from java the rank data. - * 'size' is the number of processes. */ -void ompi_java_getReadPtrRank( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int offset, int count, int size, - int rank, MPI_Datatype type, int baseType); - -/* Gets a buffer pointer for reading, but it - * 'size' is the number of processes. - * if rank == -1 it copies all data from Java. - * if rank != -1 it only copies from Java the rank data. */ -void ompi_java_getReadPtrv( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int off, int *counts, int *displs, - int size, int rank, MPI_Datatype type, int baseType); - -/* Gets a buffer pointer for reading, but it - * 'size' is the number of processes. - * if rank == -1 it copies all data from Java. - * if rank != -1 it only copies from Java the rank data. */ -void ompi_java_getReadPtrw( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int *offs, int *counts, int *displs, - int size, int rank, MPI_Datatype *types, int *baseTypes); - -/* Releases a buffer used for reading. */ -void ompi_java_releaseReadPtr( - void *ptr, ompi_java_buffer_t *item, jobject buf, jboolean db); - -/* Gets a buffer pointer for writing. */ -void ompi_java_getWritePtr( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int count, MPI_Datatype type); - -/* Gets a buffer pointer for writing. - * 'size' is the number of processes. */ -void ompi_java_getWritePtrv( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int *counts, int *displs, int size, MPI_Datatype type); - -/* Gets a buffer pointer for writing. - * 'size' is the number of processes. */ -void ompi_java_getWritePtrw( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int *counts, int *displs, int size, MPI_Datatype *types); - -/* Releases a buffer used for writing. - * It copies data to Java. */ -void ompi_java_releaseWritePtr( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, jobject buf, - jboolean db, int offset, int count, MPI_Datatype type, int baseType); - -/* Releases a buffer used for writing. - * It copies data to Java. - * 'size' is the number of processes. */ -void ompi_java_releaseWritePtrv( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, - jobject buf, jboolean db, int off, int *counts, int *displs, - int size, MPI_Datatype type, int baseType); - -/* Releases a buffer used for writing. - * It copies data to Java. - * 'size' is the number of processes. */ -void ompi_java_releaseWritePtrw( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, - jobject buf, jboolean db, int *offs, int *counts, int *displs, - int size, MPI_Datatype *types, int *baseTypes); - -void ompi_java_setStaticLongField(JNIEnv *env, jclass c, - char *field, jlong value); - -void ompi_java_setIntField(JNIEnv *env, jclass c, jobject obj, - char *field, jint value); - -jobject ompi_java_Integer_valueOf(JNIEnv *env, jint i); -jobject ompi_java_Long_valueOf(JNIEnv *env, jlong i); - -void ompi_java_getIntArray( - JNIEnv *env, jintArray array, jint **jptr, int **cptr); -void ompi_java_releaseIntArray( - JNIEnv *env, jintArray array, jint *jptr, int *cptr); -void ompi_java_forgetIntArray( - JNIEnv *env, jintArray array, jint *jptr, int *cptr); - -void ompi_java_getDatatypeArray( - JNIEnv *env, jlongArray array, jlong **jptr, MPI_Datatype **cptr); -void ompi_java_forgetDatatypeArray( - JNIEnv *env, jlongArray array, jlong *jptr, MPI_Datatype *cptr); - -void ompi_java_getBooleanArray( - JNIEnv *env, jbooleanArray array, jboolean **jptr, int **cptr); -void ompi_java_releaseBooleanArray( - JNIEnv *env, jbooleanArray array, jboolean *jptr, int *cptr); -void ompi_java_forgetBooleanArray( - JNIEnv *env, jbooleanArray array, jboolean *jptr, int *cptr); - -void ompi_java_getPtrArray( - JNIEnv *env, jlongArray array, jlong **jptr, void ***cptr); -void ompi_java_releasePtrArray( - JNIEnv *env, jlongArray array, jlong *jptr, void **cptr); - -jboolean ompi_java_exceptionCheck(JNIEnv *env, int rc); - -void* ompi_java_attrSet(JNIEnv *env, jbyteArray jval); -jbyteArray ompi_java_attrGet(JNIEnv *env, void *cval); -int ompi_java_attrCopy(void *attrValIn, void *attrValOut, int *flag); -int ompi_java_attrDelete(void *attrVal); - -MPI_Op ompi_java_op_getHandle( - JNIEnv *env, jobject jOp, jlong hOp, int baseType); - -jobject ompi_java_status_new(JNIEnv *env, MPI_Status *status); -jobject ompi_java_status_newIndex(JNIEnv *env, MPI_Status *status, int index); - -void ompi_java_status_set( - JNIEnv *env, jlongArray jData, MPI_Status *status); -void ompi_java_status_setIndex( - JNIEnv *env, jlongArray jData, MPI_Status *status, int index); - -#endif /* _MPIJAVA_H_ */ diff --git a/ompi/mpi/java/c/mpi_CartComm.c b/ompi/mpi/java/c/mpi_CartComm.c deleted file mode 100644 index 9c6a8b3040f..00000000000 --- a/ompi/mpi/java/c/mpi_CartComm.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_CartComm.c - * Headerfile : mpi_CartComm.h - * Author : Sung-Hoon Ko, Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.6 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_CartComm.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_CartComm_init(JNIEnv *env, jclass clazz) -{ - ompi_java.CartParmsInit = (*env)->GetMethodID(env, - ompi_java.CartParmsClass, "", "([I[Z[I)V"); - - ompi_java.ShiftParmsInit = (*env)->GetMethodID(env, - ompi_java.ShiftParmsClass, "", "(II)V"); -} - -JNIEXPORT jobject JNICALL Java_mpi_CartComm_getTopo( - JNIEnv *env, jobject jthis, jlong comm) -{ - int maxdims; - int rc = MPI_Cartdim_get((MPI_Comm)comm, &maxdims); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jintArray dims = (*env)->NewIntArray(env, maxdims); - jbooleanArray periods = (*env)->NewBooleanArray(env, maxdims); - jintArray coords = (*env)->NewIntArray(env, maxdims); - - if(maxdims != 0) - { - jint *jDims, *jCoords; - jboolean *jPeriods; - int *cDims, *cCoords, *cPeriods; - - ompi_java_getIntArray(env, dims, &jDims, &cDims); - ompi_java_getIntArray(env, coords, &jCoords, &cCoords); - ompi_java_getBooleanArray(env, periods, &jPeriods, &cPeriods); - - rc = MPI_Cart_get((MPI_Comm)comm, maxdims, cDims, cPeriods, cCoords); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseIntArray(env, dims, jDims, cDims); - ompi_java_releaseIntArray(env, coords, jCoords, cCoords); - ompi_java_releaseBooleanArray(env, periods, jPeriods, cPeriods); - } - - return (*env)->NewObject(env, ompi_java.CartParmsClass, - ompi_java.CartParmsInit, dims, periods, coords); -} - -JNIEXPORT jobject JNICALL Java_mpi_CartComm_shift( - JNIEnv *env, jobject jthis, jlong comm, jint direction, jint disp) -{ - int sr, dr; - int rc = MPI_Cart_shift((MPI_Comm)comm, direction, disp, &sr, &dr); - ompi_java_exceptionCheck(env, rc); - - return (*env)->NewObject(env, ompi_java.ShiftParmsClass, - ompi_java.ShiftParmsInit, sr, dr); -} - -JNIEXPORT jintArray JNICALL Java_mpi_CartComm_getCoords( - JNIEnv *env, jobject jthis, jlong comm, jint rank) -{ - int maxdims; - int rc = MPI_Cartdim_get((MPI_Comm)comm, &maxdims); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jintArray coords = (*env)->NewIntArray(env, maxdims); - jint *jCoords; - int *cCoords; - ompi_java_getIntArray(env, coords, &jCoords, &cCoords); - - rc = MPI_Cart_coords((MPI_Comm)comm, rank, maxdims, cCoords); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseIntArray(env, coords, jCoords, cCoords); - return coords; -} - -JNIEXPORT jint JNICALL Java_mpi_CartComm_map( - JNIEnv *env, jobject jthis, jlong comm, - jintArray dims, jbooleanArray periods) -{ - int nDims = (*env)->GetArrayLength(env, dims); - jint *jDims; - jboolean *jPeriods; - int *cDims, *cPeriods; - ompi_java_getIntArray(env, dims, &jDims, &cDims); - ompi_java_getBooleanArray(env, periods, &jPeriods, &cPeriods); - - int newrank; - int rc = MPI_Cart_map((MPI_Comm)comm, nDims, cDims, cPeriods, &newrank); - ompi_java_exceptionCheck(env, rc); - - ompi_java_forgetIntArray(env, dims, jDims, cDims); - ompi_java_forgetBooleanArray(env, periods, jPeriods, cPeriods); - return newrank; -} - -JNIEXPORT jint JNICALL Java_mpi_CartComm_getRank( - JNIEnv *env, jobject jthis, jlong comm, jintArray coords) -{ - jint *jCoords; - int *cCoords; - ompi_java_getIntArray(env, coords, &jCoords, &cCoords); - - int rank; - int rc = MPI_Cart_rank((MPI_Comm)comm, cCoords, &rank); - ompi_java_exceptionCheck(env, rc); - - ompi_java_forgetIntArray(env, coords, jCoords, cCoords); - return rank; -} - -JNIEXPORT jlong JNICALL Java_mpi_CartComm_sub( - JNIEnv *env, jobject jthis, jlong comm, jbooleanArray remainDims) -{ - jboolean *jRemainDims; - int *cRemainDims; - ompi_java_getBooleanArray(env, remainDims, &jRemainDims, &cRemainDims); - - MPI_Comm newcomm; - int rc = MPI_Cart_sub((MPI_Comm)comm, cRemainDims, &newcomm); - ompi_java_exceptionCheck(env, rc); - - ompi_java_forgetBooleanArray(env, remainDims, jRemainDims, cRemainDims); - return (jlong)newcomm; -} - -JNIEXPORT void JNICALL Java_mpi_CartComm_createDims_1jni( - JNIEnv *env, jclass jthis, jint nNodes, jintArray dims) -{ - int nDims = (*env)->GetArrayLength(env, dims); - jint *jDims; - int *cDims; - ompi_java_getIntArray(env, dims, &jDims, &cDims); - - int rc = MPI_Dims_create(nNodes, nDims, cDims); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseIntArray(env, dims, jDims, cDims); -} diff --git a/ompi/mpi/java/c/mpi_Comm.c b/ompi/mpi/java/c/mpi_Comm.c deleted file mode 100644 index f31f210037a..00000000000 --- a/ompi/mpi/java/c/mpi_Comm.c +++ /dev/null @@ -1,2294 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015-2018 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017-2019 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Comm.c - * Headerfile : mpi_Comm.h - * Author : Sung-Hoon Ko, Xinying Li, Sang Lim, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.17 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Comm.h" -#include "mpiJava.h" /* must come AFTER the related .h so JNI is included */ - -static void* getBufCritical(void** bufBase, JNIEnv *env, - jobject buf, jboolean db, int offset) -{ - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *bufBase = NULL; - return NULL; - } - else if(db) - { - *bufBase = (*env)->GetDirectBufferAddress(env, buf); - assert(offset == 0); - return *bufBase; - } - else - { - return ompi_java_getArrayCritical(bufBase, env, buf, offset); - } -} - -static void releaseBufCritical( - JNIEnv *env, jobject buf, jboolean db, void* bufBase) -{ - if(!db && buf) - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, 0); -} - -static int isInter(JNIEnv *env, MPI_Comm comm) -{ - int rc, flag; - rc = MPI_Comm_test_inter(comm, &flag); - ompi_java_exceptionCheck(env, rc); - return flag; -} - -static int getSize(JNIEnv *env, MPI_Comm comm, int inter) -{ - int rc, size; - - if(inter) - rc = MPI_Comm_remote_size(comm, &size); - else - rc = MPI_Comm_size(comm, &size); - - ompi_java_exceptionCheck(env, rc); - return size; -} - -static int getGroupSize(JNIEnv *env, MPI_Comm comm) -{ - int rc, size; - rc = MPI_Comm_size(comm, &size); - ompi_java_exceptionCheck(env, rc); - return size; -} - -static int getRank(JNIEnv *env, MPI_Comm comm) -{ - int rc, rank; - rc = MPI_Comm_rank(comm, &rank); - ompi_java_exceptionCheck(env, rc); - return rank; -} - -static int getTopo(JNIEnv *env, MPI_Comm comm) -{ - int rc, status; - rc = MPI_Topo_test(comm, &status); - ompi_java_exceptionCheck(env, rc); - return status; -} - -static void getNeighbors(JNIEnv *env, MPI_Comm comm, int *out, int *in) -{ - int rc, weighted; - - switch(getTopo(env, comm)) - { - case MPI_CART: - rc = MPI_Cartdim_get(comm, in); - *in *= 2; - *out = *in; - break; - case MPI_GRAPH: - rc = MPI_Graph_neighbors_count(comm, getRank(env, comm), in); - *out = *in; - break; - case MPI_DIST_GRAPH: - rc = MPI_Dist_graph_neighbors_count(comm, in, out, &weighted); - break; - default: - rc = MPI_ERR_TOPOLOGY; - break; - } - - ompi_java_exceptionCheck(env, rc); -} - -static int getSum(int *counts, int size) -{ - int i, s = 0; - - for(i = 0; i < size; i++) - s += counts[i]; - - return s; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_init(JNIEnv *env, jclass clazz) -{ - jfieldID nullHandleID = (*env)->GetStaticFieldID( - env, clazz, "nullHandle", "J"); - - (*env)->SetStaticLongField(env, clazz, nullHandleID, (jlong)MPI_COMM_NULL); - ompi_java.CommHandle = (*env)->GetFieldID(env,clazz,"handle","J"); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_getComm(JNIEnv *env, jobject jthis, - jint type) -{ - switch (type) { - case 0: - (*env)->SetLongField(env,jthis, ompi_java.CommHandle,(jlong)MPI_COMM_NULL); - break; - case 1: - (*env)->SetLongField(env,jthis, ompi_java.CommHandle,(jlong)MPI_COMM_SELF); - break; - case 2: - (*env)->SetLongField(env,jthis, ompi_java.CommHandle,(jlong)MPI_COMM_WORLD); - break; - } -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_dup( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_dup((MPI_Comm)comm, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jlongArray JNICALL Java_mpi_Comm_iDup( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Comm newcomm; - MPI_Request request; - int rc = MPI_Comm_idup((MPI_Comm)comm, &newcomm, &request); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jlongArray jcr = (*env)->NewLongArray(env, 2); - jlong *cr = (jlong*)(*env)->GetPrimitiveArrayCritical(env, jcr, NULL); - cr[0] = (jlong)newcomm; - cr[1] = (jlong)request; - (*env)->ReleasePrimitiveArrayCritical(env, jcr, cr, 0); - return jcr; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_dupWithInfo( - JNIEnv *env, jobject jthis, jlong comm, jlong info) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_dup_with_info((MPI_Comm)comm, (MPI_Info)info, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_getSize( - JNIEnv *env, jobject jthis, jlong comm) -{ - int rc, size; - rc = MPI_Comm_size((MPI_Comm)comm, &size); - ompi_java_exceptionCheck(env, rc); - return size; -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_getRank( - JNIEnv *env, jobject jthis, jlong comm) -{ - return getRank(env, (MPI_Comm)comm); -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_compare( - JNIEnv *env, jclass jthis, jlong comm1, jlong comm2) -{ - int rc, result; - rc = MPI_Comm_compare((MPI_Comm)comm1, (MPI_Comm)comm2, &result); - ompi_java_exceptionCheck(env, rc); - return result; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Comm comm = (MPI_Comm)handle; - int rc = MPI_Comm_free(&comm); - ompi_java_exceptionCheck(env, rc); - return (jlong)comm; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_setInfo( - JNIEnv *env, jobject jthis, jlong comm, jlong info) -{ - int rc = MPI_Comm_set_info((MPI_Comm)comm, (MPI_Info)info); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_getInfo( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Info info; - int rc = MPI_Comm_get_info((MPI_Comm)comm, &info); - ompi_java_exceptionCheck(env, rc); - return (jlong)info; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_disconnect( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Comm comm = (MPI_Comm)handle; - int rc = MPI_Comm_disconnect(&comm); - ompi_java_exceptionCheck(env, rc); - return (jlong)comm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_getGroup( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Group group; - int rc = MPI_Comm_group((MPI_Comm)comm, &group); - ompi_java_exceptionCheck(env, rc); - return (jlong)group; -} - -JNIEXPORT jboolean JNICALL Java_mpi_Comm_isInter( - JNIEnv *env, jobject jthis, jlong comm) -{ - return isInter(env, (MPI_Comm)comm) ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_createIntercomm( - JNIEnv *env, jobject jthis, jlong comm, jlong localComm, - jint localLeader, jint remoteLeader, jint tag) -{ - MPI_Comm newintercomm; - - int rc = MPI_Intercomm_create( - (MPI_Comm)localComm, localLeader, - (MPI_Comm)comm, remoteLeader, tag, &newintercomm); - - ompi_java_exceptionCheck(env, rc); - return (jlong)newintercomm; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_send( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, jint count, - jlong jType, jint bType, jint dest, jint tag) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - - int rc = MPI_Send(ptr, count, type, dest, tag, comm); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_recv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, jint count, - jlong jType, jint bType, jint source, jint tag, jlongArray jStatus) -{ - jboolean exception; - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - - MPI_Status status; - int rc = MPI_Recv(ptr, count, type, source, tag, comm, &status); - exception = ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseWritePtr(ptr,item,env,buf,db,offset,count,type,bType); - - if(!exception) - ompi_java_status_set(env, jStatus, &status); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_sendRecv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, jint sCount, - jlong sjType, jint sBType, jint dest, jint sTag, - jobject rBuf, jboolean rdb, jint rOff, jint rCount, - jlong rjType, jint rBType, jint source, jint rTag, - jlongArray jStatus) -{ - jboolean exception; - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - MPI_Status status; - - ompi_java_getReadPtr(&sPtr,&sItem, env, sBuf,sdb,sOff,sCount,sType,sBType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rCount, rType); - - int rc = MPI_Sendrecv(sPtr, sCount, sType, dest, sTag, - rPtr, rCount, rType, source, rTag, comm, &status); - - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rCount,rType,rBType); - - if(!exception) - ompi_java_status_set(env, jStatus, &status); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_sendRecvReplace( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, - jint count, jlong jType, jint bType, - jint dest, jint sTag, jint source, jint rTag, jlongArray jStatus) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - MPI_Status status; - - int rc = MPI_Sendrecv_replace(ptr, count, type, dest, - sTag, source, rTag, comm, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, jStatus, &status); - - ompi_java_releaseWritePtr(ptr,item,env,buf,db,offset,count,type,bType); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_bSend( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, - jint count, jlong jType, jint bType, jint dest, jint tag) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - - int rc = MPI_Bsend(ptr, count, type, dest, tag, comm); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_sSend( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, - jint count, jlong jType, jint bType, jint dest, jint tag) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - - int rc = MPI_Ssend(ptr, count, type, dest, tag, comm); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_rSend( - JNIEnv *env, jobject jthis, jlong jComm, - jobject buf, jboolean db, jint offset, - jint count, jlong jType, jint bType, jint dest, jint tag) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - - int rc = MPI_Rsend(ptr, count, type, dest, tag, comm); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iSend( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Isend(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_ibSend( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Ibsend(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_isSend( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Issend(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_irSend( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Irsend(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iRecv( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint source, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Irecv(ptr, count, (MPI_Datatype)type, - source, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_sendInit( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Send_init(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_bSendInit( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Bsend_init(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_sSendInit( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Ssend_init(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_rSendInit( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint dest, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Rsend_init(ptr, count, (MPI_Datatype)type, - dest, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_recvInit( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint source, jint tag) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Recv_init(ptr, count, (MPI_Datatype)type, - source, tag, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_pack( - JNIEnv *env, jobject jthis, jlong jComm, - jobject inBuf, jboolean indb, jint offset, - jint inCount, jlong jType, jbyteArray outBuf, jint position) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - int outSize = (*env)->GetArrayLength(env, outBuf); - - void *oBufPtr, *iBufPtr, *iBufBase; - oBufPtr = (*env)->GetPrimitiveArrayCritical(env, outBuf, NULL); - iBufPtr = getBufCritical(&iBufBase, env, inBuf, indb, offset); - - if(inCount != 0 && outSize != position) - { - /* LAM doesn't like count = 0 */ - int rc = MPI_Pack(iBufPtr, inCount, type, - oBufPtr, outSize, &position, comm); - - ompi_java_exceptionCheck(env, rc); - } - - releaseBufCritical(env, inBuf, indb, iBufBase); - (*env)->ReleasePrimitiveArrayCritical(env, outBuf, oBufPtr, 0); - return position; -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_unpack( - JNIEnv *env, jobject jthis, jlong jComm, - jbyteArray inBuf, jint position, jobject outBuf, jboolean outdb, - jint offset, jint outCount, jlong jType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - int inSize = (*env)->GetArrayLength(env, inBuf); - - void *iBufPtr, *oBufPtr, *oBufBase; - iBufPtr = (*env)->GetPrimitiveArrayCritical(env, inBuf, NULL); - oBufPtr = getBufCritical(&oBufBase, env, outBuf, outdb, offset); - - int rc = MPI_Unpack(iBufPtr, inSize, &position, - oBufPtr, outCount, type, comm); - - ompi_java_exceptionCheck(env, rc); - (*env)->ReleasePrimitiveArrayCritical(env, inBuf, iBufPtr, 0); - releaseBufCritical(env, outBuf, outdb, oBufBase); - return position; -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_packSize( - JNIEnv *env, jobject jthis, jlong comm, jint incount, jlong type) -{ - int rc, size; - rc = MPI_Pack_size(incount, (MPI_Datatype)type, (MPI_Comm)comm, &size); - ompi_java_exceptionCheck(env, rc); - return size; -} - -JNIEXPORT jobject JNICALL Java_mpi_Comm_iProbe( - JNIEnv *env, jobject jthis, jlong comm, jint source, jint tag) -{ - int flag; - MPI_Status status; - int rc = MPI_Iprobe(source, tag, (MPI_Comm)comm, &flag, &status); - ompi_java_exceptionCheck(env, rc); - return flag ? ompi_java_status_new(env, &status) : NULL; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_probe( - JNIEnv *env, jobject jthis, jlong comm, - jint source, jint tag, jlongArray jStatus) -{ - MPI_Status status; - int rc = MPI_Probe(source, tag, (MPI_Comm)comm, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, jStatus, &status); -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_getTopology( - JNIEnv *env, jobject jthis, jlong comm) -{ - return getTopo(env, (MPI_Comm)comm); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_abort( - JNIEnv *env, jobject jthis, jlong comm, jint errorcode) -{ - int rc = MPI_Abort((MPI_Comm)comm, errorcode); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_setErrhandler( - JNIEnv *env, jobject jthis, jlong comm, jlong errhandler) -{ - int rc = MPI_Comm_set_errhandler((MPI_Comm)comm, (MPI_Errhandler)errhandler); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_getErrhandler( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Errhandler errhandler; - int rc = MPI_Comm_get_errhandler((MPI_Comm)comm, &errhandler); - ompi_java_exceptionCheck(env, rc); - return (jlong)errhandler; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_callErrhandler( - JNIEnv *env, jobject jthis, jlong comm, jint errorCode) -{ - int rc = MPI_Comm_call_errhandler((MPI_Comm)comm, errorCode); - ompi_java_exceptionCheck(env, rc); -} - -static int commCopyAttr(MPI_Comm oldcomm, int keyval, void *extraState, - void *attrValIn, void *attrValOut, int *flag) -{ - return ompi_java_attrCopy(attrValIn, attrValOut, flag); -} - -static int commDeleteAttr(MPI_Comm oldcomm, int keyval, - void *attrVal, void *extraState) -{ - return ompi_java_attrDelete(attrVal); -} - -JNIEXPORT jint JNICALL Java_mpi_Comm_createKeyval_1jni( - JNIEnv *env, jclass clazz) -{ - int rc, keyval; - rc = MPI_Comm_create_keyval(commCopyAttr, commDeleteAttr, &keyval, NULL); - ompi_java_exceptionCheck(env, rc); - return keyval; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_freeKeyval_1jni( - JNIEnv *env, jclass clazz, jint keyval) -{ - int rc = MPI_Comm_free_keyval((int*)(&keyval)); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_setAttr( - JNIEnv *env, jobject jthis, jlong comm, jint keyval, jbyteArray jval) -{ - void *cval = ompi_java_attrSet(env, jval); - int rc = MPI_Comm_set_attr((MPI_Comm)comm, keyval, cval); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jobject JNICALL Java_mpi_Comm_getAttr_1predefined( - JNIEnv *env, jobject jthis, jlong comm, jint keyval) -{ - int flag, *val; - int rc = MPI_Comm_get_attr((MPI_Comm)comm, keyval, &val, &flag); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - return NULL; - - return ompi_java_Integer_valueOf(env, (jint)(*val)); -} - -JNIEXPORT jbyteArray JNICALL Java_mpi_Comm_getAttr( - JNIEnv *env, jobject jthis, jlong comm, jint keyval) -{ - int flag; - void *cval; - int rc = MPI_Comm_get_attr((MPI_Comm)comm, keyval, &cval, &flag); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - return NULL; - - return ompi_java_attrGet(env, cval); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_deleteAttr( - JNIEnv *env, jobject jthis, jlong comm, jint keyval) -{ - int rc = MPI_Comm_delete_attr((MPI_Comm)comm, keyval); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_barrier( - JNIEnv *env, jobject jthis, jlong comm) -{ - int rc = MPI_Barrier((MPI_Comm)comm); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iBarrier( - JNIEnv *env, jobject jthis, jlong comm) -{ - MPI_Request request; - int rc = MPI_Ibarrier((MPI_Comm)comm, &request); - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_bcast( - JNIEnv *env, jobject jthis, jlong jComm, jobject buf, jboolean db, - jint offset, jint count, jlong jType, jint bType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, offset, count, type, bType); - - int rc = MPI_Bcast(ptr, count, type, root, comm); - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr,item,env,buf,db,offset,count,type,bType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iBcast( - JNIEnv *env, jobject jthis, jlong comm, - jobject buf, jint count, jlong type, jint root) -{ - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_Ibcast(ptr, count, (MPI_Datatype)type, - root, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_gather( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, jint sCount, - jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, jint rCount, - jlong rjType, jint rBType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int inter = isInter(env, comm); - int rootOrInter = rank == root || inter; - - void *sPtr, *rPtr = NULL; - ompi_java_buffer_t *sItem, *rItem; - MPI_Datatype sType; - - if(sjType == 0) - { - assert(sBuf == NULL); - sType = MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sType = (MPI_Datatype)sjType; - - ompi_java_getReadPtr(&sPtr, &sItem, env, sBuf, sdb, - sOff, sCount, sType, sBType); - } - - MPI_Datatype rType = (MPI_Datatype)rjType; - int rCountTotal = rootOrInter ? rCount * getSize(env, comm, inter) : rCount; - - if(rootOrInter || sPtr == MPI_IN_PLACE) - { - if(sPtr == MPI_IN_PLACE) - { - /* We use the receive buffer as the send buffer. */ - ompi_java_getReadPtr(&rPtr, &rItem, env, rBuf, rdb, - rOff, rCountTotal, rType, rBType); - } - else - { - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, - rCountTotal, rType); - } - - if(!rootOrInter) - { - /* The receive buffer is ignored for all non-root processes. - * As we are using MPI_IN_PLACE version, we use the receive - * buffer as the send buffer. - */ - assert(sBuf == NULL); - sPtr = rPtr; - sCount = rCount; - sType = rType; - } - } - - int rc = MPI_Gather(sPtr, sCount, sType, rPtr, rCount, rType, root, comm); - ompi_java_exceptionCheck(env, rc); - - if(rootOrInter) - { - ompi_java_releaseWritePtr(rPtr, rItem, env, rBuf, rdb, - rOff, rCountTotal, rType, rBType); - } - else if(sBuf == NULL) - { - ompi_java_releaseReadPtr(rPtr, rItem, rBuf, rdb); - } - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iGather( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jint rCount, jlong rType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - MPI_Request request; - void *sPtr, *rPtr = NULL; - - if(sType == 0) - { - assert(sendBuf == NULL); - sType = (jlong)MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - } - - if(rootOrInter || sPtr == MPI_IN_PLACE) - { - /* - * In principle need the "id == root" check here and elsewhere for - * correctness, in case arguments that are not supposed to be - * significant except on root are legitimately passed in as `null', - * say. Shouldn't produce null pointer exception. - * - * (However in this case MPICH complains if `mpi_rtype' is not defined - * in all processes, notwithstanding what the spec says.) - */ - - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - if(!rootOrInter) - { - /* The receive buffer is ignored for all non-root processes. - * As we are using MPI_IN_PLACE version, we use the receive - * buffer as the send buffer. - */ - assert(sendBuf == NULL); - sPtr = rPtr; - sCount = rCount; - sType = rType; - } - } - - int rc = MPI_Igather(sPtr, sCount, (MPI_Datatype)sType, - rPtr, rCount, (MPI_Datatype)rType, - root, comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_gatherv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, jintArray rCounts, - jintArray displs, jlong rjType, jint rBType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int inter = isInter(env, comm); - int rootOrInter = rank == root || inter; - int size = rootOrInter ? getSize(env, comm, inter) : 0; - - void *sPtr, *rPtr = NULL; - ompi_java_buffer_t *sItem, *rItem; - MPI_Datatype sType; - - if(sjType == 0) - { - assert(sBuf == NULL); - sType = MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sType = (MPI_Datatype)sjType; - - ompi_java_getReadPtr(&sPtr, &sItem, env, sBuf, sdb, - sOff, sCount, sType, sBType); - } - - jint *jRCounts = NULL, *jDispls = NULL; - int *cRCounts = NULL, *cDispls = NULL; - MPI_Datatype rType = sType; - - if(rootOrInter) - { - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - rType = (MPI_Datatype)rjType; - - if(sPtr == MPI_IN_PLACE) - { - /* We use the receive buffer as the send buffer. */ - ompi_java_getReadPtrv(&rPtr, &rItem, env, rBuf, rdb, rOff, - cRCounts, cDispls, size, root, rType, rBType); - } - else - { - ompi_java_getWritePtrv(&rPtr, &rItem, env, rBuf, rdb, - cRCounts, cDispls, size, rType); - } - } - - int rc = MPI_Gatherv(sPtr, sCount, sType, rPtr, cRCounts, - cDispls, rType, root, comm); - - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - if(rootOrInter) - { - ompi_java_releaseWritePtrv(rPtr, rItem, env, rBuf, rdb, rOff, - cRCounts, cDispls, size, rType, rBType); - - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - } -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iGatherv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jintArray rCounts, - jintArray displs, jlong rType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - MPI_Request request; - void *sPtr, *rPtr = NULL; - - if(sType == 0) - { - assert(sendBuf == NULL); - sType = (jlong)MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - } - - jint *jRCounts, *jDispls; - int *cRCounts, *cDispls; - - if(rootOrInter) - { - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - } - else - { - jRCounts = jDispls = NULL; - cRCounts = cDispls = NULL; - rType = sType; - } - - int rc = MPI_Igatherv(sPtr, sCount, (MPI_Datatype)sType, rPtr, - cRCounts, cDispls, (MPI_Datatype)rType, - root, comm, &request); - - ompi_java_exceptionCheck(env, rc); - - if(rootOrInter) - { - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - } - - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_scatter( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, jint sCount, - jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, jint rCount, - jlong rjType, jint rBType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int inter = isInter(env, comm); - int rootOrInter = rank == root || inter; - - void *sPtr = NULL, *rPtr; - ompi_java_buffer_t *sItem, *rItem = NULL; - MPI_Datatype rType; - - if(rjType == 0) - { - assert(rBuf == NULL); - rType = MPI_DATATYPE_NULL; - rPtr = MPI_IN_PLACE; - } - else - { - rType = (MPI_Datatype)rjType; - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rCount, rType); - } - - MPI_Datatype sType = (MPI_Datatype)sjType; - int sCountTotal = rootOrInter ? sCount * getSize(env, comm, inter) : sCount; - - if(rootOrInter || rPtr == MPI_IN_PLACE) - { - ompi_java_getReadPtr(&sPtr, &sItem, env, sBuf, sdb, sOff, - sCountTotal, sType, sBType); - if(!rootOrInter) - { - /* The send buffer is ignored for all non-root processes. - * As we are using MPI_IN_PLACE version, we use the send - * buffer as the receive buffer. - */ - assert(rBuf == NULL); - rPtr = sPtr; - rCount = sCount; - rType = sType; - } - } - - int rc = MPI_Scatter(sPtr, sCount, sType, rPtr, rCount, rType, root, comm); - ompi_java_exceptionCheck(env, rc); - - if(rootOrInter) - { - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - } - else if(rBuf == NULL) - { - ompi_java_releaseWritePtr(sPtr, sItem, env, sBuf, sdb, - sOff, sCount, sType, sBType); - } - - if(rItem != NULL && rBuf != NULL) - { - ompi_java_releaseWritePtr(rPtr, rItem, env, rBuf, rdb, - rOff, rCount, rType, rBType); - } -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iScatter( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jint rCount, jlong rType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - void *sPtr = NULL, *rPtr; - MPI_Request request; - - if(rType == 0) - { - assert(recvBuf == NULL); - rType = (jlong)MPI_DATATYPE_NULL; - rPtr = MPI_IN_PLACE; - } - else - { - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - } - - if(rootOrInter || rPtr == MPI_IN_PLACE) - { - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - - if(!rootOrInter) - { - /* The send buffer is ignored for all non-root processes. - * As we are using MPI_IN_PLACE version, we use the send - * buffer as the receive buffer. - */ - assert(recvBuf == NULL); - rPtr = sPtr; - rCount = sCount; - rType = sType; - } - } - - int rc = MPI_Iscatter(sPtr, sCount, (MPI_Datatype)sType, - rPtr, rCount, (MPI_Datatype)rType, - root, comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_scatterv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, jintArray sCounts, - jintArray displs, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, jint rCount, - jlong rjType, jint rBType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int inter = isInter(env, comm); - int rootOrInter = rank == root || inter; - int size = rootOrInter ? getSize(env, comm, inter) : 0; - - void *sPtr = NULL, *rPtr; - ompi_java_buffer_t *sItem, *rItem = NULL; - MPI_Datatype rType; - - if(rjType == 0) - { - assert(rBuf == NULL); - rType = MPI_DATATYPE_NULL; - rPtr = MPI_IN_PLACE; - } - else - { - rType = (MPI_Datatype)rjType; - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rCount, rType); - } - - jint *jSCounts = NULL, *jDispls = NULL; - int *cSCounts = NULL, *cDispls = NULL; - MPI_Datatype sType = rType; - - if(rootOrInter) - { - ompi_java_getIntArray(env, sCounts, &jSCounts, &cSCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - sType = (MPI_Datatype)sjType; - - ompi_java_getReadPtrv(&sPtr, &sItem, env, sBuf, sdb, sOff, - cSCounts, cDispls, size, -1, sType, sBType); - } - - int rc = MPI_Scatterv(sPtr, cSCounts, cDispls, sType, - rPtr, rCount, rType, root, comm); - - ompi_java_exceptionCheck(env, rc); - - if(rItem != NULL && rBuf != NULL) - { - ompi_java_releaseWritePtr(rPtr, rItem, env, rBuf, rdb, - rOff, rCount, rType, rBType); - } - - if(rootOrInter) - { - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - ompi_java_forgetIntArray(env, sCounts, jSCounts, cSCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - } -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iScatterv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jintArray sCounts, jintArray displs, jlong sType, - jobject recvBuf, jint rCount, jlong rType, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - MPI_Request request; - void *sPtr = NULL, *rPtr; - - if(rType == 0) - { - assert(recvBuf == NULL); - rType = (jlong)MPI_DATATYPE_NULL; - rPtr = MPI_IN_PLACE; - } - else - { - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - } - - jint *jSCounts, *jDispls; - int *cSCounts, *cDispls; - - if(rootOrInter) - { - ompi_java_getIntArray(env, sCounts, &jSCounts, &cSCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - } - else - { - jSCounts = jDispls = NULL; - cSCounts = cDispls = NULL; - sType = rType; - } - - int rc = MPI_Iscatterv(sPtr, cSCounts, cDispls, (MPI_Datatype)sType, - rPtr, rCount, (MPI_Datatype)rType, root, - comm, &request); - - ompi_java_exceptionCheck(env, rc); - - if(rootOrInter) - { - ompi_java_forgetIntArray(env, sCounts, jSCounts, cSCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - } - - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allGather( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jint rCount, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType, - rType = (MPI_Datatype)rjType; - - int inter = isInter(env, comm), - size = getSize(env, comm, inter), - rTotal = rCount * size; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - if(sjType == 0) - { - assert(sBuf == NULL); - sType = MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - int rank = getRank(env, comm); - - ompi_java_getReadPtrRank(&rPtr, &rItem, env, rBuf, rdb, rOff, - rCount, size, rank, rType, rBType); - } - else - { - sType = (MPI_Datatype)sjType; - - ompi_java_getReadPtr(&sPtr, &sItem, env, sBuf, sdb, - sOff, sCount, sType, sBType); - - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rTotal, rType); - } - - int rc = MPI_Allgather(sPtr, sCount, sType, rPtr, rCount, rType, comm); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseWritePtr(rPtr, rItem, env, rBuf, rdb, - rOff, rTotal, rType, rBType); - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllGather( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jint rCount, jlong rType) -{ - void *sPtr, *rPtr; - MPI_Request request; - - if(sType == 0) - { - assert(sendBuf == NULL); - sType = (jlong)MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - } - - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - int rc = MPI_Iallgather(sPtr, sCount, (MPI_Datatype)sType, - rPtr, rCount, (MPI_Datatype)rType, - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allGatherv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jintArray rCounts, jintArray displs, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int inter = isInter(env, comm), - size = getSize(env, comm, inter); - - MPI_Datatype sType, - rType = (MPI_Datatype)rjType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - jint *jRCounts, *jDispls; - int *cRCounts, *cDispls; - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - - if(sjType == 0) - { - assert(sBuf == NULL); - sType = MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - int rank = getRank(env, comm); - - ompi_java_getReadPtrv(&rPtr, &rItem, env, rBuf, rdb, rOff, - cRCounts, cDispls, size, rank, rType, rBType); - } - else - { - sType = (MPI_Datatype)sjType; - - ompi_java_getReadPtr(&sPtr, &sItem, env, sBuf, sdb, - sOff, sCount, sType, sBType); - - ompi_java_getWritePtrv(&rPtr, &rItem, env, rBuf, rdb, - cRCounts, cDispls, size, rType); - } - - int rc = MPI_Allgatherv(sPtr, sCount, sType, rPtr, - cRCounts, cDispls, rType, comm); - - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseWritePtrv(rPtr, rItem, env, rBuf, rdb, rOff, - cRCounts, cDispls, size, rType, rBType); - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllGatherv( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jintArray rCounts, jintArray displs, jlong rType) -{ - MPI_Request request; - void *sPtr, *rPtr; - - if(sType == 0) - { - assert(sendBuf == NULL); - sType = (jlong)MPI_DATATYPE_NULL; - sPtr = MPI_IN_PLACE; - } - else - { - sPtr = ompi_java_getDirectBufferAddress(env, sendBuf); - } - - jint *jRCounts, *jDispls; - int *cRCounts, *cDispls; - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - - rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - int rc = MPI_Iallgatherv(sPtr, sCount, (MPI_Datatype)sType, - rPtr, cRCounts, cDispls, (MPI_Datatype)rType, - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allToAll( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jint rCount, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int inter = isInter(env, comm), - size = getSize(env, comm, inter), - sTotal = sCount * size, - rTotal = rCount * size; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - ompi_java_getReadPtr(&sPtr, &sItem, env,sBuf,sdb,sOff,sTotal,sType,sBType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rTotal, rType); - - int rc = MPI_Alltoall(sPtr, sCount, sType, rPtr, rCount, rType, comm); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rTotal,rType,rBType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllToAll( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jint sCount, jlong sType, - jobject recvBuf, jint rCount, jlong rType) -{ - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ialltoall(sPtr, sCount, (MPI_Datatype)sType, - rPtr, rCount, (MPI_Datatype)rType, - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allToAllv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, jintArray sCount, - jintArray sDispl, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, jintArray rCount, - jintArray rDispl, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int inter = isInter(env, comm), - size = getSize(env, comm, inter); - - jint *jSCount, *jRCount, *jSDispl, *jRDispl; - int *cSCount, *cRCount, *cSDispl, *cRDispl; - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispl, &jSDispl, &cSDispl); - ompi_java_getIntArray(env, rDispl, &jRDispl, &cRDispl); - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - ompi_java_getReadPtrv(&sPtr, &sItem, env, sBuf, sdb, sOff, - cSCount, cSDispl, size, -1, sType, sBType); - ompi_java_getWritePtrv(&rPtr, &rItem, env, rBuf, rdb, - cRCount, cRDispl, size, rType); - - int rc = MPI_Alltoallv(sPtr, cSCount, cSDispl, sType, - rPtr, cRCount, cRDispl, rType, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtrv(rPtr, rItem, env, rBuf, rdb, rOff, - cRCount, cRDispl, size, rType, rBType); - - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispl, jSDispl, cSDispl); - ompi_java_forgetIntArray(env, rDispl, jRDispl, cRDispl); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllToAllv( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jintArray sCount, jintArray sDispls, jlong sType, - jobject recvBuf, jintArray rCount, jintArray rDispls, jlong rType) -{ - jint *jSCount, *jRCount, *jSDispls, *jRDispls; - int *cSCount, *cRCount, *cSDispls, *cRDispls; - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispls, &jSDispls, &cSDispls); - ompi_java_getIntArray(env, rDispls, &jRDispls, &cRDispls); - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ialltoallv(sPtr, cSCount, cSDispls, (MPI_Datatype)sType, - rPtr, cRCount, cRDispls, (MPI_Datatype)rType, - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispls, jSDispls, cSDispls); - ompi_java_forgetIntArray(env, rDispls, jRDispls, cRDispls); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allToAllw( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jintArray sOffs, jintArray sCount, - jintArray sDispls, jlongArray sTypes, jintArray sBtypes, - jobject rBuf, jboolean rdb, jintArray rOffs, jintArray rCount, - jintArray rDispls, jlongArray rTypes, jintArray rBtypes) -{ - MPI_Comm comm = (MPI_Comm)jComm; - - int inter = isInter(env, comm), - size = getSize(env, comm, inter); - - jlong* jSTypes, *jRTypes; - MPI_Datatype *cSTypes, *cRTypes; - - ompi_java_getDatatypeArray(env, sTypes, &jSTypes, &cSTypes); - ompi_java_getDatatypeArray(env, rTypes, &jRTypes, &cRTypes); - - jint *jSCount, *jRCount, *jSDispls, *jRDispls; - int *cSCount, *cRCount, *cSDispls, *cRDispls; - jint *jSBtypes, *jRBtypes; - int *cSBtypes, *cRBtypes; - jint *jSOffs, *jROffs; - int *cSOffs, *cROffs; - - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispls, &jSDispls, &cSDispls); - ompi_java_getIntArray(env, rDispls, &jRDispls, &cRDispls); - ompi_java_getIntArray(env, sBtypes, &jSBtypes, &cSBtypes); - ompi_java_getIntArray(env, rBtypes, &jRBtypes, &cRBtypes); - ompi_java_getIntArray(env, sOffs, &jSOffs, &cSOffs); - ompi_java_getIntArray(env, rOffs, &jROffs, &cROffs); - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - ompi_java_getReadPtrw(&sPtr, &sItem, env, sBuf, sdb, cSOffs, - cSCount, cSDispls, size, -1, cSTypes, cSBtypes); - ompi_java_getWritePtrw(&rPtr, &rItem, env, rBuf, rdb, - cRCount, cRDispls, size, cRTypes); - - int rc = MPI_Alltoallw(sPtr, cSCount, cSDispls, cSTypes, - rPtr, cRCount, cRDispls, cRTypes, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtrw(rPtr, rItem, env, rBuf, rdb, cROffs, - cRCount, cRDispls, size, cRTypes, cRBtypes); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispls, jSDispls, cSDispls); - ompi_java_forgetIntArray(env, rDispls, jRDispls, cRDispls); - ompi_java_forgetIntArray(env, sBtypes, jSBtypes, cSBtypes); - ompi_java_forgetIntArray(env, rBtypes, jRBtypes, cRBtypes); - ompi_java_forgetIntArray(env, sOffs, jSOffs, cSOffs); - ompi_java_forgetIntArray(env, rOffs, jROffs, cROffs); - ompi_java_forgetDatatypeArray(env, sTypes, jSTypes, cSTypes); - ompi_java_forgetDatatypeArray(env, rTypes, jRTypes, cRTypes); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllToAllw( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jintArray sCount, jintArray sDispls, jlongArray sTypes, - jobject recvBuf, jintArray rCount, jintArray rDispls, jlongArray rTypes) -{ - MPI_Comm comm = (MPI_Comm)jComm; - - jlong* jSTypes, *jRTypes; - MPI_Datatype *cSTypes, *cRTypes; - - ompi_java_getDatatypeArray(env, sTypes, &jSTypes, &cSTypes); - ompi_java_getDatatypeArray(env, rTypes, &jRTypes, &cRTypes); - - jint *jSCount, *jRCount, *jSDispls, *jRDispls; - int *cSCount, *cRCount, *cSDispls, *cRDispls; - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispls, &jSDispls, &cSDispls); - ompi_java_getIntArray(env, rDispls, &jRDispls, &cRDispls); - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ialltoallw( - sPtr, cSCount, cSDispls, cSTypes, - rPtr, cRCount, cRDispls, cRTypes, comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispls, jSDispls, cSDispls); - ompi_java_forgetIntArray(env, rDispls, jRDispls, cRDispls); - ompi_java_forgetDatatypeArray(env, sTypes, jSTypes, cSTypes); - ompi_java_forgetDatatypeArray(env, rTypes, jRTypes, cRTypes); - - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_neighborAllGather( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jint rCount, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int sSize, rSize; - getNeighbors(env, comm, &sSize, &rSize); - int rTotal = rCount * rSize; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,sCount,sType,sBType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rTotal, rType); - - int rc = MPI_Neighbor_allgather( - sPtr, sCount, sType, rPtr, rCount, rType, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rTotal,rType,rBType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iNeighborAllGather( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sjType, - jobject recvBuf, jint rCount, jlong rjType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ineighbor_allgather( - sPtr, sCount, sType, rPtr, rCount, rType, comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_neighborAllGatherv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jintArray rCount, jintArray displs, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int sSize, rSize; - getNeighbors(env, comm, &sSize, &rSize); - - jint *jRCount, *jDispls; - int *cRCount, *cDispls; - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,sCount,sType,sBType); - - ompi_java_getWritePtrv(&rPtr, &rItem, env, rBuf, rdb, - cRCount, cDispls, rSize, rType); - - int rc = MPI_Neighbor_allgatherv( - sPtr, sCount, sType, rPtr, cRCount, cDispls, rType, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtrv(rPtr, rItem, env, rBuf, rdb, rOff, - cRCount, cDispls, rSize, rType, rBType); - - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iNeighborAllGatherv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sjType, - jobject recvBuf, jintArray rCount, jintArray displs, jlong rjType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - jint *jRCount, *jDispls; - int *cRCount, *cDispls; - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, displs, &jDispls, &cDispls); - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ineighbor_allgatherv(sPtr, sCount, sType, rPtr, cRCount, - cDispls, rType, comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, displs, jDispls, cDispls); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_neighborAllToAll( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jint sCount, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jint rCount, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int sSize, rSize; - getNeighbors(env, comm, &sSize, &rSize); - int sTotal = sCount * sSize; - int rTotal = rCount * rSize; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - ompi_java_getReadPtr(&sPtr, &sItem, env,sBuf,sdb,sOff,sTotal,sType,sBType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rTotal, rType); - - int rc = MPI_Neighbor_alltoall( - sPtr, sCount, sType, rPtr, rCount, rType, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rTotal,rType,rBType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iNeighborAllToAll( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jint sCount, jlong sjType, - jobject recvBuf, jint rCount, jlong rjType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ineighbor_alltoall( - sPtr, sCount, sType, rPtr, rCount, rType, comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_neighborAllToAllv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jintArray sCount, jintArray sDispl, jlong sjType, jint sBType, - jobject rBuf, jboolean rdb, jint rOff, - jintArray rCount, jintArray rDispl, jlong rjType, jint rBType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - int sSize, rSize; - getNeighbors(env, comm, &sSize, &rSize); - - jint *jSCount, *jRCount, *jSDispl, *jRDispl; - int *cSCount, *cRCount, *cSDispl, *cRDispl; - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispl, &jSDispl, &cSDispl); - ompi_java_getIntArray(env, rDispl, &jRDispl, &cRDispl); - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - ompi_java_getReadPtrv(&sPtr, &sItem, env, sBuf, sdb, sOff, - cSCount, cSDispl, sSize, -1, sType, sBType); - ompi_java_getWritePtrv(&rPtr, &rItem, env, rBuf, rdb, - cRCount, cRDispl, rSize, rType); - - int rc = MPI_Neighbor_alltoallv(sPtr, cSCount, cSDispl, sType, - rPtr, cRCount, cRDispl, rType, comm); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtrv(rPtr, rItem, env, rBuf, rdb, rOff, - cRCount, cRDispl, rSize, rType, rBType); - - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispl, jSDispl, cSDispl); - ompi_java_forgetIntArray(env, rDispl, jRDispl, cRDispl); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iNeighborAllToAllv( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jintArray sCount, jintArray sDispls, jlong sjType, - jobject recvBuf, jintArray rCount, jintArray rDispls, jlong rjType) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype sType = (MPI_Datatype)sjType; - MPI_Datatype rType = (MPI_Datatype)rjType; - - jint *jSCount, *jRCount, *jSDispls, *jRDispls; - int *cSCount, *cRCount, *cSDispls, *cRDispls; - ompi_java_getIntArray(env, sCount, &jSCount, &cSCount); - ompi_java_getIntArray(env, rCount, &jRCount, &cRCount); - ompi_java_getIntArray(env, sDispls, &jSDispls, &cSDispls); - ompi_java_getIntArray(env, rDispls, &jRDispls, &cRDispls); - - void *sPtr = ompi_java_getDirectBufferAddress(env, sendBuf), - *rPtr = ompi_java_getDirectBufferAddress(env, recvBuf); - - MPI_Request request; - - int rc = MPI_Ineighbor_alltoallv( - sPtr, cSCount, cSDispls, sType, - rPtr, cRCount, cRDispls, rType, comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sCount, jSCount, cSCount); - ompi_java_forgetIntArray(env, rCount, jRCount, cRCount); - ompi_java_forgetIntArray(env, sDispls, jSDispls, cSDispls); - ompi_java_forgetIntArray(env, rDispls, jRDispls, cRDispls); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_reduce( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, jint count, - jlong jType, jint bType, jobject jOp, jlong hOp, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - void *sPtr, *rPtr = NULL; - ompi_java_buffer_t *sItem, *rItem; - - if(sBuf == NULL) - { - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - sPtr = rootOrInter ? MPI_IN_PLACE : rPtr; - /* The receive buffer is ignored for all non-root processes. - * On MPI_IN_PLACE version we use receive buffer as the send buffer. - */ - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - - if(rootOrInter) - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, count, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Reduce(sPtr, rPtr, count, type, op, root, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - if(rootOrInter) - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,count,type,bType); - else if(sBuf == NULL) - ompi_java_releaseReadPtr(rPtr, rItem, rBuf, rdb); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iReduce( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sendBuf, jobject recvBuf, int count, - jlong type, jint baseType, jobject jOp, jlong hOp, jint root) -{ - MPI_Comm comm = (MPI_Comm)jComm; - int rank = getRank(env, comm); - int rootOrInter = rank == root || isInter(env, comm); - - void *sPtr, *rPtr = NULL; - MPI_Request request; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - if(rootOrInter || sendBuf == NULL) - { - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - - if(!rootOrInter) - { - /* The receive buffer is ignored for all non-root processes. - * As we are using MPI_IN_PLACE version, we use the receive - * buffer as the send buffer. - */ - assert(sendBuf == NULL); - sPtr = rPtr; - } - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - - int rc = MPI_Ireduce(sPtr, rPtr, count, (MPI_Datatype)type, - op, root, comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_allReduce( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, - jint count, jlong jType, jint bType, jobject jOp, jlong hOp) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - if(sBuf == NULL) - { - sPtr = MPI_IN_PLACE; - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, count, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Allreduce(sPtr, rPtr, count, type, op, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,count,type,bType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iAllReduce( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jobject recvBuf, jint count, - jlong type, jint baseType, jobject jOp, jlong hOp) -{ - MPI_Request request; - void *sPtr, *rPtr; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - - int rc = MPI_Iallreduce(sPtr, rPtr, count, (MPI_Datatype)type, - op, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_reduceScatter( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, - jintArray rCounts, jlong jType, jint bType, jobject jOp, jlong hOp) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - jint *jRCounts; - int *cRCounts; - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - - int size = getGroupSize(env, comm), - count = getSum(cRCounts, size), - rbCnt; /* Receive buffer count */ - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - if(sBuf == NULL) - { - sPtr = MPI_IN_PLACE; - rbCnt = count; - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - rbCnt = cRCounts[getRank(env, comm)]; - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rbCnt, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Reduce_scatter(sPtr, rPtr, cRCounts, type, op, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rbCnt,type,bType); - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iReduceScatter( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jobject recvBuf, jintArray rCounts, - jlong type, int bType, jobject jOp, jlong hOp) -{ - void *sPtr, *rPtr; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - MPI_Request request; - - jint *jRCounts; - int *cRCounts; - ompi_java_getIntArray(env, rCounts, &jRCounts, &cRCounts); - - int rc = MPI_Ireduce_scatter(sPtr, rPtr, cRCounts, (MPI_Datatype)type, - op, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, rCounts, jRCounts, cRCounts); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_reduceScatterBlock( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, - jint rCount, jlong jType, jint bType, jobject jOp, jlong hOp) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - int count = rCount * getGroupSize(env, comm), - rbCnt; /* Receive buffer count */ - - if(sBuf == NULL) - { - sPtr = MPI_IN_PLACE; - rbCnt = count; - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - rbCnt = rCount; - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, rbCnt, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Reduce_scatter_block(sPtr, rPtr, rCount, type, op, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,rbCnt,type,bType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Comm_iReduceScatterBlock( - JNIEnv *env, jobject jthis, jlong comm, jobject sendBuf, - jobject recvBuf, jint count, jlong type, jint bType, - jobject jOp, jlong hOp) -{ - void *sPtr, *rPtr; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - MPI_Request request; - - int rc = MPI_Ireduce_scatter_block(sPtr, rPtr, count, (MPI_Datatype)type, - op, (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Comm_reduceLocal( - JNIEnv *env, jclass clazz, jobject inBuf, jboolean idb, jint inOff, - jobject inOutBuf, jboolean iodb, jint inOutOff, jint count, - jlong jType, jlong op) -{ - MPI_Datatype type = (MPI_Datatype)jType; - void *inPtr, *inBase, *inOutPtr, *inOutBase; - inPtr = getBufCritical(&inBase, env, inBuf, idb, inOff); - inOutPtr = getBufCritical(&inOutBase, env, inOutBuf, iodb, inOutOff); - int rc = MPI_Reduce_local(inPtr, inOutPtr, count, type, (MPI_Op)op); - ompi_java_exceptionCheck(env, rc); - releaseBufCritical(env, inBuf, idb, inBase); - releaseBufCritical(env, inOutBuf, iodb, inOutBase); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_reduceLocalUf( - JNIEnv *env, jclass clazz, jobject inBuf, jboolean idb, jint inOff, - jobject inOutBuf, jboolean iodb, jint inOutOff, jint count, - jlong jType, jint bType, jobject jOp, jlong hOp) -{ - MPI_Datatype type = (MPI_Datatype)jType; - void *inPtr, *inOutPtr; - ompi_java_buffer_t *inItem, *inOutItem; - - ompi_java_getReadPtr(&inPtr, &inItem, env, inBuf, - idb, inOff, count, type, bType); - ompi_java_getReadPtr(&inOutPtr, &inOutItem, env, inOutBuf, - iodb, inOutOff, count, type, bType); - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Reduce_local(inPtr, inOutPtr, count, type, op); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(inPtr, inItem, inBuf, idb); - - ompi_java_releaseWritePtr(inOutPtr, inOutItem, env, inOutBuf, - iodb, inOutOff, count, type, bType); -} - -JNIEXPORT void JNICALL Java_mpi_Comm_setName( - JNIEnv *env, jobject jthis, jlong handle, jstring jname) -{ - const char *name = (*env)->GetStringUTFChars(env, jname, NULL); - int rc = MPI_Comm_set_name((MPI_Comm)handle, (char*)name); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jname, name); -} - -JNIEXPORT jstring JNICALL Java_mpi_Comm_getName( - JNIEnv *env, jobject jthis, jlong handle) -{ - char name[MPI_MAX_OBJECT_NAME]; - int len; - int rc = MPI_Comm_get_name((MPI_Comm)handle, name, &len); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - return (*env)->NewStringUTF(env, name); -} diff --git a/ompi/mpi/java/c/mpi_Constant.c b/ompi/mpi/java/c/mpi_Constant.c deleted file mode 100644 index 06884743e62..00000000000 --- a/ompi/mpi/java/c/mpi_Constant.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi_Constant.h" -#include "mpiJava.h" - -void ompi_java_setStaticLongField(JNIEnv *env, jclass c, - char *field, jlong value) -{ - jfieldID id = (*env)->GetStaticFieldID(env, c, field, "J"); - (*env)->SetStaticLongField(env, c, id, value); -} - -void ompi_java_setIntField(JNIEnv *env, jclass c, jobject obj, - char *field, jint value) -{ - jfieldID id = (*env)->GetFieldID(env, c, field, "I"); - (*env)->SetIntField(env, obj, id, value); -} - -/* - * Class: mpi_Constant - * Method: setConstant - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_mpi_Constant_setConstant(JNIEnv *env, jobject obj) -{ - jclass c = (*env)->GetObjectClass(env, obj); - ompi_java_setIntField(env, c, obj, "THREAD_SINGLE", MPI_THREAD_SINGLE); - ompi_java_setIntField(env, c, obj, "THREAD_FUNNELED", MPI_THREAD_FUNNELED); - ompi_java_setIntField(env, c, obj, "THREAD_SERIALIZED", MPI_THREAD_SERIALIZED); - ompi_java_setIntField(env, c, obj, "THREAD_MULTIPLE", MPI_THREAD_MULTIPLE); - - ompi_java_setIntField(env, c, obj, "ANY_SOURCE", MPI_ANY_SOURCE); - ompi_java_setIntField(env, c, obj, "ANY_TAG", MPI_ANY_TAG); - ompi_java_setIntField(env, c, obj, "PROC_NULL", MPI_PROC_NULL); - ompi_java_setIntField(env, c, obj, "GRAPH", MPI_GRAPH); - ompi_java_setIntField(env, c, obj, "DIST_GRAPH", MPI_DIST_GRAPH); - ompi_java_setIntField(env, c, obj, "CART", MPI_CART); - - ompi_java_setIntField(env, c, obj, "UNDEFINED", MPI_UNDEFINED); - ompi_java_setIntField(env, c, obj, "IDENT", MPI_IDENT); - ompi_java_setIntField(env, c, obj, "CONGRUENT", MPI_CONGRUENT); - ompi_java_setIntField(env, c, obj, "SIMILAR", MPI_SIMILAR); - ompi_java_setIntField(env, c, obj, "UNEQUAL", MPI_UNEQUAL); - - ompi_java_setIntField(env, c, obj, "TAG_UB", MPI_TAG_UB); - ompi_java_setIntField(env, c, obj, "HOST", MPI_HOST); - ompi_java_setIntField(env, c, obj, "IO", MPI_IO); - ompi_java_setIntField(env, c, obj, "WTIME_IS_GLOBAL", MPI_WTIME_IS_GLOBAL); - ompi_java_setIntField(env, c, obj, "APPNUM", MPI_APPNUM); - ompi_java_setIntField(env, c, obj, "LASTUSEDCODE", MPI_LASTUSEDCODE); - ompi_java_setIntField(env, c, obj, "UNIVERSE_SIZE", MPI_UNIVERSE_SIZE); - ompi_java_setIntField(env, c, obj, "WIN_BASE", MPI_WIN_BASE); - ompi_java_setIntField(env, c, obj, "WIN_SIZE", MPI_WIN_SIZE); - ompi_java_setIntField(env, c, obj, "WIN_DISP_UNIT", MPI_WIN_DISP_UNIT); - - ompi_java_setIntField(env, c, obj, "VERSION", MPI_VERSION); - ompi_java_setIntField(env, c, obj, "SUBVERSION", MPI_SUBVERSION); - ompi_java_setIntField(env, c, obj, "ROOT", MPI_ROOT); - ompi_java_setIntField(env, c, obj, "KEYVAL_INVALID", MPI_KEYVAL_INVALID); - ompi_java_setIntField(env, c, obj, "BSEND_OVERHEAD", MPI_BSEND_OVERHEAD); - ompi_java_setIntField(env, c, obj, "MAX_OBJECT_NAME", MPI_MAX_OBJECT_NAME); - ompi_java_setIntField(env, c, obj, "MAX_PORT_NAME", MPI_MAX_PORT_NAME); - ompi_java_setIntField(env, c, obj, "MAX_DATAREP_STRING", MPI_MAX_DATAREP_STRING); - ompi_java_setIntField(env, c, obj, "MAX_INFO_KEY", MPI_MAX_INFO_KEY); - ompi_java_setIntField(env, c, obj, "MAX_INFO_VAL", MPI_MAX_INFO_VAL); - ompi_java_setIntField(env, c, obj, "ORDER_C", MPI_ORDER_C); - ompi_java_setIntField(env, c, obj, "ORDER_FORTRAN", MPI_ORDER_FORTRAN); - ompi_java_setIntField(env, c, obj, "DISTRIBUTE_BLOCK", MPI_DISTRIBUTE_BLOCK); - ompi_java_setIntField(env, c, obj, "DISTRIBUTE_CYCLIC", MPI_DISTRIBUTE_CYCLIC); - ompi_java_setIntField(env, c, obj, "DISTRIBUTE_NONE", MPI_DISTRIBUTE_NONE); - ompi_java_setIntField(env, c, obj, "DISTRIBUTE_DFLT_DARG", MPI_DISTRIBUTE_DFLT_DARG); - - ompi_java_setIntField(env, c, obj, "MODE_CREATE", MPI_MODE_CREATE); - ompi_java_setIntField(env, c, obj, "MODE_RDONLY", MPI_MODE_RDONLY); - ompi_java_setIntField(env, c, obj, "MODE_WRONLY", MPI_MODE_WRONLY); - ompi_java_setIntField(env, c, obj, "MODE_RDWR", MPI_MODE_RDWR); - ompi_java_setIntField(env, c, obj, "MODE_DELETE_ON_CLOSE", MPI_MODE_DELETE_ON_CLOSE); - ompi_java_setIntField(env, c, obj, "MODE_UNIQUE_OPEN", MPI_MODE_UNIQUE_OPEN); - ompi_java_setIntField(env, c, obj, "MODE_EXCL", MPI_MODE_EXCL); - ompi_java_setIntField(env, c, obj, "MODE_APPEND", MPI_MODE_APPEND); - ompi_java_setIntField(env, c, obj, "MODE_SEQUENTIAL", MPI_MODE_SEQUENTIAL); - ompi_java_setIntField(env, c, obj, "DISPLACEMENT_CURRENT", MPI_DISPLACEMENT_CURRENT); - ompi_java_setIntField(env, c, obj, "SEEK_SET", MPI_SEEK_SET); - ompi_java_setIntField(env, c, obj, "SEEK_CUR", MPI_SEEK_CUR); - ompi_java_setIntField(env, c, obj, "SEEK_END", MPI_SEEK_END); - - ompi_java_setIntField(env, c, obj, "MODE_NOCHECK", MPI_MODE_NOCHECK); - ompi_java_setIntField(env, c, obj, "MODE_NOPRECEDE", MPI_MODE_NOPRECEDE); - ompi_java_setIntField(env, c, obj, "MODE_NOPUT", MPI_MODE_NOPUT); - ompi_java_setIntField(env, c, obj, "MODE_NOSTORE", MPI_MODE_NOSTORE); - ompi_java_setIntField(env, c, obj, "MODE_NOSUCCEED", MPI_MODE_NOSUCCEED); - ompi_java_setIntField(env, c, obj, "LOCK_EXCLUSIVE", MPI_LOCK_EXCLUSIVE); - ompi_java_setIntField(env, c, obj, "LOCK_SHARED", MPI_LOCK_SHARED); - - // Error classes and codes - ompi_java_setIntField(env, c, obj, "SUCCESS", MPI_SUCCESS); - ompi_java_setIntField(env, c, obj, "ERR_BUFFER", MPI_ERR_BUFFER); - ompi_java_setIntField(env, c, obj, "ERR_COUNT", MPI_ERR_COUNT); - ompi_java_setIntField(env, c, obj, "ERR_TYPE", MPI_ERR_TYPE); - ompi_java_setIntField(env, c, obj, "ERR_TAG", MPI_ERR_TAG); - ompi_java_setIntField(env, c, obj, "ERR_COMM", MPI_ERR_COMM); - ompi_java_setIntField(env, c, obj, "ERR_RANK", MPI_ERR_RANK); - ompi_java_setIntField(env, c, obj, "ERR_REQUEST", MPI_ERR_REQUEST); - ompi_java_setIntField(env, c, obj, "ERR_ROOT", MPI_ERR_ROOT); - ompi_java_setIntField(env, c, obj, "ERR_GROUP", MPI_ERR_GROUP); - ompi_java_setIntField(env, c, obj, "ERR_OP", MPI_ERR_OP); - ompi_java_setIntField(env, c, obj, "ERR_TOPOLOGY", MPI_ERR_TOPOLOGY); - ompi_java_setIntField(env, c, obj, "ERR_DIMS", MPI_ERR_DIMS); - ompi_java_setIntField(env, c, obj, "ERR_ARG", MPI_ERR_ARG); - ompi_java_setIntField(env, c, obj, "ERR_UNKNOWN", MPI_ERR_UNKNOWN); - ompi_java_setIntField(env, c, obj, "ERR_TRUNCATE", MPI_ERR_TRUNCATE); - ompi_java_setIntField(env, c, obj, "ERR_OTHER", MPI_ERR_OTHER); - ompi_java_setIntField(env, c, obj, "ERR_INTERN", MPI_ERR_INTERN); - ompi_java_setIntField(env, c, obj, "ERR_IN_STATUS", MPI_ERR_IN_STATUS); - ompi_java_setIntField(env, c, obj, "ERR_PENDING", MPI_ERR_PENDING); - ompi_java_setIntField(env, c, obj, "ERR_ACCESS", MPI_ERR_ACCESS); - ompi_java_setIntField(env, c, obj, "ERR_AMODE", MPI_ERR_AMODE); - ompi_java_setIntField(env, c, obj, "ERR_ASSERT", MPI_ERR_ASSERT); - ompi_java_setIntField(env, c, obj, "ERR_BAD_FILE", MPI_ERR_BAD_FILE); - ompi_java_setIntField(env, c, obj, "ERR_BASE", MPI_ERR_BASE); - ompi_java_setIntField(env, c, obj, "ERR_CONVERSION", MPI_ERR_CONVERSION); - ompi_java_setIntField(env, c, obj, "ERR_DISP", MPI_ERR_DISP); - ompi_java_setIntField(env, c, obj, "ERR_DUP_DATAREP", MPI_ERR_DUP_DATAREP); - ompi_java_setIntField(env, c, obj, "ERR_FILE_EXISTS", MPI_ERR_FILE_EXISTS); - ompi_java_setIntField(env, c, obj, "ERR_FILE_IN_USE", MPI_ERR_FILE_IN_USE); - ompi_java_setIntField(env, c, obj, "ERR_FILE", MPI_ERR_FILE); - ompi_java_setIntField(env, c, obj, "ERR_INFO_KEY", MPI_ERR_INFO_KEY); - ompi_java_setIntField(env, c, obj, "ERR_INFO_NOKEY", MPI_ERR_INFO_NOKEY); - ompi_java_setIntField(env, c, obj, "ERR_INFO_VALUE", MPI_ERR_INFO_VALUE); - ompi_java_setIntField(env, c, obj, "ERR_INFO", MPI_ERR_INFO); - ompi_java_setIntField(env, c, obj, "ERR_IO", MPI_ERR_IO); - ompi_java_setIntField(env, c, obj, "ERR_KEYVAL", MPI_ERR_KEYVAL); - ompi_java_setIntField(env, c, obj, "ERR_LOCKTYPE", MPI_ERR_LOCKTYPE); - ompi_java_setIntField(env, c, obj, "ERR_NAME", MPI_ERR_NAME); - ompi_java_setIntField(env, c, obj, "ERR_NO_MEM", MPI_ERR_NO_MEM); - ompi_java_setIntField(env, c, obj, "ERR_NOT_SAME", MPI_ERR_NOT_SAME); - ompi_java_setIntField(env, c, obj, "ERR_NO_SPACE", MPI_ERR_NO_SPACE); - ompi_java_setIntField(env, c, obj, "ERR_NO_SUCH_FILE", MPI_ERR_NO_SUCH_FILE); - ompi_java_setIntField(env, c, obj, "ERR_PORT", MPI_ERR_PORT); - ompi_java_setIntField(env, c, obj, "ERR_PROC_ABORTED", MPI_ERR_PROC_ABORTED); - ompi_java_setIntField(env, c, obj, "ERR_QUOTA", MPI_ERR_QUOTA); - ompi_java_setIntField(env, c, obj, "ERR_READ_ONLY", MPI_ERR_READ_ONLY); - ompi_java_setIntField(env, c, obj, "ERR_RMA_CONFLICT", MPI_ERR_RMA_CONFLICT); - ompi_java_setIntField(env, c, obj, "ERR_RMA_SYNC", MPI_ERR_RMA_SYNC); - ompi_java_setIntField(env, c, obj, "ERR_SERVICE", MPI_ERR_SERVICE); - ompi_java_setIntField(env, c, obj, "ERR_SIZE", MPI_ERR_SIZE); - ompi_java_setIntField(env, c, obj, "ERR_SPAWN", MPI_ERR_SPAWN); - - ompi_java_setIntField(env, c, obj, "ERR_UNSUPPORTED_DATAREP", - MPI_ERR_UNSUPPORTED_DATAREP); - - ompi_java_setIntField(env, c, obj, "ERR_UNSUPPORTED_OPERATION", - MPI_ERR_UNSUPPORTED_OPERATION); - - ompi_java_setIntField(env, c, obj, "ERR_WIN", MPI_ERR_WIN); - ompi_java_setIntField(env, c, obj, "ERR_LASTCODE", MPI_ERR_LASTCODE); -} diff --git a/ompi/mpi/java/c/mpi_Count.c b/ompi/mpi/java/c/mpi_Count.c deleted file mode 100644 index 0ef8827c017..00000000000 --- a/ompi/mpi/java/c/mpi_Count.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Version.java - * Author : Nathaniel Graham - * Created : Thu Jul 30 09:34 2015 - */ - -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Count.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_Count_initCount(JNIEnv *env, jclass jthis) -{ - jclass c = (*env)->FindClass(env, "mpi/Count"); - ompi_java.CountClass = (*env)->NewGlobalRef(env, c); - ompi_java.CountInit = (*env)->GetMethodID(env, ompi_java.CountClass, "", "(J)V"); - - (*env)->DeleteLocalRef(env, c); -} diff --git a/ompi/mpi/java/c/mpi_Datatype.c b/ompi/mpi/java/c/mpi_Datatype.c deleted file mode 100644 index 0f8be98a7e5..00000000000 --- a/ompi/mpi/java/c/mpi_Datatype.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Datatype.c - * Headerfile : mpi_Datatype.h - * Author : Sung-Hoon Ko, Xinying Li, Sang Lim, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.10 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Datatype.h" -#include "mpiJava.h" - -MPI_Datatype Dts[] = { MPI_DATATYPE_NULL, /* NULL */ - MPI_UINT8_T, /* BYTE */ - MPI_UINT16_T, /* CHAR */ - MPI_INT16_T, /* SHORT */ - MPI_UINT8_T, /* BOOLEAN (let's hope Java is - one byte..) */ - MPI_INT32_T, /* INT */ - MPI_INT64_T, /* LONG */ - MPI_FLOAT, /* FLOAT (let's hope it's the same!) */ - MPI_DOUBLE, /* DOUBLE (let's hoe it's the same!) */ - MPI_PACKED, /* PACKED */ - MPI_2INT, - MPI_SHORT_INT, - MPI_LONG_INT, - MPI_FLOAT_INT, - MPI_DOUBLE_INT, - MPI_C_FLOAT_COMPLEX, - MPI_C_DOUBLE_COMPLEX -}; - -JNIEXPORT void JNICALL Java_mpi_Datatype_init(JNIEnv *e, jclass clazz) -{ - ompi_java.DatatypeHandle = (*e)->GetFieldID(e, clazz, "handle", "J"); - ompi_java.DatatypeBaseType = (*e)->GetFieldID(e, clazz, "baseType", "I"); - ompi_java.DatatypeBaseSize = (*e)->GetFieldID(e, clazz, "baseSize", "I"); -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getDatatype( - JNIEnv *e, jobject jthis, jint type) -{ - return (jlong)Dts[type]; -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_getLbExtent( - JNIEnv *env, jobject jthis, jlong type, jintArray jLbExt) -{ - MPI_Aint lb, extent; - int rc = MPI_Type_get_extent((MPI_Datatype)type, &lb, &extent); - if(ompi_java_exceptionCheck(env, rc)) - return; - - jint *lbExt = (*env)->GetIntArrayElements(env, jLbExt, NULL); - lbExt[0] = (jint)lb; - lbExt[1] = (jint)extent; - (*env)->ReleaseIntArrayElements(env, jLbExt, lbExt, 0); -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_getTrueLbExtent( - JNIEnv *env, jobject jthis, jlong type, jintArray jLbExt) -{ - MPI_Aint lb, extent; - int rc = MPI_Type_get_true_extent((MPI_Datatype)type, &lb, &extent); - if(ompi_java_exceptionCheck(env, rc)) - return; - - jint *lbExt = (*env)->GetIntArrayElements(env, jLbExt, NULL); - lbExt[0] = (jint)lb; - lbExt[1] = (jint)extent; - (*env)->ReleaseIntArrayElements(env, jLbExt, lbExt, 0); -} - -JNIEXPORT jint JNICALL Java_mpi_Datatype_getSize( - JNIEnv *env, jobject jthis, jlong type) -{ - int rc, result; - rc = MPI_Type_size((MPI_Datatype)type, &result); - ompi_java_exceptionCheck(env, rc); - return result; -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_commit( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Datatype type = (MPI_Datatype)handle; - int rc = MPI_Type_commit(&type); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Datatype type = (MPI_Datatype)handle; - - if(type != MPI_DATATYPE_NULL) - { - int rc = MPI_Type_free(&type); - ompi_java_exceptionCheck(env, rc); - } - - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_dup( - JNIEnv *env, jobject jthis, jlong oldType) -{ - MPI_Datatype newType; - int rc = MPI_Type_dup((MPI_Datatype)oldType, &newType); - ompi_java_exceptionCheck(env, rc); - return (jlong)newType; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getContiguous( - JNIEnv *env, jclass clazz, jint count, jlong oldType) -{ - MPI_Datatype type; - int rc = MPI_Type_contiguous(count, (MPI_Datatype)oldType, &type); - ompi_java_exceptionCheck(env, rc); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getVector( - JNIEnv *env, jclass clazz, jint count, - jint blockLength, jint stride, jlong oldType) -{ - MPI_Datatype type; - - int rc = MPI_Type_vector(count, blockLength, stride, - (MPI_Datatype)oldType, &type); - - ompi_java_exceptionCheck(env, rc); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getHVector( - JNIEnv *env, jclass clazz, jint count, - jint blockLength, jint stride, jlong oldType) -{ - MPI_Datatype type; - - int rc = MPI_Type_create_hvector(count, blockLength, stride, - (MPI_Datatype)oldType, &type); - - ompi_java_exceptionCheck(env, rc); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getIndexed( - JNIEnv *env, jclass clazz, jintArray blockLengths, - jintArray disps, jlong oldType) -{ - MPI_Datatype type; - int count = (*env)->GetArrayLength(env, blockLengths); - - jint *jBlockLengths, *jDispl; - int *cBlockLengths, *cDispl; - ompi_java_getIntArray(env, blockLengths, &jBlockLengths, &cBlockLengths); - ompi_java_getIntArray(env, disps, &jDispl, &cDispl); - - int rc = MPI_Type_indexed(count, cBlockLengths, cDispl, - (MPI_Datatype)oldType, &type); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, blockLengths, jBlockLengths, cBlockLengths); - ompi_java_forgetIntArray(env, disps, jDispl, cDispl); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getHIndexed( - JNIEnv *env, jclass clazz, jintArray blockLengths, - jintArray disps, jlong oldType) -{ - MPI_Datatype type; - int count = (*env)->GetArrayLength(env, blockLengths); - jint *jBlockLengths; - int *cBlockLengths; - ompi_java_getIntArray(env, blockLengths, &jBlockLengths, &cBlockLengths); - - jint *jDisps = (*env)->GetIntArrayElements(env, disps, NULL); - MPI_Aint *cDisps = (MPI_Aint*)calloc(count, sizeof(MPI_Aint)); - int i; - - for(i = 0; i < count; i++) - cDisps[i] = jDisps[i]; - - int rc = MPI_Type_create_hindexed(count, cBlockLengths, cDisps, - (MPI_Datatype)oldType, &type); - - ompi_java_exceptionCheck(env, rc); - free(cDisps); - ompi_java_forgetIntArray(env, blockLengths, jBlockLengths, cBlockLengths); - (*env)->ReleaseIntArrayElements(env, disps, jDisps, JNI_ABORT); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getStruct( - JNIEnv *env, jclass clazz, jintArray blockLengths, - jintArray disps, jobjectArray datatypes) -{ - int count = (*env)->GetArrayLength(env, blockLengths); - jint *jBlockLengths; - int *cBlockLengths; - ompi_java_getIntArray(env, blockLengths, &jBlockLengths, &cBlockLengths); - - jint *jDisps = (*env)->GetIntArrayElements(env, disps, NULL); - MPI_Aint *cDisps = (MPI_Aint*)calloc(count, sizeof(MPI_Aint)); - - MPI_Datatype *cTypes = (MPI_Datatype*)calloc(count, sizeof(MPI_Datatype)); - int i; - - for(i = 0; i < count; i++) - { - cDisps[i] = jDisps[i]; - jobject type = (*env)->GetObjectArrayElement(env, datatypes, i); - - cTypes[i] = (MPI_Datatype)(*env)->GetLongField( - env, type, ompi_java.DatatypeHandle); - - (*env)->DeleteLocalRef(env, type); - } - - MPI_Datatype type; - int rc = MPI_Type_create_struct(count, cBlockLengths, cDisps, cTypes, &type); - ompi_java_exceptionCheck(env, rc); - - free(cDisps); - free(cTypes); - ompi_java_forgetIntArray(env, blockLengths, jBlockLengths, cBlockLengths); - (*env)->ReleaseIntArrayElements(env, disps, jDisps, JNI_ABORT); - return (jlong)type; -} - -JNIEXPORT jlong JNICALL Java_mpi_Datatype_getResized( - JNIEnv *env, jclass clazz, jlong oldType, jint lb, jint extent) -{ - MPI_Datatype type; - int rc = MPI_Type_create_resized((MPI_Datatype)oldType, lb, extent, &type); - ompi_java_exceptionCheck(env, rc); - return (jlong)type; -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_setName( - JNIEnv *env, jobject jthis, jlong handle, jstring jname) -{ - const char *name = (*env)->GetStringUTFChars(env, jname, NULL); - int rc = MPI_Type_set_name((MPI_Datatype)handle, (char*)name); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jname, name); -} - -JNIEXPORT jstring JNICALL Java_mpi_Datatype_getName( - JNIEnv *env, jobject jthis, jlong handle) -{ - char name[MPI_MAX_OBJECT_NAME]; - int len; - int rc = MPI_Type_get_name((MPI_Datatype)handle, name, &len); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - return (*env)->NewStringUTF(env, name); -} - -static int typeCopyAttr(MPI_Datatype oldType, int keyval, void *extraState, - void *attrValIn, void *attrValOut, int *flag) -{ - return ompi_java_attrCopy(attrValIn, attrValOut, flag); -} - -static int typeDeleteAttr(MPI_Datatype oldType, int keyval, - void *attrVal, void *extraState) -{ - return ompi_java_attrDelete(attrVal); -} - -JNIEXPORT jint JNICALL Java_mpi_Datatype_createKeyval_1jni( - JNIEnv *env, jclass clazz) -{ - int rc, keyval; - rc = MPI_Type_create_keyval(typeCopyAttr, typeDeleteAttr, &keyval, NULL); - ompi_java_exceptionCheck(env, rc); - return keyval; -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_freeKeyval_1jni( - JNIEnv *env, jclass clazz, jint keyval) -{ - int rc = MPI_Type_free_keyval((int*)(&keyval)); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_setAttr( - JNIEnv *env, jobject jthis, jlong type, jint keyval, jbyteArray jval) -{ - void *cval = ompi_java_attrSet(env, jval); - int rc = MPI_Type_set_attr((MPI_Datatype)type, keyval, cval); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jobject JNICALL Java_mpi_Datatype_getAttr( - JNIEnv *env, jobject jthis, jlong type, jint keyval) -{ - int flag; - void *val; - int rc = MPI_Type_get_attr((MPI_Datatype)type, keyval, &val, &flag); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - return NULL; - - return ompi_java_attrGet(env, val); -} - -JNIEXPORT void JNICALL Java_mpi_Datatype_deleteAttr( - JNIEnv *env, jobject jthis, jlong type, jint keyval) -{ - int rc = MPI_Type_delete_attr((MPI_Datatype)type, keyval); - ompi_java_exceptionCheck(env, rc); -} diff --git a/ompi/mpi/java/c/mpi_Errhandler.c b/ompi/mpi/java/c/mpi_Errhandler.c deleted file mode 100644 index de09b13a619..00000000000 --- a/ompi/mpi/java/c/mpi_Errhandler.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* - * File : mpi_Errhandler.c - * Headerfile : mpi_Errhandler.h - * Author : Bryan Carpenter - * Created : 1999 - * Revision : $Revision: 1.2 $ - * Updated : $Date: 2001/08/07 16:36:15 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include -#include "mpi_Errhandler.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_Errhandler_getFatal(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_ERRORS_ARE_FATAL; -} - -JNIEXPORT jlong JNICALL Java_mpi_Errhandler_getAbort(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_ERRORS_ABORT; -} - -JNIEXPORT jlong JNICALL Java_mpi_Errhandler_getReturn(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_ERRORS_RETURN; -} diff --git a/ompi/mpi/java/c/mpi_File.c b/ompi/mpi/java/c/mpi_File.c deleted file mode 100644 index 237b522776b..00000000000 --- a/ompi/mpi/java/c/mpi_File.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_File.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_File_open( - JNIEnv *env, jobject jthis, jlong comm, - jstring jfilename, jint amode, jlong info) -{ - const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); - MPI_File fh; - - int rc = MPI_File_open((MPI_Comm)comm, (char*)filename, - amode, (MPI_Info)info, &fh); - - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jfilename, filename); - return (jlong)fh; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_close( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_File file = (MPI_File)fh; - int rc = MPI_File_close(&file); - ompi_java_exceptionCheck(env, rc); - return (jlong)file; -} - -JNIEXPORT void JNICALL Java_mpi_File_delete( - JNIEnv *env, jclass clazz, jstring jfilename, jlong info) -{ - const char* filename = (*env)->GetStringUTFChars(env, jfilename, NULL); - int rc = MPI_File_delete((char*)filename, (MPI_Info)info); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jfilename, filename); -} - -JNIEXPORT void JNICALL Java_mpi_File_setSize( - JNIEnv *env, jobject jthis, jlong fh, jlong size) -{ - int rc = MPI_File_set_size((MPI_File)fh, (MPI_Offset)size); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_preallocate( - JNIEnv *env, jobject jthis, jlong fh, jlong size) -{ - int rc = MPI_File_preallocate((MPI_File)fh, (MPI_Offset)size); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getSize( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Offset size; - int rc = MPI_File_get_size((MPI_File)fh, &size); - ompi_java_exceptionCheck(env, rc); - return (jlong)size; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getGroup( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Group group; - int rc = MPI_File_get_group((MPI_File)fh, &group); - ompi_java_exceptionCheck(env, rc); - return (jlong)group; -} - -JNIEXPORT jint JNICALL Java_mpi_File_getAMode( - JNIEnv *env, jobject jthis, jlong fh) -{ - int amode; - int rc = MPI_File_get_amode((MPI_File)fh, &amode); - ompi_java_exceptionCheck(env, rc); - return amode; -} - -JNIEXPORT void JNICALL Java_mpi_File_setInfo( - JNIEnv *env, jobject jthis, jlong fh, jlong info) -{ - int rc = MPI_File_set_info((MPI_File)fh, (MPI_Info)info); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getInfo( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Info info; - int rc = MPI_File_get_info((MPI_File)fh, &info); - ompi_java_exceptionCheck(env, rc); - return (jlong)info; -} - -JNIEXPORT void JNICALL Java_mpi_File_setView( - JNIEnv *env, jobject jthis, jlong fh, jlong disp, - jlong etype, jlong filetype, jstring jdatarep, jlong info) -{ - const char* datarep = (*env)->GetStringUTFChars(env, jdatarep, NULL); - - int rc = MPI_File_set_view( - (MPI_File)fh, (MPI_Offset)disp, (MPI_Datatype)etype, - (MPI_Datatype)filetype, (char*)datarep, (MPI_Info)info); - - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jdatarep, datarep); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAt( - JNIEnv *env, jobject jthis, jlong fh, jlong fileOffset, - jobject buf, jboolean db, jint off, jint count, - jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - - int rc = MPI_File_read_at((MPI_File)fh, (MPI_Offset)fileOffset, - ptr, count, type, &status); - - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAtAll( - JNIEnv *env, jobject jthis, jlong fh, jlong fileOffset, - jobject buf, jboolean db, jint off, jint count, - jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - - int rc = MPI_File_read_at_all((MPI_File)fh, (MPI_Offset)fileOffset, - ptr, count, type, &status); - - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAt( - JNIEnv *env, jobject jthis, jlong fh, jlong fileOffset, - jobject buf, jboolean db, jint off, jint count, - jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - - int rc = MPI_File_write_at((MPI_File)fh, (MPI_Offset)fileOffset, - ptr, count, type, &status); - - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAtAll( - JNIEnv *env, jobject jthis, jlong fh, jlong fileOffset, - jobject buf, jboolean db, jint off, jint count, - jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - - int rc = MPI_File_write_at_all((MPI_File)fh, (MPI_Offset)fileOffset, - ptr, count, (MPI_Datatype)type, &status); - - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iReadAt( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iread_at((MPI_File)fh, (MPI_Offset)offset, - ptr, count, (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iReadAtAll( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iread_at_all((MPI_File)fh, (MPI_Offset)offset, - ptr, count, (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iWriteAt( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iwrite_at((MPI_File)fh, (MPI_Offset)offset, - ptr, count, (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iWriteAtAll( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iwrite_at_all((MPI_File)fh, (MPI_Offset)offset, - ptr, count, (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_File_read( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - int rc = MPI_File_read((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAll( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - int rc = MPI_File_read_all((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_write( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - int rc = MPI_File_write((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAll( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - int rc = MPI_File_write_all((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iRead( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iread((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iReadAll( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iread_all((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iWrite( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iwrite((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iWriteAll( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iwrite_all((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_File_seek( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, jint whence) -{ - int rc = MPI_File_seek((MPI_File)fh, (MPI_Offset)offset, whence); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getPosition( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Offset offset; - int rc = MPI_File_get_position((MPI_File)fh, &offset); - ompi_java_exceptionCheck(env, rc); - return (jlong)offset; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getByteOffset( - JNIEnv *env, jobject jthis, jlong fh, jlong offset) -{ - MPI_Offset disp; - int rc = MPI_File_get_byte_offset((MPI_File)fh, (MPI_Offset)offset, &disp); - ompi_java_exceptionCheck(env, rc); - return (jlong)disp; -} - -JNIEXPORT void JNICALL Java_mpi_File_readShared( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - int rc = MPI_File_read_shared((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeShared( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - int rc = MPI_File_write_shared((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iReadShared( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iread_shared((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_File_iWriteShared( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - MPI_Request request; - - int rc = MPI_File_iwrite_shared((MPI_File)fh, ptr, count, - (MPI_Datatype)type, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_File_readOrdered( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - MPI_Status status; - int rc = MPI_File_read_ordered((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeOrdered( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray stat) -{ - jboolean exception; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getReadPtr(&ptr, &item, env, buf, db, off, count, type, bType); - MPI_Status status; - int rc = MPI_File_write_ordered((MPI_File)fh, ptr, count, type, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releaseReadPtr(ptr, item, buf, db); - - if(!exception) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_seekShared( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, jint whence) -{ - int rc = MPI_File_seek_shared((MPI_File)fh, (MPI_Offset)offset, whence); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getPositionShared( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Offset offset; - int rc = MPI_File_get_position_shared((MPI_File)fh, &offset); - ompi_java_exceptionCheck(env, rc); - return (jlong)offset; -} - -JNIEXPORT void JNICALL Java_mpi_File_readAtAllBegin( - JNIEnv *env, jobject jthis, jlong fh, jlong offset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_read_at_all_begin((MPI_File)fh, (MPI_Offset)offset, - ptr, count, (MPI_Datatype)type); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAtAllEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_read_at_all_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAtAllBegin( - JNIEnv *env, jobject jthis, jlong fh, jlong fileOffset, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_write_at_all_begin((MPI_File)fh, (MPI_Offset)fileOffset, - ptr, count, (MPI_Datatype)type); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAtAllEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_write_at_all_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAllBegin( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_read_all_begin( - (MPI_File)fh, ptr, count, (MPI_Datatype)type); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_readAllEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_read_all_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAllBegin( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_write_all_begin( - (MPI_File)fh, ptr, count, (MPI_Datatype)type); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeAllEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_write_all_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_readOrderedBegin( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_read_ordered_begin( - (MPI_File)fh, ptr, count, (MPI_Datatype)type); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_readOrderedEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_read_ordered_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeOrderedBegin( - JNIEnv *env, jobject jthis, jlong fh, - jobject buf, jint count, jlong type) -{ - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - - int rc = MPI_File_write_ordered_begin( - (MPI_File)fh, ptr, count, (MPI_Datatype)type); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_writeOrderedEnd( - JNIEnv *env, jobject jthis, jlong fh, jobject buf, jlongArray stat) -{ - MPI_Status status; - void *ptr = (*env)->GetDirectBufferAddress(env, buf); - int rc = MPI_File_write_ordered_end((MPI_File)fh, ptr, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); -} - -JNIEXPORT jint JNICALL Java_mpi_File_getTypeExtent( - JNIEnv *env, jobject jthis, jlong fh, jlong type) -{ - MPI_Aint extent; - - int rc = MPI_File_get_type_extent( - (MPI_File)fh, (MPI_Datatype)type, &extent); - - ompi_java_exceptionCheck(env, rc); - return (int)extent; -} - -JNIEXPORT void JNICALL Java_mpi_File_setAtomicity( - JNIEnv *env, jobject jthis, jlong fh, jboolean atomicity) -{ - int rc = MPI_File_set_atomicity((MPI_File)fh, atomicity); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jboolean JNICALL Java_mpi_File_getAtomicity( - JNIEnv *env, jobject jthis, jlong fh) -{ - int atomicity; - int rc = MPI_File_get_atomicity((MPI_File)fh, &atomicity); - ompi_java_exceptionCheck(env, rc); - return atomicity ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT void JNICALL Java_mpi_File_sync( - JNIEnv *env, jobject jthis, jlong fh) -{ - int rc = MPI_File_sync((MPI_File)fh); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_File_setErrhandler( - JNIEnv *env, jobject jthis, jlong fh, jlong errhandler) -{ - int rc = MPI_File_set_errhandler( - (MPI_File)fh, (MPI_Errhandler)errhandler); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_File_getErrhandler( - JNIEnv *env, jobject jthis, jlong fh) -{ - MPI_Errhandler errhandler; - int rc = MPI_File_get_errhandler((MPI_File)fh, &errhandler); - ompi_java_exceptionCheck(env, rc); - return (jlong)errhandler; -} - -JNIEXPORT void JNICALL Java_mpi_File_callErrhandler( - JNIEnv *env, jobject jthis, jlong fh, jint errorCode) -{ - int rc = MPI_File_call_errhandler((MPI_File)fh, errorCode); - ompi_java_exceptionCheck(env, rc); -} diff --git a/ompi/mpi/java/c/mpi_GraphComm.c b/ompi/mpi/java/c/mpi_GraphComm.c deleted file mode 100644 index 8a77eb816d4..00000000000 --- a/ompi/mpi/java/c/mpi_GraphComm.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_GraphComm.c - * Headerfile : mpi_GraphComm.h - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.2 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_GraphComm.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_GraphComm_init(JNIEnv *env, jclass clazz) -{ - ompi_java.GraphParmsInit = (*env)->GetMethodID(env, - ompi_java.GraphParmsClass, "", "([I[I)V"); - ompi_java.DistGraphNeighborsInit = (*env)->GetMethodID(env, - ompi_java.DistGraphNeighborsClass, "", "([I[I[I[IZ)V"); -} - -JNIEXPORT jobject JNICALL Java_mpi_GraphComm_getDims( - JNIEnv *env, jobject jthis, jlong comm) -{ - int maxInd, maxEdg; - int rc = MPI_Graphdims_get((MPI_Comm)comm, &maxInd, &maxEdg); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jintArray index = (*env)->NewIntArray(env, maxInd), - edges = (*env)->NewIntArray(env, maxEdg); - - jint *jIndex, *jEdges; - int *cIndex, *cEdges; - ompi_java_getIntArray(env, index, &jIndex, &cIndex); - ompi_java_getIntArray(env, edges, &jEdges, &cEdges); - - rc = MPI_Graph_get((MPI_Comm)comm, maxInd, maxEdg, cIndex, cEdges); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseIntArray(env, index, jIndex, cIndex); - ompi_java_releaseIntArray(env, edges, jEdges, cEdges); - - return (*env)->NewObject(env, ompi_java.GraphParmsClass, - ompi_java.GraphParmsInit, index, edges); -} - -JNIEXPORT jintArray JNICALL Java_mpi_GraphComm_getNeighbors( - JNIEnv *env, jobject jthis, jlong comm, jint rank) -{ - int maxNs; - int rc = MPI_Graph_neighbors_count((MPI_Comm)comm, rank, &maxNs); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jintArray neighbors = (*env)->NewIntArray(env, maxNs); - jint *jNeighbors; - int *cNeighbors; - ompi_java_getIntArray(env, neighbors, &jNeighbors, &cNeighbors); - - rc = MPI_Graph_neighbors((MPI_Comm)comm, rank, maxNs, cNeighbors); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseIntArray(env, neighbors, jNeighbors, cNeighbors); - return neighbors; -} - -JNIEXPORT jobject JNICALL Java_mpi_GraphComm_getDistGraphNeighbors( - JNIEnv *env, jobject jthis, jlong comm) -{ - int inDegree, outDegree, weighted; - - int rc = MPI_Dist_graph_neighbors_count( - (MPI_Comm)comm, &inDegree, &outDegree, &weighted); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - jintArray sources = (*env)->NewIntArray(env, inDegree), - srcWeights = (*env)->NewIntArray(env, inDegree), - destinations = (*env)->NewIntArray(env, outDegree), - destWeights = (*env)->NewIntArray(env, outDegree); - - jint *jSources, *jSrcWeights, *jDestinations, *jDestWeights; - int *cSources, *cSrcWeights, *cDestinations, *cDestWeights; - - ompi_java_getIntArray(env, sources, &jSources, &cSources); - ompi_java_getIntArray(env, srcWeights, &jSrcWeights, &cSrcWeights); - ompi_java_getIntArray(env, destinations, &jDestinations, &cDestinations); - ompi_java_getIntArray(env, destWeights, &jDestWeights, &cDestWeights); - - rc = MPI_Dist_graph_neighbors((MPI_Comm)comm, - inDegree, cSources, cSrcWeights, - outDegree, cDestinations, cDestWeights); - - ompi_java_exceptionCheck(env, rc); - ompi_java_releaseIntArray(env, sources, jSources, cSources); - ompi_java_releaseIntArray(env, srcWeights, jSrcWeights, cSrcWeights); - ompi_java_releaseIntArray(env, destinations, jDestinations, cDestinations); - ompi_java_releaseIntArray(env, destWeights, jDestWeights, cDestWeights); - - return (*env)->NewObject(env, - ompi_java.DistGraphNeighborsClass, ompi_java.DistGraphNeighborsInit, - sources, srcWeights, destinations, destWeights, - weighted ? JNI_TRUE : JNI_FALSE); -} - -JNIEXPORT jint JNICALL Java_mpi_GraphComm_map( - JNIEnv *env, jobject jthis, jlong comm, - jintArray index, jintArray edges) -{ - int nNodes = (*env)->GetArrayLength(env, index); - jint *jIndex, *jEdges; - int *cIndex, *cEdges; - ompi_java_getIntArray(env, index, &jIndex, &cIndex); - ompi_java_getIntArray(env, edges, &jEdges, &cEdges); - - int newrank; - int rc = MPI_Graph_map((MPI_Comm)comm, nNodes, cIndex, cEdges, &newrank); - ompi_java_exceptionCheck(env, rc); - - ompi_java_releaseIntArray(env, index, jIndex, cIndex); - ompi_java_releaseIntArray(env, edges, jEdges, cEdges); - return newrank; -} diff --git a/ompi/mpi/java/c/mpi_Group.c b/ompi/mpi/java/c/mpi_Group.c deleted file mode 100644 index 2ea29f4acdb..00000000000 --- a/ompi/mpi/java/c/mpi_Group.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Group.c - * Headerfile : mpi_Group.h - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.3 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Group.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_Group_init(JNIEnv *env, jclass clazz) -{ - ompi_java_setStaticLongField(env, clazz, - "nullHandle", (jlong)MPI_GROUP_NULL); - - ompi_java.GroupHandle = (*env)->GetFieldID(env, clazz, "handle", "J"); -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_getEmpty(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_GROUP_EMPTY; -} - -JNIEXPORT jint JNICALL Java_mpi_Group_getSize( - JNIEnv *env, jobject jthis, jlong group) -{ - int size, rc; - rc = MPI_Group_size((MPI_Group)group, &size); - ompi_java_exceptionCheck(env, rc); - return size; -} - -JNIEXPORT jint JNICALL Java_mpi_Group_getRank( - JNIEnv *env, jobject jthis, jlong group) -{ - int rank, rc; - rc = MPI_Group_rank((MPI_Group)group, &rank); - ompi_java_exceptionCheck(env, rc); - return rank; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Group group = (MPI_Group)handle; - int rc = MPI_Group_free(&group); - ompi_java_exceptionCheck(env, rc); - return (jlong)group; -} - -JNIEXPORT jintArray JNICALL Java_mpi_Group_translateRanks( - JNIEnv *env, jclass jthis, jlong group1, - jintArray ranks1, jlong group2) -{ - jsize n = (*env)->GetArrayLength(env, ranks1); - jintArray ranks2 = (*env)->NewIntArray(env,n); - jint *jRanks1, *jRanks2; - int *cRanks1, *cRanks2; - ompi_java_getIntArray(env, ranks1, &jRanks1, &cRanks1); - ompi_java_getIntArray(env, ranks2, &jRanks2, &cRanks2); - - int rc = MPI_Group_translate_ranks((MPI_Group)group1, n, cRanks1, - (MPI_Group)group2, cRanks2); - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, ranks1, jRanks1, cRanks1); - ompi_java_releaseIntArray(env, ranks2, jRanks2, cRanks2); - return ranks2; -} - -JNIEXPORT jint JNICALL Java_mpi_Group_compare( - JNIEnv *env, jclass jthis, jlong group1, jlong group2) -{ - int result, rc; - rc = MPI_Group_compare((MPI_Group)group1, (MPI_Group)group2, &result); - ompi_java_exceptionCheck(env, rc); - return result; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_union( - JNIEnv *env, jclass jthis, jlong group1, jlong group2) -{ - MPI_Group newGroup; - int rc = MPI_Group_union((MPI_Group)group1, (MPI_Group)group2, &newGroup); - ompi_java_exceptionCheck(env, rc); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_intersection( - JNIEnv *env, jclass jthis, jlong group1, jlong group2) -{ - MPI_Group newGroup; - - int rc = MPI_Group_intersection( - (MPI_Group)group1, (MPI_Group)group2, &newGroup); - - ompi_java_exceptionCheck(env, rc); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_difference( - JNIEnv *env, jclass jthis, jlong group1, jlong group2) -{ - MPI_Group newGroup; - - int rc = MPI_Group_difference( - (MPI_Group)group1, (MPI_Group)group2, &newGroup); - - ompi_java_exceptionCheck(env, rc); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_incl( - JNIEnv *env, jobject jthis, jlong group, jintArray ranks) -{ - jsize n = (*env)->GetArrayLength(env, ranks); - jint *jRanks; - int *cRanks; - ompi_java_getIntArray(env, ranks, &jRanks, &cRanks); - - MPI_Group newGroup; - int rc = MPI_Group_incl((MPI_Group)group, n, cRanks, &newGroup); - ompi_java_exceptionCheck(env, rc); - - ompi_java_forgetIntArray(env, ranks, jRanks, cRanks); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_excl( - JNIEnv *env, jobject jthis, jlong group, jintArray ranks) -{ - jsize n = (*env)->GetArrayLength(env, ranks); - jint *jRanks; - int *cRanks; - ompi_java_getIntArray(env, ranks, &jRanks, &cRanks); - - MPI_Group newGroup; - int rc = MPI_Group_excl((MPI_Group)group, n, cRanks, &newGroup); - ompi_java_exceptionCheck(env, rc); - - ompi_java_forgetIntArray(env, ranks, jRanks, cRanks); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_rangeIncl( - JNIEnv *env, jobject jthis, jlong group, jobjectArray ranges) -{ - int i; - MPI_Group newGroup; - jsize n = (*env)->GetArrayLength(env, ranges); - int (*cRanges)[3] = (int(*)[3])calloc(n, sizeof(int[3])); - - for(i = 0; i < n; i++) - { - jintArray ri = (*env)->GetObjectArrayElement(env, ranges, i); - jint *jri = (*env)->GetIntArrayElements(env, ri, NULL); - cRanges[i][0] = jri[0]; - cRanges[i][1] = jri[1]; - cRanges[i][2] = jri[2]; - (*env)->ReleaseIntArrayElements(env, ri, jri, JNI_ABORT); - (*env)->DeleteLocalRef(env, ri); - } - - int rc = MPI_Group_range_incl((MPI_Group)group, n, cRanges, &newGroup); - ompi_java_exceptionCheck(env, rc); - free(cRanges); - return (jlong)newGroup; -} - -JNIEXPORT jlong JNICALL Java_mpi_Group_rangeExcl( - JNIEnv *env, jobject jthis, jlong group, jobjectArray ranges) -{ - int i; - MPI_Group newGroup; - jsize n = (*env)->GetArrayLength(env, ranges); - int (*cRanges)[3] = (int(*)[3])calloc(n, sizeof(int[3])); - - for(i = 0; i < n; i++) - { - jintArray ri = (*env)->GetObjectArrayElement(env, ranges, i); - jint *jri = (*env)->GetIntArrayElements(env, ri, NULL); - cRanges[i][0] = jri[0]; - cRanges[i][1] = jri[1]; - cRanges[i][2] = jri[2]; - (*env)->ReleaseIntArrayElements(env, ri, jri, JNI_ABORT); - (*env)->DeleteLocalRef(env, ri); - } - - int rc = MPI_Group_range_excl((MPI_Group)group, n, cRanges, &newGroup); - ompi_java_exceptionCheck(env, rc); - free(cRanges); - return (jlong)newGroup; -} diff --git a/ompi/mpi/java/c/mpi_Info.c b/ompi/mpi/java/c/mpi_Info.c deleted file mode 100644 index 2bfdc5e8597..00000000000 --- a/ompi/mpi/java/c/mpi_Info.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Info.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_Info_create(JNIEnv *env, jobject jthis) -{ - MPI_Info info; - int rc = MPI_Info_create(&info); - ompi_java_exceptionCheck(env, rc); - return (jlong)info; -} - -JNIEXPORT jlong JNICALL Java_mpi_Info_getEnv(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_INFO_ENV; -} - -JNIEXPORT jlong JNICALL Java_mpi_Info_getNull(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_INFO_NULL; -} - -// At least some versions of jni.h have a global named "jvalue", and -// we get a compiler warning if we have a parameter or variable of the -// same name. So use "ljvalue" instead. -JNIEXPORT void JNICALL Java_mpi_Info_set( - JNIEnv *env, jobject jthis, jlong handle, jstring jkey, jstring ljvalue) -{ - const char *key = (*env)->GetStringUTFChars(env, jkey, NULL), - *value = (*env)->GetStringUTFChars(env, ljvalue, NULL); - - int rc = MPI_Info_set((MPI_Info)handle, (char*)key, (char*)value); - ompi_java_exceptionCheck(env, rc); - - (*env)->ReleaseStringUTFChars(env, jkey, key); - (*env)->ReleaseStringUTFChars(env, ljvalue, value); -} - -JNIEXPORT jstring JNICALL Java_mpi_Info_get( - JNIEnv *env, jobject jthis, jlong handle, jstring jkey) -{ - MPI_Info info = (MPI_Info)handle; - const char *key = (*env)->GetStringUTFChars(env, jkey, NULL); - - int rc, valueLen, flag; - rc = MPI_Info_get_valuelen(info, (char*)key, &valueLen, &flag); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - { - (*env)->ReleaseStringUTFChars(env, jkey, key); - return NULL; - } - - char *value = (char*)calloc(valueLen + 1, sizeof(char)); - rc = MPI_Info_get((MPI_Info)info, (char*)key, valueLen, value, &flag); - (*env)->ReleaseStringUTFChars(env, jkey, key); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - { - free(value); - return NULL; - } - - // At least some versions of jni.h have a global named "jvalue", - // and we get a compiler warning if we have a parameter or - // variable of the same name. So use "ljvalue" instead. - jstring ljvalue = (*env)->NewStringUTF(env, value); - free(value); - return ljvalue; -} - -JNIEXPORT void JNICALL Java_mpi_Info_delete( - JNIEnv *env, jobject jthis, jlong handle, jstring jkey) -{ - const char *key = (*env)->GetStringUTFChars(env, jkey, NULL); - int rc = MPI_Info_delete((MPI_Info)handle, (char*)key); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jkey, key); -} - -JNIEXPORT jint JNICALL Java_mpi_Info_size( - JNIEnv *env, jobject jthis, jlong handle) -{ - int rc, nkeys; - rc = MPI_Info_get_nkeys((MPI_Info)handle, &nkeys); - ompi_java_exceptionCheck(env, rc); - return (jint)nkeys; -} - -JNIEXPORT jstring JNICALL Java_mpi_Info_getKey( - JNIEnv *env, jobject jthis, jlong handle, jint i) -{ - char key[MPI_MAX_INFO_KEY + 1]; - int rc = MPI_Info_get_nthkey((MPI_Info)handle, i, key); - - return ompi_java_exceptionCheck(env, rc) - ? NULL : (*env)->NewStringUTF(env, key); -} - -JNIEXPORT jlong JNICALL Java_mpi_Info_dup( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Info newInfo; - int rc = MPI_Info_dup((MPI_Info)handle, &newInfo); - ompi_java_exceptionCheck(env, rc); - return (jlong)newInfo; -} - -JNIEXPORT jlong JNICALL Java_mpi_Info_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Info info = (MPI_Info)handle; - int rc = MPI_Info_free(&info); - ompi_java_exceptionCheck(env, rc); - return (jlong)info; -} - -JNIEXPORT jboolean JNICALL Java_mpi_Info_isNull( - JNIEnv *env, jobject jthis, jlong handle) -{ - return (MPI_Info)handle == MPI_INFO_NULL ? JNI_TRUE : JNI_FALSE; -} diff --git a/ompi/mpi/java/c/mpi_Intercomm.c b/ompi/mpi/java/c/mpi_Intercomm.c deleted file mode 100644 index 8e8f1b68e98..00000000000 --- a/ompi/mpi/java/c/mpi_Intercomm.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Intercomm.c - * Headerfile : mpi_Intercomm.h - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.3 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Intercomm.h" -#include "mpiJava.h" - - -/* - * Class: mpi_Intercomm - * Method: getRemoteSize_jni - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_mpi_Intercomm_getRemoteSize_1jni( - JNIEnv *env, jobject jthis) -{ - int size, rc; - - rc = MPI_Comm_remote_size( - (MPI_Comm)((*env)->GetLongField(env,jthis,ompi_java.CommHandle)), - &size); - - ompi_java_exceptionCheck(env, rc); - return size; -} - -/* - * Class: mpi_Intercomm - * Method: getRemoteGroup_jni - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_mpi_Intercomm_getRemoteGroup_1jni( - JNIEnv *env, jobject jthis) -{ - MPI_Group group; - - int rc = MPI_Comm_remote_group( - (MPI_Comm)((*env)->GetLongField(env,jthis,ompi_java.CommHandle)), - &group); - - ompi_java_exceptionCheck(env, rc); - return (jlong)group; -} - -/* - * Class: mpi_Intercomm - * Method: merge_jni - * Signature: (Z)Lmpi/Intracomm; - */ -JNIEXPORT jlong JNICALL Java_mpi_Intercomm_merge_1jni( - JNIEnv *env, jobject jthis, jboolean high) -{ - MPI_Comm newintracomm; - - int rc = MPI_Intercomm_merge( - (MPI_Comm)((*env)->GetLongField(env,jthis,ompi_java.CommHandle)), - high, &newintracomm); - - ompi_java_exceptionCheck(env, rc); - return (jlong)newintracomm; -} - -/* - * Class: mpi_Intercomm - * Method: getParent_jni - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_mpi_Intercomm_getParent_1jni( - JNIEnv *env, jclass clazz) -{ - MPI_Comm parent; - int rc = MPI_Comm_get_parent(&parent); - ompi_java_exceptionCheck(env, rc); - return (jlong)parent; -} diff --git a/ompi/mpi/java/c/mpi_Intracomm.c b/ompi/mpi/java/c/mpi_Intracomm.c deleted file mode 100644 index f73aa0089df..00000000000 --- a/ompi/mpi/java/c/mpi_Intracomm.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Intracomm.c - * Headerfile : mpi_Intracomm.h - * Author : Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.10 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -#include "ompi_config.h" - -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Comm.h" -#include "mpi_Intracomm.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_split( - JNIEnv *env, jobject jthis, jlong comm, jint colour, jint key) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_split((MPI_Comm)comm, colour, key, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_splitType( - JNIEnv *env, jobject jthis, jlong comm, jint splitType, jint key, jlong info) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_split_type((MPI_Comm)comm, splitType, key, (MPI_Info)info, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_create( - JNIEnv *env, jobject jthis, jlong comm, jlong group) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_create((MPI_Comm)comm, (MPI_Group)group, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_createGroup( - JNIEnv *env, jobject jthis, jlong comm, jlong group, int tag) -{ - MPI_Comm newcomm; - int rc = MPI_Comm_create_group((MPI_Comm)comm, (MPI_Group)group, tag, &newcomm); - ompi_java_exceptionCheck(env, rc); - return (jlong)newcomm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_createCart( - JNIEnv *env, jobject jthis, jlong comm, - jintArray dims, jbooleanArray periods, jboolean reorder) -{ - jint *jDims; - int *cDims; - ompi_java_getIntArray(env, dims, &jDims, &cDims); - - jboolean *jPeriods; - int *cPeriods; - ompi_java_getBooleanArray(env, periods, &jPeriods, &cPeriods); - - int ndims = (*env)->GetArrayLength(env, dims); - MPI_Comm cart; - - int rc = MPI_Cart_create((MPI_Comm)comm, ndims, cDims, - cPeriods, reorder, &cart); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, dims, jDims, cDims); - ompi_java_forgetBooleanArray(env, periods, jPeriods, cPeriods); - return (jlong)cart; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_createGraph( - JNIEnv *env, jobject jthis, jlong comm, - jintArray index, jintArray edges, jboolean reorder) -{ - MPI_Comm graph; - int nnodes = (*env)->GetArrayLength(env, index); - - jint *jIndex, *jEdges; - int *cIndex, *cEdges; - ompi_java_getIntArray(env, index, &jIndex, &cIndex); - ompi_java_getIntArray(env, edges, &jEdges, &cEdges); - - int rc = MPI_Graph_create((MPI_Comm)comm, - nnodes, cIndex, cEdges, reorder, &graph); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, index, jIndex, cIndex); - ompi_java_forgetIntArray(env, edges, jEdges, cEdges); - return (jlong)graph; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_createDistGraph( - JNIEnv *env, jobject jthis, jlong comm, jintArray sources, - jintArray degrees, jintArray destins, jintArray weights, - jlong info, jboolean reorder, jboolean weighted) -{ - MPI_Comm graph; - int nnodes = (*env)->GetArrayLength(env, sources); - - jint *jSources, *jDegrees, *jDestins, *jWeights = NULL; - int *cSources, *cDegrees, *cDestins, *cWeights = MPI_UNWEIGHTED; - ompi_java_getIntArray(env, sources, &jSources, &cSources); - ompi_java_getIntArray(env, degrees, &jDegrees, &cDegrees); - ompi_java_getIntArray(env, destins, &jDestins, &cDestins); - - if(weighted) - ompi_java_getIntArray(env, weights, &jWeights, &cWeights); - - int rc = MPI_Dist_graph_create((MPI_Comm)comm, - nnodes, cSources, cDegrees, cDestins, cWeights, - (MPI_Info)info, reorder, &graph); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sources, jSources, cSources); - ompi_java_forgetIntArray(env, degrees, jDegrees, cDegrees); - ompi_java_forgetIntArray(env, destins, jDestins, cDestins); - - if(weighted) - ompi_java_forgetIntArray(env, weights, jWeights, cWeights); - - return (jlong)graph; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_createDistGraphAdjacent( - JNIEnv *env, jobject jthis, jlong comm, jintArray sources, - jintArray srcWeights, jintArray destins, jintArray desWeights, - jlong info, jboolean reorder, jboolean weighted) -{ - MPI_Comm graph; - - int inDegree = (*env)->GetArrayLength(env, sources), - outDegree = (*env)->GetArrayLength(env, destins); - - jint *jSources, *jDestins, *jSrcWeights, *jDesWeights; - int *cSources, *cDestins, *cSrcWeights, *cDesWeights; - ompi_java_getIntArray(env, sources, &jSources, &cSources); - ompi_java_getIntArray(env, destins, &jDestins, &cDestins); - - if(weighted) - { - ompi_java_getIntArray(env, srcWeights, &jSrcWeights, &cSrcWeights); - ompi_java_getIntArray(env, desWeights, &jDesWeights, &cDesWeights); - } - else - { - jSrcWeights = jDesWeights = NULL; - cSrcWeights = cDesWeights = MPI_UNWEIGHTED; - } - - int rc = MPI_Dist_graph_create_adjacent((MPI_Comm)comm, - inDegree, cSources, cSrcWeights, outDegree, cDestins, - cDesWeights, (MPI_Info)info, reorder, &graph); - - ompi_java_exceptionCheck(env, rc); - ompi_java_forgetIntArray(env, sources, jSources, cSources); - ompi_java_forgetIntArray(env, destins, jDestins, cDestins); - - if(weighted) - { - ompi_java_forgetIntArray(env, srcWeights, jSrcWeights, cSrcWeights); - ompi_java_forgetIntArray(env, desWeights, jDesWeights, cDesWeights); - } - - return (jlong)graph; -} - -JNIEXPORT void JNICALL Java_mpi_Intracomm_scan( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, jint count, - jlong jType, jint bType, jobject jOp, jlong hOp) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - if(sBuf == NULL) - { - sPtr = MPI_IN_PLACE; - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, count, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Scan(sPtr, rPtr, count, type, op, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,count,type,bType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_iScan( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jobject recvBuf, jint count, - jlong type, int baseType, jobject jOp, jlong hOp) -{ - void *sPtr, *rPtr; - MPI_Request request; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - - int rc = MPI_Iscan(sPtr, rPtr, count, (MPI_Datatype)type, - ompi_java_op_getHandle(env, jOp, hOp, baseType), - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Intracomm_exScan( - JNIEnv *env, jobject jthis, jlong jComm, - jobject sBuf, jboolean sdb, jint sOff, - jobject rBuf, jboolean rdb, jint rOff, jint count, - jlong jType, int bType, jobject jOp, jlong hOp) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Datatype type = (MPI_Datatype)jType; - - void *sPtr, *rPtr; - ompi_java_buffer_t *sItem, *rItem; - - if(sBuf == NULL) - { - sPtr = MPI_IN_PLACE; - ompi_java_getReadPtr(&rPtr,&rItem,env,rBuf,rdb,rOff,count,type,bType); - } - else - { - ompi_java_getReadPtr(&sPtr,&sItem,env,sBuf,sdb,sOff,count,type,bType); - ompi_java_getWritePtr(&rPtr, &rItem, env, rBuf, rdb, count, type); - } - - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, bType); - int rc = MPI_Exscan(sPtr, rPtr, count, type, op, comm); - ompi_java_exceptionCheck(env, rc); - - if(sBuf != NULL) - ompi_java_releaseReadPtr(sPtr, sItem, sBuf, sdb); - - ompi_java_releaseWritePtr(rPtr,rItem,env,rBuf,rdb,rOff,count,type,bType); -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_iExScan( - JNIEnv *env, jobject jthis, jlong comm, - jobject sendBuf, jobject recvBuf, jint count, - jlong type, int bType, jobject jOp, jlong hOp) -{ - void *sPtr, *rPtr; - - if(sendBuf == NULL) - sPtr = MPI_IN_PLACE; - else - sPtr = (*env)->GetDirectBufferAddress(env, sendBuf); - - rPtr = (*env)->GetDirectBufferAddress(env, recvBuf); - MPI_Request request; - - int rc = MPI_Iexscan(sPtr, rPtr, count, (MPI_Datatype)type, - ompi_java_op_getHandle(env, jOp, hOp, bType), - (MPI_Comm)comm, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jstring JNICALL Java_mpi_Intracomm_openPort( - JNIEnv *env, jclass clazz, jlong info) -{ - char port[MPI_MAX_PORT_NAME + 1]; - int rc = MPI_Open_port((MPI_Info)info, port); - - return ompi_java_exceptionCheck(env, rc) - ? NULL : (*env)->NewStringUTF(env, port); -} - -JNIEXPORT void JNICALL Java_mpi_Intracomm_closePort_1jni( - JNIEnv *env, jclass clazz, jstring jport) -{ - const char *port = (*env)->GetStringUTFChars(env, jport, NULL); - int rc = MPI_Close_port((char*)port); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jport, port); -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_accept( - JNIEnv *env, jobject jthis, jlong comm, - jstring jport, jlong info, jint root) -{ - const char *port = jport == NULL ? NULL : - (*env)->GetStringUTFChars(env, jport, NULL); - MPI_Comm newComm; - - int rc = MPI_Comm_accept((char*)port, (MPI_Info)info, - root, (MPI_Comm)comm, &newComm); - - ompi_java_exceptionCheck(env, rc); - - if(jport != NULL) - (*env)->ReleaseStringUTFChars(env, jport, port); - - return (jlong)newComm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_connect( - JNIEnv *env, jobject jthis, jlong comm, - jstring jport, jlong info, jint root) -{ - const char *port = jport == NULL ? NULL : - (*env)->GetStringUTFChars(env, jport, NULL); - MPI_Comm newComm; - - int rc = MPI_Comm_connect((char*)port, (MPI_Info)info, - root, (MPI_Comm)comm, &newComm); - - ompi_java_exceptionCheck(env, rc); - - if(jport != NULL) - (*env)->ReleaseStringUTFChars(env, jport, port); - - return (jlong)newComm; -} - -JNIEXPORT void JNICALL Java_mpi_Intracomm_publishName( - JNIEnv *env, jclass clazz, jstring jservice, jlong info, jstring jport) -{ - const char *service = (*env)->GetStringUTFChars(env, jservice, NULL), - *port = (*env)->GetStringUTFChars(env, jport, NULL); - - int rc = MPI_Publish_name((char*)service, (MPI_Info)info, (char*)port); - ompi_java_exceptionCheck(env, rc); - - (*env)->ReleaseStringUTFChars(env, jservice, service); - (*env)->ReleaseStringUTFChars(env, jport, port); -} - -JNIEXPORT void JNICALL Java_mpi_Intracomm_unpublishName( - JNIEnv *env, jclass clazz, jstring jservice, jlong info, jstring jport) -{ - const char *service = (*env)->GetStringUTFChars(env, jservice, NULL), - *port = (*env)->GetStringUTFChars(env, jport, NULL); - - int rc = MPI_Unpublish_name((char*)service, (MPI_Info)info, (char*)port); - ompi_java_exceptionCheck(env, rc); - - (*env)->ReleaseStringUTFChars(env, jservice, service); - (*env)->ReleaseStringUTFChars(env, jport, port); -} - -JNIEXPORT jstring JNICALL Java_mpi_Intracomm_lookupName( - JNIEnv *env, jclass clazz, jstring jservice, jlong info) -{ - char port[MPI_MAX_PORT_NAME + 1]; - const char *service = (*env)->GetStringUTFChars(env, jservice, NULL); - - int rc = MPI_Lookup_name((char*)service, (MPI_Info)info, port); - (*env)->ReleaseStringUTFChars(env, jservice, service); - - return ompi_java_exceptionCheck(env, rc) - ? NULL : (*env)->NewStringUTF(env, port); -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_spawn( - JNIEnv *env, jobject jthis, jlong comm, jstring jCommand, - jobjectArray jArgv, jint maxprocs, jlong info, jint root, - jintArray errCodes) -{ - int i, rc; - MPI_Comm intercomm; - const char* command = (*env)->GetStringUTFChars(env, jCommand, NULL); - - jint *jErrCodes; - int *cErrCodes = MPI_ERRCODES_IGNORE; - - if(errCodes != NULL) - ompi_java_getIntArray(env, errCodes, &jErrCodes, &cErrCodes); - - char **argv = MPI_ARGV_NULL; - - if(jArgv != NULL) - { - jsize argvLength = (*env)->GetArrayLength(env, jArgv); - argv = (char**)calloc(argvLength + 1, sizeof(char*)); - - for(i = 0; i < argvLength; i++) - { - jstring a = (*env)->GetObjectArrayElement(env, jArgv, i); - argv[i] = strdup((*env)->GetStringUTFChars(env, a, NULL)); - (*env)->DeleteLocalRef(env, a); - } - - argv[argvLength] = NULL; - } - - rc = MPI_Comm_spawn((char*)command, argv, maxprocs, (MPI_Info)info, - root, (MPI_Comm)comm, &intercomm, cErrCodes); - - ompi_java_exceptionCheck(env, rc); - - if(jArgv != NULL) - { - jsize argvLength = (*env)->GetArrayLength(env, jArgv); - - for(i = 0; i < argvLength; i++) - { - jstring a = (*env)->GetObjectArrayElement(env, jArgv, i); - (*env)->ReleaseStringUTFChars(env, a, argv[i]); - (*env)->DeleteLocalRef(env, a); - } - - free(argv); - } - - if(errCodes != NULL) - ompi_java_releaseIntArray(env, errCodes, jErrCodes, cErrCodes); - - (*env)->ReleaseStringUTFChars(env, jCommand, command); - return (jlong)intercomm; -} - -JNIEXPORT jlong JNICALL Java_mpi_Intracomm_spawnMultiple( - JNIEnv *env, jobject jthis, jlong comm, jobjectArray jCommands, - jobjectArray jArgv, jintArray maxProcs, jlongArray info, - jint root, jintArray errCodes) -{ - int i, rc; - MPI_Comm intercomm; - jlong *jInfo = (*env)->GetLongArrayElements(env, info, NULL); - - jint *jMaxProcs, *jErrCodes; - int *cMaxProcs, *cErrCodes = MPI_ERRCODES_IGNORE; - ompi_java_getIntArray(env, maxProcs, &jMaxProcs, &cMaxProcs); - - if(errCodes != NULL) - ompi_java_getIntArray(env, errCodes, &jErrCodes, &cErrCodes); - - int commandsLength = (*env)->GetArrayLength(env, jCommands), - infoLength = (*env)->GetArrayLength(env, info); - - char **commands = calloc(commandsLength, sizeof(char*)), - ***argv = MPI_ARGVS_NULL; - MPI_Info *cInfo = calloc(infoLength, sizeof(MPI_Info)); - - for(i = 0; i < infoLength; i++) - cInfo[i] = (MPI_Info)jInfo[i]; - - for(i = 0; i < commandsLength; i++) - { - jstring a = (*env)->GetObjectArrayElement(env, jCommands, i); - commands[i] = (char*)(*env)->GetStringUTFChars(env, a, NULL); - (*env)->DeleteLocalRef(env, a); - } - - if(jArgv != NULL) - { - int argvLength = (*env)->GetArrayLength(env, jArgv); - argv = calloc(argvLength, sizeof(char**)); - - for(i = 0; i < argvLength; i++) - { - jobjectArray arr = (*env)->GetObjectArrayElement(env, jArgv, i); - int j, length = (*env)->GetArrayLength(env, arr); - argv[i] = calloc(length + 1, sizeof(char*)); - - for(j = 0; j < length; j++) - { - jstring a = (*env)->GetObjectArrayElement(env, arr, j); - argv[i][j] = (char*)(*env)->GetStringUTFChars(env, a, NULL); - (*env)->DeleteLocalRef(env, a); - } - - argv[i][length] = NULL; - (*env)->DeleteLocalRef(env, arr); - } - } - - rc = MPI_Comm_spawn_multiple( - commandsLength, commands, argv, cMaxProcs, cInfo, - root, (MPI_Comm)comm, &intercomm, cErrCodes); - - ompi_java_exceptionCheck(env, rc); - - if(jArgv != NULL) - { - int argvLength = (*env)->GetArrayLength(env, jArgv); - - for(i = 0; i < argvLength; i++) - { - jobjectArray arr = (*env)->GetObjectArrayElement(env, jArgv, i); - int j, length = (*env)->GetArrayLength(env, arr); - - for(j = 0; j < length; j++) - { - jstring a = (*env)->GetObjectArrayElement(env, arr, j); - (*env)->ReleaseStringUTFChars(env, a, argv[i][j]); - (*env)->DeleteLocalRef(env, a); - } - - (*env)->DeleteLocalRef(env, arr); - free(argv[i]); - } - - free(argv); - } - - for(i = 0; i < commandsLength; i++) - { - jstring a = (*env)->GetObjectArrayElement(env, jCommands, i); - (*env)->ReleaseStringUTFChars(env, a, commands[i]); - (*env)->DeleteLocalRef(env, a); - } - - if(errCodes != NULL) - ompi_java_releaseIntArray(env, errCodes, jErrCodes, cErrCodes); - - free(cInfo); - free(commands); - (*env)->ReleaseLongArrayElements(env, info, jInfo, JNI_ABORT); - ompi_java_forgetIntArray(env, maxProcs, jMaxProcs, cMaxProcs); - return (jlong)intercomm; -} diff --git a/ompi/mpi/java/c/mpi_MPI.c b/ompi/mpi/java/c/mpi_MPI.c deleted file mode 100644 index f596411c05d..00000000000 --- a/ompi/mpi/java/c/mpi_MPI.c +++ /dev/null @@ -1,1352 +0,0 @@ -/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015-2016 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2015-2016 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2015 Intel, Inc. All rights reserved. - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2016-2017 IBM Corporation. All rights reserved. - * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_MPI.c - * Headerfile : mpi_MPI.h - * Author : SungHoon Ko, Xinying Li (contributions from MAEDA Atusi) - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.17 $ - * Updated : $Date: 2003/01/17 01:50:37 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_DLFCN_H -#include -#endif -#include -#ifdef HAVE_LIBGEN_H -#include -#endif - -#include "opal/util/output.h" -#include "opal/datatype/opal_convertor.h" -#include "opal/mca/base/mca_base_var.h" - -#include "mpi.h" -#include "ompi/errhandler/errcode.h" -#include "ompi/errhandler/errcode-internal.h" -#include "ompi/datatype/ompi_datatype.h" -#include "mpi_MPI.h" -#include "mpiJava.h" - -ompi_java_globals_t ompi_java = {0}; -int ompi_mpi_java_eager = 65536; -opal_free_list_t ompi_java_buffers = {{{0}}}; - -static void bufferConstructor(ompi_java_buffer_t *item) -{ - item->buffer = malloc(ompi_mpi_java_eager); -} - -static void bufferDestructor(ompi_java_buffer_t *item) -{ - free(item->buffer); -} - -OBJ_CLASS_INSTANCE(ompi_java_buffer_t, - opal_free_list_item_t, - bufferConstructor, - bufferDestructor); - -/* - * Class: mpi_MPI - * Method: loadGlobalLibraries - * - */ -jint JNI_OnLoad(JavaVM *vm, void *reserved) -{ - // Ensure that PSM signal hijacking is disabled *before* loading - // the library (see comment in the function for more detail). - opal_init_psm(); - - return JNI_VERSION_1_6; -} - -static void initFreeList(void) -{ - OBJ_CONSTRUCT(&ompi_java_buffers, opal_free_list_t); - - int r = opal_free_list_init(&ompi_java_buffers, - sizeof(ompi_java_buffer_t), - opal_cache_line_size, - OBJ_CLASS(ompi_java_buffer_t), - 0, /* payload size */ - 0, /* payload align */ - 2, /* initial elements to alloc */ - -1, /* max elements */ - 2, /* num elements per alloc */ - NULL, /* mpool */ - 0, /* mpool reg flags */ - NULL, /* unused0 */ - NULL, /* item_init */ - NULL /* inem_init context */); - if(r != OPAL_SUCCESS) - { - fprintf(stderr, "Unable to initialize ompi_java_buffers.\n"); - exit(1); - } -} - -static jclass findClass(JNIEnv *env, const char *className) -{ - jclass c = (*env)->FindClass(env, className), - r = (*env)->NewGlobalRef(env, c); - - (*env)->DeleteLocalRef(env, c); - return r; -} - -static void findClasses(JNIEnv *env) -{ - ompi_java.CartParmsClass = findClass(env, "mpi/CartParms"); - ompi_java.ShiftParmsClass = findClass(env, "mpi/ShiftParms"); - ompi_java.GraphParmsClass = findClass(env, "mpi/GraphParms"); - - ompi_java.DistGraphNeighborsClass = findClass( - env, "mpi/DistGraphNeighbors"); - - ompi_java.StatusClass = findClass(env, "mpi/Status"); - ompi_java.ExceptionClass = findClass(env, "mpi/MPIException"); - - ompi_java.ExceptionInit = (*env)->GetMethodID( - env, ompi_java.ExceptionClass, - "", "(IILjava/lang/String;)V"); - - ompi_java.IntegerClass = findClass(env, "java/lang/Integer"); - ompi_java.LongClass = findClass(env, "java/lang/Long"); - - ompi_java.IntegerValueOf = (*env)->GetStaticMethodID( - env, ompi_java.IntegerClass, "valueOf", "(I)Ljava/lang/Integer;"); - ompi_java.LongValueOf = (*env)->GetStaticMethodID( - env, ompi_java.LongClass, "valueOf", "(J)Ljava/lang/Long;"); -} - -static void deleteClasses(JNIEnv *env) -{ - (*env)->DeleteGlobalRef(env, ompi_java.CartParmsClass); - (*env)->DeleteGlobalRef(env, ompi_java.ShiftParmsClass); - (*env)->DeleteGlobalRef(env, ompi_java.VersionClass); - (*env)->DeleteGlobalRef(env, ompi_java.CountClass); - (*env)->DeleteGlobalRef(env, ompi_java.GraphParmsClass); - (*env)->DeleteGlobalRef(env, ompi_java.DistGraphNeighborsClass); - (*env)->DeleteGlobalRef(env, ompi_java.StatusClass); - (*env)->DeleteGlobalRef(env, ompi_java.ExceptionClass); - (*env)->DeleteGlobalRef(env, ompi_java.IntegerClass); - (*env)->DeleteGlobalRef(env, ompi_java.LongClass); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_newInt2(JNIEnv *env, jclass clazz) -{ - struct { int a; int b; } s; - int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a))); - jclass c = (*env)->FindClass(env, "mpi/Int2"); - jmethodID m = (*env)->GetMethodID(env, c, "", "(II)V"); - return (*env)->NewObject(env, c, m, iOff, sizeof(int)); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_newShortInt(JNIEnv *env, jclass clazz) -{ - struct { short a; int b; } s; - int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a))); - jclass c = (*env)->FindClass(env, "mpi/ShortInt"); - jmethodID m = (*env)->GetMethodID(env, c, "", "(III)V"); - return (*env)->NewObject(env, c, m, sizeof(short), iOff, sizeof(int)); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_newLongInt(JNIEnv *env, jclass clazz) -{ - struct { long a; int b; } s; - int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a))); - jclass c = (*env)->FindClass(env, "mpi/LongInt"); - jmethodID m = (*env)->GetMethodID(env, c, "", "(III)V"); - return (*env)->NewObject(env, c, m, sizeof(long), iOff, sizeof(int)); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_newFloatInt(JNIEnv *env, jclass clazz) -{ - struct { float a; int b; } s; - int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a))); - jclass c = (*env)->FindClass(env, "mpi/FloatInt"); - jmethodID m = (*env)->GetMethodID(env, c, "", "(II)V"); - return (*env)->NewObject(env, c, m, iOff, sizeof(int)); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_newDoubleInt(JNIEnv *env, jclass clazz) -{ - struct { double a; int b; } s; - int iOff = (int)((MPI_Aint)(&(s.b)) - (MPI_Aint)(&(s.a))); - jclass c = (*env)->FindClass(env, "mpi/DoubleInt"); - jmethodID m = (*env)->GetMethodID(env, c, "", "(II)V"); - return (*env)->NewObject(env, c, m, iOff, sizeof(int)); -} - -JNIEXPORT void JNICALL Java_mpi_MPI_initVersion(JNIEnv *env, jclass jthis) -{ - ompi_java.VersionClass = findClass(env, "mpi/Version"); - ompi_java.VersionInit = (*env)->GetMethodID(env, ompi_java.VersionClass, "", "(II)V"); -} - -JNIEXPORT jobjectArray JNICALL Java_mpi_MPI_Init_1jni( - JNIEnv *env, jclass clazz, jobjectArray argv) -{ - jsize i; - jclass string; - jobject value; - - int len = (*env)->GetArrayLength(env, argv); - char **sargs = (char**)calloc(len+1, sizeof(char*)); - - for(i = 0; i < len; i++) - { - jstring jc = (jstring)(*env)->GetObjectArrayElement(env, argv, i); - const char *s = (*env)->GetStringUTFChars(env, jc, NULL); - sargs[i] = strdup(s); - (*env)->ReleaseStringUTFChars(env, jc, s); - (*env)->DeleteLocalRef(env, jc); - } - - int rc = MPI_Init(&len, &sargs); - - if(ompi_java_exceptionCheck(env, rc)) { - for(i = 0; i < len; i++) - free (sargs[i]); - free(sargs); - return NULL; - } - - mca_base_var_register("ompi", "mpi", "java", "eager", - "Java buffers eager size", - MCA_BASE_VAR_TYPE_INT, NULL, 0, 0, - OPAL_INFO_LVL_5, - MCA_BASE_VAR_SCOPE_READONLY, - &ompi_mpi_java_eager); - - string = (*env)->FindClass(env, "java/lang/String"); - value = (*env)->NewObjectArray(env, len, string, NULL); - - for(i = 0; i < len; i++) - { - jstring jc = (*env)->NewStringUTF(env, sargs[i]); - (*env)->SetObjectArrayElement(env, value, i, jc); - (*env)->DeleteLocalRef(env, jc); - free (sargs[i]); - } - - free (sargs); - - findClasses(env); - initFreeList(); - return value; -} - -JNIEXPORT jint JNICALL Java_mpi_MPI_InitThread_1jni( - JNIEnv *env, jclass clazz, jobjectArray argv, jint required) -{ - jsize i; - int len = (*env)->GetArrayLength(env,argv); - char **sargs = (char**)calloc(len+1, sizeof(char*)); - - for(i = 0; i < len; i++) - { - jstring jc = (jstring)(*env)->GetObjectArrayElement(env, argv, i); - const char *s = (*env)->GetStringUTFChars(env, jc, 0); - sargs[i] = strdup(s); - (*env)->ReleaseStringUTFChars(env, jc, s); - (*env)->DeleteLocalRef(env, jc); - } - - int provided; - int rc = MPI_Init_thread(&len, &sargs, required, &provided); - - if(ompi_java_exceptionCheck(env, rc)) { - for(i = 0; i < len; i++) - free (sargs[i]); - free(sargs); - return -1; - } - - findClasses(env); - initFreeList(); - return provided; -} - -JNIEXPORT jint JNICALL Java_mpi_MPI_queryThread_1jni(JNIEnv *env, jclass clazz) -{ - int provided; - int rc = MPI_Query_thread(&provided); - ompi_java_exceptionCheck(env, rc); - return provided; -} - -JNIEXPORT jboolean JNICALL Java_mpi_MPI_isThreadMain_1jni( - JNIEnv *env, jclass clazz) -{ - int flag; - int rc = MPI_Is_thread_main(&flag); - ompi_java_exceptionCheck(env, rc); - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT void JNICALL Java_mpi_MPI_Finalize_1jni(JNIEnv *env, jclass obj) -{ - OBJ_DESTRUCT(&ompi_java_buffers); - int rc = MPI_Finalize(); - ompi_java_exceptionCheck(env, rc); - deleteClasses(env); -} - -JNIEXPORT jobject JNICALL Java_mpi_MPI_getVersionJNI(JNIEnv *env, jclass jthis) -{ - int version, subversion; - int rc = MPI_Get_version(&version, &subversion); - ompi_java_exceptionCheck(env, rc); - - return (*env)->NewObject(env, ompi_java.VersionClass, - ompi_java.VersionInit, version, subversion); -} - -JNIEXPORT jstring JNICALL Java_mpi_MPI_getLibVersionJNI(JNIEnv *env, jclass jthis) -{ - int length; - char version[MPI_MAX_LIBRARY_VERSION_STRING]; - int rc = MPI_Get_library_version(version, &length); - ompi_java_exceptionCheck(env, rc); - - return (*env)->NewStringUTF(env, version); -} - -JNIEXPORT jint JNICALL Java_mpi_MPI_getProcessorName( - JNIEnv *env, jclass obj, jbyteArray buf) -{ - int len; - jbyte* bufc = (jbyte*)((*env)->GetByteArrayElements(env, buf, NULL)); - int rc = MPI_Get_processor_name((char*)bufc, &len); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseByteArrayElements(env, buf, bufc, 0); - return len; -} - -JNIEXPORT jdouble JNICALL Java_mpi_MPI_wtime_1jni(JNIEnv *env, jclass jthis) -{ - return MPI_Wtime(); -} - -JNIEXPORT jdouble JNICALL Java_mpi_MPI_wtick_1jni(JNIEnv *env, jclass jthis) -{ - return MPI_Wtick(); -} - -JNIEXPORT jboolean JNICALL Java_mpi_MPI_isInitialized(JNIEnv *env, jclass jthis) -{ - int flag; - int rc = MPI_Initialized(&flag); - ompi_java_exceptionCheck(env, rc); - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT jboolean JNICALL Java_mpi_MPI_isFinalized(JNIEnv *env, jclass jthis) -{ - int flag; - int rc = MPI_Finalized(&flag); - ompi_java_exceptionCheck(env, rc); - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT void JNICALL Java_mpi_MPI_attachBuffer_1jni( - JNIEnv *env, jclass jthis, jbyteArray buf) -{ - int size=(*env)->GetArrayLength(env,buf); - jbyte* bufptr = (*env)->GetByteArrayElements(env, buf, NULL); - int rc = MPI_Buffer_attach(bufptr,size); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_MPI_detachBuffer_1jni( - JNIEnv *env, jclass jthis, jbyteArray buf) -{ - int size; - jbyte* bufptr; - int rc = MPI_Buffer_detach(&bufptr, &size); - ompi_java_exceptionCheck(env, rc); - - if(buf != NULL) - (*env)->ReleaseByteArrayElements(env,buf,bufptr,0); -} - -void* ompi_java_getArrayCritical(void** bufBase, JNIEnv *env, - jobject buf, int offset) -{ - *bufBase = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, buf, NULL); - return ((jbyte*)*bufBase) + offset; -} - -void* ompi_java_getDirectBufferAddress(JNIEnv *env, jobject buf) -{ - /* Allow NULL buffers to send/recv 0 items as control messages. */ - return buf == NULL ? NULL : (*env)->GetDirectBufferAddress(env, buf); -} - -static int getTypeExtent(JNIEnv *env, MPI_Datatype type) -{ - MPI_Aint lb, extent; - int rc = MPI_Type_get_extent(type, &lb, &extent); - ompi_java_exceptionCheck(env, rc); - int value = extent; - assert(((MPI_Aint)value) == extent); - return value; -} - -static void getArrayRegion(JNIEnv *env, jobject buf, int baseType, - int offset, int length, void *ptr) -{ - switch(baseType) - { - case 0: - break; - case 1: - (*env)->GetByteArrayRegion(env, buf, offset, length, ptr); - break; - case 2: - (*env)->GetCharArrayRegion(env, buf, offset / 2, length / 2, ptr); - break; - case 3: - (*env)->GetShortArrayRegion(env, buf, offset / 2, length / 2, ptr); - break; - case 4: - (*env)->GetBooleanArrayRegion(env, buf, offset, length, ptr); - break; - case 5: - (*env)->GetIntArrayRegion(env, buf, offset / 4, length / 4, ptr); - break; - case 6: - (*env)->GetLongArrayRegion(env, buf, offset / 8, length / 8, ptr); - break; - case 7: - (*env)->GetFloatArrayRegion(env, buf, offset / 4, length / 4, ptr); - break; - case 8: - (*env)->GetDoubleArrayRegion(env, buf, offset / 8, length / 8, ptr); - break; - case 9: - (*env)->GetByteArrayRegion(env, buf, offset, length, ptr); - break; - default: - assert(0); - } -} - -static void setArrayRegion(JNIEnv *env, jobject buf, int baseType, - int offset, int length, void *ptr) -{ - switch(baseType) - { - case 0: - break; - case 1: - (*env)->SetByteArrayRegion(env, buf, offset, length, ptr); - break; - case 2: - (*env)->SetCharArrayRegion(env, buf, offset / 2, length / 2, ptr); - break; - case 3: - (*env)->SetShortArrayRegion(env, buf, offset / 2, length / 2, ptr); - break; - case 4: - (*env)->SetBooleanArrayRegion(env, buf, offset, length, ptr); - break; - case 5: - (*env)->SetIntArrayRegion(env, buf, offset / 4, length / 4, ptr); - break; - case 6: - (*env)->SetLongArrayRegion(env, buf, offset / 8, length / 8, ptr); - break; - case 7: - (*env)->SetFloatArrayRegion(env, buf, offset / 4, length / 4, ptr); - break; - case 8: - (*env)->SetDoubleArrayRegion(env, buf, offset / 8, length / 8, ptr); - break; - case 9: - (*env)->SetByteArrayRegion(env, buf, offset, length, ptr); - break; - default: - assert(0); - } -} - -static void* getBuffer(JNIEnv *env, ompi_java_buffer_t **item, int size) -{ - if(size > ompi_mpi_java_eager) - { - *item = NULL; - return malloc(size); - } - else - { - opal_free_list_item_t *freeListItem; - freeListItem = opal_free_list_get (&ompi_java_buffers); - - ompi_java_exceptionCheck(env, NULL == freeListItem ? MPI_ERR_NO_MEM : - MPI_SUCCESS); - if (NULL == freeListItem) { - return NULL; - } - - *item = (ompi_java_buffer_t*)freeListItem; - return (*item)->buffer; - } -} - -static void releaseBuffer(void *ptr, ompi_java_buffer_t *item) -{ - if(item == NULL) - { - free(ptr); - } - else - { - assert(item->buffer == ptr); - opal_free_list_return (&ompi_java_buffers, (opal_free_list_item_t*)item); - } -} - -static int getCountv(int *counts, int *displs, int size) -{ - /* Maybe displs is not ordered. */ - int i, max = 0; - - for(i = 1; i < size; i++) - { - if(displs[max] < displs[i]) - max = i; - } - - return displs[max] * counts[max]; -} - -static void* getReadPtr(ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - int offset, int count, MPI_Datatype type, int baseType) -{ - int length = count * getTypeExtent(env, type); - void *ptr = getBuffer(env, item, length); - - if(opal_datatype_is_contiguous_memory_layout(&type->super, count)) - { - getArrayRegion(env, buf, baseType, offset, length, ptr); - } - else - { - void *inBuf, *inBase; - inBuf = ompi_java_getArrayCritical(&inBase, env, buf, offset); - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, count, ptr, inBuf); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, JNI_ABORT); - } - - return ptr; -} - -static void* getReadPtrRank( - ompi_java_buffer_t **item, JNIEnv *env, jobject buf, int offset, - int count, int size, int rank, MPI_Datatype type, int baseType) -{ - int extent = getTypeExtent(env, type), - rLen = extent * count, - length = rLen * size, - rDispl = rLen * rank, - rOff = offset + rDispl; - void *ptr = getBuffer(env, item, length); - void *rPtr = (char*)ptr + rDispl; - - if(opal_datatype_is_contiguous_memory_layout(&type->super, count)) - { - getArrayRegion(env, buf, baseType, rOff, rLen, rPtr); - } - else - { - void *bufPtr, *bufBase; - bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, rOff); - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, count, rPtr, bufPtr); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, JNI_ABORT); - } - - return ptr; -} - -static void* getReadPtrvRank( - ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - int offset, int *counts, int *displs, int size, - int rank, MPI_Datatype type, int baseType) -{ - int extent = getTypeExtent(env, type), - length = extent * getCountv(counts, displs, size); - void *ptr = getBuffer(env, item, length); - int rootOff = offset + extent * displs[rank]; - - if(opal_datatype_is_contiguous_memory_layout(&type->super, counts[rank])) - { - int rootLength = extent * counts[rank]; - void *rootPtr = (char*)ptr + extent * displs[rank]; - getArrayRegion(env, buf, baseType, rootOff, rootLength, rootPtr); - } - else - { - void *inBuf, *inBase; - inBuf = ompi_java_getArrayCritical(&inBase, env, buf, rootOff); - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, counts[rank], ptr, inBuf); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, JNI_ABORT); - } - - return ptr; -} - -static void* getReadPtrwRank( - ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - int *offsets, int *counts, int *displs, int size, - int rank, MPI_Datatype *types, int *baseTypes) -{ - int extent = getTypeExtent(env, types[rank]), - length = getCountv(counts, displs, size); - void *ptr = getBuffer(env, item, length); - int rootOff = offsets[rank] + displs[rank]; - - if(opal_datatype_is_contiguous_memory_layout(&types[rank]->super, counts[rank])) - { - int rootLength = extent * counts[rank]; - void *rootPtr = (char*)ptr + displs[rank]; - getArrayRegion(env, buf, baseTypes[rank], rootOff, rootLength, rootPtr); - } - else - { - void *inBuf, *inBase; - inBuf = ompi_java_getArrayCritical(&inBase, env, buf, rootOff); - - int rc = opal_datatype_copy_content_same_ddt( - &types[rank]->super, counts[rank], ptr, inBuf); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, JNI_ABORT); - } - - return ptr; -} - -static void* getReadPtrvAll( - ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - int offset, int *counts, int *displs, int size, - MPI_Datatype type, int baseType) -{ - int i, - extent = getTypeExtent(env, type), - length = extent * getCountv(counts, displs, size); - void *ptr = getBuffer(env, item, length); - - if(opal_datatype_is_contiguous_memory_layout(&type->super, 2)) - { - for(i = 0; i < size; i++) - { - int iOff = offset + extent * displs[i], - iLen = extent * counts[i]; - void *iPtr = (char*)ptr + extent * displs[i]; - getArrayRegion(env, buf, baseType, iOff, iLen, iPtr); - } - } - else - { - void *bufPtr, *bufBase; - bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offset); - - for(i = 0; i < size; i++) - { - int iOff = extent * displs[i]; - char *iBuf = iOff + (char*)bufPtr, - *iPtr = iOff + (char*)ptr; - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, counts[i], iPtr, iBuf); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - } - - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, JNI_ABORT); - } - - return ptr; -} - -static void* getReadPtrwAll( - ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - int *offsets, int *counts, int *displs, int size, - MPI_Datatype *types, int *baseTypes) -{ - - int length = getCountv(counts, displs, size); - void *ptr = getBuffer(env, item, length); - - for(int i = 0; i < size; i++) - { - int extent = getTypeExtent(env, types[i]); - - if(opal_datatype_is_contiguous_memory_layout(&types[i]->super, 2)) - { - int iOff = offsets[i] + displs[i], - iLen = extent * counts[i]; - void *iPtr = (char*)ptr + displs[i]; - getArrayRegion(env, buf, baseTypes[i], iOff, iLen, iPtr); - } - else - { - void *bufPtr, *bufBase; - bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offsets[i]); - - int iOff = displs[i]; - char *iBuf = iOff + (char*)bufPtr, - *iPtr = iOff + (char*)ptr; - - int rc = opal_datatype_copy_content_same_ddt( - &types[i]->super, counts[i], iPtr, iBuf); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, JNI_ABORT); - } - - } - - return ptr; -} - -static void* getWritePtr(ompi_java_buffer_t **item, JNIEnv *env, - int count, MPI_Datatype type) -{ - int extent = getTypeExtent(env, type), - length = count * extent; - - return getBuffer(env, item, length); -} - -static void* getWritePtrv(ompi_java_buffer_t **item, JNIEnv *env, - int *counts, int *displs, int size, MPI_Datatype type) -{ - int extent = getTypeExtent(env, type), - count = getCountv(counts, displs, size), - length = extent * count; - - return getBuffer(env, item, length); -} - -static void* getWritePtrw(ompi_java_buffer_t **item, JNIEnv *env, - int *counts, int *displs, int size, MPI_Datatype *types) -{ - int length = getCountv(counts, displs, size); - - return getBuffer(env, item, length); -} - -void ompi_java_getReadPtr( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int offset, int count, MPI_Datatype type, int baseType) -{ - if(buf == NULL || baseType == 0) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - assert(offset == 0); - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else - { - *ptr = getReadPtr(item, env, buf, offset, count, type, baseType); - } -} - -void ompi_java_getReadPtrRank( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int offset, int count, int size, - int rank, MPI_Datatype type, int baseType) -{ - if(buf == NULL || baseType == 0) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - assert(offset == 0); - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else - { - *ptr = getReadPtrRank(item, env, buf, offset, count, - size, rank, type, baseType); - } -} - -void ompi_java_getReadPtrv( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int offset, int *counts, int *displs, - int size, int rank, MPI_Datatype type, int baseType) -{ - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - assert(offset == 0); - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else if(rank == -1) - { - *ptr = getReadPtrvAll(item, env, buf, offset, counts, - displs, size, type, baseType); - } - else - { - *ptr = getReadPtrvRank(item, env, buf, offset, counts, - displs, size, rank, type, baseType); - } -} - -void ompi_java_getReadPtrw( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int *offsets, int *counts, int *displs, - int size, int rank, MPI_Datatype *types, int *baseTypes) -{ - int i; - - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - for(i = 0; i < size; i++){ - assert(offsets[i] == 0); - } - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else if(rank == -1) - { - *ptr = getReadPtrwAll(item, env, buf, offsets, counts, - displs, size, types, baseTypes); - } - else - { - *ptr = getReadPtrwRank(item, env, buf, offsets, counts, - displs, size, rank, types, baseTypes); - } -} - -void ompi_java_releaseReadPtr( - void *ptr, ompi_java_buffer_t *item, jobject buf, jboolean db) -{ - if(!db && buf && ptr) - releaseBuffer(ptr, item); -} - -void ompi_java_getWritePtr( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, - jobject buf, jboolean db, int count, MPI_Datatype type) -{ - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else - { - *ptr = getWritePtr(item, env, count, type); - } -} - -void ompi_java_getWritePtrv( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int *counts, int *displs, int size, MPI_Datatype type) -{ - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else - { - *ptr = getWritePtrv(item, env, counts, displs, size, type); - } -} - -void ompi_java_getWritePtrw( - void **ptr, ompi_java_buffer_t **item, JNIEnv *env, jobject buf, - jboolean db, int *counts, int *displs, int size, MPI_Datatype *types) -{ - if(buf == NULL) - { - /* Allow NULL buffers to send/recv 0 items as control messages. */ - *ptr = NULL; - *item = NULL; - } - else if(db) - { - *ptr = (*env)->GetDirectBufferAddress(env, buf); - *item = NULL; - } - else - { - *ptr = getWritePtrw(item, env, counts, displs, size, types); - } -} - -void ompi_java_releaseWritePtr( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, jobject buf, - jboolean db, int offset, int count, MPI_Datatype type, int baseType) -{ - if(db || !buf || !ptr) - return; - - if(opal_datatype_is_contiguous_memory_layout(&type->super, count)) - { - int length = count * getTypeExtent(env, type); - setArrayRegion(env, buf, baseType, offset, length, ptr); - } - else - { - void *inBuf, *inBase; - inBuf = ompi_java_getArrayCritical(&inBase, env, buf, offset); - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, count, inBuf, ptr); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, inBase, 0); - } - - releaseBuffer(ptr, item); -} - -void ompi_java_releaseWritePtrv( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, - jobject buf, jboolean db, int offset, int *counts, int *displs, - int size, MPI_Datatype type, int baseType) -{ - if(db || !buf || !ptr) - return; - - int i; - int extent = getTypeExtent(env, type); - - if(opal_datatype_is_contiguous_memory_layout(&type->super, 2)) - { - for(i = 0; i < size; i++) - { - int iOff = offset + extent * displs[i], - iLen = extent * counts[i]; - void *iPtr = (char*)ptr + extent * displs[i]; - setArrayRegion(env, buf, baseType, iOff, iLen, iPtr); - } - } - else - { - void *bufPtr, *bufBase; - bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offset); - - for(i = 0; i < size; i++) - { - int iOff = extent * displs[i]; - char *iBuf = iOff + (char*)bufPtr, - *iPtr = iOff + (char*)ptr; - - int rc = opal_datatype_copy_content_same_ddt( - &type->super, counts[i], iBuf, iPtr); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - } - - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, 0); - } - - releaseBuffer(ptr, item); -} - -void ompi_java_releaseWritePtrw( - void *ptr, ompi_java_buffer_t *item, JNIEnv *env, - jobject buf, jboolean db, int *offsets, int *counts, int *displs, - int size, MPI_Datatype *types, int *baseTypes) -{ - if(db || !buf || !ptr) - return; - - int i; - - for(i = 0; i < size; i++) - { - int extent = getTypeExtent(env, types[i]); - - if(opal_datatype_is_contiguous_memory_layout(&types[i]->super, 2)) - { - int iOff = offsets[i] + displs[i], - iLen = extent * counts[i]; - void *iPtr = (char*)ptr + displs[i]; - setArrayRegion(env, buf, baseTypes[i], iOff, iLen, iPtr); - } - else - { - void *bufPtr, *bufBase; - - bufPtr = ompi_java_getArrayCritical(&bufBase, env, buf, offsets[i]); - int iOff = displs[i]; - char *iBuf = iOff + (char*)bufPtr, - *iPtr = iOff + (char*)ptr; - - int rc = opal_datatype_copy_content_same_ddt( - &types[i]->super, counts[i], iBuf, iPtr); - - ompi_java_exceptionCheck(env, - rc==OPAL_SUCCESS ? OMPI_SUCCESS : OMPI_ERROR); - - (*env)->ReleasePrimitiveArrayCritical(env, buf, bufBase, 0); - } - - } - releaseBuffer(ptr, item); -} - -jobject ompi_java_Integer_valueOf(JNIEnv *env, jint i) -{ - return (*env)->CallStaticObjectMethod(env, - ompi_java.IntegerClass, ompi_java.IntegerValueOf, i); -} - -jobject ompi_java_Long_valueOf(JNIEnv *env, jlong i) -{ - return (*env)->CallStaticObjectMethod(env, - ompi_java.LongClass, ompi_java.LongValueOf, i); -} - -void ompi_java_getIntArray(JNIEnv *env, jintArray array, - jint **jptr, int **cptr) -{ - jint *jInts = (*env)->GetIntArrayElements(env, array, NULL); - *jptr = jInts; - - if(sizeof(int) == sizeof(jint)) - { - *cptr = (int*)jInts; - } - else - { - int i, length = (*env)->GetArrayLength(env, array); - int *cInts = calloc(length, sizeof(int)); - - for(i = 0; i < length; i++) - cInts[i] = jInts[i]; - - *cptr = cInts; - } -} - -void ompi_java_releaseIntArray(JNIEnv *env, jintArray array, - jint *jptr, int *cptr) -{ - if(jptr != cptr) - { - int i, length = (*env)->GetArrayLength(env, array); - - for(i = 0; i < length; i++) - jptr[i] = cptr[i]; - - free(cptr); - } - - (*env)->ReleaseIntArrayElements(env, array, jptr, 0); -} - -void ompi_java_forgetIntArray(JNIEnv *env, jintArray array, - jint *jptr, int *cptr) -{ - if(jptr != cptr) - free(cptr); - - (*env)->ReleaseIntArrayElements(env, array, jptr, JNI_ABORT); -} - -void ompi_java_getDatatypeArray(JNIEnv *env, jlongArray array, - jlong **jptr, MPI_Datatype **cptr) -{ - jlong *jLongs = (*env)->GetLongArrayElements(env, array, NULL); - *jptr = jLongs; - - int i, length = (*env)->GetArrayLength(env, array); - MPI_Datatype *cDatatypes = calloc(length, sizeof(MPI_Datatype)); - - for(i = 0; i < length; i++){ - cDatatypes[i] = (MPI_Datatype)jLongs[i]; - } - *cptr = cDatatypes; -} - -void ompi_java_forgetDatatypeArray(JNIEnv *env, jlongArray array, - jlong *jptr, MPI_Datatype *cptr) -{ - if((long)jptr != (long)cptr) - free(cptr); - - (*env)->ReleaseLongArrayElements(env, array, jptr, JNI_ABORT); -} - -void ompi_java_getBooleanArray(JNIEnv *env, jbooleanArray array, - jboolean **jptr, int **cptr) -{ - int i, length = (*env)->GetArrayLength(env, array); - jboolean *jb = (*env)->GetBooleanArrayElements(env, array, NULL); - int *cb = (int*)calloc(length, sizeof(int)); - - for(i = 0; i < length; i++) - cb[i] = jb[i]; - - *jptr = jb; - *cptr = cb; -} - -void ompi_java_releaseBooleanArray(JNIEnv *env, jbooleanArray array, - jboolean *jptr, int *cptr) -{ - int i, length = (*env)->GetArrayLength(env, array); - - for(i = 0; i < length; i++) - jptr[i] = cptr[i] ? JNI_TRUE : JNI_FALSE; - - free(cptr); - (*env)->ReleaseBooleanArrayElements(env, array, jptr, 0); -} - -void ompi_java_forgetBooleanArray(JNIEnv *env, jbooleanArray array, - jboolean *jptr, int *cptr) -{ - free(cptr); - (*env)->ReleaseBooleanArrayElements(env, array, jptr, JNI_ABORT); -} - -void ompi_java_getPtrArray(JNIEnv *env, jlongArray array, - jlong **jptr, void ***cptr) -{ - jlong *jp = *jptr = (*env)->GetLongArrayElements(env, array, NULL); - - if(sizeof(jlong) == sizeof(void*)) - { - *cptr = (void**)jp; - } - else - { - int i, length = (*env)->GetArrayLength(env, array); - void **cp = *cptr = calloc(length, sizeof(void*)); - - for(i = 0; i < length; i++) - cp[i] = (void*)jp[i]; - } -} - -void ompi_java_releasePtrArray(JNIEnv *env, jlongArray array, - jlong *jptr, void **cptr) -{ - if(jptr != (jlong*)cptr) - { - int i, length = (*env)->GetArrayLength(env, array); - - for(i = 0; i < length; i++) - jptr[i] = (jlong)cptr[i]; - - free(cptr); - } - - (*env)->ReleaseLongArrayElements(env, array, jptr, 0); -} - -/* This method checks whether an MPI or JNI exception has occurred. - * If an exception occurs, the C code will continue running. Once - * code execution returns to Java code, an exception is immediately - * thrown. Since an exception has occurred somewhere in the C code, - * the object that is returned from C may not be valid. This is not - * an issue, however, as the assignment operation will not be - * executed. The results of this method need not be checked if the - * only following code cleans up memory and then returns to Java. - * If existing objects are changed after a call to this method, the - * results need to be checked and, if an error has occurred, the - * code should instead cleanup any memory and return. - */ -jboolean ompi_java_exceptionCheck(JNIEnv *env, int rc) -{ - jboolean jni_exception; - - if (rc < 0) { - /* handle ompi error code */ - rc = ompi_errcode_get_mpi_code (rc); - /* ompi_mpi_errcode_get_class CAN NOT handle negative error codes. - * all Open MPI MPI error codes should be > 0. */ - assert (rc >= 0); - } - jni_exception = (*env)->ExceptionCheck(env); - - if(MPI_SUCCESS == rc && JNI_FALSE == jni_exception) - { - return JNI_FALSE; - } - else if(MPI_SUCCESS != rc) - { - int errClass = ompi_mpi_errcode_get_class(rc); - char *message = ompi_mpi_errnum_get_string(rc); - jstring jmessage = (*env)->NewStringUTF(env, (const char*)message); - - jobject mpiex = (*env)->NewObject(env, ompi_java.ExceptionClass, - ompi_java.ExceptionInit, - rc, errClass, jmessage); - (*env)->Throw(env, mpiex); - (*env)->DeleteLocalRef(env, mpiex); - (*env)->DeleteLocalRef(env, jmessage); - return JNI_TRUE; - } - /* If we get here, a JNI error has occurred. */ - return JNI_TRUE; -} - -void* ompi_java_attrSet(JNIEnv *env, jbyteArray jval) -{ - int length = (*env)->GetArrayLength(env, jval); - void *cval = malloc(sizeof(int) + length); - *((int*)cval) = length; - - (*env)->GetByteArrayRegion(env, jval, - 0, length, (jbyte*)cval + sizeof(int)); - - return cval; -} - -jbyteArray ompi_java_attrGet(JNIEnv *env, void *cval) -{ - int length = *((int*)cval); - jbyteArray jval = (*env)->NewByteArray(env, length); - - (*env)->SetByteArrayRegion(env, jval, - 0, length, (jbyte*)cval + sizeof(int)); - - return jval; -} - -int ompi_java_attrCopy(void *attrValIn, void *attrValOut, int *flag) -{ - int length = *((int*)attrValIn) + sizeof(int); - *((void**)attrValOut) = malloc(length); - memcpy(*((void**)attrValOut), attrValIn, length); - *flag = 1; - return MPI_SUCCESS; -} - -int ompi_java_attrDelete(void *attrVal) -{ - free(attrVal); - return MPI_SUCCESS; -} diff --git a/ompi/mpi/java/c/mpi_Message.c b/ompi/mpi/java/c/mpi_Message.c deleted file mode 100644 index b78dc782649..00000000000 --- a/ompi/mpi/java/c/mpi_Message.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Message.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_Message_init(JNIEnv *e, jclass c) -{ - ompi_java_setStaticLongField(e, c, "NULL", (jlong)MPI_MESSAGE_NULL); - ompi_java_setStaticLongField(e, c, "NO_PROC", (jlong)MPI_MESSAGE_NO_PROC); - ompi_java.MessageHandle = (*e)->GetFieldID(e, c, "handle", "J"); -} - -JNIEXPORT jlong JNICALL Java_mpi_Message_mProbe( - JNIEnv *env, jobject jthis, - jint source, jint tag, jlong jComm, jlongArray jStatus) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Message message; - MPI_Status status; - int rc = MPI_Mprobe(source, tag, comm, &message, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, jStatus, &status); - - return (jlong)message; -} - -JNIEXPORT jobject JNICALL Java_mpi_Message_imProbe( - JNIEnv *env, jobject jthis, jint source, jint tag, jlong jComm) -{ - MPI_Comm comm = (MPI_Comm)jComm; - MPI_Message message; - MPI_Status status; - int rc, flag; - rc = MPI_Improbe(source, tag, comm, &flag, &message, &status); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - return NULL; - - (*env)->SetLongField(env, jthis, ompi_java.MessageHandle, (jlong)message); - return ompi_java_status_new(env, &status); -} - -JNIEXPORT jlong JNICALL Java_mpi_Message_mRecv( - JNIEnv *env, jobject jthis, jlong jMessage, jobject buf, jboolean db, - jint off, jint count, jlong jType, jint bType, jlongArray jStatus) -{ - MPI_Message message = (MPI_Message)jMessage; - MPI_Datatype type = (MPI_Datatype)jType; - - void *ptr; - ompi_java_buffer_t *item; - ompi_java_getWritePtr(&ptr, &item, env, buf, db, count, type); - - MPI_Status status; - int rc = MPI_Mrecv(ptr, count, type, &message, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, jStatus, &status); - - ompi_java_releaseWritePtr(ptr, item, env, buf, db, off, count, type, bType); - return (jlong)message; -} - -JNIEXPORT jlong JNICALL Java_mpi_Message_imRecv( - JNIEnv *env, jobject jthis, jlong jMessage, - jobject buf, jint count, jlong jType) -{ - MPI_Message message = (MPI_Message)jMessage; - MPI_Datatype type = (MPI_Datatype)jType; - void *ptr = ompi_java_getDirectBufferAddress(env, buf); - - MPI_Request request; - int rc = MPI_Imrecv(ptr, count, type, &message, &request); - ompi_java_exceptionCheck(env, rc); - (*env)->SetLongField(env, jthis, ompi_java.MessageHandle, (jlong)message); - return (jlong)request; -} diff --git a/ompi/mpi/java/c/mpi_Op.c b/ompi/mpi/java/c/mpi_Op.c deleted file mode 100644 index 90d22fcaa96..00000000000 --- a/ompi/mpi/java/c/mpi_Op.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* - * File : mpi_Op.c - * Headerfile : mpi_Op.h - * Author : Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.7 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -#include "ompi_config.h" - -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Op.h" -#include "mpiJava.h" -#include "ompi/op/op.h" - -JNIEXPORT void JNICALL Java_mpi_Op_init(JNIEnv *env, jclass clazz) -{ - ompi_java.OpHandle = (*env)->GetFieldID(env, clazz, "handle", "J"); - ompi_java.OpCommute = (*env)->GetFieldID(env, clazz, "commute", "Z"); - - ompi_java.OpCall = (*env)->GetMethodID(env, clazz, "call", - "(Ljava/lang/Object;Ljava/lang/Object;I)V"); -} - -JNIEXPORT void JNICALL Java_mpi_Op_getOp(JNIEnv *env, jobject jthis, jint type) -{ - static MPI_Op Ops[] = { - MPI_OP_NULL, MPI_MAX, MPI_MIN, MPI_SUM, - MPI_PROD, MPI_LAND, MPI_BAND, MPI_LOR, MPI_BOR, MPI_LXOR, - MPI_BXOR, MPI_MINLOC, MPI_MAXLOC, MPI_REPLACE, MPI_NO_OP - }; - (*env)->SetLongField(env,jthis, ompi_java.OpHandle, (jlong)Ops[type]); -} - -static jobject setBooleanArray(JNIEnv *env, void *vec, int len) -{ - jobject obj = (*env)->NewBooleanArray(env, len); - - if(obj != NULL) - (*env)->SetBooleanArrayRegion(env, obj, 0, len, vec); - - return obj; -} - -static void getBooleanArray(JNIEnv *env, jobject obj, void *vec, int len) -{ - (*env)->GetBooleanArrayRegion(env, obj, 0, len, vec); -} - -static void opIntercept(void *invec, void *inoutvec, int *count, - MPI_Datatype *datatype, int baseType, - void *jnienv, void *object) -{ - JNIEnv *env = jnienv; - jobject jthis = object; - jobject jin, jio; - - MPI_Aint lb, extent; - int rc = MPI_Type_get_extent(*datatype, &lb, &extent); - - if(ompi_java_exceptionCheck(env, rc)) - return; - - int len = (*count) * extent; - - if(baseType == 4) - { - jin = setBooleanArray(env, invec, len); - jio = setBooleanArray(env, inoutvec, len); - } - else - { - jin = (*env)->NewDirectByteBuffer(env, invec, len); - jio = (*env)->NewDirectByteBuffer(env, inoutvec, len); - } - - if((*env)->ExceptionCheck(env)) - return; - - (*env)->CallVoidMethod(env, jthis, ompi_java.OpCall, jin, jio, *count); - - if(baseType == 4) - getBooleanArray(env, jio, inoutvec, len); - - (*env)->DeleteLocalRef(env, jin); - (*env)->DeleteLocalRef(env, jio); -} - -MPI_Op ompi_java_op_getHandle(JNIEnv *env, jobject jOp, jlong hOp, int baseType) -{ - MPI_Op op = (MPI_Op)hOp; - - if(op == NULL) - { - /* It is an uninitialized user Op. */ - int commute = (*env)->GetBooleanField( - env, jOp, ompi_java.OpCommute); - - int rc = MPI_Op_create((MPI_User_function*)opIntercept, commute, &op); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - (*env)->SetLongField(env, jOp, ompi_java.OpHandle, (jlong)op); - ompi_op_set_java_callback(op, env, jOp, baseType); - } - - return op; -} - -JNIEXPORT void JNICALL Java_mpi_Op_free(JNIEnv *env, jobject jthis) -{ - MPI_Op op = (MPI_Op)((*env)->GetLongField(env, jthis, ompi_java.OpHandle)); - - if(op != NULL && op != MPI_OP_NULL) - { - int rc = MPI_Op_free(&op); - ompi_java_exceptionCheck(env, rc); - ((*env)->SetLongField(env,jthis,ompi_java.OpHandle,(long)MPI_OP_NULL)); - } -} - -JNIEXPORT jboolean JNICALL Java_mpi_Op_isNull(JNIEnv *env, jobject jthis) -{ - MPI_Op op = (MPI_Op)((*env)->GetLongField(env, jthis, ompi_java.OpHandle)); - return op == NULL || op == MPI_OP_NULL ? JNI_TRUE : JNI_FALSE; -} diff --git a/ompi/mpi/java/c/mpi_Prequest.c b/ompi/mpi/java/c/mpi_Prequest.c deleted file mode 100644 index a036d45906e..00000000000 --- a/ompi/mpi/java/c/mpi_Prequest.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Prequest.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_Prequest_start( - JNIEnv *env, jobject jthis, jlong jRequest) -{ - MPI_Request request = (MPI_Request)jRequest; - int rc = MPI_Start(&request); - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Prequest_startAll( - JNIEnv *env, jclass clazz, jlongArray prequests) -{ - int count = (*env)->GetArrayLength(env, prequests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, prequests, &jReq, (void***)&cReq); - int rc = MPI_Startall(count, cReq); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, prequests, jReq, (void**)cReq); -} diff --git a/ompi/mpi/java/c/mpi_Request.c b/ompi/mpi/java/c/mpi_Request.c deleted file mode 100644 index 81e1d468167..00000000000 --- a/ompi/mpi/java/c/mpi_Request.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2016 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Request.c - * Headerfile : mpi_Request.h - * Author : Sung-Hoon Ko, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.11 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -#include "ompi_config.h" -#include -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Request.h" -#include "mpiJava.h" - -JNIEXPORT void JNICALL Java_mpi_Request_init(JNIEnv *env, jclass c) -{ - ompi_java.ReqHandle = (*env)->GetFieldID(env, c, "handle", "J"); -} - -static void setIndices(JNIEnv *env, jintArray indices, int *cIdx, int count) -{ - jint *jIdx; - - if(sizeof(int) == sizeof(jint)) - { - jIdx = cIdx; - } - else - { - jIdx = (jint*)calloc(count, sizeof(jint)); - int i; - - for(i = 0; i < count; i++) - jIdx[i] = cIdx[i]; - } - - (*env)->SetIntArrayRegion(env, indices, 0, count, jIdx); - - if(jIdx != cIdx) - free(jIdx); -} - -static jobjectArray newStatuses(JNIEnv *env, MPI_Status *statuses, int count) -{ - jobjectArray array = (*env)->NewObjectArray(env, - count, ompi_java.StatusClass, NULL); - int i; - for(i = 0; i < count; i++) - { - jobject st = ompi_java_status_new(env, statuses + i); - (*env)->SetObjectArrayElement(env, array, i, st); - (*env)->DeleteLocalRef(env, st); - } - - return array; -} - -static jobjectArray newStatusesIndices( - JNIEnv *env, MPI_Status *statuses, int *indices, int count) -{ - if(count < 0) - return NULL; - - jobjectArray array = (*env)->NewObjectArray(env, - count, ompi_java.StatusClass, NULL); - int i; - for(i = 0; i < count; i++) - { - jobject st = ompi_java_status_newIndex(env, statuses + i, indices[i]); - (*env)->SetObjectArrayElement(env, array, i, st); - (*env)->DeleteLocalRef(env, st); - } - - return array; -} - -JNIEXPORT jlong JNICALL Java_mpi_Request_getNull(JNIEnv *env, jclass clazz) -{ - return (jlong)MPI_REQUEST_NULL; -} - -JNIEXPORT void JNICALL Java_mpi_Request_cancel( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int rc = MPI_Cancel(&req); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Request_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int rc = MPI_Request_free(&req); - ompi_java_exceptionCheck(env, rc); - return (jlong)req; -} - -JNIEXPORT jlong JNICALL Java_mpi_Request_waitStatus( - JNIEnv *env, jobject jthis, jlong handle, jlongArray stat) -{ - MPI_Request req = (MPI_Request)handle; - MPI_Status status; - int rc = MPI_Wait(&req, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - ompi_java_status_set(env, stat, &status); - - return (jlong)req; -} - -JNIEXPORT jlong JNICALL Java_mpi_Request_waitFor( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int rc = MPI_Wait(&req, MPI_STATUS_IGNORE); - ompi_java_exceptionCheck(env, rc); - return (jlong)req; -} - -JNIEXPORT jobject JNICALL Java_mpi_Request_testStatus( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int flag; - MPI_Status status; - int rc = MPI_Test(&req, &flag, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - (*env)->SetLongField(env, jthis, ompi_java.ReqHandle, (jlong)req); - - return flag ? ompi_java_status_new(env, &status) : NULL; -} - -JNIEXPORT jobject JNICALL Java_mpi_Request_getStatus( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int flag; - MPI_Status status; - int rc = MPI_Request_get_status(req, &flag, &status); - - if(!ompi_java_exceptionCheck(env, rc)) - (*env)->SetLongField(env, jthis, ompi_java.ReqHandle, (jlong)req); - - return flag ? ompi_java_status_new(env, &status) : NULL; -} - -JNIEXPORT jboolean JNICALL Java_mpi_Request_test( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Request req = (MPI_Request)handle; - int flag; - int rc = MPI_Test(&req, &flag, MPI_STATUS_IGNORE); - - if(!ompi_java_exceptionCheck(env, rc)) - (*env)->SetLongField(env, jthis, ompi_java.ReqHandle, (jlong)req); - - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT void JNICALL Java_mpi_Request_waitAnyStatus( - JNIEnv *env, jclass clazz, jlongArray requests, jobject stat) -{ - jboolean exception; - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int index; - MPI_Status status; - int rc = MPI_Waitany(count, cReq, &index, &status); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - - if(!exception) - ompi_java_status_setIndex(env, stat, &status, index); -} - -JNIEXPORT jint JNICALL Java_mpi_Request_waitAny( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int index; - int rc = MPI_Waitany(count, cReq, &index, MPI_STATUS_IGNORE); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - return index; -} - -JNIEXPORT jobject JNICALL Java_mpi_Request_testAnyStatus( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int index, flag; - MPI_Status status; - int rc = MPI_Testany(count, cReq, &index, &flag, &status); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - return flag ? ompi_java_status_newIndex(env, &status, index) : NULL; -} - -JNIEXPORT jint JNICALL Java_mpi_Request_testAny( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int index, flag; - int rc = MPI_Testany(count, cReq, &index, &flag, MPI_STATUS_IGNORE); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - return index; -} - -JNIEXPORT jobjectArray JNICALL Java_mpi_Request_waitAllStatus( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - MPI_Status *statuses = (MPI_Status*)calloc(count, sizeof(MPI_Status)); - int rc = MPI_Waitall(count, cReq, statuses); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - jobjectArray jStatuses = newStatuses(env, statuses, count); - free(statuses); - return jStatuses; -} - -JNIEXPORT void JNICALL Java_mpi_Request_waitAll( - JNIEnv *env, jclass jthis, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int rc = MPI_Waitall(count, cReq, MPI_STATUSES_IGNORE); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); -} - -JNIEXPORT jobjectArray JNICALL Java_mpi_Request_testAllStatus( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - MPI_Status *statuses = (MPI_Status*)calloc(count, sizeof(MPI_Status)); - int flag; - int rc = MPI_Testall(count, cReq, &flag, statuses); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - jobjectArray jStatuses = flag ? newStatuses(env, statuses, count) : NULL; - free(statuses); - return jStatuses; -} - -JNIEXPORT jboolean JNICALL Java_mpi_Request_testAll( - JNIEnv *env, jclass jthis, jlongArray requests) -{ - int count = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int flag; - int rc = MPI_Testall(count, cReq, &flag, MPI_STATUSES_IGNORE); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT jobjectArray JNICALL Java_mpi_Request_waitSomeStatus( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int incount = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - MPI_Status *statuses = (MPI_Status*)calloc(incount, sizeof(MPI_Status)); - int *indices = (int*)calloc(incount, sizeof(int)); - int outcount; - int rc = MPI_Waitsome(incount, cReq, &outcount, indices, statuses); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - jobjectArray jStatuses = newStatusesIndices(env, statuses, indices, outcount); - free(statuses); - free(indices); - return jStatuses; -} - -JNIEXPORT jintArray JNICALL Java_mpi_Request_waitSome( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - jboolean exception; - int incount = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int *indices = (int*)calloc(incount, sizeof(int)); - int outcount; - int rc = MPI_Waitsome(incount, cReq, &outcount, indices, MPI_STATUSES_IGNORE); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - - if(exception) { - free(indices); - return NULL; - } - - jintArray jindices = NULL; - - if(outcount != MPI_UNDEFINED) - { - jindices = (*env)->NewIntArray(env, outcount); - setIndices(env, jindices, indices, outcount); - } - - free(indices); - return jindices; -} - -JNIEXPORT jobjectArray JNICALL Java_mpi_Request_testSomeStatus( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - int incount = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - MPI_Status *statuses = (MPI_Status*)calloc(incount, sizeof(MPI_Status)); - int *indices = (int*)calloc(incount, sizeof(int)); - int outcount; - int rc = MPI_Testsome(incount, cReq, &outcount, indices, statuses); - ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - jobjectArray jStatuses = newStatusesIndices(env, statuses, indices, outcount); - free(statuses); - free(indices); - return jStatuses; -} - -JNIEXPORT jintArray JNICALL Java_mpi_Request_testSome( - JNIEnv *env, jclass clazz, jlongArray requests) -{ - jboolean exception; - int incount = (*env)->GetArrayLength(env, requests); - jlong* jReq; - MPI_Request *cReq; - ompi_java_getPtrArray(env, requests, &jReq, (void***)&cReq); - int *indices = (int*)calloc(incount, sizeof(int)); - int outcount; - int rc = MPI_Testsome(incount, cReq, &outcount, indices, MPI_STATUSES_IGNORE); - exception = ompi_java_exceptionCheck(env, rc); - ompi_java_releasePtrArray(env, requests, jReq, (void**)cReq); - - if(exception) { - free(indices); - return NULL; - } - - jintArray jindices = NULL; - - if(outcount != MPI_UNDEFINED) - { - jindices = (*env)->NewIntArray(env, outcount); - setIndices(env, jindices, indices, outcount); - } - - free(indices); - return jindices; -} diff --git a/ompi/mpi/java/c/mpi_Status.c b/ompi/mpi/java/c/mpi_Status.c deleted file mode 100644 index 0863a872b7f..00000000000 --- a/ompi/mpi/java/c/mpi_Status.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - * File : mpi_Status.c - * Headerfile : mpi_Status.h - * Author : Sung-Hoon Ko, Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.9 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Status.h" -#include "mpiJava.h" - -static void getStatus(MPI_Status *status, jint source, jint tag, - jint error, jint cancelled, jlong ucount) -{ - /* Copy the whole thing to C */ - status->MPI_SOURCE = source; - status->MPI_TAG = tag; - status->MPI_ERROR = error; - status->_cancelled = cancelled; - status->_ucount = ucount; -} - -JNIEXPORT void JNICALL Java_mpi_Status_init(JNIEnv *env, jclass clazz) -{ - ompi_java.StatusData = (*env)->GetFieldID(env, clazz, "data", "[J"); -} - -JNIEXPORT jint JNICALL Java_mpi_Status_getCount( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, jlong jType) -{ - int count; - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - MPI_Datatype datatype = (MPI_Datatype)jType; - int rc = MPI_Get_count(&stat, datatype, &count); - ompi_java_exceptionCheck(env, rc); - return count; -} - -JNIEXPORT jboolean JNICALL Java_mpi_Status_isCancelled( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount) -{ - int flag; - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - int rc = MPI_Test_cancelled(&stat, &flag); - ompi_java_exceptionCheck(env, rc); - return flag==0 ? JNI_FALSE : JNI_TRUE; -} - -JNIEXPORT jint JNICALL Java_mpi_Status_getElements( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, jlong jType) -{ - int count; - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - MPI_Datatype datatype = (MPI_Datatype)jType; - int rc = MPI_Get_elements(&stat, datatype, &count); - ompi_java_exceptionCheck(env, rc); - return count; -} - -JNIEXPORT jobject JNICALL Java_mpi_Status_getElementsX( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, jlong jType) -{ - MPI_Count count; - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - MPI_Datatype datatype = (MPI_Datatype)jType; - int rc = MPI_Get_elements_x(&stat, datatype, &count); - ompi_java_exceptionCheck(env, rc); - - return (*env)->NewObject(env, ompi_java.CountClass, - ompi_java.CountInit, (jlong)count); -} - -JNIEXPORT jint JNICALL Java_mpi_Status_setElements( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, jlong jType, int count) -{ - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - MPI_Datatype datatype = (MPI_Datatype)jType; - int rc = MPI_Status_set_elements(&stat, datatype, count); - ompi_java_exceptionCheck(env, rc); - return stat._ucount; -} - -JNIEXPORT jlong JNICALL Java_mpi_Status_setElementsX( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, jlong jType, jlong jcount) -{ - MPI_Status stat; - MPI_Count count = (long)jcount; - getStatus(&stat, source, tag, error, cancelled, ucount); - MPI_Datatype datatype = (MPI_Datatype)jType; - int rc = MPI_Status_set_elements_x(&stat, datatype, count); - ompi_java_exceptionCheck(env, rc); - return (jlong)stat._ucount; -} - -JNIEXPORT void JNICALL Java_mpi_Status_setCancelled( - JNIEnv *env, jobject jthis, jint source, jint tag, - jint error, jint cancelled, jlong ucount, int flag) -{ - MPI_Status stat; - getStatus(&stat, source, tag, error, cancelled, ucount); - int rc = MPI_Status_set_cancelled(&stat, flag); - ompi_java_exceptionCheck(env, rc); -} - -jobject ompi_java_status_new(JNIEnv *env, MPI_Status *status) -{ - jlongArray jData = (*env)->NewLongArray(env, 6); - ompi_java_status_set(env, jData, status); - jobject jStatus = (*env)->AllocObject(env, ompi_java.StatusClass); - (*env)->SetObjectField(env, jStatus, ompi_java.StatusData, jData); - return jStatus; -} - -jobject ompi_java_status_newIndex(JNIEnv *env, MPI_Status *status, int index) -{ - jlongArray jData = (*env)->NewLongArray(env, 6); - ompi_java_status_setIndex(env, jData, status, index); - jobject jStatus = (*env)->AllocObject(env, ompi_java.StatusClass); - (*env)->SetObjectField(env, jStatus, ompi_java.StatusData, jData); - return jStatus; -} - -void ompi_java_status_set(JNIEnv *env, jlongArray jData, MPI_Status *status) -{ - /* Copy the whole thing to Java */ - int i = 0; - jlong *data = (*env)->GetPrimitiveArrayCritical(env, jData, NULL); - data[i++] = status->MPI_SOURCE; - data[i++] = status->MPI_TAG; - data[i++] = status->MPI_ERROR; - data[i++] = status->_cancelled; - data[i++] = status->_ucount; - (*env)->ReleasePrimitiveArrayCritical(env, jData, data, 0); -} - -void ompi_java_status_setIndex( - JNIEnv *env, jlongArray jData, MPI_Status *status, int index) -{ - /* Copy the whole thing to Java */ - int i = 0; - jlong *data = (*env)->GetPrimitiveArrayCritical(env, jData, NULL); - data[i++] = status->MPI_SOURCE; - data[i++] = status->MPI_TAG; - data[i++] = status->MPI_ERROR; - data[i++] = status->_cancelled; - data[i++] = status->_ucount; - data[i++] = index; - (*env)->ReleasePrimitiveArrayCritical(env, jData, data, 0); -} diff --git a/ompi/mpi/java/c/mpi_Win.c b/ompi/mpi/java/c/mpi_Win.c deleted file mode 100644 index 551b6e258e6..00000000000 --- a/ompi/mpi/java/c/mpi_Win.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -#include "ompi_config.h" - -#include -#ifdef HAVE_TARGETCONDITIONALS_H -#include -#endif - -#include "mpi.h" -#include "mpi_Win.h" -#include "mpiJava.h" - -JNIEXPORT jlong JNICALL Java_mpi_Win_createWin( - JNIEnv *env, jobject jthis, jobject jBase, - jint size, jint dispUnit, jlong info, jlong comm) -{ - void *base = (*env)->GetDirectBufferAddress(env, jBase); - MPI_Win win; - - int rc = MPI_Win_create(base, (MPI_Aint)size, dispUnit, - (MPI_Info)info, (MPI_Comm)comm, &win); - - ompi_java_exceptionCheck(env, rc); - return (jlong)win; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_allocateWin(JNIEnv *env, jobject jthis, - jint size, jint dispUnit, jlong info, jlong comm, jobject jBase) -{ - void *basePtr = (*env)->GetDirectBufferAddress(env, jBase); - MPI_Win win; - - int rc = MPI_Win_allocate((MPI_Aint)size, dispUnit, - (MPI_Info)info, (MPI_Comm)comm, basePtr, &win); - - ompi_java_exceptionCheck(env, rc); - return (jlong)win; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_allocateSharedWin(JNIEnv *env, jobject jthis, - jint size, jint dispUnit, jlong info, jlong comm, jobject jBase) -{ - void *basePtr = (*env)->GetDirectBufferAddress(env, jBase); - MPI_Win win; - - int rc = MPI_Win_allocate_shared((MPI_Aint)size, dispUnit, - (MPI_Info)info, (MPI_Comm)comm, basePtr, &win); - - ompi_java_exceptionCheck(env, rc); - return (jlong)win; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_createDynamicWin( - JNIEnv *env, jobject jthis, - jlong info, jlong comm) -{ - MPI_Win win; - - int rc = MPI_Win_create_dynamic( - (MPI_Info)info, (MPI_Comm)comm, &win); - - ompi_java_exceptionCheck(env, rc); - return (jlong)win; -} - -JNIEXPORT void JNICALL Java_mpi_Win_attach( - JNIEnv *env, jobject jthis, jlong win, jobject jBase, - jint size) -{ - void *base = (*env)->GetDirectBufferAddress(env, jBase); - - int rc = MPI_Win_attach((MPI_Win)win, base, (MPI_Aint)size); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_detach( - JNIEnv *env, jobject jthis, jlong win, jobject jBase) -{ - void *base = (*env)->GetDirectBufferAddress(env, jBase); - - int rc = MPI_Win_detach((MPI_Win)win, base); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_getGroup( - JNIEnv *env, jobject jthis, jlong win) -{ - MPI_Group group; - int rc = MPI_Win_get_group((MPI_Win)win, &group); - ompi_java_exceptionCheck(env, rc); - return (jlong)group; -} - -JNIEXPORT void JNICALL Java_mpi_Win_put( - JNIEnv *env, jobject jthis, jlong win, jobject origin, - jint orgCount, jlong orgType, jint targetRank, jint targetDisp, - jint targetCount, jlong targetType, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - - int rc = MPI_Put(orgPtr, orgCount, (MPI_Datatype)orgType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, (MPI_Win)win); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_get( - JNIEnv *env, jobject jthis, jlong win, jobject origin, - jint orgCount, jlong orgType, jint targetRank, jint targetDisp, - jint targetCount, jlong targetType, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - - int rc = MPI_Get(orgPtr, orgCount, (MPI_Datatype)orgType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, (MPI_Win)win); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_accumulate( - JNIEnv *env, jobject jthis, jlong win, - jobject origin, jint orgCount, jlong orgType, - jint targetRank, jint targetDisp, jint targetCount, jlong targetType, - jobject jOp, jlong hOp, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - - int rc = MPI_Accumulate(orgPtr, orgCount, (MPI_Datatype)orgType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, op, (MPI_Win)win); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_fence( - JNIEnv *env, jobject jthis, jlong win, jint assertion) -{ - int rc = MPI_Win_fence(assertion, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_start( - JNIEnv *env, jobject jthis, jlong win, jlong group, jint assertion) -{ - int rc = MPI_Win_start((MPI_Group)group, assertion, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_complete( - JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_complete((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_post( - JNIEnv *env, jobject jthis, jlong win, jlong group, jint assertion) -{ - int rc = MPI_Win_post((MPI_Group)group, assertion, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_waitFor( - JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_wait((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jboolean JNICALL Java_mpi_Win_test( - JNIEnv *env, jobject jthis, jlong win) -{ - int flag; - int rc = MPI_Win_test((MPI_Win)win, &flag); - ompi_java_exceptionCheck(env, rc); - return flag ? JNI_TRUE : JNI_FALSE; -} - -JNIEXPORT void JNICALL Java_mpi_Win_lock( - JNIEnv *env, jobject jthis, jlong win, - jint lockType, jint rank, jint assertion) -{ - int rc = MPI_Win_lock(lockType, rank, assertion, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_unlock( - JNIEnv *env, jobject jthis, jlong win, jint rank) -{ - int rc = MPI_Win_unlock(rank, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_setErrhandler( - JNIEnv *env, jobject jthis, jlong win, jlong errhandler) -{ - int rc = MPI_Win_set_errhandler( - (MPI_Win)win, (MPI_Errhandler)errhandler); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_getErrhandler( - JNIEnv *env, jobject jthis, jlong win) -{ - MPI_Errhandler errhandler; - int rc = MPI_Win_get_errhandler((MPI_Win)win, &errhandler); - ompi_java_exceptionCheck(env, rc); - return (jlong)errhandler; -} - -JNIEXPORT void JNICALL Java_mpi_Win_callErrhandler( - JNIEnv *env, jobject jthis, jlong win, jint errorCode) -{ - int rc = MPI_Win_call_errhandler((MPI_Win)win, errorCode); - ompi_java_exceptionCheck(env, rc); -} - -static int winCopyAttr(MPI_Win oldwin, int keyval, void *extraState, - void *attrValIn, void *attrValOut, int *flag) -{ - return ompi_java_attrCopy(attrValIn, attrValOut, flag); -} - -static int winDeleteAttr(MPI_Win oldwin, int keyval, - void *attrVal, void *extraState) -{ - return ompi_java_attrDelete(attrVal); -} - -JNIEXPORT jint JNICALL Java_mpi_Win_createKeyval_1jni(JNIEnv *env, jclass clazz) -{ - int rc, keyval; - rc = MPI_Win_create_keyval(winCopyAttr, winDeleteAttr, &keyval, NULL); - ompi_java_exceptionCheck(env, rc); - return keyval; -} - -JNIEXPORT void JNICALL Java_mpi_Win_freeKeyval_1jni( - JNIEnv *env, jclass clazz, jint keyval) -{ - int rc = MPI_Win_free_keyval((int*)(&keyval)); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_setAttr( - JNIEnv *env, jobject jthis, jlong win, jint keyval, jbyteArray jval) -{ - void *cval = ompi_java_attrSet(env, jval); - int rc = MPI_Win_set_attr((MPI_Win)win, keyval, cval); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jobject JNICALL Java_mpi_Win_getAttr( - JNIEnv *env, jobject jthis, jlong win, jint keyval) -{ - int flag; - void *val; - int rc = MPI_Win_get_attr((MPI_Win)win, keyval, &val, &flag); - - if(ompi_java_exceptionCheck(env, rc) || !flag) - return NULL; - - switch(keyval) - { - case MPI_WIN_SIZE: - return ompi_java_Integer_valueOf(env, (jint)(*((MPI_Aint*)val))); - case MPI_WIN_DISP_UNIT: - return ompi_java_Integer_valueOf(env, (jint)(*((int*)val))); - case MPI_WIN_BASE: - return ompi_java_Long_valueOf(env, (jlong)val); - default: - return ompi_java_attrGet(env, val); - } -} - -JNIEXPORT void JNICALL Java_mpi_Win_deleteAttr( - JNIEnv *env, jobject jthis, jlong win, jint keyval) -{ - int rc = MPI_Win_delete_attr((MPI_Win)win, keyval); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_free( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Win win = (MPI_Win)handle; - int rc = MPI_Win_free(&win); - ompi_java_exceptionCheck(env, rc); - return (jlong)win; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_getInfo( - JNIEnv *env, jobject jthis, jlong handle) -{ - MPI_Win win = (MPI_Win)handle; - MPI_Info info; - int rc = MPI_Win_get_info((MPI_Win)win, &info); - ompi_java_exceptionCheck(env, rc); - return (jlong)info; -} - -JNIEXPORT void JNICALL Java_mpi_Win_setInfo( - JNIEnv *env, jobject jthis, jlong handle, jlong i) -{ - MPI_Win win = (MPI_Win)handle; - MPI_Info info = (MPI_Info)i; - int rc = MPI_Win_set_info(win, info); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_rPut(JNIEnv *env, jobject jthis, - jlong win, jobject origin_addr, jint origin_count, jlong origin_type, - jint target_rank, jint target_disp, jint target_count, jlong target_datatype, - jint basetype) -{ - void *origPtr = ompi_java_getDirectBufferAddress(env, origin_addr); - MPI_Request request; - - int rc = MPI_Rput(origPtr, origin_count, (MPI_Datatype)origin_type, - target_rank, (MPI_Aint)target_disp, target_count, (MPI_Datatype)target_datatype, - (MPI_Win)win, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_rGet(JNIEnv *env, jobject jthis, jlong win, - jobject origin, jint orgCount, jlong orgType, jint targetRank, jint targetDisp, - jint targetCount, jlong targetType, jint base) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - MPI_Request request; - - int rc = MPI_Rget(orgPtr, orgCount, (MPI_Datatype)orgType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, (MPI_Win)win, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_rAccumulate(JNIEnv *env, jobject jthis, jlong win, - jobject origin, jint orgCount, jlong orgType, jint targetRank, jint targetDisp, - jint targetCount, jlong targetType, jobject jOp, jlong hOp, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - MPI_Request request; - - int rc = MPI_Raccumulate(orgPtr, orgCount, (MPI_Datatype)orgType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, op, (MPI_Win)win, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Win_getAccumulate(JNIEnv *env, jobject jthis, jlong win, - jobject origin, jint orgCount, jlong orgType, jobject resultBuff, jint resultCount, - jlong resultType, jint targetRank, jint targetDisp, jint targetCount, jlong targetType, - jobject jOp, jlong hOp, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - void *resultPtr = (*env)->GetDirectBufferAddress(env, resultBuff); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - - int rc = MPI_Get_accumulate(orgPtr, orgCount, (MPI_Datatype)orgType, - resultPtr, resultCount, (MPI_Datatype)resultType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, op, (MPI_Win)win); - - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT jlong JNICALL Java_mpi_Win_rGetAccumulate(JNIEnv *env, jobject jthis, jlong win, - jobject origin, jint orgCount, jlong orgType, jobject resultBuff, jint resultCount, - jlong resultType, jint targetRank, jint targetDisp, jint targetCount, jlong targetType, - jobject jOp, jlong hOp, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - void *resultPtr = (*env)->GetDirectBufferAddress(env, resultBuff); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - MPI_Request request; - - int rc = MPI_Rget_accumulate(orgPtr, orgCount, (MPI_Datatype)orgType, - resultPtr, resultCount, (MPI_Datatype)resultType, - targetRank, (MPI_Aint)targetDisp, targetCount, - (MPI_Datatype)targetType, op, (MPI_Win)win, &request); - - ompi_java_exceptionCheck(env, rc); - return (jlong)request; -} - -JNIEXPORT void JNICALL Java_mpi_Win_lockAll(JNIEnv *env, jobject jthis, jlong win, jint assertion) -{ - int rc = MPI_Win_lock_all(assertion, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_unlockAll(JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_unlock_all((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_sync(JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_sync((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_flush(JNIEnv *env, jobject jthis, jlong win, jint targetRank) -{ - int rc = MPI_Win_flush(targetRank, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_flushAll(JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_flush_all((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_compareAndSwap (JNIEnv *env, jobject jthis, jlong win, jobject origin, - jobject compareAddr, jobject resultAddr, jlong dataType, jint targetRank, jint targetDisp) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - void *compPtr = (*env)->GetDirectBufferAddress(env, compareAddr); - void *resultPtr = (*env)->GetDirectBufferAddress(env, resultAddr); - - int rc = MPI_Compare_and_swap(orgPtr, compPtr, resultPtr, (MPI_Datatype)dataType, - targetRank, targetDisp, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_fetchAndOp(JNIEnv *env, jobject jthis, jlong win, jobject origin, - jobject resultAddr, jlong dataType, jint targetRank, jint targetDisp, jobject jOp, jlong hOp, jint baseType) -{ - void *orgPtr = (*env)->GetDirectBufferAddress(env, origin); - void *resultPtr = (*env)->GetDirectBufferAddress(env, resultAddr); - MPI_Op op = ompi_java_op_getHandle(env, jOp, hOp, baseType); - - int rc = MPI_Fetch_and_op(orgPtr, resultPtr, (MPI_Datatype)dataType, targetRank, - targetDisp, op, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_flushLocal(JNIEnv *env, jobject jthis, jlong win, jint targetRank) -{ - int rc = MPI_Win_flush_local(targetRank, (MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_flushLocalAll(JNIEnv *env, jobject jthis, jlong win) -{ - int rc = MPI_Win_flush_local_all((MPI_Win)win); - ompi_java_exceptionCheck(env, rc); -} - -JNIEXPORT void JNICALL Java_mpi_Win_setName( - JNIEnv *env, jobject jthis, jlong handle, jstring jname) -{ - const char *name = (*env)->GetStringUTFChars(env, jname, NULL); - int rc = MPI_Win_set_name((MPI_Win)handle, (char*)name); - ompi_java_exceptionCheck(env, rc); - (*env)->ReleaseStringUTFChars(env, jname, name); -} - -JNIEXPORT jstring JNICALL Java_mpi_Win_getName( - JNIEnv *env, jobject jthis, jlong handle) -{ - char name[MPI_MAX_OBJECT_NAME]; - int len; - int rc = MPI_Win_get_name((MPI_Win)handle, name, &len); - - if(ompi_java_exceptionCheck(env, rc)) - return NULL; - - return (*env)->NewStringUTF(env, name); -} diff --git a/ompi/mpi/java/java/CartComm.java b/ompi/mpi/java/java/CartComm.java deleted file mode 100644 index 4c49262e0e8..00000000000 --- a/ompi/mpi/java/java/CartComm.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Cartcomm.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.7 $ - * Updated : $Date: 2001/10/22 21:07:55 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Communicator with cartesian structure. - */ -public final class CartComm extends Intracomm -{ - static - { - init(); - } - - private static native void init(); - - protected CartComm(long handle) throws MPIException - { - super(handle); - } - - protected CartComm(long[] commRequest) - { - super(commRequest); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return copy of this communicator - */ - @Override public CartComm clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public CartComm dup() throws MPIException - { - MPI.check(); - return new CartComm(dup(handle)); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_IDUP}. - *

The new communicator can't be used before the operation completes. - * The request object must be obtained calling {@link #getRequest}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. Signals that an MPI exception of some sort has occurred. - */ - @Override public CartComm iDup() throws MPIException - { - MPI.check(); - return new CartComm(iDup(handle)); - } - - /** - * Duplicates this communicator with the info object used in the call. - *

Java binding of {@code MPI_COMM_DUP_WITH_INFO}. - * @param info info object to associate with the new communicator - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public CartComm dupWithInfo(Info info) throws MPIException - { - MPI.check(); - return new CartComm(dupWithInfo(handle, info.handle)); - } - - /** - * Returns cartesian topology information. - *

Java binding of the MPI operations {@code MPI_CARTDIM_GET} and - * {@code MPI_CART_GET}. - *

The number of dimensions can be obtained from the size of (eg) - * {@code dims} field of the returned object. - * @return object containing dimensions, periods and local coordinates - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public CartParms getTopo() throws MPIException - { - MPI.check(); - return getTopo(handle); - } - - private native CartParms getTopo(long comm) throws MPIException; - - /** - * Translate logical process coordinates to process rank. - *

Java binding of the MPI operation {@code MPI_CART_RANK}. - * @param coords Cartesian coordinates of a process - * @return rank of the specified process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getRank(int[] coords) throws MPIException - { - MPI.check(); - return getRank(handle, coords); - } - - private native int getRank(long comm, int[] coords) throws MPIException; - - /** - * Translate process rank to logical process coordinates. - *

Java binding of the MPI operation {@code MPI_CART_COORDS}. - * @param rank rank of a process - * @return Cartesian coordinates of the specified process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int[] getCoords(int rank) throws MPIException - { - MPI.check(); - return getCoords(handle, rank); - } - - private native int[] getCoords(long comm, int rank) throws MPIException; - - /** - * Compute source and destination ranks for "shift" communication. - *

Java binding of the MPI operation {@code MPI_CART_SHIFT}. - * @param direction coordinate dimension of shift - * @param disp displacement - * @return object containing ranks of source and destination processes - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public ShiftParms shift(int direction, int disp) throws MPIException - { - MPI.check(); - return shift(handle, direction, disp); - } - - private native ShiftParms shift(long comm, int direction, int disp) - throws MPIException; - - /** - * Partition cartesian communicator into subgroups of lower dimension. - *

Java binding of the MPI operation {@code MPI_CART_SUB}. - * @param remainDims by dimension, {@code true} if dimension is to be kept, - * {@code false} otherwise - * @return communicator containing subgrid including this process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public CartComm sub(boolean[] remainDims) throws MPIException - { - MPI.check(); - return new CartComm(sub(handle, remainDims)); - } - - private native long sub(long comm, boolean[] remainDims) throws MPIException; - - /** - * Compute an optimal placement. - *

Java binding of the MPI operation {@code MPI_CART_MAP}. - *

The number of dimensions is taken to be size of the {@code dims} argument. - * @param dims the number of processes in each dimension - * @param periods {@code true} if grid is periodic, - * {@code false} if not, in each dimension - * @return reordered rank of calling process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int map(int[] dims, boolean[] periods) throws MPIException - { - MPI.check(); - return map(handle, dims, periods); - } - - private native int map(long comm, int[] dims, boolean[] periods) - throws MPIException; - - /** - * Select a balanced distribution of processes per coordinate direction. - *

Java binding of the MPI operation {@code MPI_DIMS_CREATE}. - * @param nnodes number of nodes in a grid - * @param dims array specifying the number of nodes in each dimension - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void createDims(int nnodes, int[] dims) throws MPIException - { - MPI.check(); - createDims_jni(nnodes, dims); - } - - private static native void createDims_jni(int nnodes, int[] dims) - throws MPIException; - -} // Cartcomm diff --git a/ompi/mpi/java/java/CartParms.java b/ompi/mpi/java/java/CartParms.java deleted file mode 100644 index aefd2d8fe5b..00000000000 --- a/ompi/mpi/java/java/CartParms.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : CartParms.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.1 $ - * Updated : $Date: 1998/08/26 18:49:50 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Cartesian topology information associated with a communicator. - */ -public final class CartParms -{ - /** Number of processes for each cartesian dimension. */ - private final int[] dims; - - /** Periodicity (true/false) for each cartesian dimension. */ - private final boolean[] periods; - - /** Coordinates of calling process in cartesian structure. */ - private final int[] coords; - - /** - * Constructs a cartesian topology information object. - * @param dims number of processes for each cartesian dimension. - * @param periods periodicity (true/false) for each cartesian dimension. - * @param coords coordinates of calling process in cartesian structure. - */ - protected CartParms(int[] dims, boolean[] periods, int[] coords) - { - this.dims = dims; - this.periods = periods; - this.coords = coords; - } - - /** - * Returns the number of dimensions. - * @return number of dimensions. - */ - public int getDimCount() - { - return dims.length; - } - - /** - * Returns the number of processes for a cartesian dimension. - * @param i cartesian dimension. - * @return number of processes for a cartesian dimension. - */ - public int getDim(int i) - { - return dims[i]; - } - - /** - * Returns the periodicity (true/false) for a cartesian dimension. - * @param i cartesian dimension. - * @return periodicity for a cartesian dimension. - */ - public boolean getPeriod(int i) - { - return periods[i]; - } - - /** - * Returns the coordinate of calling process for a cartesian dimension. - * @param i cartesian dimension. - * @return coordinate of calling process for a cartesian dimension. - */ - public int getCoord(int i) - { - return coords[i]; - } - -} // CartParms diff --git a/ompi/mpi/java/java/Comm.java b/ompi/mpi/java/java/Comm.java deleted file mode 100644 index 7483e8987f3..00000000000 --- a/ompi/mpi/java/java/Comm.java +++ /dev/null @@ -1,3469 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017-2019 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Comm.java - * Author : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.20 $ - * Updated : $Date: 2001/08/07 16:36:25 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - * - * - * - * IMPLEMENTATION DETAILS - * - * All methods with buffers that can be direct or non direct have - * a companion argument 'db' which is true if the buffer is direct. - * For example, if the buffer argument is recvBuf, the companion - * argument will be 'rdb', meaning if the receive buffer is direct. - * - * Checking if a buffer is direct is faster in Java than C. - */ -package mpi; - -import java.nio.*; -import static mpi.MPI.assertDirectBuffer; - -/** - * The {@code Comm} class represents communicators. - */ -public class Comm implements Freeable, Cloneable -{ - public final static int TYPE_SHARED = 0; - protected final static int SELF = 1; - protected final static int WORLD = 2; - protected long handle; - private Request request; - - private static long nullHandle; - - static - { - init(); - } - - private static native void init(); - - protected Comm() - { - } - - protected Comm(long handle) - { - this.handle = handle; - } - - protected Comm(long[] commRequest) - { - handle = commRequest[0]; - request = new Request(commRequest[1]); - } - - protected final void setType(int type) - { - getComm(type); - } - - private native void getComm(int type); - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return copy of this communicator - */ - @Override public Comm clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Comm dup() throws MPIException - { - MPI.check(); - return new Comm(dup(handle)); - } - - protected final native long dup(long comm) throws MPIException; - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_IDUP}. - *

The new communicator can't be used before the operation completes. - * The request object must be obtained calling {@link #getRequest}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Comm iDup() throws MPIException - { - MPI.check(); - return new Comm(iDup(handle)); - } - - protected final native long[] iDup(long comm) throws MPIException; - - /** - * Duplicates this communicator with the info object used in the call. - *

Java binding of {@code MPI_COMM_DUP_WITH_INFO}. - * @param info info object to associate with the new communicator - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Comm dupWithInfo(Info info) throws MPIException - { - MPI.check(); - return new Comm(dupWithInfo(handle, info.handle)); - } - - protected final native long dupWithInfo(long comm, long info) throws MPIException; - - /** - * Returns the associated request to this communicator if it was - * created using {@link #iDup}. - * @return associated request if this communicator was created - * using {@link #iDup}, or null otherwise. - */ - public final Request getRequest() - { - return request; - } - - /** - * Size of group of this communicator. - *

Java binding of the MPI operation {@code MPI_COMM_SIZE}. - * @return number of processors in the group of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int getSize() throws MPIException - { - MPI.check(); - return getSize(handle); - } - - private native int getSize(long comm) throws MPIException; - - /** - * Rank of this process in group of this communicator. - *

Java binding of the MPI operation {@code MPI_COMM_RANK}. - * @return rank of the calling process in the group of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int getRank() throws MPIException - { - MPI.check(); - return getRank(handle); - } - - private native int getRank(long comm) throws MPIException; - - /** - * Compare two communicators. - *

Java binding of the MPI operation {@code MPI_COMM_COMPARE}. - * @param comm1 first communicator - * @param comm2 second communicator - * @return - * {@code MPI.IDENT} results if the {@code comm1} and {@code comm2} - * are references to the same object (ie, if {@code comm1 == comm2}).
- * {@code MPI.CONGRUENT} results if the underlying groups are identical - * but the communicators differ by context.
- * {@code MPI.SIMILAR} results if the underlying groups are similar - * but the communicators differ by context.
- * {@code MPI.UNEQUAL} results otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int compare(Comm comm1, Comm comm2) throws MPIException - { - MPI.check(); - return compare(comm1.handle, comm2.handle); - } - - private static native int compare(long comm1, long comm2) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_COMM_FREE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override final public void free() throws MPIException - { - MPI.check(); - handle = free(handle); - } - - private native long free(long comm) throws MPIException; - - /** - * Test if communicator object is null (has been freed). - * Java binding of {@code MPI_COMM_NULL}. - * @return true if the comm object is null, false otherwise - */ - public final boolean isNull() - { - return handle == nullHandle; - } - - /** - * Java binding of {@code MPI_COMM_SET_INFO}. - * @param info info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void setInfo(Info info) throws MPIException - { - MPI.check(); - setInfo(handle, info.handle); - } - - private native void setInfo(long comm, long info) throws MPIException; - - /** - * Java binding of {@code MPI_COMM_GET_INFO}. - * @return new info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Info getInfo() throws MPIException - { - MPI.check(); - return new Info(getInfo(handle)); - } - - private native long getInfo(long comm) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_COMM_DISCONNECT}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void disconnect() throws MPIException - { - MPI.check(); - handle = disconnect(handle); - } - - private native long disconnect(long comm) throws MPIException; - - /** - * Return group associated with a communicator. - *

Java binding of the MPI operation {@code MPI_COMM_GROUP}. - * @return group corresponding to this communicator group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Group getGroup() throws MPIException - { - MPI.check(); - return new Group(getGroup(handle)); - } - - private native long getGroup(long comm); - - // Inter-communication - - /** - * Test if this communicator is an inter-communicator. - *

Java binding of the MPI operation {@code MPI_COMM_TEST_INTER}. - * @return {@code true} if this is an inter-communicator, - * {@code false} otherwise - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final boolean isInter() throws MPIException - { - MPI.check(); - return isInter(handle); - } - - private native boolean isInter(long comm) throws MPIException; - - /** - * Create an inter-communicator. - *

- * Java binding of the MPI operation {@code MPI_INTERCOMM_CREATE}. - *

- * This operation is defined as a method on the "peer communicator", - * making it analogous to a {@code send} or {@code recv} communication - * with the remote group leader. - * @param localComm local intra-communicator - * @param localLeader rank of local group leader in {@code localComm} - * @param remoteLeader rank of remote group leader in this communicator - * @param tag "safe" tag - * @return new inter-communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm createIntercomm(Comm localComm, int localLeader, - int remoteLeader, int tag) - throws MPIException - { - MPI.check(); - - return new Intercomm(createIntercomm(handle, localComm.handle, - localLeader, remoteLeader, tag)); - } - - private native long createIntercomm( - long comm, long localComm, int localLeader, - int remoteLeader, int tag) throws MPIException; - - // Blocking Send and Recv - - /** - * Blocking send operation. - *

Java binding of the MPI operation {@code MPI_SEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void send(Object buf, int count, Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - send(handle, buf, db, off, count, type.handle, type.baseType, dest, tag); - } - - private native void send( - long comm, Object buf, boolean db, int offset, int count, - long type, int baseType, int dest, int tag) throws MPIException; - - /** - * Blocking receive operation. - *

Java binding of the MPI operation {@code MPI_RECV}. - * @param buf receive buffer - * @param count number of items in receive buffer - * @param type datatype of each item in receive buffer - * @param source rank of source - * @param tag message tag - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status recv(Object buf, int count, - Datatype type, int source, int tag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - Status status = new Status(); - - recv(handle, buf, db, off, count, - type.handle, type.baseType, source, tag, status.data); - - return status; - } - - private native void recv( - long comm, Object buf, boolean db, int offset, int count, - long type, int basetype, int source, int tag, long[] stat) - throws MPIException; - - // Send-Recv - - /** - * Execute a blocking send and receive operation. - *

Java binding of the MPI operation {@code MPI_SENDRECV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param dest rank of destination - * @param sendtag send tag - * @param recvbuf receive buffer - * @param recvcount number of items in receive buffer - * @param recvtype datatype of each item in receive buffer - * @param source rank of source - * @param recvtag receive tag - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - * @see mpi.Comm#recv(Object, int, Datatype, int, int) - */ - public final Status sendRecv( - Object sendbuf, int sendcount, Datatype sendtype, int dest, int sendtag, - Object recvbuf, int recvcount, Datatype recvtype, int source, int recvtag) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - Status status = new Status(); - - sendRecv(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, dest, sendtag, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType, source, recvtag, status.data); - - return status; - } - - private native void sendRecv( - long comm, Object sbuf, boolean sdb, int soffset, int scount, - long sType, int sBaseType, int dest, int stag, - Object rbuf, boolean rdb, int roffset, int rcount, - long rType, int rBaseType, int source, int rtag, - long[] stat) throws MPIException; - - /** - * Execute a blocking send and receive operation, - * receiving message into send buffer. - *

Java binding of the MPI operation {@code MPI_SENDRECV_REPLACE}. - * @param buf buffer - * @param count number of items to send - * @param type datatype of each item in buffer - * @param dest rank of destination - * @param sendtag send tag - * @param source rank of source - * @param recvtag receive tag - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - * @see mpi.Comm#recv(Object, int, Datatype, int, int) - */ - public final Status sendRecvReplace( - Object buf, int count, Datatype type, - int dest, int sendtag, int source, int recvtag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - Status status = new Status(); - - sendRecvReplace(handle, buf, db, off, count, type.handle, type.baseType, - dest, sendtag, source, recvtag, status.data); - - return status; - } - - private native void sendRecvReplace( - long comm, Object buf, boolean db, int offset, int count, - long type, int baseType, int dest, int stag, - int source, int rtag, long[] stat) throws MPIException; - - // Communication Modes - - /** - * Send in buffered mode. - *

Java binding of the MPI operation {@code MPI_BSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final void bSend(Object buf, int count, Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - bSend(handle, buf, db, off, count, type.handle, type.baseType, dest, tag); - } - - private native void bSend( - long comm, Object buf, boolean db, int offset, int count, - long type, int baseType, int dest, int tag) throws MPIException; - - /** - * Send in synchronous mode. - *

Java binding of the MPI operation {@code MPI_SSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final void sSend(Object buf, int count, Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - sSend(handle, buf, db, off, count, type.handle, type.baseType, dest, tag); - } - - private native void sSend( - long comm, Object buf, boolean db, int offset, int count, - long type, int baseType, int dest, int tag) throws MPIException; - - /** - * Send in ready mode. - *

Java binding of the MPI operation {@code MPI_RSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final void rSend(Object buf, int count, Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - rSend(handle, buf, db, off, count, type.handle, type.baseType, dest, tag); - } - - private native void rSend( - long comm, Object buf, boolean db, int offset, int count, - long type, int baseType, int dest, int tag) throws MPIException; - - // Nonblocking communication - - /** - * Start a standard mode, nonblocking send. - *

Java binding of the MPI operation {@code MPI_ISEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Request iSend(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iSend(handle, buf, count, type.handle, dest, tag)); - req.addSendBufRef(buf); - return req; - } - - private native long iSend( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Start a buffered mode, nonblocking send. - *

Java binding of the MPI operation {@code MPI_IBSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Request ibSend(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(ibSend(handle, buf, count, type.handle, dest, tag)); - req.addSendBufRef(buf); - return req; - } - - private native long ibSend( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Start a synchronous mode, nonblocking send. - *

Java binding of the MPI operation {@code MPI_ISSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Request isSend(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(isSend(handle, buf, count, type.handle, dest, tag)); - req.addSendBufRef(buf); - return req; - } - - private native long isSend( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Start a ready mode, nonblocking send. - *

Java binding of the MPI operation {@code MPI_IRSEND}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Request irSend(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(irSend(handle, buf, count, type.handle, dest, tag)); - req.addSendBufRef(buf); - return req; - } - - private native long irSend( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Start a nonblocking receive. - *

Java binding of the MPI operation {@code MPI_IRECV}. - * @param buf receive buffer - * @param count number of items in receive buffer - * @param type datatype of each item in receive buffer - * @param source rank of source - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#recv(Object, int, Datatype, int, int) - */ - public final Request iRecv(Buffer buf, int count, - Datatype type, int source, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iRecv(handle, buf, count, type.handle, source, tag)); - req.addRecvBufRef(buf); - return req; - } - - private native long iRecv( - long comm, Buffer buf, int count, long type, int source, int tag) - throws MPIException; - - - // Persistent communication requests - - /** - * Creates a persistent communication request for a standard mode send. - *

Java binding of the MPI operation {@code MPI_SEND_INIT}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return persistent communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Prequest sendInit(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Prequest preq = new Prequest(sendInit(handle, buf, count, type.handle, dest, tag)); - preq.addSendBufRef(buf); - return preq; - } - - private native long sendInit( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Creates a persistent communication request for a buffered mode send. - *

Java binding of the MPI operation {@code MPI_BSEND_INIT}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return persistent communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Prequest bSendInit(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Prequest preq = new Prequest(bSendInit(handle, buf, count, type.handle, dest, tag)); - preq.addSendBufRef(buf); - return preq; - } - - private native long bSendInit( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Creates a persistent communication request for a synchronous mode send. - *

Java binding of the MPI operation {@code MPI_SSEND_INIT}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return persistent communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Prequest sSendInit(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Prequest preq = new Prequest(sSendInit(handle, buf, count, type.handle, dest, tag)); - preq.addSendBufRef(buf); - return preq; - } - - private native long sSendInit( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Creates a persistent communication request for a ready mode send. - *

Java binding of the MPI operation {@code MPI_RSEND_INIT}. - * @param buf send buffer - * @param count number of items to send - * @param type datatype of each item in send buffer - * @param dest rank of destination - * @param tag message tag - * @return persistent communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#send(Object, int, Datatype, int, int) - */ - public final Prequest rSendInit(Buffer buf, int count, - Datatype type, int dest, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Prequest preq = new Prequest(rSendInit(handle, buf, count, type.handle, dest, tag)); - preq.addSendBufRef(buf); - return preq; - } - - private native long rSendInit( - long comm, Buffer buf, int count, long type, int dest, int tag) - throws MPIException; - - /** - * Creates a persistent communication request for a receive operation. - *

Java binding of the MPI operation {@code MPI_RECV_INIT}. - * @param buf receive buffer - * @param count number of items in receive buffer - * @param type datatype of each item in receive buffer - * @param source rank of source - * @param tag message tag - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - * @see mpi.Comm#recv(Object, int, Datatype, int, int) - */ - public final Prequest recvInit(Buffer buf, int count, - Datatype type, int source, int tag) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Prequest preq = new Prequest(recvInit(handle, buf, count, type.handle, source, tag)); - preq.addRecvBufRef(buf); - return preq; - } - - private native long recvInit( - long comm, Buffer buf, int count, long type, int source, int tag) - throws MPIException; - - // Pack and Unpack - - /** - * Packs message in send buffer {@code inbuf} into space specified in - * {@code outbuf}. - *

- * Java binding of the MPI operation {@code MPI_PACK}. - *

- * The return value is the output value of {@code position} - the - * initial value incremented by the number of bytes written. - * @param inbuf input buffer - * @param incount number of items in input buffer - * @param type datatype of each item in input buffer - * @param outbuf output buffer - * @param position initial position in output buffer - * @return final position in output buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int pack(Object inbuf, int incount, Datatype type, - byte[] outbuf, int position) - throws MPIException - { - MPI.check(); - int offset = 0; - boolean indb = false; - - if(inbuf instanceof Buffer && !(indb = ((Buffer)inbuf).isDirect())) - { - offset = type.getOffset(inbuf); - inbuf = ((Buffer)inbuf).array(); - } - - return pack(handle, inbuf, indb, offset, incount, - type.handle, outbuf, position); - } - - private native int pack( - long comm, Object inbuf, boolean indb, int offset, int incount, - long type, byte[] outbuf, int position) throws MPIException; - - /** - * Unpacks message in receive buffer {@code outbuf} into space specified in - * {@code inbuf}. - *

- * Java binding of the MPI operation {@code MPI_UNPACK}. - *

- * The return value is the output value of {@code position} - the - * initial value incremented by the number of bytes read. - * @param inbuf input buffer - * @param position initial position in input buffer - * @param outbuf output buffer - * @param outcount number of items in output buffer - * @param type datatype of each item in output buffer - * @return final position in input buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int unpack(byte[] inbuf, int position, - Object outbuf, int outcount, Datatype type) - throws MPIException - { - MPI.check(); - int offset = 0; - boolean outdb = false; - - if(outbuf instanceof Buffer && !(outdb = ((Buffer)outbuf).isDirect())) - { - offset = type.getOffset(outbuf); - outbuf = ((Buffer)outbuf).array(); - } - - return unpack(handle, inbuf, position, outbuf, outdb, - offset, outcount, type.handle); - } - - private native int unpack( - long comm, byte[] inbuf, int position, Object outbuf, boolean outdb, - int offset, int outcount, long type) throws MPIException; - - /** - * Returns an upper bound on the increment of {@code position} effected - * by {@code pack}. - *

Java binding of the MPI operation {@code MPI_PACK_SIZE}. - * @param incount number of items in input buffer - * @param type datatype of each item in input buffer - * @return upper bound on size of packed message - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int packSize(int incount, Datatype type) throws MPIException - { - MPI.check(); - return packSize(handle, incount, type.handle); - } - - private native int packSize(long comm, int incount, long type) - throws MPIException; - - // Probe and Cancel - - /** - * Check if there is an incoming message matching the pattern specified. - *

Java binding of the MPI operation {@code MPI_IPROBE}. - *

If such a message is currently available, a status object similar - * to the return value of a matching {@code recv} operation is returned. - * @param source rank of source - * @param tag message tag - * @return status object if such a message is currently available, - * {@code null} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status iProbe(int source, int tag) throws MPIException - { - MPI.check(); - return iProbe(handle, source, tag); - } - - private native Status iProbe(long comm, int source, int tag) - throws MPIException; - - /** - * Wait until there is an incoming message matching the pattern specified. - *

Java binding of the MPI operation {@code MPI_PROBE}. - *

Returns a status object similar to the return value of a matching - * {@code recv} operation. - * @param source rank of source - * @param tag message tag - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status probe(int source, int tag) throws MPIException - { - MPI.check(); - Status status = new Status(); - probe(handle, source, tag, status.data); - return status; - } - - private native void probe(long comm, int source, int tag, long[] stat) - throws MPIException; - - // Caching - - /** - * Create a new attribute key. - *

Java binding of the MPI operation {@code MPI_COMM_CREATE_KEYVAL}. - * @return attribute key for future access - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int createKeyval() throws MPIException - { - MPI.check(); - return createKeyval_jni(); - } - - private static native int createKeyval_jni() throws MPIException; - - /** - * Frees an attribute key for communicators. - *

Java binding of the MPI operation {@code MPI_COMM_FREE_KEYVAL}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void freeKeyval(int keyval) throws MPIException - { - MPI.check(); - freeKeyval_jni(keyval); - } - - private static native void freeKeyval_jni(int keyval) throws MPIException; - - /** - * Stores attribute value associated with a key. - *

Java binding of the MPI operation {@code MPI_COMM_SET_ATTR}. - * @param keyval attribute key - * @param value attribute value - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void setAttr(int keyval, Object value) throws MPIException - { - MPI.check(); - setAttr(handle, keyval, MPI.attrSet(value)); - } - - private native void setAttr(long comm, int keyval, byte[] value) - throws MPIException; - - /** - * Retrieves attribute value by key. - *

Java binding of the MPI operation {@code MPI_COMM_GET_ATTR}. - * @param keyval attribute key - * @return attribute value or null if no attribute is associated with the key. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Object getAttr(int keyval) throws MPIException - { - MPI.check(); - - if( keyval == MPI.TAG_UB || - keyval == MPI.HOST || - keyval == MPI.IO || - keyval == MPI.APPNUM || - keyval == MPI.LASTUSEDCODE || - keyval == MPI.UNIVERSE_SIZE) - { - return getAttr_predefined(handle, keyval); - } - else if(keyval == MPI.WTIME_IS_GLOBAL) - { - Integer value = (Integer)getAttr_predefined(handle, keyval); - return value==null ? null : value.intValue() != 0; - } - else - { - return MPI.attrGet(getAttr(handle, keyval)); - } - } - - private native Object getAttr_predefined(long comm, int keyval) - throws MPIException; - - private native byte[] getAttr(long comm, int keyval) throws MPIException; - - /** - * Deletes an attribute value associated with a key on a communicator. - *

Java binding of the MPI operation {@code MPI_COMM_DELETE_ATTR}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void deleteAttr(int keyval) throws MPIException - { - MPI.check(); - deleteAttr(handle, keyval); - } - - private native void deleteAttr(long comm, int keyval) throws MPIException; - - // Process Topologies - - /** - * Returns the type of topology associated with the communicator. - *

Java binding of the MPI operation {@code MPI_TOPO_TEST}. - *

The return value will be one of {@code MPI.GRAPH}, {@code MPI.CART}, - * {@code MPI.DIST_GRAPH} or {@code MPI.UNDEFINED}. - * @return topology type of communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int getTopology() throws MPIException - { - MPI.check(); - return getTopology(handle); - } - - private native int getTopology(long comm) throws MPIException; - - // Environmental Management - - /** - * Abort MPI. - *

Java binding of the MPI operation {@code MPI_ABORT}. - * @param errorcode error code for Unix or POSIX environments - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void abort(int errorcode) throws MPIException - { - MPI.check(); - abort(handle, errorcode); - } - - private native void abort(long comm, int errorcode) throws MPIException; - - // Error handler - - /** - * Associates a new error handler with communicator at the calling process. - *

Java binding of the MPI operation {@code MPI_COMM_SET_ERRHANDLER}. - * @param errhandler new MPI error handler for communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void setErrhandler(Errhandler errhandler) throws MPIException - { - MPI.check(); - setErrhandler(handle, errhandler.handle); - } - - private native void setErrhandler(long comm, long errhandler) - throws MPIException; - - /** - * Returns the error handler currently associated with the communicator. - *

Java binding of the MPI operation {@code MPI_COMM_GET_ERRHANDLER}. - * @return MPI error handler currently associated with communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Errhandler getErrhandler() throws MPIException - { - MPI.check(); - return new Errhandler(getErrhandler(handle)); - } - - private native long getErrhandler(long comm); - - /** - * Calls the error handler currently associated with the communicator. - *

Java binding of the MPI operation {@code MPI_COMM_CALL_ERRHANDLER}. - * @param errorCode error code - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void callErrhandler(int errorCode) throws MPIException - { - callErrhandler(handle, errorCode); - } - - private native void callErrhandler(long handle, int errorCode) - throws MPIException; - - // Collective Communication - - /** - * A call to {@code barrier} blocks the caller until all process - * in the group have called it. - *

Java binding of the MPI operation {@code MPI_BARRIER}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void barrier() throws MPIException - { - MPI.check(); - barrier(handle); - } - - private native void barrier(long comm) throws MPIException; - - /** - * Nonblocking barrier synchronization. - *

Java binding of the MPI operation {@code MPI_IBARRIER}. - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iBarrier() throws MPIException - { - MPI.check(); - return new Request(iBarrier(handle)); - } - - private native long iBarrier(long comm) throws MPIException; - - /** - * Broadcast a message from the process with rank {@code root} - * to all processes of the group. - *

Java binding of the MPI operation {@code MPI_BCAST}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each item in buffer - * @param root rank of broadcast root - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void bcast(Object buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - bcast(handle, buf, db, off, count, type.handle, type.baseType, root); - } - - private native void bcast( - long comm, Object buf, boolean db, int offset, int count, - long type, int basetype, int root) throws MPIException; - - /** - * Broadcast a message from the process with rank {@code root} - * to all processes of the group. - *

Java binding of the MPI operation {@code MPI_IBCAST}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each item in buffer - * @param root rank of broadcast root - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iBcast(Buffer buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iBcast(handle, buf, count, type.handle, root)); - req.addSendBufRef(buf); - return req; - } - - private native long iBcast( - long comm, Buffer buf, int count, long type, int root) - throws MPIException; - - /** - * Each process sends the contents of its send buffer to the root process. - *

Java binding of the MPI operation {@code MPI_GATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void gather( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - gather(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType, root); - } - - /** - * Each process sends the contents of its send buffer to the root process. - *

Java binding of the MPI operation {@code MPI_GATHER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * The buffer is used by the root process to receive data, - * and it is used by the non-root processes to send data. - * @param buf buffer - * @param count number of items to send/receive - * @param type datatype of each item in buffer - * @param root rank of receiving process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void gather(Object buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - gather(handle, null, false, 0, 0, 0, 0, - buf, db, off, count, type.handle, type.baseType, root); - } - - private native void gather( - long comm, Object sendBuf, boolean sdb, int sendOff, int sendCount, - long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOff, int recvCount, - long recvType, int recvBaseType, int root) - throws MPIException; - - /** - * Each process sends the contents of its send buffer to the root process. - *

Java binding of the MPI operation {@code MPI_IGATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iGather( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iGather(handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle, root)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Each process sends the contents of its send buffer to the root process. - *

Java binding of the MPI operation {@code MPI_IGATHER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * The buffer is used by the root process to receive data, - * and it is used by the non-root processes to send data. - * @param buf buffer - * @param count number of items to send/receive - * @param type datatype of each item in buffer - * @param root rank of receiving process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iGather(Buffer buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iGather(handle, null, 0, 0, - buf, count, type.handle, root)); - req.addRecvBufRef(buf); - return req; - } - - private native long iGather( - long comm, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int recvcount, long recvtype, - int root) throws MPIException; - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_GATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void gatherv(Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int[] recvcount, int[] displs, - Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - gatherv(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, displs, - recvtype.handle, recvtype.baseType, root); - } - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_GATHERV} using - * {@code MPI_IN_PLACE} instead of the send buffer in the root process. - * This method must be used in the root process. - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void gatherv(Object recvbuf, int[] recvcount, int[] displs, - Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - int recvoff = 0; - boolean rdb = false; - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - gatherv(handle, null, false, 0, 0, 0, 0, recvbuf, rdb, recvoff, recvcount, - displs, recvtype.handle, recvtype.baseType, root); - } - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_GATHERV} using - * {@code MPI_IN_PLACE} instead of the send buffer in the root process. - * This method must be used in the non-root processes. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param root rank of receiving process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void gatherv(Object sendbuf, int sendcount, - Datatype sendtype, int root) - throws MPIException - { - MPI.check(); - int sendoff = 0; - boolean sdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - gatherv(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - null, false, 0, null, null, 0, 0, root); - } - - private native void gatherv( - long comm, Object sendBuf, boolean sdb, int sendOffset, - int sendCount, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, - int[] recvCount, int[] displs, long recvType, int recvBaseType, - int root) throws MPIException; - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_IGATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iGatherv( - Buffer sendbuf, int sendcount, Datatype sendtype, Buffer recvbuf, - int[] recvcount, int[] displs, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iGatherv( - handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, displs, recvtype.handle, root)); - req.addSendBufRef(sendbuf); - return req; - } - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_IGATHERV} using - * {@code MPI_IN_PLACE} instead of the send buffer in the root process. - * This method must be used in the root process. - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @param root rank of receiving process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iGatherv(Buffer recvbuf, int[] recvcount, int[] displs, - Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(recvbuf); - Request req = new Request(iGatherv(handle, null, 0, 0, - recvbuf, recvcount, displs, recvtype.handle, root)); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Extends functionality of {@code gather} by allowing varying - * counts of data from each process. - *

Java binding of the MPI operation {@code MPI_IGATHERV} using - * {@code MPI_IN_PLACE} instead of the send buffer in the root process. - * This method must be used in the non-root processes. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param root rank of receiving process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iGatherv(Buffer sendbuf, int sendcount, - Datatype sendtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf); - Request req = new Request(iGatherv(handle, sendbuf, sendcount, sendtype.handle, - null, null, null, 0, root)); - req.addSendBufRef(sendbuf); - return req; - } - - private native long iGatherv( - long handle, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int[] recvcount, int[] displs, - long recvtype, int root) - throws MPIException; - - /** - * Inverse of the operation {@code gather}. - *

Java binding of the MPI operation {@code MPI_SCATTER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scatter( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - scatter(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType, root); - } - - /** - * Inverse of the operation {@code gather}. - *

Java binding of the MPI operation {@code MPI_SCATTER} - * using {@code MPI_IN_PLACE} instead of the receive buffer. - * The buffer is used by the root process to send data, - * and it is used by the non-root processes to receive data. - * @param buf send/receive buffer - * @param count number of items to send/receive - * @param type datatype of each item in buffer - * @param root rank of sending process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scatter(Object buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - scatter(handle, buf, db, off, count, type.handle, type.baseType, - null, false, 0, 0, 0, 0, root); - } - - private native void scatter( - long comm, Object sendBuf, boolean sdb, int sendOffset, int sendCount, - long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, int recvCount, - long recvType, int recvBaseType, int root) throws MPIException; - - /** - * Inverse of the operation {@code gather}. - *

Java binding of the MPI operation {@code MPI_ISCATTER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScatter( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iScatter(handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle, root)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Inverse of the operation {@code gather}. - *

Java binding of the MPI operation {@code MPI_ISCATTER} - * using {@code MPI_IN_PLACE} instead of the receive buffer. - * The buffer is used by the root process to send data, - * and it is used by the non-root processes to receive data. - * @param buf send/receive buffer - * @param count number of items to send/receive - * @param type datatype of each item in buffer - * @param root rank of sending process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScatter(Buffer buf, int count, Datatype type, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iScatter(handle, buf, count, type.handle, - null, 0, 0, root)); - req.addSendBufRef(buf); - return req; - } - - private native long iScatter( - long comm, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int recvcount, long recvtype, int root) - throws MPIException; - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_SCATTERV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param displs displacements from which to take outgoing data - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scatterv( - Object sendbuf, int[] sendcount, int[] displs, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - scatterv(handle, sendbuf, sdb, sendoff, sendcount, displs, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType, root); - } - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_SCATTERV} using - * {@code MPI_IN_PLACE} instead of the receive buffer in the root process. - * This method must be used in the root process. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param displs displacements from which to take outgoing data - * @param sendtype datatype of each item in send buffer - * @param root rank of sending process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scatterv(Object sendbuf, int[] sendcount, int[] displs, - Datatype sendtype, int root) - throws MPIException - { - MPI.check(); - int sendoff = 0; - boolean sdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - scatterv(handle, sendbuf, sdb, sendoff, sendcount, displs, - sendtype.handle, sendtype.baseType, - null, false, 0, 0, 0, 0, root); - } - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_SCATTERV} using - * {@code MPI_IN_PLACE} instead of the receive buffer in the root process. - * This method must be used in the non-root processes. - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scatterv(Object recvbuf, int recvcount, - Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - int recvoff = 0; - boolean rdb = false; - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - scatterv(handle, null, false, 0, null, null, 0, 0, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType, root); - } - - private native void scatterv( - long comm, Object sendBuf, boolean sdb, int sendOffset, - int[] sendCount, int[] displs, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, int recvCount, - long recvType, int recvBaseType, int root) - throws MPIException; - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_ISCATTERV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param displs displacements from which to take outgoing data - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScatterv( - Buffer sendbuf, int[] sendcount, int[] displs, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iScatterv( - handle, sendbuf, sendcount, displs, sendtype.handle, - recvbuf, recvcount, recvtype.handle, root)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_ISCATTERV} using - * {@code MPI_IN_PLACE} instead of the receive buffer in the root process. - * This method must be used in the root process. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param displs displacements from which to take outgoing data - * @param sendtype datatype of each item in send buffer - * @param root rank of sending process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScatterv(Buffer sendbuf, int[] sendcount, int[] displs, - Datatype sendtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf); - Request req = new Request(iScatterv(handle, sendbuf, sendcount, displs, - sendtype.handle, null, 0, 0, root)); - req.addSendBufRef(sendbuf); - return req; - } - - /** - * Inverse of the operation {@code gatherv}. - *

Java binding of the MPI operation {@code MPI_ISCATTERV} using - * {@code MPI_IN_PLACE} instead of the receive buffer in the root process. - * This method must be used in the non-root processes. - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @param root rank of sending process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScatterv(Buffer recvbuf, int recvcount, - Datatype recvtype, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(recvbuf); - Request req = new Request(iScatterv(handle, null, null, null, 0, - recvbuf, recvcount, recvtype.handle, root)); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iScatterv( - long comm, Buffer sendbuf, int[] sendcount, int[] displs, long sendtype, - Buffer recvbuf, int recvcount, long recvtype, int root) - throws MPIException; - - /** - * Similar to {@code gather}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_ALLGATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allGather(Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allGather(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType); - } - - /** - * Similar to {@code gather}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_ALLGATHER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count number of items to receive - * @param type datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allGather(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - allGather(handle, null, false, 0, 0, 0, 0, - buf, db, off, count, type.handle, type.baseType); - } - - private native void allGather( - long comm, Object sendBuf, boolean sdb, int sendOffset, int sendCount, - long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, int recvCount, - long recvType, int recvBaseType) throws MPIException; - - /** - * Similar to {@code gather}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_IALLGATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllGather( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iAllGather(handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Similar to {@code gather}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_IALLGATHER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count number of items to receive - * @param type datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllGather(Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iAllGather(handle, null, 0, 0, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iAllGather( - long comm, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int recvcount, long recvtype) throws MPIException; - - /** - * Similar to {@code gatherv}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_ALLGATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allGatherv( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int[] recvcount, int[] displs, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allGatherv(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, displs, - recvtype.handle, recvtype.baseType); - } - - /** - * Similar to {@code gatherv}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_ALLGATHERV} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allGatherv(Object recvbuf, int[] recvcount, - int[] displs, Datatype recvtype) - throws MPIException - { - MPI.check(); - int recvoff = 0; - boolean rdb = false; - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allGatherv(handle, null, false, 0, 0, 0, 0, - recvbuf, rdb, recvoff, recvcount, - displs, recvtype.handle, recvtype.baseType); - } - - private native void allGatherv( - long comm, Object sendBuf, boolean sdb, int sendOffset, int sendCount, - long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, int[] recvCount, - int[] displs, long recvType, int recvBasetype) throws MPIException; - - /** - * Similar to {@code gatherv}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_IALLGATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param displs displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllGatherv( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int[] recvcount, int[] displs, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iAllGatherv( - handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, displs, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Similar to {@code gatherv}, but all processes receive the result. - *

Java binding of the MPI operation {@code MPI_IALLGATHERV} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count number of elements received from each process - * @param displs displacements at which to place incoming data - * @param type datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllGatherv( - Buffer buf, int[] count, int[] displs, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iAllGatherv( - handle, null, 0, 0, buf, count, displs, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iAllGatherv( - long handle, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int[] recvcount, int[] displs, long recvtype) - throws MPIException; - - /** - * Extension of {@code allGather} to the case where each process sends - * distinct data to each of the receivers. - *

Java binding of the MPI operation {@code MPI_ALLTOALL}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of items received from any process - * @param recvtype datatype of receive buffer items - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allToAll(Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allToAll(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType); - } - - private native void allToAll( - long comm, Object sendBuf, boolean sdb, int sendOffset, int sendCount, - long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, int recvCount, - long recvType, int recvBaseType) throws MPIException; - - /** - * Extension of {@code allGather} to the case where each process sends - * distinct data to each of the receivers. - *

Java binding of the MPI operation {@code MPI_IALLTOALL}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each process - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of items received from any process - * @param recvtype datatype of receive buffer items - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllToAll(Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iAllToAll(handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iAllToAll( - long comm, Buffer sendbuf, int sendcount, long sendtype, - Buffer recvbuf, int recvcount, long recvtype) throws MPIException; - - /** - * Adds flexibility to {@code allToAll}: location of data for send is - * specified by {@code sdispls} and location to place data on receive - * side is specified by {@code rdispls}. - *

Java binding of the MPI operation {@code MPI_ALLTOALLV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each buffer - * @param sdispls displacements from which to take outgoing data - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param rdispls displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allToAllv( - Object sendbuf, int[] sendcount, int[] sdispls, Datatype sendtype, - Object recvbuf, int[] recvcount, int[] rdispls, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allToAllv(handle, sendbuf, sdb, sendoff, sendcount, sdispls, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, rdispls, - recvtype.handle, recvtype.baseType); - } - - private native void allToAllv( - long comm, Object sendBuf, boolean sdb, int sendOffset, - int[] sendCount, int[] sdispls, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, - int[] recvCount, int[] rdispls, long recvType, int recvBaseType) - throws MPIException; - - /** - * Adds flexibility to {@code allToAll}: location of data for send is - * specified by {@code sdispls} and location to place data on receive - * side is specified by {@code rdispls}. - *

Java binding of the MPI operation {@code MPI_IALLTOALLV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each buffer - * @param sdispls displacements from which to take outgoing data - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param rdispls displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllToAllv( - Buffer sendbuf, int[] sendcount, int[] sdispls, Datatype sendtype, - Buffer recvbuf, int[] recvcount, int[] rdispls, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iAllToAllv( - handle, sendbuf, sendcount, sdispls, sendtype.handle, - recvbuf, recvcount, rdispls, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iAllToAllv(long comm, - Buffer sendbuf, int[] sendcount, int[] sdispls, long sendtype, - Buffer recvbuf, int[] recvcount, int[] rdispls, long recvtype) - throws MPIException; - - /** - * Adds more flexibility to {@code allToAllv}: datatypes for send are - * specified by {@code sendTypes} and datatypes for receive are specified - * by {@code recvTypes} per process. - *

Java binding of the MPI operation {@code MPI_ALLTOALLW}. - * @param sendBuf send buffer - * @param sendCount number of items sent to each buffer - * @param sDispls displacements from which to take outgoing data - * @param sendTypes datatypes of send buffer items - * @param recvBuf receive buffer - * @param recvCount number of elements received from each process - * @param rDispls displacements at which to place incoming data - * @param recvTypes datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allToAllw( - Object sendBuf, int[] sendCount, int[] sDispls, Datatype[] sendTypes, - Object recvBuf, int[] recvCount, int[] rDispls, Datatype[] recvTypes) - throws MPIException - { - MPI.check(); - - int[] sendoffs = new int[sendTypes.length]; - int[] recvoffs = new int[recvTypes.length]; - - boolean sdb = false, - rdb = false; - - if(sendBuf instanceof Buffer && !(sdb = ((Buffer)sendBuf).isDirect())) - { - - for (int i = 0; i < sendTypes.length; i++){ - sendoffs[i] = sendTypes[i].getOffset(sendBuf); - } - sendBuf = ((Buffer)sendBuf).array(); - } - - if(recvBuf instanceof Buffer && !(rdb = ((Buffer)recvBuf).isDirect())) - { - for (int i = 0; i < recvTypes.length; i++){ - recvoffs[i] = recvTypes[i].getOffset(recvBuf); - } - recvBuf = ((Buffer)recvBuf).array(); - } - - long[] sendHandles = convertTypeArray(sendTypes); - long[] recvHandles = convertTypeArray(recvTypes); - int[] sendHandles_btypes = convertTypeArrayBtype(sendTypes); - int[] recvHandles_btypes = convertTypeArrayBtype(recvTypes); - - allToAllw(handle, sendBuf, sdb, sendoffs, sendCount, sDispls, - sendHandles, sendHandles_btypes, - recvBuf, rdb, recvoffs, recvCount, rDispls, - recvHandles, recvHandles_btypes); - } - - private native void allToAllw(long comm, - Object sendBuf, boolean sdb, int[] sendOffsets, - int[] sendCount, int[] sDispls, long[] sendTypes, int[] sendBaseTypes, - Object recvBuf, boolean rdb, int[] recvOffsets, - int[] recvCount, int[] rDispls, long[] recvTypes, int[] recvBaseTypes) - throws MPIException; - - /** - * Adds more flexibility to {@code iAllToAllv}: datatypes for send are - * specified by {@code sendTypes} and datatypes for receive are specified - * by {@code recvTypes} per process. - *

Java binding of the MPI operation {@code MPI_IALLTOALLW}. - * @param sendBuf send buffer - * @param sendCount number of items sent to each buffer - * @param sDispls displacements from which to take outgoing data - * @param sendTypes datatype send buffer items - * @param recvBuf receive buffer - * @param recvCount number of elements received from each process - * @param rDispls displacements at which to place incoming data - * @param recvTypes datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllToAllw( - Buffer sendBuf, int[] sendCount, int[] sDispls, Datatype[] sendTypes, - Buffer recvBuf, int[] recvCount, int[] rDispls, Datatype[] recvTypes) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendBuf, recvBuf); - - long[] sendHandles = convertTypeArray(sendTypes); - long[] recvHandles = convertTypeArray(recvTypes); - Request req = new Request(iAllToAllw( - handle, sendBuf, sendCount, sDispls, sendHandles, - recvBuf, recvCount, rDispls, recvHandles)); - req.addSendBufRef(sendBuf); - req.addRecvBufRef(recvBuf); - return req; - } - - private native long iAllToAllw(long comm, - Buffer sendBuf, int[] sendCount, int[] sDispls, long[] sendTypes, - Buffer recvBuf, int[] recvCount, int[] rDispls, long[] recvTypes) - throws MPIException; - - /** - * Java binding of {@code MPI_NEIGHBOR_ALLGATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void neighborAllGather( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - neighborAllGather(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType); - } - - private native void neighborAllGather( - long comm, Object sendBuf, boolean sdb, int sendOffset, - int sendCount, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOffset, - int recvCount, long recvType, int recvBaseType) - throws MPIException; - - /** - * Java binding of {@code MPI_INEIGHBOR_ALLGATHER}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iNeighborAllGather( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iNeighborAllGather( - handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iNeighborAllGather( - long comm, Buffer sendBuf, int sendCount, long sendType, - Buffer recvBuf, int recvCount, long recvType) - throws MPIException; - - /** - * Java binding of {@code MPI_NEIGHBOR_ALLGATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements that are received from each neighbor - * @param displs displacements at which to place incoming data - * @param recvtype datatype of receive buffer elements - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void neighborAllGatherv( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int[] recvcount, int[] displs, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - neighborAllGatherv(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, displs, - recvtype.handle, recvtype.baseType); - } - - private native void neighborAllGatherv( - long comm, Object sendBuf, boolean sdb, int sendOff, - int sendCount, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOff, - int[] recvCount, int[] displs, long recvType, int recvBaseType); - - /** - * Java binding of {@code MPI_INEIGHBOR_ALLGATHERV}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of elements that are received from each neighbor - * @param displs displacements at which to place incoming data - * @param recvtype datatype of receive buffer elements - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iNeighborAllGatherv( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int[] recvcount, int[] displs, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iNeighborAllGatherv( - handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, displs, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iNeighborAllGatherv( - long comm, Buffer sendBuf, int sendCount, long sendType, - Buffer recvBuf, int[] recvCount, int[] displs, long recvType) - throws MPIException; - - /** - * Java binding of {@code MPI_NEIGHBOR_ALLTOALL}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void neighborAllToAll( - Object sendbuf, int sendcount, Datatype sendtype, - Object recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - neighborAllToAll(handle, sendbuf, sdb, sendoff, sendcount, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, - recvtype.handle, recvtype.baseType); - } - - private native void neighborAllToAll( - long comm, Object sendBuf, boolean sdb, int sendOff, - int sendCount, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOff, - int recvCount, long recvType, int recvBaseType) - throws MPIException; - - /** - * Java binding of {@code MPI_INEIGHBOR_ALLTOALL}. - * @param sendbuf send buffer - * @param sendcount number of items to send - * @param sendtype datatype of each item in send buffer - * @param recvbuf receive buffer - * @param recvcount number of items to receive - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iNeighborAllToAll( - Buffer sendbuf, int sendcount, Datatype sendtype, - Buffer recvbuf, int recvcount, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iNeighborAllToAll( - handle, sendbuf, sendcount, sendtype.handle, - recvbuf, recvcount, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iNeighborAllToAll( - long comm, Buffer sendBuf, int sendCount, long sendType, - Buffer recvBuf, int recvCount, long recvType); - - /** - * Java binding of {@code MPI_NEIGHBOR_ALLTOALLV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each buffer - * @param sdispls displacements from which to take outgoing data - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param rdispls displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void neighborAllToAllv( - Object sendbuf, int[] sendcount, int[] sdispls, Datatype sendtype, - Object recvbuf, int[] recvcount, int[] rdispls, Datatype recvtype) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = sendtype.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = recvtype.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - neighborAllToAllv(handle, - sendbuf, sdb, sendoff, sendcount, sdispls, - sendtype.handle, sendtype.baseType, - recvbuf, rdb, recvoff, recvcount, rdispls, - recvtype.handle, recvtype.baseType); - } - - private native void neighborAllToAllv( - long comm, Object sendBuf, boolean sdb, int sendOff, - int[] sendCount, int[] sdispls, long sendType, int sendBaseType, - Object recvBuf, boolean rdb, int recvOff, - int[] recvCount, int[] rdispls, long recvType, int recvBaseType) - throws MPIException; - - /** - * Java binding of {@code MPI_INEIGHBOR_ALLTOALLV}. - * @param sendbuf send buffer - * @param sendcount number of items sent to each buffer - * @param sdispls displacements from which to take outgoing data - * @param sendtype datatype send buffer items - * @param recvbuf receive buffer - * @param recvcount number of elements received from each process - * @param rdispls displacements at which to place incoming data - * @param recvtype datatype of each item in receive buffer - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iNeighborAllToAllv( - Buffer sendbuf, int[] sendcount, int[] sdispls, Datatype sendtype, - Buffer recvbuf, int[] recvcount, int[] rdispls, Datatype recvtype) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iNeighborAllToAllv( - handle, sendbuf, sendcount, sdispls, sendtype.handle, - recvbuf, recvcount, rdispls, recvtype.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - private native long iNeighborAllToAllv( - long comm, Buffer sendBuf, int[] sendCount, int[] sdispls, long sType, - Buffer recvBuf, int[] recvCount, int[] rdispls, long rType) - throws MPIException; - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and return the combined value in the output buffer of the - * root process. - *

- * Java binding of the MPI operation {@code MPI_REDUCE}. - *

- * The predefined operations are available in Java as {@code MPI.MAX}, - * {@code MPI.MIN}, {@code MPI.SUM}, {@code MPI.PROD}, {@code MPI.LAND}, - * {@code MPI.BAND}, {@code MPI.LOR}, {@code MPI.BOR}, {@code MPI.LXOR}, - * {@code MPI.BXOR}, {@code MPI.MINLOC} and {@code MPI.MAXLOC}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @param root rank of root process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduce(Object sendbuf, Object recvbuf, int count, - Datatype type, Op op, int root) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - reduce(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - count, type.handle, type.baseType, op, op.handle, root); - } - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and return the combined value in the output buffer of the - * root process. - *

Java binding of the MPI operation {@code MPI_REDUCE} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf send/receive buffer - * @param count number of items in buffer - * @param type data type of each item in buffer - * @param op reduce operation - * @param root rank of root process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduce(Object buf, int count, Datatype type, Op op, int root) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - reduce(handle, null, false, 0, buf, db, off, count, - type.handle, type.baseType, op, op.handle, root); - } - - private native void reduce( - long comm, Object sendbuf, boolean sdb, int sendoff, - Object recvbuf, boolean rdb, int recvoff, int count, - long type, int baseType, Op jOp, long hOp, int root) - throws MPIException; - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and return the combined value in the output buffer of the - * root process. - *

Java binding of the MPI operation {@code MPI_IREDUCE}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @param root rank of root process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduce(Buffer sendbuf, Buffer recvbuf, - int count, Datatype type, Op op, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - op.setDatatype(type); - Request req = new Request(iReduce( - handle, sendbuf, recvbuf, count, - type.handle, type.baseType, op, op.handle, root)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and return the combined value in the output buffer of the - * root process. - *

Java binding of the MPI operation {@code MPI_IREDUCE} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf send/receive buffer - * @param count number of items in buffer - * @param type data type of each item in buffer - * @param op reduce operation - * @param root rank of root process - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduce(Buffer buf, int count, - Datatype type, Op op, int root) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - op.setDatatype(type); - Request req = new Request(iReduce( - handle, null, buf, count, - type.handle, type.baseType, op, op.handle, root)); - req.addSendBufRef(buf); - return req; - } - - private native long iReduce( - long comm, Buffer sendbuf, Buffer recvbuf, int count, - long type, int baseType, Op jOp, long hOp, int root) - throws MPIException; - - /** - * Same as {@code reduce} except that the result appears in receive - * buffer of all process in the group. - *

Java binding of the MPI operation {@code MPI_ALLREDUCE}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allReduce(Object sendbuf, Object recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - allReduce(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - count, type.handle, type.baseType, op, op.handle); - } - - /** - * Same as {@code reduce} except that the result appears in receive - * buffer of all process in the group. - *

Java binding of the MPI operation {@code MPI_ALLREDUCE} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void allReduce(Object buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - allReduce(handle, null, false, 0, buf, db, off, count, - type.handle, type.baseType, op, op.handle); - } - - private native void allReduce( - long comm, Object sendbuf, boolean sdb, int sendoff, - Object recvbuf, boolean rdb, int recvoff, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Same as {@code reduce} except that the result appears in receive - * buffer of all process in the group. - *

Java binding of the MPI operation {@code MPI_IALLREDUCE}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllReduce(Buffer sendbuf, Buffer recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - assertDirectBuffer(sendbuf, recvbuf); - op.setDatatype(type); - Request req = new Request(iAllReduce(handle, sendbuf, recvbuf, count, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Same as {@code reduce} except that the result appears in receive - * buffer of all process in the group. - *

Java binding of the MPI operation {@code MPI_IALLREDUCE} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count number of items in send buffer - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iAllReduce(Buffer buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(buf); - Request req = new Request(iAllReduce( - handle, null, buf, count, - type.handle, type.baseType, op, op.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iAllReduce( - long comm, Buffer sendbuf, Buffer recvbuf, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and scatter the combined values over the output buffers - * of the processes. - *

Java binding of the MPI operation {@code MPI_REDUCE_SCATTER}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param recvcounts numbers of result elements distributed to each process - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduceScatter(Object sendbuf, Object recvbuf, - int[] recvcounts, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - reduceScatter(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - recvcounts, type.handle, type.baseType, op, op.handle); - } - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and scatter the combined values over the output buffers - * of the processes. - *

Java binding of the MPI operation {@code MPI_REDUCE_SCATTER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param counts numbers of result elements distributed to each process - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduceScatter(Object buf, int[] counts, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - reduceScatter(handle, null, false, 0, buf, db, off, counts, - type.handle, type.baseType, op, op.handle); - } - - private native void reduceScatter( - long comm, Object sendbuf, boolean sdb, int sendoff, - Object recvbuf, boolean rdb, int recvoff, int[] recvcounts, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and scatter the combined values over the output buffers - * of the processes. - *

Java binding of the MPI operation {@code MPI_IREDUCE_SCATTER}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param recvcounts numbers of result elements distributed to each process - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduceScatter(Buffer sendbuf, Buffer recvbuf, - int[] recvcounts, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iReduceScatter( - handle, sendbuf, recvbuf, recvcounts, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Combine elements in input buffer of each process using the reduce - * operation, and scatter the combined values over the output buffers - * of the processes. - *

Java binding of the MPI operation {@code MPI_IREDUCE_SCATTER} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param counts numbers of result elements distributed to each process - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduceScatter( - Buffer buf, int[] counts, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(buf); - Request req = new Request(iReduceScatter( - handle, null, buf, counts, - type.handle, type.baseType, op, op.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReduceScatter( - long handle, Buffer sendbuf, Object recvbuf, int[] recvcounts, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Combine values and scatter the results. - *

Java binding of the MPI operation {@code MPI_REDUCE_SCATTER_BLOCK}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param recvcount element count per block - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduceScatterBlock(Object sendbuf, Object recvbuf, - int recvcount, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - reduceScatterBlock(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - recvcount, type.handle, type.baseType, op, op.handle); - } - - /** - * Combine values and scatter the results. - *

Java binding of the MPI operation {@code MPI_REDUCE_SCATTER_BLOCK} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count element count per block - * @param type data type of each item in send buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void reduceScatterBlock( - Object buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - reduceScatterBlock(handle, null, false, 0, buf, db, off, count, - type.handle, type.baseType, op, op.handle); - } - - private native void reduceScatterBlock( - long comm, Object sendBuf, boolean sdb, int sOffset, - Object recvBuf, boolean rdb, int rOffset, int rCount, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Combine values and scatter the results. - *

Java binding of the MPI operation {@code MPI_IREDUCE_SCATTER_BLOCK}. - * @param sendbuf send buffer - * @param recvbuf receive buffer - * @param recvcount element count per block - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduceScatterBlock( - Buffer sendbuf, Buffer recvbuf, int recvcount, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iReduceScatterBlock( - handle, sendbuf, recvbuf, recvcount, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Combine values and scatter the results. - *

Java binding of the MPI operation {@code MPI_IREDUCE_SCATTER_BLOCK} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer - * @param count element count per block - * @param type data type of each item in send buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iReduceScatterBlock( - Buffer buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(buf); - Request req = new Request(iReduceScatterBlock( - handle, null, buf, count, type.handle, - type.baseType, op, op.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReduceScatterBlock( - long handle, Buffer sendbuf, Buffer recvbuf, int recvcount, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Apply the operation given by {@code op} element-wise to the - * elements of {@code inBuf} and {@code inOutBuf} with the result - * stored element-wise in {@code inOutBuf}. - *

Java binding of the MPI operation {@code MPI_REDUCE_LOCAL}. - * @param inBuf input buffer - * @param inOutBuf input buffer, will contain combined output - * @param count number of elements - * @param type data type of each item - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void reduceLocal( - Object inBuf, Object inOutBuf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - - int inOff = 0, - inOutOff = 0; - - boolean idb = false, - iodb = false; - - if(inBuf instanceof Buffer && !(idb = ((Buffer)inBuf).isDirect())) - { - inOff = type.getOffset(inBuf); - inBuf = ((Buffer)inBuf).array(); - } - - if(inOutBuf instanceof Buffer && !(iodb = ((Buffer)inOutBuf).isDirect())) - { - inOutOff = type.getOffset(inOutBuf); - inOutBuf = ((Buffer)inOutBuf).array(); - } - - if(op.uf == null) - { - reduceLocal(inBuf, idb, inOff, inOutBuf, iodb, inOutOff, - count, type.handle, op.handle); - } - else - { - reduceLocalUf(inBuf, idb, inOff, inOutBuf, iodb, inOutOff, - count, type.handle, type.baseType, op, op.handle); - } - } - - private static native void reduceLocal( - Object inBuf, boolean idb, int inOff, - Object inOutBuf, boolean iodb, int inOutOff, int count, - long type, long op) throws MPIException; - - private static native void reduceLocalUf( - Object inBuf, boolean idb, int inOff, - Object inOutBuf, boolean iodb, int inOutOff, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Sets the print name for the communicator. - * @param name name for the communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void setName(String name) throws MPIException - { - MPI.check(); - setName(handle, name); - } - - private native void setName(long handle, String name) throws MPIException; - - /** - * Return the print name from the communicator. - * @return name of the communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final String getName() throws MPIException - { - MPI.check(); - return getName(handle); - } - - private native String getName(long handle) throws MPIException; - - /** - * A helper method to convert an array of Datatypes to - * an array of longs (handles). - * @param dArray Array of Datatypes - * @return converted Datatypes - */ - private long[] convertTypeArray(Datatype[] dArray) { - long[] lArray = new long[dArray.length]; - - for(int i = 0; i < lArray.length; i++) { - if(dArray[i] != null) { - lArray[i] = dArray[i].handle; - } - } - return lArray; - } - - /** - * A helper method to convert an array of Datatypes to - * an array of ints (basetypes). - * @param dArray Array of Datatypes - * @return converted basetypes - */ - private int[] convertTypeArrayBtype(Datatype[] dArray) { - int[] lArray = new int[dArray.length]; - - for(int i = 0; i < lArray.length; i++) { - if(dArray[i] != null) { - lArray[i] = dArray[i].baseType; - } - } - return lArray; - } - -} // Comm diff --git a/ompi/mpi/java/java/Constant.java b/ompi/mpi/java/java/Constant.java deleted file mode 100644 index a5e95708b70..00000000000 --- a/ompi/mpi/java/java/Constant.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -class Constant -{ - protected int THREAD_SINGLE, THREAD_FUNNELED, THREAD_SERIALIZED, THREAD_MULTIPLE; - - protected int GRAPH, DIST_GRAPH, CART; - protected int ANY_SOURCE, ANY_TAG; - protected int PROC_NULL; - protected int UNDEFINED; - protected int IDENT, CONGRUENT, SIMILAR, UNEQUAL; - protected int TAG_UB, HOST, IO, WTIME_IS_GLOBAL; - - protected int APPNUM, LASTUSEDCODE, UNIVERSE_SIZE, WIN_BASE, WIN_SIZE, WIN_DISP_UNIT; - - protected int VERSION, SUBVERSION; - protected int ROOT, KEYVAL_INVALID, BSEND_OVERHEAD; - protected int MAX_OBJECT_NAME, MAX_PORT_NAME, MAX_DATAREP_STRING; - protected int MAX_INFO_KEY, MAX_INFO_VAL; - protected int ORDER_C, ORDER_FORTRAN; - - protected int DISTRIBUTE_BLOCK, DISTRIBUTE_CYCLIC, DISTRIBUTE_NONE, DISTRIBUTE_DFLT_DARG; - - protected int MODE_CREATE, MODE_RDONLY, MODE_WRONLY, MODE_RDWR, - MODE_DELETE_ON_CLOSE, MODE_UNIQUE_OPEN, MODE_EXCL, - MODE_APPEND, MODE_SEQUENTIAL; - - protected int DISPLACEMENT_CURRENT; - protected int SEEK_SET, SEEK_CUR, SEEK_END; - - protected int MODE_NOCHECK, MODE_NOPRECEDE, MODE_NOPUT, MODE_NOSTORE, - MODE_NOSUCCEED; - - protected int LOCK_EXCLUSIVE, LOCK_SHARED; - - // Error classes and codes - protected int SUCCESS; - protected int ERR_BUFFER; - protected int ERR_COUNT; - protected int ERR_TYPE; - protected int ERR_TAG; - protected int ERR_COMM; - protected int ERR_RANK; - protected int ERR_REQUEST; - protected int ERR_ROOT; - protected int ERR_GROUP; - protected int ERR_OP; - protected int ERR_TOPOLOGY; - protected int ERR_DIMS; - protected int ERR_ARG; - protected int ERR_UNKNOWN; - protected int ERR_TRUNCATE; - protected int ERR_OTHER; - protected int ERR_INTERN; - protected int ERR_IN_STATUS; - protected int ERR_PENDING; - protected int ERR_ACCESS; - protected int ERR_AMODE; - protected int ERR_ASSERT; - protected int ERR_BAD_FILE; - protected int ERR_BASE; - protected int ERR_CONVERSION; - protected int ERR_DISP; - protected int ERR_DUP_DATAREP; - protected int ERR_FILE_EXISTS; - protected int ERR_FILE_IN_USE; - protected int ERR_FILE; - protected int ERR_INFO_KEY; - protected int ERR_INFO_NOKEY; - protected int ERR_INFO_VALUE; - protected int ERR_INFO; - protected int ERR_IO; - protected int ERR_KEYVAL; - protected int ERR_LOCKTYPE; - protected int ERR_NAME; - protected int ERR_NO_MEM; - protected int ERR_NOT_SAME; - protected int ERR_NO_SPACE; - protected int ERR_NO_SUCH_FILE; - protected int ERR_PORT; - protected int ERR_PROC_ABORTED; - protected int ERR_QUOTA; - protected int ERR_READ_ONLY; - protected int ERR_RMA_CONFLICT; - protected int ERR_RMA_SYNC; - protected int ERR_SERVICE; - protected int ERR_SIZE; - protected int ERR_SPAWN; - protected int ERR_UNSUPPORTED_DATAREP; - protected int ERR_UNSUPPORTED_OPERATION; - protected int ERR_WIN; - protected int ERR_LASTCODE; - protected int ERR_SYSRESOURCE; - - protected Constant() - { - setConstant(); - } - - private native void setConstant(); - -} // Constant diff --git a/ompi/mpi/java/java/Count.java b/ompi/mpi/java/java/Count.java deleted file mode 100644 index 7c175c4549f..00000000000 --- a/ompi/mpi/java/java/Count.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Count.java - * Author : Nathaniel Graham - * Created : Thu Jul 29 17:13 2015 - */ - -package mpi; - -/** - * This class represents {@code MPI_Count}. - */ -public final class Count implements Comparable -{ - private long count; - - static - { - System.loadLibrary("mpi_java"); - initCount(); - } - - private static native void initCount(); - - public Count(long count) - { - this.count = count; - } - - /** - * Gets value associated with this Count object. - * @return Count value - */ - public long getCount() - { - return this.count; - } - - /** - * Sets the value associated with this Count object. - * @param count the value to set for this count object - */ - public void setCount(long count) - { - this.count = count; - } - - @Override - public boolean equals(Object obj) - { - if(obj instanceof Count) { - if(this.count == ((Count)obj).getCount()) { - return true; - } - } - return false; - } - - public int compareTo(Object obj) - { - if(obj instanceof Count) { - if(this.count - ((Count)obj).getCount() > 0) { - return 1; - } else if(this.count - ((Count)obj).getCount() == 0) { - return 0; - } - } - return -1; - } -} // Count diff --git a/ompi/mpi/java/java/Datatype.java b/ompi/mpi/java/java/Datatype.java deleted file mode 100644 index 4b9e8295f43..00000000000 --- a/ompi/mpi/java/java/Datatype.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Datatype.java - * Author : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.14 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -import java.nio.*; - -/** - * The {@code Datatype} class represents {@code MPI_Datatype} handles. - */ -public final class Datatype implements Freeable, Cloneable -{ - protected long handle; - protected int baseType; - protected int baseSize; - - // Cache to avoid unnecessary jni calls. - private int lb, extent, trueLb, trueExtent; - - protected static final int NULL = 0; - protected static final int BYTE = 1; - protected static final int CHAR = 2; - protected static final int SHORT = 3; - protected static final int BOOLEAN = 4; - protected static final int INT = 5; - protected static final int LONG = 6; - protected static final int FLOAT = 7; - protected static final int DOUBLE = 8; - protected static final int PACKED = 9; - protected static final int INT2 = 10; - protected static final int SHORT_INT = 11; - protected static final int LONG_INT = 12; - protected static final int FLOAT_INT = 13; - protected static final int DOUBLE_INT = 14; - protected static final int FLOAT_COMPLEX = 15; - protected static final int DOUBLE_COMPLEX = 16; - - static - { - init(); - } - - private static native void init(); - - /* - * Constructor used in static initializer of 'MPI'. - * - * (Called before MPI.Init(), so cannot make any native MPI calls.) - * - * (Initialization done in separate 'setBasic', so can create - * datatype objects for 'BYTE', etc in static initializers invoked before - * MPI.Init(), then initialize objects after MPI initialized.) - */ - protected Datatype() - { - } - - protected void setBasic(int type) - { - baseType = type; - handle = getDatatype(type); - baseSize = type == NULL ? 0 : getSize(handle); - } - - protected void setBasic(int type, Datatype oldType) - { - baseType = oldType.baseType; - handle = getDatatype(type); - baseSize = oldType.baseSize; - } - - private static native long getDatatype(int type); - - /* - * Constructor used in 'create*' methods. - */ - private Datatype(Datatype oldType, long handle) - { - baseType = oldType.baseType; - baseSize = oldType.baseSize; - this.handle = handle; - } - - /* - * Constructor used in 'create*' methods. - */ - private Datatype(int baseType, int baseSize, long handle) - { - this.baseType = baseType; - this.baseSize = baseSize; - this.handle = handle; - } - - /** - * Returns the lower bound of a datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_GET_EXTENT}. - * @return lower bound of datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getLb() throws MPIException - { - if(extent == 0) - getLbExtent(); - - return lb; - } - - /** - * Returns the extent of a datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_GET_EXTENT}. - * @return datatype extent - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getExtent() throws MPIException - { - if(extent == 0) - getLbExtent(); - - return extent; - } - - private void getLbExtent() throws MPIException - { - MPI.check(); - int lbExt[] = new int[2]; - getLbExtent(handle, lbExt); - lb = lbExt[0] / baseSize; - extent = lbExt[1] / baseSize; - } - - private native void getLbExtent(long handle, int[] lbExt); - - /** - * Returns the true lower bound of a datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_GET_TRUE_EXTENT}. - * @return lower bound of datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getTrueLb() throws MPIException - { - if(trueExtent == 0) - getTrueLbExtent(); - - return trueLb; - } - - /** - * Returns the true extent of a datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_GET_TRUE_EXTENT}. - * @return datatype true extent - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getTrueExtent() throws MPIException - { - if(trueExtent == 0) - getTrueLbExtent(); - - return trueExtent; - } - - private void getTrueLbExtent() throws MPIException - { - MPI.check(); - int lbExt[] = new int[2]; - getTrueLbExtent(handle, lbExt); - trueLb = lbExt[0] / baseSize; - trueExtent = lbExt[1] / baseSize; - } - - private native void getTrueLbExtent(long handle, int[] lbExt); - - /** - * Returns the total size of a datatype - the number of buffer - * elements it represents. - *

Java binding of the MPI operation {@code MPI_TYPE_SIZE}. - * @return datatype size - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getSize() throws MPIException - { - MPI.check(); - return getSize(handle) / baseSize; - } - - private native int getSize(long type); - - /** - * Commits a derived datatype. - * Java binding of the MPI operation {@code MPI_TYPE_COMMIT}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void commit() throws MPIException - { - MPI.check(); - commit(handle); - } - - private native void commit(long type); - - /** - * Frees the datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_FREE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public void free() throws MPIException - { - MPI.check(); - handle = free(handle); - } - - private native long free(long type) throws MPIException; - - /** - * Returns {@code true} if this datatype is MPI_DATATYPE_NULL. - * @return {@code true} if this datatype is MPI_DATATYPE_NULL - */ - public boolean isNull() - { - return handle == MPI.DATATYPE_NULL.handle; - } - - /** - * Java binding of {@code MPI_TYPE_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return new datatype - */ - @Override public Datatype clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Java binding of {@code MPI_TYPE_DUP}. - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Datatype dup() throws MPIException - { - MPI.check(); - return new Datatype(this, dup(handle)); - } - - private native long dup(long type) throws MPIException; - - /** - * Construct new datatype representing replication of old datatype into - * contiguous locations. - *

Java binding of the MPI operation {@code MPI_TYPE_CONTIGUOUS}. - *

The base type of the new datatype is the same as the base type of - * {@code oldType}. - * @param count replication count - * @param oldType old datatype - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createContiguous(int count, Datatype oldType) - throws MPIException - { - MPI.check(); - return new Datatype(oldType, getContiguous(count, oldType.handle)); - } - - private static native long getContiguous(int count, long oldType); - - /** - * Construct new datatype representing replication of old datatype into - * locations that consist of equally spaced blocks. - *

Java binding of the MPI operation {@code MPI_TYPE_VECTOR}. - *

The base type of the new datatype is the same as the base type of - * {@code oldType}. - * @param count number of blocks - * @param blockLength number of elements in each block - * @param stride number of elements between start of each block - * @param oldType old datatype - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createVector(int count, int blockLength, - int stride, Datatype oldType) - throws MPIException - { - MPI.check(); - long handle = getVector(count, blockLength, stride, oldType.handle); - return new Datatype(oldType, handle); - } - - private static native long getVector( - int count, int blockLength, int stride, long oldType) - throws MPIException; - - /** - * Identical to {@code createVector} except that the stride is expressed - * directly in terms of the buffer index, rather than the units of - * the old type. - *

Java binding of the MPI operation {@code MPI_TYPE_CREATE_HVECTOR}. - * @param count number of blocks - * @param blockLength number of elements in each - * @param stride number of bytes between start of each block - * @param oldType old datatype - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createHVector(int count, int blockLength, - int stride, Datatype oldType) - throws MPIException - { - MPI.check(); - long handle = getHVector(count, blockLength, stride, oldType.handle); - return new Datatype(oldType, handle); - } - - private static native long getHVector( - int count, int blockLength, int stride, long oldType) - throws MPIException; - - /** - * Construct new datatype representing replication of old datatype into - * a sequence of blocks where each block can contain a different number - * of copies and have a different displacement. - *

Java binding of the MPI operation {@code MPI_TYPE_INDEXED}. - *

The number of blocks is taken to be size of the {@code blockLengths} - * argument. The second argument, {@code displacements}, should be the - * same size. The base type of the new datatype is the same as the base - * type of {@code oldType}. - * @param blockLengths number of elements per block - * @param displacements displacement of each block in units of old type - * @param oldType old datatype - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createIndexed(int[] blockLengths, - int[] displacements, Datatype oldType) - throws MPIException - { - MPI.check(); - long handle = getIndexed(blockLengths, displacements, oldType.handle); - return new Datatype(oldType, handle); - } - - private static native long getIndexed( - int[] blockLengths, int[] displacements, long oldType) - throws MPIException; - - /** - * Identical to {@code createIndexed} except that the displacements are - * expressed directly in terms of the buffer index, rather than the - * units of the old type. - *

Java binding of the MPI operation {@code MPI_TYPE_CREATE_HINDEXED}. - * @param blockLengths number of elements per block - * @param displacements byte displacement in buffer for each block - * @param oldType old datatype - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createHIndexed(int[] blockLengths, - int[] displacements, Datatype oldType) - throws MPIException - { - MPI.check(); - long handle = getHIndexed(blockLengths, displacements, oldType.handle); - return new Datatype(oldType, handle); - } - - private static native long getHIndexed( - int[] blockLengths, int[] displacements, long oldType) - throws MPIException; - - /** - * The most general type constructor. - *

Java binding of the MPI operation {@code MPI_TYPE_CREATE_STRUCT}. - *

The number of blocks is taken to be size of the {@code blockLengths} - * argument. The second and third arguments, {@code displacements}, - * and {@code types}, should be the same size. - * @param blockLengths number of elements in each block - * @param displacements byte displacement of each block - * @param types type of elements in each block - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createStruct(int[] blockLengths, - int[] displacements, Datatype[] types) - throws MPIException - { - MPI.check(); - long handle = getStruct(blockLengths, displacements, types); - return new Datatype(MPI.BYTE, handle); - } - - private static native long getStruct( - int[] blockLengths, int[] displacements, Datatype[] types) - throws MPIException; - - /* - * JMS add proper documentation here - * JMS int != Aint! This needs to be fixed throughout. - */ - /** - * Create a datatype with a new lower bound and extent from an existing - * datatype. - *

Java binding of the MPI operation {@code MPI_TYPE_CREATE_RESIZED}. - * @param oldType input datatype - * @param lb new lower bound of datatype (address integer) - * @param extent new extent of datatype (address integer) - * @return new datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Datatype createResized(Datatype oldType, int lb, int extent) - throws MPIException - { - MPI.check(); - long handle = getResized(oldType.handle, lb, extent); - return new Datatype(oldType, handle); - } - - private static native long getResized(long oldType, int lb, int extent); - - /** - * Sets the print name for the datatype. - * @param name name for the datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setName(String name) throws MPIException - { - MPI.check(); - setName(handle, name); - } - - private native void setName(long handle, String name) throws MPIException; - - /** - * Return the print name from the datatype. - * @return name of the datatype - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public String getName() throws MPIException - { - MPI.check(); - return getName(handle); - } - - private native String getName(long handle) throws MPIException; - - /** - * Create a new attribute key. - *

Java binding of the MPI operation {@code MPI_TYPE_CREATE_KEYVAL}. - * @return attribute key for future access - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int createKeyval() throws MPIException - { - MPI.check(); - return createKeyval_jni(); - } - - private static native int createKeyval_jni() throws MPIException; - - /** - * Frees an attribute key. - *

Java binding of the MPI operation {@code MPI_TYPE_FREE_KEYVAL}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void freeKeyval(int keyval) throws MPIException - { - MPI.check(); - freeKeyval_jni(keyval); - } - - private static native void freeKeyval_jni(int keyval) throws MPIException; - - /** - * Stores attribute value associated with a key. - *

Java binding of the MPI operation {@code MPI_TYPE_SET_ATTR}. - * @param keyval attribute key - * @param value attribute value - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setAttr(int keyval, Object value) throws MPIException - { - MPI.check(); - setAttr(handle, keyval, MPI.attrSet(value)); - } - - private native void setAttr(long type, int keyval, byte[] value) - throws MPIException; - - /** - * Retrieves attribute value by key. - *

Java binding of the MPI operation {@code MPI_TYPE_GET_ATTR}. - * @param keyval attribute key - * @return attribute value or null if no attribute is associated with the key. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Object getAttr(int keyval) throws MPIException - { - MPI.check(); - Object obj = getAttr(handle, keyval); - return obj instanceof byte[] ? MPI.attrGet((byte[])obj) : obj; - } - - private native Object getAttr(long type, int keyval) throws MPIException; - - /** - * Deletes an attribute value associated with a key. - *

Java binding of the MPI operation {@code MPI_TYPE_DELETE_ATTR}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void deleteAttr(int keyval) throws MPIException - { - MPI.check(); - deleteAttr(handle, keyval); - } - - private native void deleteAttr(long type, int keyval) throws MPIException; - - /** - * Gets the offset of a buffer in bytes. - * @param buffer buffer - * @return offset in bytes - */ - protected int getOffset(Object buffer) - { - return baseSize * ((Buffer)buffer).arrayOffset(); - } - -} // Datatype diff --git a/ompi/mpi/java/java/DistGraphNeighbors.java b/ompi/mpi/java/java/DistGraphNeighbors.java deleted file mode 100644 index e96243bb0d8..00000000000 --- a/ompi/mpi/java/java/DistGraphNeighbors.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Adjacency information for a distributed graph topology. - */ -public final class DistGraphNeighbors -{ - private final int[] sources, sourceWeights, destinations, destWeights; - private final boolean weighted; - - protected DistGraphNeighbors( - int[] sources, int[] sourceWeights, - int[] destinations, int[] destWeights, boolean weighted) - { - this.sources = sources; - this.sourceWeights = sourceWeights; - this.destinations = destinations; - this.destWeights = destWeights; - this.weighted = weighted; - } - - /** - * Gets the number of edges into this process. - * @return number of edges into this process - */ - public int getInDegree() - { - return sources.length; - } - - /** - * Gets the number of edges out of this process. - * @return number of edges out of this process - */ - public int getOutDegree() - { - return destinations.length; - } - - /** - * Returns false if {@code MPI_UNWEIGHTED} was supplied during creation. - * @return false if {@code MPI_UNWEIGHTED} was supplied, true otherwise - */ - public boolean isWeighted() - { - return weighted; - } - - /** - * Gets a process for which the calling process is a destination. - * @param i source index - * @return process for which the calling process is a destination - */ - public int getSource(int i) - { - return sources[i]; - } - - /** - * Gets the weight of an edge into the calling process. - * @param i source index - * @return weight of the edge into the calling process - */ - public int getSourceWeight(int i) - { - return sourceWeights[i]; - } - - /** - * Gets a process for which the calling process is a source - * @param i destination index - * @return process for which the calling process is a source - */ - public int getDestination(int i) - { - return destinations[i]; - } - - /** - * Gets the weight of an edge out of the calling process. - * @param i destination index - * @return weight of an edge out of the calling process - */ - public int getDestinationWeight(int i) - { - return destWeights[i]; - } - -} // DistGraphNeighbors diff --git a/ompi/mpi/java/java/DoubleComplex.java b/ompi/mpi/java/java/DoubleComplex.java deleted file mode 100644 index 3a75e3e6866..00000000000 --- a/ompi/mpi/java/java/DoubleComplex.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -import java.nio.*; - -/** - * This class wraps a complex number stored in a buffer. - */ -public final class DoubleComplex -{ - private final int offset; - private final DoubleBuffer buffer; - - private DoubleComplex(DoubleBuffer buffer, int index) - { - this.buffer = buffer; - this.offset = index * 2; - } - - /** - * Wraps a complex number stored in a buffer - * @param buffer buffer - * @return complex number - */ - public static DoubleComplex get(DoubleBuffer buffer) - { - return new DoubleComplex(buffer, 0); - } - - /** - * Wraps the complex number at the specified position - * of an array of complex numbers stored in a buffer. - * @param buffer buffer - * @param index index - * @return complex number - */ - public static DoubleComplex get(DoubleBuffer buffer, int index) - { - return new DoubleComplex(buffer, index); - } - - /** - * Wraps a complex number stored in the first two values of an array. - * @param array array - * @return complex number - */ - public static DoubleComplex get(double[] array) - { - return new DoubleComplex(DoubleBuffer.wrap(array), 0); - } - - /** - * Wraps the complex number at the specified position of - * an array of complex numbers stored in an array of doubles. - * @param array array - * @param index index - * @return complex number - */ - public static DoubleComplex get(double[] array, int index) - { - return new DoubleComplex(DoubleBuffer.wrap(array), index); - } - - /** - * Wraps a complex number stored in a buffer - * @param buffer buffer - * @return complex number - */ - public static DoubleComplex get(ByteBuffer buffer) - { - return new DoubleComplex(buffer.asDoubleBuffer(), 0); - } - - /** - * Wraps the complex number at the specified position - * of an array of complex numbers stored in a buffer. - * @param buffer buffer - * @param index index - * @return complex number - */ - public static DoubleComplex get(ByteBuffer buffer, int index) - { - return new DoubleComplex(buffer.asDoubleBuffer(), index); - } - - /** - * Gets the real value. - * @return real value - */ - public double getReal() - { - return buffer.get(offset); - } - - /** - * Gets the imaginary value. - * @return imaginary value. - */ - public double getImag() - { - return buffer.get(offset + 1); - } - - /** - * Puts the real value. - * @param real real value - */ - public void putReal(double real) - { - buffer.put(offset, real); - } - - /** - * Puts the imaginary value. - * @param imag imaginary value - */ - public void putImag(double imag) - { - buffer.put(offset + 1, imag); - } - - /** - * Gets the buffer where the complex number is stored. - * @return buffer where the complex number is stored - */ - public DoubleBuffer getBuffer() - { - return offset == 0 ? buffer : MPI.slice(buffer, offset); - } - -} // DoubleComplex diff --git a/ompi/mpi/java/java/DoubleInt.java b/ompi/mpi/java/java/DoubleInt.java deleted file mode 100644 index ac75ffb5e7a..00000000000 --- a/ompi/mpi/java/java/DoubleInt.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Struct class for {@link MPI#DOUBLE_INT} datatype. - */ -public final class DoubleInt extends Struct -{ - private final int iOff, iSize; - - /** - * The struct object will be created only in MPI class. - * @param intOff int offset - * @param intSize int size - * @see MPI#doubleInt - */ - protected DoubleInt(int intOff, int intSize) - { - int dOff = addDouble(); - assert dOff == 0; - - iSize = intSize; - setOffset(intOff); - - switch(iSize) - { - case 4: iOff = addInt(); break; - case 8: iOff = addLong(); break; - default: throw new AssertionError("Unsupported int size: "+ iSize); - } - - assert(intOff == iOff); - } - - /** - * Creates a Data object. - * @return new Data object. - */ - @Override protected DoubleInt.Data newData() - { - return new DoubleInt.Data(); - } - - /** - * Class for reading/writing data in a struct stored in a byte buffer. - */ - public final class Data extends Struct.Data - { - /** - * Gets the double value. - * @return double value - */ - public double getValue() - { - return getDouble(0); - } - - /** - * Gets the int value. - * @return int value - */ - public int getIndex() - { - switch(iSize) - { - case 4: return getInt(iOff); - case 8: return (int)getLong(iOff); - default: throw new AssertionError(); - } - } - - /** - * Puts the double value. - * @param v double value - */ - public void putValue(double v) - { - putDouble(0, v); - } - - /** - * Puts the int value. - * @param v int value - */ - public void putIndex(int v) - { - switch(iSize) - { - case 4: putInt(iOff, v); break; - case 8: putLong(iOff, v); break; - default: throw new AssertionError(); - } - } - } // Data - -} // DoubleInt diff --git a/ompi/mpi/java/java/Errhandler.java b/ompi/mpi/java/java/Errhandler.java deleted file mode 100644 index cc7fa6e73e1..00000000000 --- a/ompi/mpi/java/java/Errhandler.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Errhandler.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.3 $ - * Updated : $Date: 2001/08/07 16:36:25 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Error handler. - */ -public final class Errhandler -{ - protected long handle; - - protected static native long getFatal(); - protected static native long getAbort(); - protected static native long getReturn(); - - protected Errhandler(long handle) - { - this.handle = handle; - } - -} // Errhandler diff --git a/ompi/mpi/java/java/File.java b/ompi/mpi/java/java/File.java deleted file mode 100644 index 08534be2744..00000000000 --- a/ompi/mpi/java/java/File.java +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017-2018 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * IMPLEMENTATION DETAILS - * - * All methods with buffers that can be direct or non direct have - * a companion argument 'db' which is true if the buffer is direct. - * - * Checking if a buffer is direct is faster in Java than C. - */ - -package mpi; - -import java.nio.*; -import static mpi.MPI.isHeapBuffer; -import static mpi.MPI.isDirectBuffer; -import static mpi.MPI.assertDirectBuffer; - -/** - * This class represents {@code MPI_File}. - */ -public final class File -{ - private long handle; - private FileView view = new FileView(0, MPI.BYTE, MPI.BYTE, "native"); - private Status beginStatus; - - /** - * Java binding of {@code MPI_FILE_OPEN} using {@code MPI_INFO_NULL}. - * @param comm communicator - * @param filename name of the file to open - * @param amode file access mode - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public File(Comm comm, String filename, int amode) throws MPIException - { - MPI.check(); - handle = open(comm.handle, filename, amode, Info.NULL); - } - - /** - * Java binding of {@code MPI_FILE_OPEN}. - * @param comm communicator - * @param filename name of the file to open - * @param amode file access mode - * @param info info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public File(Comm comm, String filename, int amode, Info info) - throws MPIException - { - MPI.check(); - handle = open(comm.handle, filename, amode, info.handle); - } - - private native long open(long comm, String filename, int amode, long info) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_CLOSE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void close() throws MPIException - { - MPI.check(); - handle = close(handle); - } - - private native long close(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_DELETE} using {@code MPI_INFO_NULL}. - * @param filename name of the file to delete - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void delete(String filename) throws MPIException - { - MPI.check(); - delete(filename, Info.NULL); - } - - /** - * Java binding of {@code MPI_FILE_DELETE}. - * @param filename name of the file to delete - * @param info info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void delete(String filename, Info info) throws MPIException - { - MPI.check(); - delete(filename, info.handle); - } - - private static native void delete(String filename, long info) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SET_SIZE}. - * @param size size to truncate or expand file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setSize(long size) throws MPIException - { - MPI.check(); - setSize(handle, size); - } - - private native void setSize(long fh, long size) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_PREALLOCATE}. - * @param size size to preallocate file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void preallocate(long size) throws MPIException - { - MPI.check(); - preallocate(handle, size); - } - - private native void preallocate(long fh, long size) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_SIZE}. - * @return size of file in bytes - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public long getSize() throws MPIException - { - MPI.check(); - return getSize(handle); - } - - private native long getSize(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_GROUP}. - * @return group which opened the file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group getGroup() throws MPIException - { - MPI.check(); - return new Group(getGroup(handle)); - } - - private native long getGroup(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_AMODE}. - * @return file access mode to open the file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getAMode() throws MPIException - { - MPI.check(); - return getAMode(handle); - } - - private native int getAMode(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SET_INFO}. - * @param info info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setInfo(Info info) throws MPIException - { - MPI.check(); - setInfo(handle, info.handle); - } - - private native void setInfo(long fh, long info) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_INFO}. - * @return new info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Info getInfo() throws MPIException - { - MPI.check(); - return new Info(getInfo(handle)); - } - - private native long getInfo(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SET_VIEW} using {@code MPI_INFO_NULL}. - * @param disp displacement - * @param etype elementary datatype - * @param filetype filetype - * @param datarep data representation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setView(long disp, Datatype etype, - Datatype filetype, String datarep) - throws MPIException - { - MPI.check(); - setView(handle, disp, etype.handle, filetype.handle, datarep, Info.NULL); - view = new FileView(disp, etype, filetype, datarep); - } - - /** - * Java binding of {@code MPI_FILE_SET_VIEW}. - * @param disp displacement - * @param etype elementary datatype - * @param filetype filetype - * @param datarep data representation - * @param info info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setView(long disp, Datatype etype, - Datatype filetype, String datarep, Info info) - throws MPIException - { - MPI.check(); - setView(handle, disp, etype.handle, filetype.handle, datarep, info.handle); - view = new FileView(disp, etype, filetype, datarep); - } - - private native void setView( - long fh, long disp, long etype, - long filetype, String datarep, long info) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_VIEW}. - * @return file view - */ - public FileView getView() - { - return view; - } - - /** - * Java binding of {@code MPI_FILE_READ_AT}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readAt(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readAt(handle, offset, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void readAt( - long fh, long fileOffset, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_AT_ALL}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readAtAll(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readAtAll(handle, offset, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void readAtAll( - long fh, long fileOffset, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_AT}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeAt(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeAt(handle, offset, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void writeAt( - long fh, long fileOffset, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_AT_ALL}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeAtAll(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeAtAll(handle, offset, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void writeAtAll( - long fh, long fileOffset, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IREAD_AT}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iReadAt(long offset, Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iReadAt(handle, offset, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReadAt( - long fh, long offset, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IREAD_AT_ALL}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iReadAtAll(long offset, Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iReadAtAll(handle, offset, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReadAtAll( - long fh, long offset, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IWRITE_AT}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iWriteAt(long offset, Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iWriteAt(handle, offset, buf, count, type.handle)); - req.addSendBufRef(buf); - return req; - } - - private native long iWriteAt( - long fh, long offset, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IWRITE_AT_ALL}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iWriteAtAll(long offset, Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iWriteAtAll(handle, offset, buf, count, type.handle)); - req.addSendBufRef(buf); - return req; - } - - private native long iWriteAtAll( - long fh, long offset, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status read(Object buf, int count, Datatype type) throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - read(handle, buf, db, off, count, type.handle, type.baseType, status.data); - return status; - } - - private native void read( - long fh, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ALL}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readAll(Object buf, int count, Datatype type) throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readAll(handle, buf,db,off, count, type.handle, type.baseType, status.data); - return status; - } - - private native void readAll( - long fh, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status write(Object buf, int count, Datatype type) throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - write(handle, buf, db, off, count, type.handle, type.baseType, status.data); - return status; - } - - private native void write( - long fh, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ALL}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeAll(Object buf, int count, Datatype type) throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeAll(handle, buf,db,off, count, type.handle,type.baseType, status.data); - return status; - } - - private native void writeAll( - long fh, Object buf, boolean db, int offset, - int count, long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IREAD}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iRead(Buffer buf, int count, Datatype type) throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iRead(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iRead(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IREAD_ALL}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iReadAll(Buffer buf, int count, Datatype type) throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iReadAll(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReadAll(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IWRITE}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iWrite(Buffer buf, int count, Datatype type) throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iWrite(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iWrite(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IWRITE_ALL}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iWriteAll(Buffer buf, int count, Datatype type) throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iWriteAll(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iWriteAll(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SEEK}. - * @param offset file offset - * @param whence update mode - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void seek(long offset, int whence) throws MPIException - { - MPI.check(); - seek(handle, offset, whence); - } - - private native void seek(long fh, long offset, int whence) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_POSITION}. - * @return offset of individual pointer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public long getPosition() throws MPIException - { - MPI.check(); - return getPosition(handle); - } - - private native long getPosition(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_BYTE_OFFSET}. - * @param offset offset - * @return absolute byte position of offset - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public long getByteOffset(long offset) throws MPIException - { - MPI.check(); - return getByteOffset(handle, offset); - } - - private native long getByteOffset(long fh, long offset) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_SHARED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readShared(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readShared(handle, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void readShared( - long fh, Object buf, boolean db, int offset, int count, - long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_SHARED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeShared(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeShared(handle, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void writeShared( - long fh, Object buf, boolean db, int offset, int count, - long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IREAD_SHARED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iReadShared(Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iReadShared(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iReadShared(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_IWRITE_SHARED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request iWriteShared(Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(iWriteShared(handle, buf, count, type.handle)); - req.addSendBufRef(buf); - return req; - } - - private native long iWriteShared(long fh, Buffer buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ORDERED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readOrdered(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readOrdered(handle, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void readOrdered( - long fh, Object buf, boolean db, int offset, int count, - long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ORDERED}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeOrdered(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeOrdered(handle, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native void writeOrdered( - long fh, Object buf, boolean db, int offset, int count, - long type, int baseType, long[] stat) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SEEK_SHARED}. - * @param offset file offset - * @param whence update mode - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void seekShared(long offset, int whence) throws MPIException - { - MPI.check(); - seekShared(handle, offset, whence); - } - - private native void seekShared(long fh, long offset, int whence) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_POSITION_SHARED}. - * @return offset of individual pointer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public long getPositionShared() throws MPIException - { - MPI.check(); - return getPositionShared(handle); - } - - private native long getPositionShared(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_AT_ALL_BEGIN}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void readAtAllBegin(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - readAtAllBegin(handle, offset, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readAtAll(handle, offset, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void readAtAllBegin( - long fh, long offset, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_AT_ALL_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readAtAllEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - readAtAllEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void readAtAllEnd(long fh, Object buf, long[] stat) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_AT_ALL_BEGIN}. - * @param offset file offset - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void writeAtAllBegin(long offset, Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - writeAtAllBegin(handle, offset, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeAtAll(handle, offset, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void writeAtAllBegin( - long fh, long fileOffset, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_AT_ALL_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeAtAllEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - writeAtAllEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void writeAtAllEnd(long fh, Object buf, long[] stat) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ALL_BEGIN}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void readAllBegin(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - readAllBegin(handle, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readAll(handle, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void readAllBegin(long fh, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ALL_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readAllEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - readAllEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void readAllEnd(long fh, Object buf, long[] stat) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ALL_BEGIN}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void writeAllBegin(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - writeAllBegin(handle, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeAll(handle, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void writeAllBegin(long fh, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ALL_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeAllEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - writeAllEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void writeAllEnd(long fh, Object buf, long[] stat) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ORDERED_BEGIN}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void readOrderedBegin(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - readOrderedBegin(handle, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - readOrdered(handle, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void readOrderedBegin(long fh, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_READ_ORDERED_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status readOrderedEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - readOrderedEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void readOrderedEnd(long fh, Object buf, long[] stat) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ORDERED_BEGIN}. - * @param buf buffer - * @param count number of items in buffer - * @param type datatype of each buffer element - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void writeOrderedBegin(Object buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - writeOrderedBegin(handle, buf, count, type.handle); - } - else - { - int off = 0; - Status status = new Status(); - - if(isHeapBuffer(buf)) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - writeOrdered(handle, buf, false, off, count, - type.handle, type.baseType, status.data); - - beginStatus = status; - } - } - - private native void writeOrderedBegin(long fh, Object buf, int count, long type) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_WRITE_ORDERED_END}. - * @param buf buffer - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status writeOrderedEnd(Object buf) throws MPIException - { - MPI.check(); - - if(isDirectBuffer(buf)) - { - Status status = new Status(); - writeOrderedEnd(handle, buf, status.data); - return status; - } - else - { - return getBeginStatus(); - } - } - - private native void writeOrderedEnd(long fh, Object buf, long[] stat) - throws MPIException; - - private Status getBeginStatus() - { - Status s = beginStatus; - beginStatus = null; - return s; - } - - /** - * Java binding of {@code MPI_FILE_GET_TYPE_EXTENT}. - * @param type type of data - * @return datatype extent - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getTypeExtent(Datatype type) throws MPIException - { - MPI.check(); - return getTypeExtent(handle, type.handle) / type.baseSize; - } - - private native int getTypeExtent(long fh, long type) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SET_ATOMICITY}. - * @param atomicity true to set atomic mode, false to set nonatomic mode - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setAtomicity(boolean atomicity) throws MPIException - { - MPI.check(); - setAtomicity(handle, atomicity); - } - - private native void setAtomicity(long fh, boolean atomicity) - throws MPIException; - - /** - * Java binding of {@code MPI_FILE_GET_ATOMICITY}. - * @return current consistency of the file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public boolean getAtomicity() throws MPIException - { - MPI.check(); - return getAtomicity(handle); - } - - private native boolean getAtomicity(long fh) throws MPIException; - - /** - * Java binding of {@code MPI_FILE_SYNC}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void sync() throws MPIException - { - MPI.check(); - sync(handle); - } - - private native void sync(long handle) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_FILE_SET_ERRHANDLER}. - * @param errhandler new MPI error handler for file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setErrhandler(Errhandler errhandler) throws MPIException - { - MPI.check(); - setErrhandler(handle, errhandler.handle); - } - - private native void setErrhandler(long fh, long errhandler) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_FILE_GET_ERRHANDLER}. - * @return MPI error handler currently associated with file - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Errhandler getErrhandler() throws MPIException - { - MPI.check(); - return new Errhandler(getErrhandler(handle)); - } - - private native long getErrhandler(long fh); - - /** - * Java binding of the MPI operation {@code MPI_FILE_CALL_ERRHANDLER}. - * @param errorCode error code - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void callErrhandler(int errorCode) throws MPIException - { - callErrhandler(handle, errorCode); - } - - private native void callErrhandler(long handle, int errorCode) - throws MPIException; - -} // File diff --git a/ompi/mpi/java/java/FileView.java b/ompi/mpi/java/java/FileView.java deleted file mode 100644 index cb791056c42..00000000000 --- a/ompi/mpi/java/java/FileView.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * This class represents file views. - */ -public final class FileView -{ - private final long disp; - private final Datatype etype, filetype; - private final String datarep; - - /** - * Constructs a file view. - * @param disp displacement - * @param etype elementary datatype - * @param filetype file type - * @param datarep data representation - */ - public FileView(long disp, Datatype etype, Datatype filetype, String datarep) - { - this.disp = disp; - this.etype = etype; - this.filetype = filetype; - this.datarep = datarep; - } - - /** - * Gets the displacement. - * @return displacement - */ - public long getDisp() - { - return disp; - } - - /** - * Gets the elementary datatype. - * @return elementary datatype - */ - public Datatype getEType() - { - return etype; - } - - /** - * Gets the file type. - * @return file type - */ - public Datatype getFileType() - { - return filetype; - } - - /** - * Gets the data representation. - * @return data representation - */ - public String getDataRep() - { - return datarep; - } - -} // FileView diff --git a/ompi/mpi/java/java/FloatComplex.java b/ompi/mpi/java/java/FloatComplex.java deleted file mode 100644 index 572f1d6fb30..00000000000 --- a/ompi/mpi/java/java/FloatComplex.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -import java.nio.*; - -/** - * This class wraps a complex number stored in a buffer. - */ -public final class FloatComplex -{ - private final int offset; - private final FloatBuffer buffer; - - private FloatComplex(FloatBuffer buffer, int index) - { - this.buffer = buffer; - this.offset = index * 2; - } - - /** - * Wraps a complex number stored in a buffer - * @param buffer buffer - * @return complex number - */ - public static FloatComplex get(FloatBuffer buffer) - { - return new FloatComplex(buffer, 0); - } - - /** - * Wraps the complex number at the specified position - * of an array of complex numbers stored in a buffer. - * @param buffer buffer - * @param index index - * @return complex number - */ - public static FloatComplex get(FloatBuffer buffer, int index) - { - return new FloatComplex(buffer, index); - } - - /** - * Wraps a complex number stored in the first two values of an array. - * @param array array - * @return complex number - */ - public static FloatComplex get(float[] array) - { - return new FloatComplex(FloatBuffer.wrap(array), 0); - } - - /** - * Wraps the complex number at the specified position of - * an array of complex numbers stored in an array of floats. - * @param array array - * @param index index - * @return complex number - */ - public static FloatComplex get(float[] array, int index) - { - return new FloatComplex(FloatBuffer.wrap(array), index); - } - - /** - * Wraps a complex number stored in a buffer - * @param buffer buffer - * @return complex number - */ - public static FloatComplex get(ByteBuffer buffer) - { - return new FloatComplex(buffer.asFloatBuffer(), 0); - } - - /** - * Wraps the complex number at the specified position - * of an array of complex numbers stored in a buffer. - * @param buffer buffer - * @param index index - * @return complex number - */ - public static FloatComplex get(ByteBuffer buffer, int index) - { - return new FloatComplex(buffer.asFloatBuffer(), index); - } - - /** - * Gets the real value. - * @return real value - */ - public float getReal() - { - return buffer.get(offset); - } - - /** - * Gets the imaginary value. - * @return imaginary value. - */ - public float getImag() - { - return buffer.get(offset + 1); - } - - /** - * Puts the real value. - * @param real real value - */ - public void putReal(float real) - { - buffer.put(offset, real); - } - - /** - * Puts the imaginary value. - * @param imag imaginary value - */ - public void putImag(float imag) - { - buffer.put(offset + 1, imag); - } - - /** - * Gets the buffer where the complex number is stored. - * @return buffer where the complex number is stored - */ - public FloatBuffer getBuffer() - { - return offset == 0 ? buffer : MPI.slice(buffer, offset); - } - -} // FloatComplex diff --git a/ompi/mpi/java/java/FloatInt.java b/ompi/mpi/java/java/FloatInt.java deleted file mode 100644 index 1eb55bde76c..00000000000 --- a/ompi/mpi/java/java/FloatInt.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Struct class for {@link MPI#FLOAT_INT} datatype. - */ -public final class FloatInt extends Struct -{ - private final int iOff, iSize; - - /** - * The struct object will be created only in MPI class. - * @param intOff int offset - * @param intSize int size - * @see MPI#floatInt - */ - protected FloatInt(int intOff, int intSize) - { - int fOff = addFloat(); - assert fOff == 0; - - iSize = intSize; - setOffset(intOff); - - switch(iSize) - { - case 4: iOff = addInt(); break; - case 8: iOff = addLong(); break; - default: throw new AssertionError("Unsupported int size: "+ iSize); - } - - assert(intOff == iOff); - } - - /** - * Creates a Data object. - * @return new Data object. - */ - @Override protected Data newData() - { - return new Data(); - } - - /** - * Class for reading/writing data in a struct stored in a byte buffer. - */ - public final class Data extends Struct.Data - { - /** - * Gets the float value. - * @return float value - */ - public float getValue() - { - return getFloat(0); - } - - /** - * Gets the int value. - * @return int value - */ - public int getIndex() - { - switch(iSize) - { - case 4: return getInt(iOff); - case 8: return (int)getLong(iOff); - default: throw new AssertionError(); - } - } - - /** - * Puts the float value. - * @param v float value - */ - public void putValue(float v) - { - putFloat(0, v); - } - - /** - * Puts the int value. - * @param v int value - */ - public void putIndex(int v) - { - switch(iSize) - { - case 4: putInt(iOff, v); break; - case 8: putLong(iOff, v); break; - default: throw new AssertionError(); - } - } - } // Data - -} // FloatInt diff --git a/ompi/mpi/java/java/Freeable.java b/ompi/mpi/java/java/Freeable.java deleted file mode 100644 index 736a729fee1..00000000000 --- a/ompi/mpi/java/java/Freeable.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Freeable.java - * Author : Bryan Carpenter - * Created : Wed Jan 15 23:14:43 EST 2003 - * Revision : $Revision: 1.1 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - */ - -package mpi; - -/** - * Objects freeables must be freed calling the method free. - */ -public interface Freeable -{ - /** - * Frees a freeable object. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - void free() throws MPIException; -} - diff --git a/ompi/mpi/java/java/GraphComm.java b/ompi/mpi/java/java/GraphComm.java deleted file mode 100644 index 8ee75c2459a..00000000000 --- a/ompi/mpi/java/java/GraphComm.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Graphcomm.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.5 $ - * Updated : $Date: 2001/10/22 21:07:55 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Communicator with graph structure. - */ -public final class GraphComm extends Intracomm -{ - static - { - init(); - } - - private static native void init(); - - protected GraphComm(long handle) throws MPIException - { - super(handle); - } - - protected GraphComm(long[] commRequest) - { - super(commRequest); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return copy of this communicator - */ - @Override public GraphComm clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public GraphComm dup() throws MPIException - { - MPI.check(); - return new GraphComm(dup(handle)); - } - - /** - * Duplicates this communicator. - *

The new communicator can't be used before the operation completes. - * The request object must be obtained calling {@link #getRequest}. - *

Java binding of {@code MPI_COMM_IDUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public GraphComm iDup() throws MPIException - { - MPI.check(); - return new GraphComm(iDup(handle)); - } - - /** - * Duplicates this communicator with the info object used in the call. - *

Java binding of {@code MPI_COMM_DUP_WITH_INFO}. - * @param info info object to associate with the new communicator - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public GraphComm dupWithInfo(Info info) throws MPIException - { - MPI.check(); - return new GraphComm(dupWithInfo(handle, info.handle)); - } - - /** - * Returns graph topology information. - *

Java binding of the MPI operations {@code MPI_GRAPHDIMS_GET} - * and {@code MPI_GRAPH_GET}. - *

The number of nodes and number of edges can be extracted - * from the sizes of the {@code index} and {@code edges} fields - * of the returned object. - * @return object defining node degrees and edges of graph - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public GraphParms getDims() throws MPIException - { - MPI.check(); - return getDims(handle); - } - - private native GraphParms getDims(long comm) throws MPIException; - - /** - * Provides adjacency information for general graph topology. - *

Java binding of the MPI operations {@code MPI_GRAPH_NEIGHBORS_COUNT} - * and {@code MPI_GRAPH_NEIGHBORS}. - *

The number of neighbors can be extracted from the size of the result. - * @param rank rank of a process in the group of this communicator - * @return array of ranks of neighboring processes to one specified - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int[] getNeighbors(int rank) throws MPIException - { - MPI.check(); - return getNeighbors(handle, rank); - } - - private native int[] getNeighbors(long comm, int rank) throws MPIException; - - /** - * Gets the adjacency information for a distributed graph topology. - * @return adjacency information for a distributed graph topology - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public DistGraphNeighbors getDistGraphNeighbors() throws MPIException - { - MPI.check(); - return getDistGraphNeighbors(handle); - } - - private native DistGraphNeighbors getDistGraphNeighbors(long comm) - throws MPIException; - - /** - * Compute an optimal placement. - *

Java binding of the MPI operation {@code MPI_GRAPH_MAP}. - *

The number of nodes is taken to be size of the {@code index} argument. - * @param index node degrees - * @param edges graph edges - * @return reordered rank of calling process - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int map(int[] index, int[] edges) throws MPIException - { - MPI.check(); - return map(handle, index, edges); - } - - private native int map(long comm, int[] index, int[] edges) throws MPIException; - -} // Graphcomm diff --git a/ompi/mpi/java/java/GraphParms.java b/ompi/mpi/java/java/GraphParms.java deleted file mode 100644 index 49dc5b1a789..00000000000 --- a/ompi/mpi/java/java/GraphParms.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : GraphParms.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.1 $ - * Updated : $Date: 1998/08/26 18:49:55 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Graph topology information associated with a communicator. - */ -public final class GraphParms -{ - /** Node degrees. */ - private final int[] index; - - /** Graph edges. */ - private final int[] edges; - - /** - * Constructs a graph topology information object. - * @param index node degrees. - * @param edges graph edges. - */ - protected GraphParms(int[] index, int[] edges) - { - this.index = index; - this.edges = edges; - } - - /** - * Returns the number of nodes. - * @return number of nodes. - */ - public int getIndexCount() - { - return index.length; - } - - /** - * Returns the index of the node {@code i}. - *

{@code getIndex(0)} returns the degree of the node {@code 0}, and - * {@code getIndex(i)-getIndex(i-1)} is the degree of the node {@code i}. - * @param i position of the node. - * @return the index. - */ - public int getIndex(int i) - { - return index[i]; - } - - /** - * Returns the number of edges. - * @return number of edges. - */ - public int getEdgeCount() - { - return edges.length; - } - - /** - * Returns the edge {@code i}. - *

The list of neighbors of node zero is stored in {@code getEdge(j)}, - * for {@code 0} ≤ {@code j} ≤ {@code getIndex(0)-1} and the list - * of neighbors of node {@code i}, {@code i} > {@code 0}, is stored - * in {@code getEdge(j)}, {@code getIndex(i-1)} ≤ {@code j} ≤ - * {@code getIndex(i)-1}. - * @param i index of the edge. - * @return the edge. - */ - public int getEdge(int i) - { - return edges[i]; - } - -} // GraphParms diff --git a/ompi/mpi/java/java/Group.java b/ompi/mpi/java/java/Group.java deleted file mode 100644 index 254af2100fb..00000000000 --- a/ompi/mpi/java/java/Group.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Group.java - * Author : Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.8 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * This class represents {@code MPI_Group}. - */ -public final class Group implements Freeable -{ - protected long handle; - private static long nullHandle; - - static - { - init(); - } - - private static native void init(); - - protected static native long getEmpty(); - - protected Group(long handle) - { - this.handle = handle; - } - - /** - * Java binding of the MPI operation {@code MPI_GROUP_SIZE}. - * @return number of processes in the group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getSize() throws MPIException - { - MPI.check(); - return getSize(handle); - } - - private native int getSize(long group) throws MPIException; - - /** - * Rank of this process in the group. - *

Java binding of the MPI operation {@code MPI_GROUP_RANK}. - * @return rank of this process in the group, or {@code MPI.UNDEFINED} - * if this process is not a member of the group. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getRank() throws MPIException - { - MPI.check(); - return getRank(handle); - } - - private native int getRank(long group) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_GROUP_FREE}. - */ - @Override public void free() throws MPIException - { - MPI.check(); - handle = free(handle); - } - - private native long free(long group); - - /** - * Test if group object is null. - * @return true if the group object is null. - */ - public boolean isNull() - { - return handle == nullHandle; - } - - /** - * Translate ranks within one group to ranks within another. - *

Java binding of the MPI operation {@code MPI_GROUP_TRANSLATE_RANKS}. - *

Result elements are {@code MPI.UNDEFINED} where no correspondence exists. - * @param group1 a group - * @param ranks1 array of valid ranks in group1 - * @param group2 another group - * @return array of corresponding ranks in group2 - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int[] translateRanks(Group group1, int[] ranks1, Group group2) - throws MPIException - { - MPI.check(); - return translateRanks(group1.handle, ranks1, group2.handle); - } - - private static native int[] translateRanks( - long group1, int[] ranks1, long group2) throws MPIException; - - /** - * Compare two groups. - *

Java binding of the MPI operation {@code MPI_GROUP_COMPARE}. - * @param group1 first group - * @param group2 second group - * @return {@code MPI.IDENT} if the group members and group order are exactly - * the same in both groups, {@code MPI.SIMILAR} if the group members are - * the same but the order is different, {@code MPI.UNEQUAL} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int compare(Group group1, Group group2) throws MPIException - { - MPI.check(); - return compare(group1.handle, group2.handle); - } - - private static native int compare(long group1, long group2) throws MPIException; - - /** - * Set union of two groups. - *

Java binding of the MPI operation {@code MPI_GROUP_UNION}. - * @param group1 first group - * @param group2 second group - * @return union group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Group union(Group group1, Group group2) throws MPIException - { - MPI.check(); - return new Group(union(group1.handle, group2.handle)); - } - - private static native long union(long group1, long group2); - - /** - * Set intersection of two groups. - * Java binding of the MPI operation {@code MPI_GROUP_INTERSECTION}. - * @param group1 first group - * @param group2 second group - * @return intersection group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Group intersection(Group group1, Group group2) throws MPIException - { - MPI.check(); - return new Group(intersection(group1.handle, group2.handle)); - } - - private static native long intersection(long group1, long group2); - - /** - * Set difference of two groups. - * Java binding of the MPI operation {@code MPI_GROUP_DIFFERENCE}. - * @param group1 first group - * @param group2 second group - * @return difference group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Group difference(Group group1, Group group2) throws MPIException - { - MPI.check(); - return new Group(difference(group1.handle, group2.handle)); - } - - private static native long difference(long group1, long group2); - - /** - * Create a subset group including specified processes. - *

Java binding of the MPI operation {@code MPI_GROUP_INCL}. - * @param ranks ranks from this group to appear in new group - * @return new group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group incl(int[] ranks) throws MPIException - { - MPI.check(); - return new Group(incl(handle, ranks)); - } - - private native long incl(long group, int[] ranks); - - /** - * Create a subset group excluding specified processes. - *

Java binding of the MPI operation {@code MPI_GROUP_EXCL}. - * @param ranks ranks from this group not to appear in new group - * @return new group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group excl(int[] ranks) throws MPIException - { - MPI.check(); - return new Group(excl(handle, ranks)); - } - - private native long excl(long group, int[] ranks); - - /** - * Create a subset group including processes specified - * by strided intervals of ranks. - *

Java binding of the MPI operation {@code MPI_GROUP_RANGE_INCL}. - *

The triplets are of the form (first rank, last rank, stride) - * indicating ranks in this group to be included in the new group. - * The size of the first dimension of {@code ranges} is the number - * of triplets. The size of the second dimension is 3. - * @param ranges array of integer triplets - * @return new group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group rangeIncl(int[][] ranges) throws MPIException - { - MPI.check(); - return new Group(rangeIncl(handle, ranges)); - } - - private native long rangeIncl(long group, int[][] ranges); - - /** - * Create a subset group excluding processes specified - * by strided intervals of ranks. - *

Java binding of the MPI operation {@code MPI_GROUP_RANGE_EXCL}. - *

Triplet array is defined as for {@code rangeIncl}, the ranges - * indicating ranks in this group to be excluded from the new group. - * @param ranges array of integer triplets - * @return new group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group rangeExcl(int[][] ranges) throws MPIException - { - MPI.check(); - return new Group(rangeExcl(handle, ranges)); - } - - private native long rangeExcl(long group, int[][] ranges); - -} // Group diff --git a/ompi/mpi/java/java/Info.java b/ompi/mpi/java/java/Info.java deleted file mode 100644 index 0579f123868..00000000000 --- a/ompi/mpi/java/java/Info.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * This class represents {@code MPI_Info}. - */ -public final class Info implements Freeable, Cloneable -{ - protected long handle; - protected static final long NULL = getNull(); - - /** - * Java binding of the MPI operation {@code MPI_INFO_CREATE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Info() throws MPIException - { - MPI.check(); - handle = create(); - } - - protected Info(long handle) - { - this.handle = handle; - } - - private native long create(); - - protected static Info newEnv() - { - return new Info(getEnv()); - } - - private native static long getEnv(); - private native static long getNull(); - - /** - * Java binding of the MPI operation {@code MPI_INFO_SET}. - * @param key key - * @param value value - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void set(String key, String value) throws MPIException - { - MPI.check(); - set(handle, key, value); - } - - private native void set(long handle, String key, String value) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_GET}. - * @param key key - * @return value or {@code null} if key is not defined - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public String get(String key) throws MPIException - { - MPI.check(); - return get(handle, key); - } - - private native String get(long handle, String key) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_DELETE}. - * @param key key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void delete(String key) throws MPIException - { - MPI.check(); - delete(handle, key); - } - - private native void delete(long handle, String key) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_GET_NKEYS}. - * @return number of defined keys - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int size() throws MPIException - { - MPI.check(); - return size(handle); - } - - private native int size(long handle) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_GET_NTHKEY}. - * @param i key number - * @return key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public String getKey(int i) throws MPIException - { - MPI.check(); - return getKey(handle, i); - } - - private native String getKey(long handle, int i) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return info object - */ - @Override public Info clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Java binding of the MPI operation {@code MPI_INFO_DUP}. - * @return info object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Info dup() throws MPIException - { - MPI.check(); - return new Info(dup(handle)); - } - - private native long dup(long handle) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_INFO_FREE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public void free() throws MPIException - { - MPI.check(); - handle = free(handle); - } - - private native long free(long handle) throws MPIException; - - /** - * Tests if the info object is {@code MPI_INFO_NULL} (has been freed). - * @return true if the info object is {@code MPI_INFO_NULL}, false otherwise. - */ - public boolean isNull() - { - return isNull(handle); - } - - private native boolean isNull(long handle); - -} // Info diff --git a/ompi/mpi/java/java/Int2.java b/ompi/mpi/java/java/Int2.java deleted file mode 100644 index 0ba594d65cf..00000000000 --- a/ompi/mpi/java/java/Int2.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Struct class for {@link MPI#INT2} datatype. - */ -public final class Int2 extends Struct -{ - private final int iOff, iSize; - - /** - * The struct object will be created only in MPI class. - * @param intOff int offset - * @param intSize int size - * @see MPI#int2 - */ - protected Int2(int intOff, int intSize) - { - iSize = intSize; - int off = addIntField(); - assert off == 0; - setOffset(intOff); - iOff = addIntField(); - assert intOff == iOff; - } - - private int addIntField() - { - switch(iSize) - { - case 4: return addInt(); - case 8: return addLong(); - default: throw new AssertionError("Unsupported int size: "+ iSize); - } - } - - /** - * Creates a Data object. - * @return new Data object. - */ - @Override protected Int2.Data newData() - { - return new Int2.Data(); - } - - /** - * Class for reading/writing data in a struct stored in a byte buffer. - */ - public final class Data extends Struct.Data - { - /** - * Gets the first int. - * @return first int - */ - public int getValue() - { - return get(0); - } - - /** - * Gets the second int. - * @return second int - */ - public int getIndex() - { - return get(iOff); - } - - /** - * Puts the first int. - * @param v first value - */ - public void putValue(int v) - { - put(0, v); - } - - /** - * Puts the second int. - * @param v second int - */ - public void putIndex(int v) - { - put(iOff, v); - } - - private int get(int off) - { - switch(iSize) - { - case 4: return getInt(off); - case 8: return (int)getLong(off); - default: throw new AssertionError(); - } - } - - private void put(int off, int v) - { - switch(iSize) - { - case 4: putInt(off, v); break; - case 8: putLong(off, v); break; - default: throw new AssertionError(); - } - } - } // Data - -} // Int2 diff --git a/ompi/mpi/java/java/Intercomm.java b/ompi/mpi/java/java/Intercomm.java deleted file mode 100644 index 1cce85e2a80..00000000000 --- a/ompi/mpi/java/java/Intercomm.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Intercomm.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.5 $ - * Updated : $Date: 1999/09/14 20:50:11 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * This class represents intercommunicators. - */ -public final class Intercomm extends Comm -{ - protected Intercomm(long handle) - { - super(handle); - } - - protected Intercomm(long[] commRequest) - { - super(commRequest); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return copy of this communicator - */ - @Override public Intercomm clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intercomm dup() throws MPIException - { - MPI.check(); - return new Intercomm(dup(handle)); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_IDUP}. - *

The new communicator can't be used before the operation completes. - * The request object must be obtained calling {@link #getRequest}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intercomm iDup() throws MPIException - { - MPI.check(); - return new Intercomm(iDup(handle)); - } - - /** - * Duplicates this communicator with the info object used in the call. - *

Java binding of {@code MPI_COMM_DUP_WITH_INFO}. - * @param info info object to associate with the new communicator - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intercomm dupWithInfo(Info info) throws MPIException - { - MPI.check(); - return new Intercomm(dupWithInfo(handle, info.handle)); - } - - // Inter-Communication - - /** - * Size of remote group. - *

Java binding of the MPI operation {@code MPI_COMM_REMOTE_SIZE}. - * @return number of process in remote group of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getRemoteSize() throws MPIException - { - MPI.check(); - return getRemoteSize_jni(); - } - - private native int getRemoteSize_jni() throws MPIException; - - /** - * Return the remote group. - *

Java binding of the MPI operation {@code MPI_COMM_REMOTE_GROUP}. - * @return remote group of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group getRemoteGroup() throws MPIException - { - MPI.check(); - return new Group(getRemoteGroup_jni()); - } - - private native long getRemoteGroup_jni(); - - /** - * Creates an intracommuncator from an intercommunicator - *

Java binding of the MPI operation {@code MPI_INTERCOMM_MERGE}. - * @param high true if the local group has higher ranks in combined group - * @return new intra-communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Intracomm merge(boolean high) throws MPIException - { - MPI.check(); - return new Intracomm(merge_jni(high)); - } - - private native long merge_jni(boolean high); - - /** - * Java binding of {@code MPI_COMM_GET_PARENT}. - * @return the parent communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Intercomm getParent() throws MPIException - { - MPI.check(); - return new Intercomm(getParent_jni()); - } - - private native static long getParent_jni() throws MPIException; - -} // Intercomm diff --git a/ompi/mpi/java/java/Intracomm.java b/ompi/mpi/java/java/Intracomm.java deleted file mode 100644 index 95decb25ef0..00000000000 --- a/ompi/mpi/java/java/Intracomm.java +++ /dev/null @@ -1,887 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Intracommm.java - * Author : Sang Lim, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.14 $ - * Updated : $Date: 2002/12/16 15:25:13 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - * - * - * - * IMPLEMENTATION DETAILS - * - * All methods with buffers that can be direct or non direct have - * a companion argument 'db' which is true if the buffer is direct. - * For example, if the buffer argument is recvBuf, the companion - * argument will be 'rdb', meaning if the receive buffer is direct. - * - * Checking if a buffer is direct is faster in Java than C. - */ -package mpi; - -import java.nio.*; -import static mpi.MPI.assertDirectBuffer; - -/** - * This class represents intracommunicator. - */ -public class Intracomm extends Comm -{ - protected Intracomm() - { - } - - protected Intracomm(long handle) - { - super(handle); - } - - protected Intracomm(long[] commRequest) - { - super(commRequest); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - *

It is recommended to use {@link #dup} instead of {@link #clone} - * because the last can't throw an {@link mpi.MPIException}. - * @return copy of this communicator - */ - @Override public Intracomm clone() - { - try - { - return dup(); - } - catch(MPIException e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_DUP}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intracomm dup() throws MPIException - { - MPI.check(); - return new Intracomm(dup(handle)); - } - - /** - * Duplicates this communicator. - *

Java binding of {@code MPI_COMM_IDUP}. - *

The new communicator can't be used before the operation completes. - * The request object must be obtained calling {@link #getRequest}. - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intracomm iDup() throws MPIException - { - MPI.check(); - return new Intracomm(iDup(handle)); - } - - /** - * Duplicates this communicator with the info object used in the call. - *

Java binding of {@code MPI_COMM_DUP_WITH_INFO}. - * @param info info object to associate with the new communicator - * @return copy of this communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public Intracomm dupWithInfo(Info info) throws MPIException - { - MPI.check(); - return new Intracomm(dupWithInfo(handle, info.handle)); - } - - /** - * Partition the group associated with this communicator and create - * a new communicator within each subgroup. - *

Java binding of the MPI operation {@code MPI_COMM_SPLIT}. - * @param colour control of subset assignment - * @param key control of rank assignment - * @return new communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intracomm split(int colour, int key) throws MPIException - { - MPI.check(); - return new Intracomm(split(handle, colour, key)); - } - - private native long split(long comm, int colour, int key) throws MPIException; - - /** - * Partition the group associated with this communicator and create - * a new communicator within each subgroup. - *

Java binding of the MPI operation {@code MPI_COMM_SPLIT_TYPE}. - * @param splitType type of processes to be grouped together - * @param key control of rank assignment - * @param info info argument - * @return new communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intracomm splitType(int splitType, int key, Info info) throws MPIException - { - MPI.check(); - return new Intracomm(splitType(handle, splitType, key, info.handle)); - } - - private native long splitType(long comm, int colour, int key, long info) throws MPIException; - - /** - * Create a new communicator. - *

Java binding of the MPI operation {@code MPI_COMM_CREATE}. - * @param group group which is a subset of the group of this communicator - * @return new communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intracomm create(Group group) throws MPIException - { - MPI.check(); - return new Intracomm(create(handle, group.handle)); - } - - private native long create(long comm, long group); - - /** - * Create a new intracommunicator for the given group. - *

Java binding of the MPI operation {@code MPI_COMM_CREATE_GROUP}. - * @param group group which is a subset of the group of this communicator - * @param tag an integer tag - * @return new communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intracomm createGroup(Group group, int tag) throws MPIException - { - MPI.check(); - return new Intracomm(createGroup(handle, group.handle, tag)); - } - - private native long createGroup(long comm, long group, int tag); - - // Topology Constructors - - /** - * Creates a communicator to which the Cartesian topology - * information is attached. - * Create a cartesian topology communicator whose group is a subset - * of the group of this communicator. - *

Java binding of the MPI operation {@code MPI_CART_CREATE}. - *

The number of dimensions of the Cartesian grid is taken to be the - * size of the {@code dims} argument. The array {@code periods} must - * be the same size. - * @param dims the number of processes in each dimension - * @param periods {@code true} if grid is periodic, - * {@code false} if not, in each dimension - * @param reorder {@code true} if ranking may be reordered, - * {@code false} if not - * @return new cartesian topology communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final CartComm createCart(int[] dims, boolean[] periods, boolean reorder) - throws MPIException - { - MPI.check(); - return new CartComm(createCart(handle, dims, periods, reorder)); - } - - private native long createCart( - long comm, int[] dims, boolean[] periods, boolean reorder) - throws MPIException; - - /** - * Creates a communicator to which the graph topology information is attached. - *

Java binding of the MPI operation {@code MPI_GRAPH_CREATE}. - *

The number of nodes in the graph, nnodes, is taken - * to be size of the {@code index} argument. - * @param index node degrees - * @param edges graph edges - * @param reorder {@code true} if ranking may be reordered, - * {@code false} if not - * @return new graph topology communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final GraphComm createGraph(int[] index, int[] edges, boolean reorder) - throws MPIException - { - MPI.check(); - return new GraphComm(createGraph(handle, index, edges, reorder)); - } - - private native long createGraph( - long comm, int[] index, int[] edges, boolean reorder) - throws MPIException; - - /** - * Creates a communicator to which the distributed graph topology - * information is attached. - *

Java binding of the MPI operation {@code MPI_DIST_GRAPH_CREATE}. - *

The number of source nodes is the size of the {@code sources} argument. - * @param sources source nodes for which this process specifies edges - * @param degrees number of destinations for each source node - * @param destinations destination nodes for the source nodes - * @param weights weights for source to destination edges - * @param info hints on optimization and interpretation of weights - * @param reorder the process may be reordered (true) or not (false) - * @return communicator with distributed graph topology - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final GraphComm createDistGraph( - int[] sources, int[] degrees, int[] destinations, - int[] weights, Info info, boolean reorder) - throws MPIException - { - MPI.check(); - - return new GraphComm(createDistGraph( - handle, sources, degrees, destinations, - weights, info.handle, reorder, true)); - } - - /** - * Creates a communicator to which the distributed graph topology - * information is attached. - *

Java binding of the MPI operation {@code MPI_DIST_GRAPH_CREATE} - * using {@code MPI_UNWEIGHTED}. - *

The number of source nodes is the size of the {@code sources} argument. - * @param sources source nodes for which this process specifies edges - * @param degrees number of destinations for each source node - * @param destinations destination nodes for the source nodes - * @param info hints on optimization and interpretation of weights - * @param reorder the process may be reordered (true) or not (false) - * @return communicator with distributed graph topology - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final GraphComm createDistGraph( - int[] sources, int[] degrees, int[] destinations, - Info info, boolean reorder) - throws MPIException - { - MPI.check(); - - return new GraphComm(createDistGraph( - handle, sources, degrees, destinations, - null, info.handle, reorder, false)); - } - - private native long createDistGraph( - long comm, int[] sources, int[] degrees, int[] destinations, - int[] weights, long info, boolean reorder, boolean weighted) - throws MPIException; - - - /** - * Creates a communicator to which the distributed graph topology - * information is attached. - *

Java binding of the MPI operation {@code MPI_DIST_GRAPH_CREATE_ADJACENT}. - *

The number of source/destination nodes is the size of the - * {@code sources}/{@code destinations} argument. - * @param sources ranks of processes for which the calling process - * is a destination - * @param sourceWeights weights of the edges into the calling process - * @param destinations ranks of processes for which the calling process - * is a source - * @param destWeights weights of the edges out of the calling process - * @param info hints on optimization and interpretation of weights - * @param reorder the process may be reordered (true) or not (false) - * @return communicator with distributed graph topology - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final GraphComm createDistGraphAdjacent( - int[] sources, int[] sourceWeights, - int[] destinations, int[] destWeights, Info info, boolean reorder) - throws MPIException - { - MPI.check(); - - return new GraphComm(createDistGraphAdjacent( - handle, sources, sourceWeights, destinations, - destWeights, info.handle, reorder, true)); - } - - /** - * Creates a communicator to which the distributed graph topology - * information is attached. - *

Java binding of the MPI operation {@code MPI_DIST_GRAPH_CREATE_ADJACENT} - * using {@code MPI_UNWEIGHTED}. - *

The number of source/destination nodes is the size of the - * {@code sources}/{@code destinations} argument. - * @param sources ranks of processes for which the calling process - * is a destination - * @param destinations ranks of processes for which the calling process - * is a source - * @param info hints on optimization and interpretation of weights - * @param reorder the process may be reordered (true) or not (false) - * @return communicator with distributed graph topology - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final GraphComm createDistGraphAdjacent( - int[] sources, int[] destinations, Info info, boolean reorder) - throws MPIException - { - MPI.check(); - - return new GraphComm(createDistGraphAdjacent( - handle, sources, null, destinations, null, - info.handle, reorder, false)); - } - - private native long createDistGraphAdjacent( - long comm, int[] sources, int []sourceweights, int[] destinations, - int[] distweights, long info, boolean reorder, boolean weighted) - throws MPIException; - - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_SCAN}. - * @param sendbuf send buffer array - * @param recvbuf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scan(Object sendbuf, Object recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - op.setDatatype(type); - - scan(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - count, type.handle, type.baseType, op, op.handle); - } - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_SCAN} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param recvbuf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void scan(Object recvbuf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - int recvoff = 0; - boolean rdb = false; - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - op.setDatatype(type); - - scan(handle, null, false, 0, recvbuf, rdb, recvoff, - count, type.handle, type.baseType, op, op.handle); - } - - private native void scan( - long comm, Object sendbuf, boolean sdb, int sendoff, - Object recvbuf, boolean rdb, int recvoff, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_ISCAN}. - * @param sendbuf send buffer array - * @param recvbuf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScan(Buffer sendbuf, Buffer recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iScan(handle, sendbuf, recvbuf, count, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_ISCAN} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf send/receive buffer array - * @param count number of items in buffer - * @param type data type of each item in buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iScan(Buffer buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(buf); - Request req = new Request(iScan( - handle, null, buf, count, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(buf); - return req; - } - - private native long iScan( - long comm, Buffer sendbuf, Buffer recvbuf, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_EXSCAN}. - * @param sendbuf send buffer array - * @param recvbuf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void exScan(Object sendbuf, Object recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - - int sendoff = 0, - recvoff = 0; - - boolean sdb = false, - rdb = false; - - if(sendbuf instanceof Buffer && !(sdb = ((Buffer)sendbuf).isDirect())) - { - sendoff = type.getOffset(sendbuf); - sendbuf = ((Buffer)sendbuf).array(); - } - - if(recvbuf instanceof Buffer && !(rdb = ((Buffer)recvbuf).isDirect())) - { - recvoff = type.getOffset(recvbuf); - recvbuf = ((Buffer)recvbuf).array(); - } - - op.setDatatype(type); - - exScan(handle, sendbuf, sdb, sendoff, recvbuf, rdb, recvoff, - count, type.handle, type.baseType, op, op.handle); - } - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_EXSCAN} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void exScan(Object buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - op.setDatatype(type); - - exScan(handle, null, false, 0, buf, db, off, count, - type.handle, type.baseType, op, op.handle); - } - - private native void exScan( - long comm, Object sendbuf, boolean sdb, int sendoff, - Object recvbuf, boolean rdb, int recvoff, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_IEXSCAN}. - * @param sendbuf send buffer array - * @param recvbuf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iExScan(Buffer sendbuf, Buffer recvbuf, - int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(sendbuf, recvbuf); - Request req = new Request(iExScan(handle, sendbuf, recvbuf, count, - type.handle, type.baseType, op, op.handle)); - req.addSendBufRef(sendbuf); - req.addRecvBufRef(recvbuf); - return req; - } - - /** - * Perform a prefix reduction on data distributed across the group. - *

Java binding of the MPI operation {@code MPI_IEXSCAN} - * using {@code MPI_IN_PLACE} instead of the send buffer. - * @param buf receive buffer array - * @param count number of items in input buffer - * @param type data type of each item in input buffer - * @param op reduce operation - * @return communication request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request iExScan(Buffer buf, int count, Datatype type, Op op) - throws MPIException - { - MPI.check(); - op.setDatatype(type); - assertDirectBuffer(buf); - Request req = new Request(iExScan( - handle, null, buf, count, - type.handle, type.baseType, op, op.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long iExScan( - long comm, Buffer sendbuf, Buffer recvbuf, int count, - long type, int baseType, Op jOp, long hOp) throws MPIException; - - /** - * Java binding of {@code MPI_OPEN_PORT} using {@code MPI_INFO_NULL}. - * @return port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static String openPort() throws MPIException - { - MPI.check(); - return openPort(Info.NULL); - } - - /** - * Java binding of {@code MPI_OPEN_PORT}. - * @param info implementation-specific information - * @return port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static String openPort(Info info) throws MPIException - { - MPI.check(); - return openPort(info.handle); - } - - private native static String openPort(long info) throws MPIException; - - /** - * Java binding of {@code MPI_CLOSE_PORT}. - * @param name port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void closePort(String name) throws MPIException - { - MPI.check(); - closePort_jni(name); - } - - private native static void closePort_jni(String name) throws MPIException; - - /** - * Java binding of {@code MPI_COMM_ACCEPT} using {@code MPI_INFO_NULL}. - * @param port port name - * @param root rank in comm of root node - * @return intercommunicator with client as remote group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm accept(String port, int root) throws MPIException - { - MPI.check(); - return new Intercomm(accept(handle, port, Info.NULL, root)); - } - - /** - * Java binding of {@code MPI_COMM_ACCEPT}. - * @param port port name - * @param info implementation-specific information - * @param root rank in comm of root node - * @return intercommunicator with client as remote group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm accept(String port, Info info, int root) - throws MPIException - { - MPI.check(); - return new Intercomm(accept(handle, port, info.handle, root)); - } - - private native long accept(long comm, String port, long info, int root) - throws MPIException; - - /** - * Java binding of {@code MPI_COMM_CONNECT} using {@code MPI_INFO_NULL}. - * @param port port name - * @param root rank in comm of root node - * @return intercommunicator with server as remote group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm connect(String port, int root) throws MPIException - { - MPI.check(); - return new Intercomm(connect(handle, port, Info.NULL, root)); - } - - /** - * Java binding of {@code MPI_COMM_CONNECT}. - * @param port port name - * @param info implementation-specific information - * @param root rank in comm of root node - * @return intercommunicator with server as remote group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm connect(String port, Info info, int root) - throws MPIException - { - MPI.check(); - return new Intercomm(connect(handle, port, info.handle, root)); - } - - private native long connect(long comm, String port, long info, int root) - throws MPIException; - - /** - * Java binding of {@code MPI_PUBLISH_NAME} using {@code MPI_INFO_NULL}. - * @param service service name - * @param port port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void publishName(String service, String port) - throws MPIException - { - MPI.check(); - publishName(service, Info.NULL, port); - } - - /** - * Java binding of {@code MPI_PUBLISH_NAME}. - * @param service service name - * @param info implementation-specific information - * @param port port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void publishName(String service, Info info, String port) - throws MPIException - { - MPI.check(); - publishName(service, info.handle, port); - } - - private native static void publishName(String service, long info, String port) - throws MPIException; - - /** - * Java binding of {@code MPI_UNPUBLISH_NAME} using {@code MPI_INFO_NULL}. - * @param service service name - * @param port port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void unpublishName(String service, String port) - throws MPIException - { - MPI.check(); - unpublishName(service, Info.NULL, port); - } - - /** - * Java binding of {@code MPI_UNPUBLISH_NAME}. - * @param service service name - * @param info implementation-specific information - * @param port port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void unpublishName(String service, Info info, String port) - throws MPIException - { - MPI.check(); - unpublishName(service, info.handle, port); - } - - private native static void unpublishName(String service, long info, String port) - throws MPIException; - - /** - * Java binding of {@code MPI_LOOKUP_NAME} using {@code MPI_INFO_NULL}. - * @param service service name - * @return port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static String lookupName(String service) throws MPIException - { - MPI.check(); - return lookupName(service, Info.NULL); - } - - /** - * Java binding of {@code MPI_LOOKUP_NAME}. - * @param service service name - * @param info implementation-specific information - * @return port name - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static String lookupName(String service, Info info) throws MPIException - { - MPI.check(); - return lookupName(service, info.handle); - } - - private native static String lookupName(String service, long info) - throws MPIException; - - /** - * Java binding of {@code MPI_COMM_SPAWN}. - * This intracommunicator will contain the group of spawned processes. - * @param command name of program to be spawned - * @param argv arguments to command; if this parameter is null, - * {@code MPI_ARGV_NULL} will be used. - * @param maxprocs maximum number of processes to start - * @param info info object telling the runtime where - * and how to start the processes - * @param root rank of process in which previous arguments are examined - * @param errcodes one code per process; if this parameter is null, - * {@code MPI_ERRCODES_IGNORE} will be used. - * @return intercommunicator between original group and the newly spawned group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm spawn(String command, String[] argv, int maxprocs, - Info info, int root, int[] errcodes) - throws MPIException - { - MPI.check(); - - return new Intercomm(spawn(handle, command, argv, maxprocs, - info.handle, root, errcodes)); - } - - private native long spawn(long comm, String command, String[] argv, - int maxprocs, long info, int root, int[] errcodes) - throws MPIException; - - /** - * Java binding of {@code MPI_COMM_SPAWN_MULTIPLE}. - * This intracommunicator will contain the group of spawned processes. - * @param commands programs to be executed - * @param argv arguments for commands; if this parameter is null, - * {@code MPI_ARGVS_NULL} will be used. - * @param maxprocs maximum number of processes to start for each command - * @param info info objects telling the runtime where - * and how to start the processes - * @param root rank of process in which previous arguments are examined - * @param errcodes one code per process; if this parameter is null, - * {@code MPI_ERRCODES_IGNORE} will be used. - * @return intercommunicator between original group and the newly spawned group - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Intercomm spawnMultiple( - String[] commands, String[][] argv, int[] maxprocs, - Info[] info, int root, int[] errcodes) - throws MPIException - { - MPI.check(); - - long hInfo[] = new long[info.length]; - - for(int i = 0; i < info.length; i++) - hInfo[i] = info[i].handle; - - return new Intercomm(spawnMultiple(handle, commands, argv, maxprocs, - hInfo, root, errcodes)); - } - - private native long spawnMultiple( - long comm, String[] commands, String[][] argv, int[] maxprocs, - long[] info, int root, int[] errcodes) throws MPIException; - -} // Intracomm diff --git a/ompi/mpi/java/java/LongInt.java b/ompi/mpi/java/java/LongInt.java deleted file mode 100644 index 2d9a9143f31..00000000000 --- a/ompi/mpi/java/java/LongInt.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Struct class for {@link MPI#LONG_INT} datatype. - */ -public final class LongInt extends Struct -{ - private final int lSize, iOff, iSize; - - /** - * The struct object will be created only in MPI class. - * @param longSize size of long - * @param intOff int offset - * @param intSize int size - * @see MPI#longInt - */ - protected LongInt(int longSize, int intOff, int intSize) - { - lSize = longSize; - iSize = intSize; - int lOff; - - switch(lSize) - { - case 4: lOff = addInt(); break; - case 8: lOff = addLong(); break; - default: throw new AssertionError("Unsupported long size: "+ lSize); - } - - assert lOff == 0; - setOffset(intOff); - - switch(iSize) - { - case 4: iOff = addInt(); break; - case 8: iOff = addLong(); break; - default: throw new AssertionError("Unsupported int size: "+ iSize); - } - - assert(intOff == iOff); - } - - /** - * Creates a Data object. - * @return new Data object. - */ - @Override protected LongInt.Data newData() - { - return new LongInt.Data(); - } - - /** - * Class for reading/writing data in a struct stored in a byte buffer. - */ - public final class Data extends Struct.Data - { - /** - * Gets the long value. - * @return long value - */ - public long getValue() - { - switch(lSize) - { - case 8: return getLong(0); - case 4: return getInt(0); - default: throw new AssertionError(); - } - } - - /** - * Gets the int value. - * @return int value - */ - public int getIndex() - { - switch(iSize) - { - case 4: return getInt(iOff); - case 8: return (int)getLong(iOff); - default: throw new AssertionError(); - } - } - - /** - * Puts the long value. - * @param v long value - */ - public void putValue(long v) - { - switch(lSize) - { - case 8: putLong(0, v); break; - case 4: putInt(0, (int)v); break; - default: throw new AssertionError(); - } - } - - /** - * Puts the int value. - * @param v int value - */ - public void putIndex(int v) - { - switch(iSize) - { - case 4: putInt(iOff, v); break; - case 8: putLong(iOff, v); break; - default: throw new AssertionError(); - } - } - } // Data - -} // LongInt diff --git a/ompi/mpi/java/java/MPI.java b/ompi/mpi/java/java/MPI.java deleted file mode 100644 index e8887faede0..00000000000 --- a/ompi/mpi/java/java/MPI.java +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2020 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : MPI.java - * Author : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter - * (contributions from MAEDA Atusi) - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.18 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ -package mpi; - -import java.io.*; -import java.nio.*; - -/** - * MPI environment. - */ -public final class MPI -{ - private static boolean initialized, finalized; - private static byte[] buffer = null; // Buffer allocation - private static final int MAX_PROCESSOR_NAME = 256; - private static final ByteOrder nativeOrder = ByteOrder.nativeOrder(); - - public static final Intracomm COMM_WORLD, COMM_SELF; - - public static final int THREAD_SINGLE, THREAD_FUNNELED, THREAD_SERIALIZED, - THREAD_MULTIPLE; - - public static final int GRAPH, DIST_GRAPH, CART; - public static final int ANY_SOURCE, ANY_TAG; - - public static final Op MAX, MIN, SUM, PROD, LAND, BAND, - LOR, BOR, LXOR, BXOR, REPLACE, NO_OP; - - /** - * Global minimum operator. - *

{@code MINLOC} and {@link #MAXLOC} can be used with each of the following - * datatypes: {@link #INT2}, {@link #SHORT_INT}, {@link #LONG_INT}, - * {@link #FLOAT_INT} and {@link #DOUBLE_INT}. - */ - public static final Op MINLOC; - - /** Global maximum operator. See {@link #MINLOC}.*/ - public static final Op MAXLOC; - - public static final Datatype DATATYPE_NULL; - - public static final Datatype BYTE, CHAR, SHORT, BOOLEAN, - INT, LONG, FLOAT, DOUBLE, PACKED, - FLOAT_COMPLEX, DOUBLE_COMPLEX; - - /** Struct which must be used with {@link #int2}. */ - public static final Datatype INT2; - /** Struct which must be used with {@link #shortInt}. */ - public static final Datatype SHORT_INT; - /** Struct which must be used with {@link #longInt}. */ - public static final Datatype LONG_INT; - /** Struct which must be used with {@link #floatInt}. */ - public static final Datatype FLOAT_INT; - /** Struct which must be used with {@link #doubleInt}. */ - public static final Datatype DOUBLE_INT; - - /** Struct object for {@link #INT2} datatype. */ - public static final Int2 int2; - /** Struct object for {@link #SHORT_INT} datatype. */ - public static final ShortInt shortInt; - /** Struct object for {@link #LONG_INT} datatype. */ - public static final LongInt longInt; - /** Struct object for {@link #FLOAT_INT} datatype. */ - public static final FloatInt floatInt; - /** Struct object for {@link #DOUBLE_INT} datatype. */ - public static final DoubleInt doubleInt; - - public static final Request REQUEST_NULL; - public static final Group GROUP_EMPTY; - public static final Info INFO_ENV, INFO_NULL; - - public static final int PROC_NULL; - public static final int UNDEFINED; - public static final int IDENT, CONGRUENT, SIMILAR, UNEQUAL; - public static final int TAG_UB, HOST, IO, WTIME_IS_GLOBAL; - - public static final int APPNUM, LASTUSEDCODE, UNIVERSE_SIZE, WIN_BASE, - WIN_SIZE, WIN_DISP_UNIT; - - public static final int VERSION, SUBVERSION; - public static final int ROOT, KEYVAL_INVALID, BSEND_OVERHEAD; - public static final int MAX_OBJECT_NAME, MAX_PORT_NAME, MAX_DATAREP_STRING; - public static final int MAX_INFO_KEY, MAX_INFO_VAL; - public static final int ORDER_C, ORDER_FORTRAN; - public static final int DISTRIBUTE_BLOCK, DISTRIBUTE_CYCLIC, DISTRIBUTE_NONE, - DISTRIBUTE_DFLT_DARG; - - public static final int MODE_CREATE, MODE_RDONLY, MODE_WRONLY, MODE_RDWR, - MODE_DELETE_ON_CLOSE, MODE_UNIQUE_OPEN, MODE_EXCL, - MODE_APPEND, MODE_SEQUENTIAL; - public static final int DISPLACEMENT_CURRENT; - public static final int SEEK_SET, SEEK_CUR, SEEK_END; - - public static final int MODE_NOCHECK, MODE_NOPRECEDE, MODE_NOPUT, - MODE_NOSTORE, MODE_NOSUCCEED; - public static final int LOCK_EXCLUSIVE, LOCK_SHARED; - - public static final Errhandler ERRORS_ARE_FATAL, ERRORS_ABORT, ERRORS_RETURN; - - // Error classes and codes - public static final int SUCCESS; - public static final int ERR_BUFFER; - public static final int ERR_COUNT; - public static final int ERR_TYPE; - public static final int ERR_TAG; - public static final int ERR_COMM; - public static final int ERR_RANK; - public static final int ERR_REQUEST; - public static final int ERR_ROOT; - public static final int ERR_GROUP; - public static final int ERR_OP; - public static final int ERR_TOPOLOGY; - public static final int ERR_DIMS; - public static final int ERR_ARG; - public static final int ERR_UNKNOWN; - public static final int ERR_TRUNCATE; - public static final int ERR_OTHER; - public static final int ERR_INTERN; - public static final int ERR_IN_STATUS; - public static final int ERR_PENDING; - public static final int ERR_ACCESS; - public static final int ERR_AMODE; - public static final int ERR_ASSERT; - public static final int ERR_BAD_FILE; - public static final int ERR_BASE; - public static final int ERR_CONVERSION; - public static final int ERR_DISP; - public static final int ERR_DUP_DATAREP; - public static final int ERR_FILE_EXISTS; - public static final int ERR_FILE_IN_USE; - public static final int ERR_FILE; - public static final int ERR_INFO_KEY; - public static final int ERR_INFO_NOKEY; - public static final int ERR_INFO_VALUE; - public static final int ERR_INFO; - public static final int ERR_IO; - public static final int ERR_KEYVAL; - public static final int ERR_LOCKTYPE; - public static final int ERR_NAME; - public static final int ERR_NO_MEM; - public static final int ERR_NOT_SAME; - public static final int ERR_NO_SPACE; - public static final int ERR_NO_SUCH_FILE; - public static final int ERR_PORT; - public static final int ERR_PROC_ABORTED; - public static final int ERR_QUOTA; - public static final int ERR_READ_ONLY; - public static final int ERR_RMA_CONFLICT; - public static final int ERR_RMA_SYNC; - public static final int ERR_SERVICE; - public static final int ERR_SIZE; - public static final int ERR_SPAWN; - public static final int ERR_UNSUPPORTED_DATAREP; - public static final int ERR_UNSUPPORTED_OPERATION; - public static final int ERR_WIN; - public static final int ERR_LASTCODE; - public static final int ERR_SYSRESOURCE; - - static - { - try - { - System.loadLibrary("mpi_java") ; - } - catch (UnsatisfiedLinkError e) - { - System.err.println("mpi java lib failed to load: " + e + "\n") ; - System.exit(1) ; - } - - DATATYPE_NULL = new Datatype(); - - BYTE = new Datatype(); - CHAR = new Datatype(); - SHORT = new Datatype(); - BOOLEAN = new Datatype(); - INT = new Datatype(); - LONG = new Datatype(); - FLOAT = new Datatype(); - DOUBLE = new Datatype(); - PACKED = new Datatype(); - INT2 = new Datatype(); - - SHORT_INT = new Datatype(); - LONG_INT = new Datatype(); - FLOAT_INT = new Datatype(); - DOUBLE_INT = new Datatype(); - FLOAT_COMPLEX = new Datatype(); - DOUBLE_COMPLEX = new Datatype(); - - int2 = newInt2(); - shortInt = newShortInt(); - longInt = newLongInt(); - floatInt = newFloatInt(); - doubleInt = newDoubleInt(); - - MAX = new Op(1); - MIN = new Op(2); - SUM = new Op(3); - PROD = new Op(4); - LAND = new Op(5); - BAND = new Op(6); - LOR = new Op(7); - BOR = new Op(8); - LXOR = new Op(9); - BXOR = new Op(10); - MINLOC = new Op(11); - MAXLOC = new Op(12); - REPLACE = new Op(13); - NO_OP = new Op(14); - - GROUP_EMPTY = new Group(Group.getEmpty()); - REQUEST_NULL = new Request(Request.getNull()); - INFO_ENV = Info.newEnv(); - INFO_NULL = new Info(Info.NULL); - - Constant c = new Constant(); - - THREAD_SINGLE = c.THREAD_SINGLE; - THREAD_FUNNELED = c.THREAD_FUNNELED; - THREAD_SERIALIZED = c.THREAD_SERIALIZED; - THREAD_MULTIPLE = c.THREAD_MULTIPLE; - - GRAPH = c.GRAPH; - DIST_GRAPH = c.DIST_GRAPH; - CART = c.CART; - - ANY_SOURCE = c.ANY_SOURCE; - ANY_TAG = c.ANY_TAG; - PROC_NULL = c.PROC_NULL; - - UNDEFINED = c.UNDEFINED; - - IDENT = c.IDENT; - CONGRUENT = c.CONGRUENT; - SIMILAR = c.SIMILAR; - UNEQUAL = c.UNEQUAL; - - TAG_UB = c.TAG_UB; - HOST = c.HOST; - IO = c.IO; - WTIME_IS_GLOBAL = c.WTIME_IS_GLOBAL; - - APPNUM = c.APPNUM; - LASTUSEDCODE = c.LASTUSEDCODE; - UNIVERSE_SIZE = c.UNIVERSE_SIZE; - WIN_BASE = c.WIN_BASE; - WIN_SIZE = c.WIN_SIZE; - WIN_DISP_UNIT = c.WIN_DISP_UNIT; - - VERSION = c.VERSION; - SUBVERSION = c.SUBVERSION; - - ROOT = c.ROOT; - KEYVAL_INVALID = c.KEYVAL_INVALID; - BSEND_OVERHEAD = c.BSEND_OVERHEAD; - - MAX_OBJECT_NAME = c.MAX_OBJECT_NAME; - MAX_PORT_NAME = c.MAX_PORT_NAME; - MAX_DATAREP_STRING = c.MAX_DATAREP_STRING; - - MAX_INFO_KEY = c.MAX_INFO_KEY; - MAX_INFO_VAL = c.MAX_INFO_VAL; - - ORDER_C = c.ORDER_C; - ORDER_FORTRAN = c.ORDER_FORTRAN; - - DISTRIBUTE_BLOCK = c.DISTRIBUTE_BLOCK; - DISTRIBUTE_CYCLIC = c.DISTRIBUTE_CYCLIC; - DISTRIBUTE_NONE = c.DISTRIBUTE_NONE; - DISTRIBUTE_DFLT_DARG = c.DISTRIBUTE_DFLT_DARG; - - MODE_CREATE = c.MODE_CREATE; - MODE_RDONLY = c.MODE_RDONLY; - MODE_WRONLY = c.MODE_WRONLY; - MODE_RDWR = c.MODE_RDWR; - MODE_DELETE_ON_CLOSE = c.MODE_DELETE_ON_CLOSE; - MODE_UNIQUE_OPEN = c.MODE_UNIQUE_OPEN; - MODE_EXCL = c.MODE_EXCL; - MODE_APPEND = c.MODE_APPEND; - MODE_SEQUENTIAL = c.MODE_SEQUENTIAL; - - DISPLACEMENT_CURRENT = c.DISPLACEMENT_CURRENT; - - SEEK_SET = c.SEEK_SET; - SEEK_CUR = c.SEEK_CUR; - SEEK_END = c.SEEK_END; - - MODE_NOCHECK = c.MODE_NOCHECK; - MODE_NOPRECEDE = c.MODE_NOPRECEDE; - MODE_NOPUT = c.MODE_NOPUT; - MODE_NOSTORE = c.MODE_NOSTORE; - MODE_NOSUCCEED = c.MODE_NOSUCCEED; - LOCK_EXCLUSIVE = c.LOCK_EXCLUSIVE; - LOCK_SHARED = c.LOCK_SHARED; - - ERRORS_ARE_FATAL = new Errhandler(Errhandler.getFatal()); - ERRORS_ABORT = new Errhandler(Errhandler.getAbort()); - ERRORS_RETURN = new Errhandler(Errhandler.getReturn()); - - COMM_WORLD = new Intracomm(); - COMM_SELF = new Intracomm(); - - // Error classes and codes - SUCCESS = c.SUCCESS; - ERR_BUFFER = c.ERR_BUFFER; - ERR_COUNT = c.ERR_COUNT; - ERR_TYPE = c.ERR_TYPE; - ERR_TAG = c.ERR_TAG; - ERR_COMM = c.ERR_COMM; - ERR_RANK = c.ERR_RANK; - ERR_REQUEST = c.ERR_REQUEST; - ERR_ROOT = c.ERR_ROOT; - ERR_GROUP = c.ERR_GROUP; - ERR_OP = c.ERR_OP; - ERR_TOPOLOGY = c.ERR_TOPOLOGY; - ERR_DIMS = c.ERR_DIMS; - ERR_ARG = c.ERR_ARG; - ERR_UNKNOWN = c.ERR_UNKNOWN; - ERR_TRUNCATE = c.ERR_TRUNCATE; - ERR_OTHER = c.ERR_OTHER; - ERR_INTERN = c.ERR_INTERN; - ERR_IN_STATUS = c.ERR_IN_STATUS; - ERR_PENDING = c.ERR_PENDING; - ERR_ACCESS = c.ERR_ACCESS; - ERR_AMODE = c.ERR_AMODE; - ERR_ASSERT = c.ERR_ASSERT; - ERR_BAD_FILE = c.ERR_BAD_FILE; - ERR_BASE = c.ERR_BASE; - ERR_CONVERSION = c.ERR_CONVERSION; - ERR_DISP = c.ERR_DISP; - ERR_DUP_DATAREP = c.ERR_DUP_DATAREP; - ERR_FILE_EXISTS = c.ERR_FILE_EXISTS; - ERR_FILE_IN_USE = c.ERR_FILE_IN_USE; - ERR_FILE = c.ERR_FILE; - ERR_INFO_KEY = c.ERR_INFO_KEY; - ERR_INFO_NOKEY = c.ERR_INFO_NOKEY; - ERR_INFO_VALUE = c.ERR_INFO_VALUE; - ERR_INFO = c.ERR_INFO; - ERR_IO = c.ERR_IO; - ERR_KEYVAL = c.ERR_KEYVAL; - ERR_LOCKTYPE = c.ERR_LOCKTYPE; - ERR_NAME = c.ERR_NAME; - ERR_NO_MEM = c.ERR_NO_MEM; - ERR_NOT_SAME = c.ERR_NOT_SAME; - ERR_NO_SPACE = c.ERR_NO_SPACE; - ERR_NO_SUCH_FILE = c.ERR_NO_SUCH_FILE; - ERR_PORT = c.ERR_PORT; - ERR_PROC_ABORTED = c.ERR_PROC_ABORTED; - ERR_QUOTA = c.ERR_QUOTA; - ERR_READ_ONLY = c.ERR_READ_ONLY; - ERR_RMA_CONFLICT = c.ERR_RMA_CONFLICT; - ERR_RMA_SYNC = c.ERR_RMA_SYNC; - ERR_SERVICE = c.ERR_SERVICE; - ERR_SIZE = c.ERR_SIZE; - ERR_SPAWN = c.ERR_SPAWN; - ERR_UNSUPPORTED_DATAREP = c.ERR_UNSUPPORTED_DATAREP; - ERR_UNSUPPORTED_OPERATION = c.ERR_UNSUPPORTED_OPERATION; - ERR_WIN = c.ERR_WIN; - ERR_LASTCODE = c.ERR_LASTCODE; - ERR_SYSRESOURCE = c.ERR_SYSRESOURCE; - - initVersion(); - } - - private static native Int2 newInt2(); - private static native ShortInt newShortInt(); - private static native LongInt newLongInt(); - private static native FloatInt newFloatInt(); - private static native DoubleInt newDoubleInt(); - private static native void initVersion(); - - private static void initCommon() throws MPIException - { - initialized = true; - - DATATYPE_NULL.setBasic(Datatype.NULL); - - BYTE.setBasic(Datatype.BYTE); - CHAR.setBasic(Datatype.CHAR); - SHORT.setBasic(Datatype.SHORT); - BOOLEAN.setBasic(Datatype.BOOLEAN); - INT.setBasic(Datatype.INT); - LONG.setBasic(Datatype.LONG); - FLOAT.setBasic(Datatype.FLOAT); - DOUBLE.setBasic(Datatype.DOUBLE); - PACKED.setBasic(Datatype.PACKED); - - INT2.setBasic(Datatype.INT2, MPI.BYTE); - SHORT_INT.setBasic(Datatype.SHORT_INT, MPI.BYTE); - LONG_INT.setBasic(Datatype.LONG_INT, MPI.BYTE); - FLOAT_INT.setBasic(Datatype.FLOAT_INT, MPI.BYTE); - DOUBLE_INT.setBasic(Datatype.DOUBLE_INT, MPI.BYTE); - FLOAT_COMPLEX.setBasic(Datatype.FLOAT_COMPLEX, MPI.FLOAT); - DOUBLE_COMPLEX.setBasic(Datatype.DOUBLE_COMPLEX, MPI.DOUBLE); - - COMM_WORLD.setType(Intracomm.WORLD); - COMM_SELF.setType(Intracomm.SELF); - } - - /** - * Initialize MPI. - *

Java binding of the MPI operation {@code MPI_INIT}. - * @param args arguments to the {@code main} method. - * @return arguments - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static String[] Init(String[] args) throws MPIException - { - if(initialized) - throw new MPIException("MPI is already initialized."); - - String[] newArgs = Init_jni(args); - initCommon(); - return newArgs; - } - - private static native String [] Init_jni(String[] args); - - /** - * Initialize MPI with threads. - *

Java binding of the MPI operation {@code MPI_INIT_THREAD}. - * @param args arguments to the {@code main} method. - * @param required desired level of thread support - * @return provided level of thread support - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int InitThread(String[] args, int required) throws MPIException - { - if(initialized) - throw new MPIException("MPI is already initialized."); - - int provided = InitThread_jni(args, required); - initCommon(); - return provided; - } - - private static native int InitThread_jni(String[] args, int required) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_QUERY_THREAD}. - * @return provided level of thread support - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int queryThread() throws MPIException - { - MPI.check(); - return queryThread_jni(); - } - - private static native int queryThread_jni() throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_IS_THREAD_MAIN}. - * @return true if it is the main thread - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static boolean isThreadMain() throws MPIException - { - MPI.check(); - return isThreadMain_jni(); - } - - private static native boolean isThreadMain_jni() throws MPIException; - - /** - * Finalize MPI. - *

Java binding of the MPI operation {@code MPI_FINALIZE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void Finalize() throws MPIException - { - check(); - Finalize_jni(); - finalized = true; - } - - private static native void Finalize_jni() throws MPIException; - - /** - * Returns an elapsed time on the calling processor. - *

Java binding of the MPI operation {@code MPI_WTIME}. - * @return time in seconds since an arbitrary time in the past. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static double wtime() throws MPIException - { - check(); - return wtime_jni(); - } - - private static native double wtime_jni(); - - /** - * Returns resolution of timer. - *

Java binding of the MPI operation {@code MPI_WTICK}. - * @return resolution of {@code wtime} in seconds. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static double wtick() throws MPIException - { - check(); - return wtick_jni(); - } - - private static native double wtick_jni(); - - /** - * Returns a version object representing the version of MPI being used. - *

Java binding of the MPI operation {@code MPI_GET_VERSION}. - * @return A version object representing the version and subversion of MPI being used. - */ - public static Version getVersion() { - return getVersionJNI(); - } - - private static native Version getVersionJNI(); - - /** - * Returns the version of the MPI Library - *

Java binding of the MPI operation {@code MPI_GET_LIBRARY_VERSION}. - * @return A string representation of the MPI Library - */ - public static String getLibVersion() { - return getLibVersionJNI(); - } - - private static native String getLibVersionJNI(); - - /** - * Returns the name of the processor on which it is called. - *

Java binding of the MPI operation {@code MPI_GET_PROCESSOR_NAME}. - * @return A unique specifier for the actual node. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - static public String getProcessorName() throws MPIException - { - check(); - byte[] buf = new byte[MAX_PROCESSOR_NAME]; - int lengh = getProcessorName(buf); - return new String(buf,0,lengh); - } - - static private native int getProcessorName(byte[] buf); - - /** - * Test if MPI has been initialized. - *

Java binding of the MPI operation {@code MPI_INITIALIZED}. - * @return {@code true} if {@code Init} has been called, - * {@code false} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - static public native boolean isInitialized() throws MPIException; - - /** - * Test if MPI has been finalized. - *

Java binding of the MPI operation {@code MPI_FINALIZED}. - * @return {@code true} if {@code Finalize} has been called, - * {@code false} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - static public native boolean isFinalized() throws MPIException; - - /** - * Attaches a user-provided buffer for sending. - *

Java binding of the MPI operation {@code MPI_BUFFER_ATTACH}. - * @param buffer initial buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - static public void attachBuffer(byte[] buffer) throws MPIException - { - check(); - MPI.buffer = buffer; - attachBuffer_jni(buffer); - } - - static private native void attachBuffer_jni(byte[] buffer); - - /** - * Removes an existing buffer (for use in sending). - *

Java binding of the MPI operation {@code MPI_BUFFER_DETACH}. - * @return initial buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - static public byte[] detachBuffer() throws MPIException - { - check(); - detachBuffer_jni(buffer); - byte[] result = MPI.buffer; - MPI.buffer = null; - return result; - } - - static private native void detachBuffer_jni(byte[] buffer); - - /** - * Controls profiling. - *

This method is not implemented. - *

Java binding of the MPI operation {@code MPI_PCONTROL}. - * @param level Profiling level. - * @param obj Profiling information. - */ - public static void pControl(int level, Object obj) - { - // Nothing to do here. - } - - /** - * Check if MPI has been initialized and hasn't been finalized. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - protected static void check() throws MPIException - { - if(!initialized) - throw new MPIException("MPI is not initialized."); - - if(finalized) - throw new MPIException("MPI is finalized."); - } - - protected static byte[] attrSet(Object value) throws MPIException - { - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream os = new ObjectOutputStream(baos); - os.writeObject(value); - os.close(); - return baos.toByteArray(); - } - catch(IOException ex) - { - MPIException mpiex = new MPIException(ex); - mpiex.setStackTrace(ex.getStackTrace()); - throw mpiex; - } - } - - protected static Object attrGet(byte[] value) throws MPIException - { - if(value == null) - return null; - - try - { - ByteArrayInputStream bais = new ByteArrayInputStream(value); - ObjectInputStream is = new ObjectInputStream(bais); - Object obj = is.readObject(); - is.close(); - return obj; - } - catch(ClassNotFoundException ex) - { - throw new MPIException(ex); - } - catch(IOException ex) - { - throw new MPIException(ex); - } - } - - /** - * Allocates a new direct byte buffer. - * @param capacity The new buffer's capacity, in bytes - * @return The new byte buffer - */ - public static ByteBuffer newByteBuffer(int capacity) - { - ByteBuffer buf = ByteBuffer.allocateDirect(capacity); - buf.order(nativeOrder); - return buf; - } - - /** - * Allocates a new direct char buffer. - * @param capacity The new buffer's capacity, in chars - * @return The new char buffer - */ - public static CharBuffer newCharBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 2; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 2); - buf.order(nativeOrder); - return buf.asCharBuffer(); - } - - /** - * Allocates a new direct short buffer. - * @param capacity The new buffer's capacity, in shorts - * @return The new short buffer - */ - public static ShortBuffer newShortBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 2; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 2); - buf.order(nativeOrder); - return buf.asShortBuffer(); - } - - /** - * Allocates a new direct int buffer. - * @param capacity The new buffer's capacity, in ints - * @return The new int buffer - */ - public static IntBuffer newIntBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 4; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 4); - buf.order(nativeOrder); - return buf.asIntBuffer(); - } - - /** - * Allocates a new direct long buffer. - * @param capacity The new buffer's capacity, in longs - * @return The new long buffer - */ - public static LongBuffer newLongBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 8; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 8); - buf.order(nativeOrder); - return buf.asLongBuffer(); - } - - /** - * Allocates a new direct float buffer. - * @param capacity The new buffer's capacity, in floats - * @return The new float buffer - */ - public static FloatBuffer newFloatBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 4; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 4); - buf.order(nativeOrder); - return buf.asFloatBuffer(); - } - - /** - * Allocates a new direct double buffer. - * @param capacity The new buffer's capacity, in doubles - * @return The new double buffer - */ - public static DoubleBuffer newDoubleBuffer(int capacity) - { - assert capacity <= Integer.MAX_VALUE / 8; - ByteBuffer buf = ByteBuffer.allocateDirect(capacity * 8); - buf.order(nativeOrder); - return buf.asDoubleBuffer(); - } - - /** - * Asserts that a buffer is direct. - * @param buf buffer - */ - protected static void assertDirectBuffer(Buffer buf) - { - if(!buf.isDirect()) - throw new IllegalArgumentException("The buffer must be direct."); - } - - /** - * Asserts that buffers are direct. - * @param sendbuf The send buffer - * @param recvbuf The receive buffer - */ - protected static void assertDirectBuffer(Buffer sendbuf, Buffer recvbuf) - { - if(!sendbuf.isDirect()) - throw new IllegalArgumentException("The send buffer must be direct."); - - if(!recvbuf.isDirect()) - throw new IllegalArgumentException("The recv. buffer must be direct."); - } - - /** - * Checks if an object is a direct buffer. - * @param obj object - * @return true if the object is a direct buffer - */ - protected static boolean isDirectBuffer(Object obj) - { - return obj instanceof Buffer && ((Buffer)obj).isDirect(); - } - - /** - * Checks if an object is a heap buffer. - * @param obj object - * @return true if the object is a heap buffer - */ - protected static boolean isHeapBuffer(Object obj) - { - return obj instanceof Buffer && !((Buffer)obj).isDirect(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static ByteBuffer slice(ByteBuffer buf, int offset) - { - return ((ByteBuffer)buf.clear().position(offset)) - .slice().order(nativeOrder); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static CharBuffer slice(CharBuffer buf, int offset) - { - return ((CharBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static ShortBuffer slice(ShortBuffer buf, int offset) - { - return ((ShortBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static IntBuffer slice(IntBuffer buf, int offset) - { - return ((IntBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static LongBuffer slice(LongBuffer buf, int offset) - { - return ((LongBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static FloatBuffer slice(FloatBuffer buf, int offset) - { - return ((FloatBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static DoubleBuffer slice(DoubleBuffer buf, int offset) - { - return ((DoubleBuffer)buf.clear().position(offset)).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static ByteBuffer slice(byte[] buf, int offset) - { - return ByteBuffer.wrap(buf, offset, buf.length - offset) - .slice().order(nativeOrder); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static CharBuffer slice(char[] buf, int offset) - { - return CharBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static ShortBuffer slice(short[] buf, int offset) - { - return ShortBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static IntBuffer slice(int[] buf, int offset) - { - return IntBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static LongBuffer slice(long[] buf, int offset) - { - return LongBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static FloatBuffer slice(float[] buf, int offset) - { - return FloatBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - - /** - * Creates a new buffer whose content is a shared subsequence of a buffer. - *

The content of the new buffer will start at the specified offset. - * @param buf buffer - * @param offset offset - * @return the new buffer. - */ - public static DoubleBuffer slice(double[] buf, int offset) - { - return DoubleBuffer.wrap(buf, offset, buf.length - offset).slice(); - } - -} // MPI diff --git a/ompi/mpi/java/java/MPIException.java b/ompi/mpi/java/java/MPIException.java deleted file mode 100644 index fb6c7744f0c..00000000000 --- a/ompi/mpi/java/java/MPIException.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : MPIException.java - * Author : Bryan Carpenter - * Created : Tue Sep 14 13:03:57 EDT 1999 - * Revision : $Revision: 1.1 $ - * Updated : $Date: 1999/09/14 22:01:52 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1999 - * - * Sidenote from August 2020: this class probably should have been - * called MPIError, not MPIException. - */ - -package mpi; - -/** - * Signals that an MPI error of some sort has occurred. - *

The Java binding of the MPI operation {@code MPI_Error_string} is the - * method {@code getMessage}, which is inherited from the class Exception. - */ -public final class MPIException extends Exception -{ - private int errorCode, errorClass; - - protected MPIException(int code, int clazz, String message) - { - super(message); - errorCode = code; - errorClass = clazz; - } - - /** - * Creates an exception. - * @param message message associated to the error - */ - public MPIException(String message) - { - super(message); - } - - /** - * Creates an exception: - * @param cause cause associated to the error - */ - public MPIException(Throwable cause) - { - super(cause); - setStackTrace(cause.getStackTrace()); - } - - /** - * Gets the MPI error code. - * @return error code - */ - public int getErrorCode() - { - return errorCode; - } - - /** - * Gets the MPI error class. - * @return error class - */ - public int getErrorClass() - { - return errorClass; - } - -} // MPIException diff --git a/ompi/mpi/java/java/Makefile.am b/ompi/mpi/java/java/Makefile.am deleted file mode 100644 index eb818ea0eeb..00000000000 --- a/ompi/mpi/java/java/Makefile.am +++ /dev/null @@ -1,220 +0,0 @@ -# -*- makefile -*- -# -# Copyright (c) 2011-2018 Cisco Systems, Inc. All rights reserved -# Copyright (c) 2015 Los Alamos National Security, LLC. All rights -# reserved. -# Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. -# Copyright (c) 2018 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -include $(top_srcdir)/Makefile.ompi-rules - -# -# We generate three general things in this directory: -# -# 1. *.java files get compiled into mpi/*.class files. -# 2. The mpi/*.class files are then assembled into an mpi.jar file. -# 3. The mpi/*.class files are analyzed to make *.h JNI files. -# - -# These are the Java source files. However, Automake doesn't directly -# know about them, and we compile them via *.java below (ick!). So we -# just list them here in EXTRA_DIST so that they get picked up by -# "make dist". -JAVA_SRC_FILES = \ - CartComm.java \ - CartParms.java \ - Comm.java \ - Constant.java \ - Count.java \ - Datatype.java \ - DistGraphNeighbors.java \ - DoubleInt.java \ - DoubleComplex.java \ - Errhandler.java \ - FloatComplex.java \ - FloatInt.java \ - File.java \ - FileView.java \ - Freeable.java \ - GraphComm.java \ - GraphParms.java \ - Group.java \ - Info.java \ - Int2.java \ - Intercomm.java \ - Intracomm.java \ - LongInt.java \ - Message.java \ - MPI.java \ - MPIException.java \ - Op.java \ - Prequest.java \ - Request.java \ - ShiftParms.java \ - ShortInt.java \ - Status.java \ - Struct.java \ - UserFunction.java \ - Version.java \ - Win.java - -EXTRA_DIST = $(JAVA_SRC_FILES) - -# Only do this stuff if we want the Java bindings -if OMPI_WANT_JAVA_BINDINGS - -# These files get generated. They have a 1:1 correspondence to .java -# files, but there is not a .h file for every .java file. That's why -# we have a specific list of files here, as opposed to deriving them -# from JAVA_SRC_FILES. -JAVA_H = \ - mpi_MPI.h \ - mpi_CartComm.h \ - mpi_Comm.h \ - mpi_Constant.h \ - mpi_Count.h \ - mpi_Datatype.h \ - mpi_Errhandler.h \ - mpi_File.h \ - mpi_GraphComm.h \ - mpi_Group.h \ - mpi_Info.h \ - mpi_Intercomm.h \ - mpi_Intracomm.h \ - mpi_Message.h \ - mpi_Op.h \ - mpi_Prequest.h \ - mpi_Request.h \ - mpi_Status.h \ - mpi_Win.h - -# A little verbosity magic; see Makefile.ompi-rules for an explanation. -OMPI_V_JAVAC = $(ompi__v_JAVAC_$V) -ompi__v_JAVAC_ = $(ompi__v_JAVAC_$AM_DEFAULT_VERBOSITY) -ompi__v_JAVAC_0 = @echo " JAVAC " `basename $@`; - -OMPI_V_JAVAH = $(ompi__v_JAVAH_$V) -ompi__v_JAVAH_ = $(ompi__v_JAVAH_$AM_DEFAULT_VERBOSITY) -ompi__v_JAVAH_0 = @echo " JAVAH " `basename $@`; - -OMPI_V_JAR = $(ompi__v_JAR_$V) -ompi__v_JAR_ = $(ompi__v_JAR_$AM_DEFAULT_VERBOSITY) -ompi__v_JAR_0 = @echo " JAR " `basename $@`; - -OMPI_V_JAVADOC = $(ompi__v_JAVADOC_$V) -ompi__v_JAVADOC_ = $(ompi__v_JAVADOC_$AM_DEFAULT_VERBOSITY) -ompi__v_JAVADOC_0 = @echo "JAVADOC " `basename $@`; - -OMPI_V_JAVADOC_QUIET = $(ompi__v_JAVADOC_QUIET_$V) -ompi__v_JAVADOC_QUIET_ = $(ompi__v_JAVADOC_QUIET_$AM_DEFAULT_VERBOSITY) -ompi__v_JAVADOC_QUIET_0 = -quiet - -# All the .java files seem to have circular references, such that I -# can't figure out a linear order in which to compile them -# sequentially that does not generate dependency errors. Hence, the -# only way I can figure out how to compile them is via *.java -- this -# could well be due to my own misunderstanding of Java or the -# compiler. Shrug. -# -# So instead of listing all the .class files, since the rule below -# will generate *all* the .class files simulanteously, just use -# mpi/MPI.class as a token class file for both the rule and all the -# dependencies below. -# -# Note too, that all of them will be recompiled if any of them change, -# since Automake doesn't know how to automatically generate -# dependencies for Java source files. So I made the token MPI.class -# file dependent upon *all* the .java source files. -# -# Note that the javac compile will generate all the .class files in -# the "mpi" subdirectory, because that's the java package that they're -# in. This, along with the fact that the .java files seem to have -# circular references, prevents us from using a .foo.bar: generic -# Makefile rule. :-( -if OMPI_HAVE_JAVAH_SUPPORT -mpi/MPI.class: $(JAVA_SRC_FILES) - $(OMPI_V_JAVAC) CLASSPATH=. ; \ - export CLASSPATH ; \ - $(JAVAC) -d . $(top_srcdir)/ompi/mpi/java/java/*.java - -# Similar to above, all the generated .h files are dependent upon the -# token mpi/MPI.class file. Hence, all the classes will be generated -# first, then we'll individually generate each of the .h files. - -$(JAVA_H): mpi/MPI.class - $(OMPI_V_JAVAH) sourcename=mpi.`echo $@ | sed -e s/^mpi_// -e s/.h$$//`; \ - CLASSPATH=. ; \ - export CLASSPATH ; \ - $(JAVAH) -d . -jni $$sourcename -else -mpi/MPI.class: $(JAVA_SRC_FILES) - $(OMPI_V_JAVAC) CLASSPATH=. ; \ - export CLASSPATH ; \ - $(JAVAC) -h . -d . $(top_srcdir)/ompi/mpi/java/java/*.java -endif # OMPI_HAVE_JAVAH_SUPPORT - -# Generate the .jar file from all the class files. List mpi/MPI.class -# as a dependency so that it fires the rule above that will generate -# *all* the mpi/*.class files. -mpi.jar: mpi/MPI.class - $(OMPI_V_JAR) $(JAR) cf mpi.jar mpi/*.class - -# Install the jar file into libdir. Use the DATA Automake primary, -# because Automake will complain if you try to use LIBRARIES with a -# filename that doesn't fit the lib.* format. Also use an -# indirection to get to the libdir -- Automake does not allow putting -# libdir for the DATA primary. -javadir = $(libdir) -java_DATA = mpi.jar - -# List all the header files in BUILT_SOURCES so that Automake's "all" -# target will build them. This will also force the building of the -# mpi/*.class files (for the jar file). -if OMPI_HAVE_JAVAH_SUPPORT -BUILT_SOURCES = $(JAVA_H) doc -else -BUILT_SOURCES = mpi/MPI.class doc -endif - -# Convenience for building Javadoc docs -jdoc: doc - -# Make the "doc" target (and subdir) dependent upon mpi/MPI.class; if -# mpi.jar is ever rebuilt, then also make the docs eligible to be -# rebuilt. -doc: mpi/MPI.class - $(OMPI_V_JAVADOC) $(JAVADOC) $(OMPI_V_JAVADOC_QUIET) -d doc $(srcdir)/*.java - @touch doc - -jdoc-install: doc - -$(MKDIR_P) $(DESTDIR)$(docdir)/javadoc-openmpi - cp -rp doc/* $(DESTDIR)$(docdir)/javadoc-openmpi - -jdoc-uninstall: - -rm -rf $(DESTDIR)$(docdir)/javadoc - -install-data-hook: jdoc-install -uninstall-local: jdoc-uninstall - -# Clean up all the things that this Makefile.am generates. -CLEANFILES += $(JAVA_H) mpi.jar - -# Can only put *files* in CLEANFILES; need to remove the generated doc -# and mpi directories separately. -clean-local: - -rm -rf doc mpi - -# Conditionally install the header files -if WANT_INSTALL_HEADERS -ompihdir = $(ompiincludedir)/$(subdir) -nobase_nodist_ompih_HEADERS = $(JAVA_H) -endif - -endif diff --git a/ompi/mpi/java/java/Message.java b/ompi/mpi/java/java/Message.java deleted file mode 100644 index a88974a6267..00000000000 --- a/ompi/mpi/java/java/Message.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * IMPLEMENTATION DETAILS - * - * All methods with buffers that can be direct or non direct have - * a companion argument 'db' which is true if the buffer is direct. - * - * Checking if a buffer is direct is faster in Java than C. - */ - -package mpi; - -import java.nio.*; -import static mpi.MPI.assertDirectBuffer; - -/** - * This class represents {@code MPI_Message}. - */ -public final class Message -{ - protected long handle; - private static long NULL, NO_PROC; - - static - { - init(); - } - - private static native void init(); - - /** - * Creates a {@code MPI_MESSAGE_NULL}. - */ - public Message() - { - handle = NULL; - } - - /** - * Tests if the message is {@code MPI_MESSAGE_NULL}. - * @return true if the message is {@code MPI_MESSAGE_NULL}. - */ - public boolean isNull() - { - return handle == NULL; - } - - /** - * Tests if the message is {@code MPI_MESSAGE_NO_PROC}. - * @return true if the message is {@code MPI_MESSAGE_NO_PROC}. - */ - public boolean isNoProc() - { - return handle == NO_PROC; - } - - /** - * Java binding of {@code MPI_MPROBE}. - * @param source rank of the source - * @param tag message tag - * @param comm communicator - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status mProbe(int source, int tag, Comm comm) throws MPIException - { - MPI.check(); - Status status = new Status(); - handle = mProbe(source, tag, comm.handle, status.data); - return status; - } - - private native long mProbe(int source, int tag, long comm, long[] status) - throws MPIException; - - /** - * Java binding of {@code MPI_IMPROBE}. - * @param source rank of the source - * @param tag message tag - * @param comm communicator - * @return status object if there is a message, {@code null} otherwise - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status imProbe(int source, int tag, Comm comm) throws MPIException - { - MPI.check(); - return imProbe(source, tag, comm.handle); - } - - private native Status imProbe(int source, int tag, long comm) - throws MPIException; - - /** - * Java binding of {@code MPI_MRECV}. - * @param buf receive buffer - * @param count number of elements in receive buffer - * @param type datatype of each receive buffer element - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Status mRecv(Object buf, int count, Datatype type) throws MPIException - { - MPI.check(); - int off = 0; - boolean db = false; - Status status = new Status(); - - if(buf instanceof Buffer && !(db = ((Buffer)buf).isDirect())) - { - off = type.getOffset(buf); - buf = ((Buffer)buf).array(); - } - - handle = mRecv(handle, buf, db, off, count, - type.handle, type.baseType, status.data); - - return status; - } - - private native long mRecv( - long message, Object buf, boolean db, int offset, int count, - long type, int baseType, long[] status) throws MPIException; - - /** - * Java binding of {@code MPI_IMRECV}. - * @param buf receive buffer - * @param count number of elements in receive buffer - * @param type datatype of each receive buffer element - * @return request object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request imRecv(Buffer buf, int count, Datatype type) - throws MPIException - { - MPI.check(); - assertDirectBuffer(buf); - Request req = new Request(imRecv(handle, buf, count, type.handle)); - req.addRecvBufRef(buf); - return req; - } - - private native long imRecv(long message, Object buf, int count, long type) - throws MPIException; - -} // Message diff --git a/ompi/mpi/java/java/Op.java b/ompi/mpi/java/java/Op.java deleted file mode 100644 index f7dd25a25b0..00000000000 --- a/ompi/mpi/java/java/Op.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Op.java - * Author : Xinying Li, Sang LIm - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.11 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -import java.nio.*; - -/** - * This class represents {@code MPI_Op}. - */ -public final class Op implements Freeable -{ - protected final UserFunction uf; - private boolean commute; - private Datatype datatype; - protected long handle; - - static - { - init(); - } - - private static native void init(); - - protected Op(int type) - { - getOp(type); - uf = null; - commute = true; - } - - private native void getOp(int type); - - /** - * Bind a user-defined global reduction operation to an {@code Op} object. - *

Java binding of the MPI operation {@code MPI_OP_CREATE}. - * @param function user defined function - * @param commute {@code true} if commutative, {@code false} otherwise - */ - public Op(UserFunction function, boolean commute) - { - handle = 0; // When JNI code gets the handle it will be initialized. - uf = function; - this.commute = commute; - } - - protected void setDatatype(Datatype t) - { - datatype = t; - } - - protected void call(Object invec, Object inoutvec, int count) - throws MPIException - { - if(datatype.baseType == Datatype.BOOLEAN) - { - uf.call(invec, inoutvec, count, datatype); - } - else - { - uf.call(((ByteBuffer)invec).order(ByteOrder.nativeOrder()), - ((ByteBuffer)inoutvec).order(ByteOrder.nativeOrder()), - count, datatype); - } - } - - /** - * Test if the operation is commutative. - *

Java binding of the MPI operation {@code MPI_OP_COMMUTATIVE}. - * @return {@code true} if commutative, {@code false} otherwise - */ - public boolean isCommutative() - { - return commute; - } - - /** - * Java binding of the MPI operation {@code MPI_OP_FREE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public native void free() throws MPIException; - - /** - * Test if operation object is null. - * @return true if the operation object is null, false otherwise - */ - public native boolean isNull(); - -} // Op diff --git a/ompi/mpi/java/java/Prequest.java b/ompi/mpi/java/java/Prequest.java deleted file mode 100644 index 205e0d489a0..00000000000 --- a/ompi/mpi/java/java/Prequest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Prequest.java - * Author : Sang Lim, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.11 $ - * Updated : $Date: 2001/10/22 21:07:55 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Persistent request object. - */ -public final class Prequest extends Request -{ - /** - * Constructor used by {@code sendInit}, etc. - * @param handle Handle for the Prequest object - */ - protected Prequest(long handle) - { - super(handle); - } - - /** - * Activate a persistent communication request. - *

Java binding of the MPI operation {@code MPI_START}. - * The communication is completed by using the request in - * one of the {@code wait} or {@code test} operations. - * On successful completion the request becomes inactive again. - * It can be reactivated by a further call to {@code Start}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void start() throws MPIException - { - handle = start(handle); - } - - private native long start(long request) throws MPIException; - - /** - * Activate a list of communication requests. - *

Java binding of the MPI operation {@code MPI_STARTALL}. - * @param requests array of requests - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void startAll(Prequest[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - startAll(r); - setHandles(requests, r); - } - - private native static void startAll(long[] requests) throws MPIException; - -} // Prequest diff --git a/ompi/mpi/java/java/Request.java b/ompi/mpi/java/java/Request.java deleted file mode 100644 index eb841731af3..00000000000 --- a/ompi/mpi/java/java/Request.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * File : Request.java - * Author : Sang Lim, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.11 $ - * Updated : $Date: 2001/08/07 16:36:25 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - * - * - * - * Note: in a send request for a buffer containing objects, the primary - * `MPI_Request' referenced by `handle' is the request to send the data. - * The request to send the header is in the secondary field, `hdrReq'. - * Conversely, in a *receive* request for a buffer containing objects - * the primary `MPI_Request' is the request to send the header. - * The receive of the data is not initiated until a `wait' or `test' - * operation succeeds. - * - * - * - * Probably `Request' should be an abstract class, and there should - * be several concrete subclasses. At the moment requests are created - * in a few different ways, and the differently constructed requests are - * typically using different subsets of fields. DBC 7/12/01 - */ - -package mpi; - -import java.nio.Buffer; - -/** - * Request object. - */ -public class Request implements Freeable -{ - protected long handle; - protected Buffer sendBuf; - protected Buffer recvBuf; - - static - { - init(); - } - - private static native void init(); - - protected static native long getNull(); - - protected Request(long handle) - { - this.handle = handle; - } - - /** - * Set the request object to be void. - * Java binding of the MPI operation {@code MPI_REQUEST_FREE}. - */ - @Override public void free() throws MPIException - { - if(!isNull()) - { - MPI.check(); - handle = free(handle); - } - } - - private native long free(long req) throws MPIException; - - /** - * Mark a pending nonblocking communication for cancellation. - * Java binding of the MPI operation {@code MPI_CANCEL}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void cancel() throws MPIException - { - MPI.check(); - cancel(handle); - } - - private native void cancel(long request) throws MPIException; - - /** - * Adds a receive buffer to this Request object. This method - * should be called by the internal api whenever a persistent - * request is created and any time a request object, that has - * an associated buffer, is returned from an operation to protect - * the buffer from getting prematurely garbage collected. - * @param buf buffer to add to the array list - */ - protected final void addRecvBufRef(Buffer buf) - { - this.recvBuf = buf; - } - - /** - * Adds a send buffer to this Request object. This method - * should be called by the internal api whenever a persistent - * request is created and any time a request object, that has - * an associated buffer, is returned from an operation to protect - * the buffer from getting prematurely garbage collected. - * @param buf buffer to add to the array list - */ - protected final void addSendBufRef(Buffer buf) - { - this.sendBuf = buf; - } - - /** - * Test if request object is null. - * @return true if the request object is null, false otherwise - */ - public final boolean isNull() - { - return handle == 0 || handle == MPI.REQUEST_NULL.handle; - } - - /** - * Blocks until the operation identified by the request is complete. - *

Java binding of the MPI operation {@code MPI_WAIT}. - *

After the call returns, the request object becomes inactive. - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status waitStatus() throws MPIException - { - MPI.check(); - Status status = new Status(); - handle = waitStatus(handle, status.data); - return status; - } - - private native long waitStatus(long request, long[] stat) throws MPIException; - - /** - * Blocks until the operation identified by the request is complete. - *

Java binding of the MPI operation {@code MPI_WAIT}. - *

After the call returns, the request object becomes inactive. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final void waitFor() throws MPIException - { - MPI.check(); - handle = waitFor(handle); - } - - private native long waitFor(long request) throws MPIException; - - /** - * Returns a status object if the operation identified by the request - * is complete, or a null reference otherwise. - *

Java binding of the MPI operation {@code MPI_TEST}. - *

After the call, if the operation is complete (ie, if the return - * value is non-null), the request object becomes inactive. - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status testStatus() throws MPIException - { - MPI.check(); - return testStatus(handle); - } - - private native Status testStatus(long request) throws MPIException; - - /** - * Returns a status object if the operation identified by the request - * is complete, or a null reference otherwise. - *

Java binding of the MPI operation {@code MPI_REQUEST_GET_STATUS}. - *

After the call, if the operation is complete (ie, if the return - * value is non-null), the request object remains active. - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Status getStatus() throws MPIException - { - MPI.check(); - return getStatus(handle); - } - - private native Status getStatus(long request) throws MPIException; - - /** - * Returns true if the operation identified by the request - * is complete, or false otherwise. - *

Java binding of the MPI operation {@code MPI_TEST}. - *

After the call, if the operation is complete (ie, if the return - * value is true), the request object becomes inactive. - * @return true if the operation identified by the request, false otherwise - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final boolean test() throws MPIException - { - MPI.check(); - return test(handle); - } - - private native boolean test(long handle) throws MPIException; - - /** - * Blocks until one of the operations associated with the active - * requests in the array has completed. - *

Java binding of the MPI operation {@code MPI_WAITANY}. - *

The index in array of {@code requests} for the request that - * completed can be obtained from the returned status object through - * the {@code Status.getIndex()} method. The corresponding element - * of array of {@code requests} becomes inactive. - * @param requests array of requests - * @return status object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status waitAnyStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status status = new Status(); - waitAnyStatus(r, status.data); - setHandles(requests, r); - return status; - } - - private static native void waitAnyStatus(long[] requests, long[] status) - throws MPIException; - - /** - * Blocks until one of the operations associated with the active - * requests in the array has completed. - *

Java binding of the MPI operation {@code MPI_WAITANY}. - *

The request that completed becomes inactive. - * @param requests array of requests - * @return The index in array of {@code requests} for the request that - * completed. If all of the requests are MPI_REQUEST_NULL, then index - * is returned as {@code MPI.UNDEFINED}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int waitAny(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - int index = waitAny(r); - setHandles(requests, r); - return index; - } - - private static native int waitAny(long[] requests) throws MPIException; - - /** - * Tests for completion of either one or none of the operations - * associated with active requests. - *

Java binding of the MPI operation {@code MPI_TESTANY}. - *

If some request completed, the index in array of {@code requests} - * for that request can be obtained from the returned status object. - * The corresponding element in array of {@code requests} becomes inactive. - * If no request completed, {@code testAnyStatus} returns {@code null}. - * @param requests array of requests - * @return status object if one request completed, {@code null} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status testAnyStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status status = testAnyStatus(r); - setHandles(requests, r); - return status; - } - - private static native Status testAnyStatus(long[] requests) throws MPIException; - - /** - * Tests for completion of either one or none of the operations - * associated with active requests. - *

Java binding of the MPI operation {@code MPI_TESTANY}. - *

If some request completed, it becomes inactive. - * @param requests array of requests - * @return index of operation that completed, or {@code MPI.UNDEFINED} - * if none completed. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int testAny(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - int index = testAny(r); - setHandles(requests, r); - return index; - } - - private static native int testAny(long[] requests) throws MPIException; - - /** - * Blocks until all of the operations associated with the active - * requests in the array have completed. - *

Java binding of the MPI operation {@code MPI_WAITALL}. - *

On exit, requests become inactive. If the input value of - * array of {@code requests} contains inactive requests, corresponding - * elements of the status array will contain null status references. - * @param requests array of requests - * @return array of statuses - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status[] waitAllStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status[] status = waitAllStatus(r); - setHandles(requests, r); - return status; - } - - private static native Status[] waitAllStatus(long[] requests) - throws MPIException; - - /** - * Blocks until all of the operations associated with the active - * requests in the array have completed. - *

Java binding of the MPI operation {@code MPI_WAITALL}. - * @param requests array of requests - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void waitAll(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - waitAll(r); - setHandles(requests, r); - } - - private static native void waitAll(long[] requests) throws MPIException; - - /** - * Tests for completion of all of the operations associated - * with active requests. - *

Java binding of the MPI operation {@code MPI_TESTALL}. - *

If all operations have completed, the exit value of the argument array - * is as for {@code waitAllStatus}. - * @param requests array of requests - * @return array of statuses if all operations have completed, - * {@code null} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status[] testAllStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status[] status = testAllStatus(r); - setHandles(requests, r); - return status; - } - - private static native Status[] testAllStatus(long[] requests) - throws MPIException; - - /** - * Tests for completion of all of the operations associated - * with active requests. - *

Java binding of the MPI operation {@code MPI_TESTALL}. - * @param requests array of requests - * @return {@code true} if all operations have completed, - * {@code false} otherwise. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static boolean testAll(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - boolean completed = testAll(r); - setHandles(requests, r); - return completed; - } - - private static native boolean testAll(long[] requests) throws MPIException; - - /** - * Blocks until at least one of the operations associated with the active - * requests in the array has completed. - *

Java binding of the MPI operation {@code MPI_WAITSOME}. - *

The size of the result array will be the number of operations that - * completed. The index in array of {@code requests} for each request that - * completed can be obtained from the returned status objects through the - * {@code Status.getIndex()} method. The corresponding element in - * array of {@code requests} becomes inactive. - * @param requests array of requests - * @return array of statuses or {@code null} if the number of operations - * completed is {@code MPI_UNDEFINED}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status[] waitSomeStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status[] status = waitSomeStatus(r); - setHandles(requests, r); - return status; - } - - private static native Status[] waitSomeStatus(long[] requests) - throws MPIException; - - /** - * Blocks until at least one of the operations associated with the active - * active requests in the array has completed. - *

Java binding of the MPI operation {@code MPI_WAITSOME}. - *

The size of the result array will be the number of operations that - * completed. The corresponding element in array of {@code requests} becomes - * inactive. - * @param requests array of requests - * @return array of indexes of {@code requests} that completed or {@code null} - * if the number of operations completed is {@code MPI_UNDEFINED}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int[] waitSome(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - int[] indexes = waitSome(r); - setHandles(requests, r); - return indexes; - } - - private static native int[] waitSome(long[] requests) throws MPIException; - - /** - * Behaves like {@code waitSome}, except that it returns immediately. - *

Java binding of the MPI operation {@code MPI_TESTSOME}. - *

If no operation has completed, {@code testSome} returns an array of - * length zero, otherwise the return value are as for {@code waitSome}. - * @param requests array of requests - * @return array of statuses - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static Status[] testSomeStatus(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - Status[] status = testSomeStatus(r); - setHandles(requests, r); - return status; - } - - private static native Status[] testSomeStatus(long[] requests) - throws MPIException; - - /** - * Behaves like {@code waitSome}, except that it returns immediately. - *

Java binding of the MPI operation {@code MPI_TESTSOME}. - *

If no operation has completed, {@code testSome} returns an array of - * length zero, otherwise the return value are as for {@code waitSome}. - * @param requests array of requests - * @return array of indexes of {@code requests} that completed. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int[] testSome(Request[] requests) throws MPIException - { - MPI.check(); - long[] r = getHandles(requests); - int[] indexes = testSome(r); - setHandles(requests, r); - return indexes; - } - - private static native int[] testSome(long[] requests) throws MPIException; - - protected static long[] getHandles(Request[] r) - { - long[] h = new long[r.length]; - - for(int i = 0; i < r.length; i++) { - if(r[i] != null) - h[i] = r[i].handle; - else - h[i] = 0; - } - - return h; - } - - protected static void setHandles(Request[] r, long[] h) - { - for(int i = 0; i < r.length; i++) - r[i].handle = h[i]; - } - -} // Request diff --git a/ompi/mpi/java/java/ShiftParms.java b/ompi/mpi/java/java/ShiftParms.java deleted file mode 100644 index 49ddc72014f..00000000000 --- a/ompi/mpi/java/java/ShiftParms.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : ShiftParms.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.1 $ - * Updated : $Date: 1998/08/26 18:50:05 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * Source and destination ranks for "shift" communication. - */ -public final class ShiftParms -{ - private final int rankSource; - private final int rankDest; - - protected ShiftParms(int rankSource, int rankDest) - { - this.rankSource = rankSource; - this.rankDest = rankDest; - } - - /** - * Gets the source rank. - * @return source rank - */ - public int getRankSource() - { - return rankSource; - } - - /** - * Gets the destination rank. - * @return destination rank - */ - public int getRankDest() - { - return rankDest; - } - -} // ShiftParms diff --git a/ompi/mpi/java/java/ShortInt.java b/ompi/mpi/java/java/ShortInt.java deleted file mode 100644 index 18c1a421f05..00000000000 --- a/ompi/mpi/java/java/ShortInt.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -/** - * Struct class for {@link MPI#SHORT_INT} datatype. - */ -public final class ShortInt extends Struct -{ - private final int sSize, iOff, iSize; - - /** - * The struct object will be created only in MPI class. - * @param shortSize short size - * @param intOff int offset - * @param intSize int size - * @see MPI#shortInt - */ - protected ShortInt(int shortSize, int intOff, int intSize) - { - sSize = shortSize; - iSize = intSize; - int sOff; - - switch(sSize) - { - case 2: sOff = addShort(); break; - case 4: sOff = addInt(); break; - case 8: sOff = addLong(); break; - default: throw new AssertionError("Unsupported short size: "+ sSize); - } - - assert sOff == 0; - setOffset(intOff); - - switch(iSize) - { - case 4: iOff = addInt(); break; - case 8: iOff = addLong(); break; - default: throw new AssertionError("Unsupported int size: "+ iSize); - } - - assert(intOff == iOff); - } - - /** - * Creates a Data object. - * @return new Data object. - */ - @Override protected Data newData() - { - return new Data(); - } - - /** - * Class for reading/writing data in a struct stored in a byte buffer. - */ - public final class Data extends Struct.Data - { - /** - * Gets the short value. - * @return short value - */ - public short getValue() - { - switch(sSize) - { - case 2: return getShort(0); - case 4: return (short)getInt(0); - case 8: return (short)getLong(0); - default: throw new AssertionError(); - } - } - - /** - * Gets the int value. - * @return int value - */ - public int getIndex() - { - switch(iSize) - { - case 4: return getInt(iOff); - case 8: return (int)getLong(iOff); - default: throw new AssertionError(); - } - } - - /** - * Puts the short value. - * @param v short value - */ - public void putValue(short v) - { - switch(sSize) - { - case 2: putShort(0, v); break; - case 4: putInt(0, v); break; - case 8: putLong(0, v); break; - default: throw new AssertionError(); - } - } - - /** - * Puts the int value. - * @param v int value - */ - public void putIndex(int v) - { - switch(iSize) - { - case 4: putInt(iOff, v); break; - case 8: putLong(iOff, v); break; - default: throw new AssertionError(); - } - } - } // Data - -} // ShortInt diff --git a/ompi/mpi/java/java/Status.java b/ompi/mpi/java/java/Status.java deleted file mode 100644 index eaeb467cf58..00000000000 --- a/ompi/mpi/java/java/Status.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Status.java - * Author : Sang Lim, Sung-Hoon Ko, Xinying Li, Bryan Carpenter - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.15 $ - * Updated : $Date: 2003/01/16 16:39:34 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -/** - * This class represents {@code MPI_Status}. - */ -public final class Status -{ - protected final long[] data; - - static - { - init(); - } - - private static native void init(); - - /** - * Status objects must be created only by the MPI methods. - */ - protected Status() - { - data = new long[6]; - } - - /** - * Returns the number of received entries. - *

Java binding of the MPI operation {@code MPI_GET_COUNT}. - * @param datatype datatype of each item in receive buffer - * @return number of received entries - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getCount(Datatype datatype) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - return getCount(source, tag, error, cancelled, ucount, datatype.handle); - } - - private native int getCount( - int source, int tag, int error, - int cancelled, long ucount, long datatype) throws MPIException; - - /** - * Tests if the communication was cancelled. - *

Java binding of the MPI operation {@code MPI_TEST_CANCELLED}. - * @return true if the operation was successfully cancelled, false otherwise - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public boolean isCancelled() throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - return isCancelled(source, tag, error, cancelled, ucount); - } - - private native boolean isCancelled( - int source, int tag, int error, int cancelled, long ucount) - throws MPIException; - - /** - * Retrieves the number of basic elements from status. - *

Java binding of the MPI operation {@code MPI_GET_ELEMENTS}. - * @param datatype datatype used by receive operation - * @return number of received basic elements - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public int getElements(Datatype datatype) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - return getElements(source, tag, error, cancelled, ucount, datatype.handle); - } - - private native int getElements( - int source, int tag, int error, - int cancelled, long ucount, long datatype) throws MPIException; - - /** - * Retrieves the number of basic elements from status. - *

Java binding of the MPI operation {@code MPI_GET_ELEMENTS_X}. - * @param datatype datatype used by receive operation - * @return number of received basic elements - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Count getElementsX(Datatype datatype) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - return getElementsX(source, tag, error, cancelled, ucount, datatype.handle); - } - - private native Count getElementsX( - int source, int tag, int error, - int cancelled, long ucount, long datatype) throws MPIException; - - /** - * Sets the number of basic elements for this status object. - *

Java binding of the MPI operation {@code MPI_STATUS_SET_ELEMENTS}. - * @param datatype datatype used by receive operation - * @param count number of elements to associate with the status - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setElements(Datatype datatype, int count) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - data[4] = setElements(source, tag, error, cancelled, ucount, datatype.handle, count); - } - - private native int setElements( - int source, int tag, int error, - int cancelled, long ucount, long datatype, int count) throws MPIException; - - /** - * Sets the number of basic elements for this status object. - *

Java binding of the MPI operation {@code MPI_STATUS_SET_ELEMENTS_X}. - * @param datatype datatype used by receive operation - * @param count number of elements to associate with the status - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setElementsX(Datatype datatype, Count count) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - data[4] = setElementsX(source, tag, error, cancelled, ucount, datatype.handle, count.getCount()); - } - - private native long setElementsX( - int source, int tag, int error, - int cancelled, long ucount, long datatype, long count) throws MPIException; - - /** - * Sets the cancelled flag. - *

Java binding of the MPI operation {@code MPI_STATUS_SET_CANCELLED}. - * @param flag if true indicates request was cancelled - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setCancelled(boolean flag) throws MPIException - { - MPI.check(); - int i = 0; - int source = (int)data[i++]; - int tag = (int)data[i++]; - int error = (int)data[i++]; - int cancelled = (int)data[i++]; - long ucount = data[i++]; - - if(flag) { - setCancelled(source, tag, error, cancelled, ucount, 1); - data[3] = 1; - } else { - setCancelled(source, tag, error, cancelled, ucount, 0); - data[3] = 0; - } - - } - - private native void setCancelled( - int source, int tag, int error, - int cancelled, long ucount, int flag) throws MPIException; - - /** - * Returns the "source" of message. - *

Java binding of the MPI value {@code MPI_SOURCE}. - * @return source of message - */ - public int getSource() - { - return (int)data[0]; - } - - /** - * Returns the "tag" of message. - *

Java binding of the MPI value {@code MPI_TAG}. - * @return tag of message - */ - public int getTag() - { - return (int)data[1]; - } - - /** - * Returns the {@code MPI_ERROR} of message. - * @return error of message. - */ - public int getError() - { - return (int)data[2]; - } - - /** - * Returns the index of message. - * @return index of message. - */ - public int getIndex() - { - return (int)data[5]; - } - -} // Status diff --git a/ompi/mpi/java/java/Struct.java b/ompi/mpi/java/java/Struct.java deleted file mode 100644 index 95e45db6bd8..00000000000 --- a/ompi/mpi/java/java/Struct.java +++ /dev/null @@ -1,802 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -import java.nio.*; -import java.util.*; - -/** - * Base class for defining struct data types. - */ -public abstract class Struct -{ - private int extent; - private ArrayList fields = new ArrayList(); - - private Datatype datatype, types[]; - private int offsets[], lengths[]; - private static final String typeMismatch = "Type mismatch"; - - private void commit() throws MPIException - { - if(datatype == null) - createStruct(); - } - - private void createStruct() throws MPIException - { - int count = fields.size(); - types = new Datatype[count]; - offsets = new int[count]; - lengths = new int[count]; - - for(int i = 0; i < count; i++) - { - Field f = fields.get(i); - - types[i] = f.type instanceof Struct ? ((Struct)f.type).datatype - : (Datatype)f.type; - offsets[i] = f.offset; - lengths[i] = f.length; - } - - datatype = Datatype.createStruct(lengths, offsets, types); - datatype.commit(); - extent = datatype.getExtent(); - } - - /** - * Returns the extent of the struct data type. - * @return Extent of the struct data type. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int getExtent() throws MPIException - { - commit(); - return extent; - } - - /** - * Returns the data type of the struct. - * @return The data type of the struct. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Datatype getType() throws MPIException - { - commit(); - return datatype; - } - - /** - * Creates a Data object. - * @return New Data object. - */ - protected abstract Data newData(); - - @SuppressWarnings("unchecked") - private T newData(ByteBuffer buffer, int offset) - { - Data d = newData(); - d.buffer = buffer; - d.offset = offset; - return (T)d; - } - - @SuppressWarnings("javadoc") - /** - * Gets a Data object in order to access to the buffer. - * @param buffer the Data object will read/write on this buffer. - * @return Data object - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final T getData(ByteBuffer buffer) throws MPIException - { - commit(); - return newData(buffer, 0); - } - - @SuppressWarnings("javadoc") - /** - * Gets a Data object in order to access to the struct at the - * specified position of a struct array stored in a Buffer. - * @param buffer The Data object will read/write on this buffer. - * @param index Index of the struct in the buffer. - * @return Data object. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final T getData(ByteBuffer buffer, int index) - throws MPIException - { - commit(); - return newData(buffer, index * extent); - } - - @SuppressWarnings("javadoc") - /** - * Gets a Data object in order to access to the byte array. - * @param array The Data object will read/write on this byte array. - * @return Data object. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final T getData(byte[] array) throws MPIException - { - ByteBuffer buffer = ByteBuffer.wrap(array); - buffer.order(ByteOrder.nativeOrder()); - return getData(buffer); - } - - @SuppressWarnings("javadoc") - /** - * Gets a Data object in order to access to the struct at the - * specified position of a struct array stored in a byte array. - * @param array The Data object will read/write on this byte array. - * @param index Index of the struct in the array. - * @return Data object. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final T getData(byte[] array, int index) - throws MPIException - { - ByteBuffer buffer = ByteBuffer.wrap(array); - buffer.order(ByteOrder.nativeOrder()); - return getData(buffer, index); - } - - private int addField(Object type, int typeExtent, int length) - { - if(datatype != null) - throw new AssertionError("The struct data type was committed."); - - int offset = extent; - extent += typeExtent * length; - fields.add(new Field(type, offset, length)); - return offset; - } - - /** - * Sets the offset of the next field. - *

The offset must be greater or equal to the accumulated extent. - * @param offset offset of the next field - * @return this object in order to allow adding fields in a chained expression - */ - public final Struct setOffset(int offset) - { - if(datatype != null) - throw new AssertionError("The struct data type was committed."); - - if(offset < extent) - { - throw new IllegalArgumentException( - "The offset must be greater or equal to the accumulated extent."); - } - - extent = offset; - return this; - } - - /** - * Adds a byte field to this struct. - * @return Offset of the new field. - */ - public final int addByte() - { - return addByte(1); - } - - /** - * Adds a byte array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addByte(int length) - { - return addField(MPI.BYTE, 1, length); - } - - /** - * Adds a char field to this struct. - * @return Offset of the new field. - */ - public final int addChar() - { - return addChar(1); - } - - /** - * Adds a char array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addChar(int length) - { - return addField(MPI.CHAR, 2, length); - } - - /** - * Adds a short field to this struct. - * @return Offset of the new field. - */ - public final int addShort() - { - return addShort(1); - } - - /** - * Adds a short array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addShort(int length) - { - return addField(MPI.SHORT, 2, length); - } - - /** - * Adds an int field to this struct. - * @return Offset of the new field. - */ - public final int addInt() - { - return addInt(1); - } - - /** - * Adds an int array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addInt(int length) - { - return addField(MPI.INT, 4, length); - } - - /** - * Adds a long field to this struct. - * @return Offset of the new field. - */ - public final int addLong() - { - return addLong(1); - } - - /** - * Adds a long array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addLong(int length) - { - return addField(MPI.LONG, 8, length); - } - - /** - * Adds a float field to this struct. - * @return Offset of the new field. - */ - public final int addFloat() - { - return addFloat(1); - } - - /** - * Adds a float array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addFloat(int length) - { - return addField(MPI.FLOAT, 4, length); - } - - /** - * Adds a double field to this struct. - * @return Offset of the new field. - */ - public final int addDouble() - { - return addDouble(1); - } - - /** - * Adds a double array to this struct. - * @param length Length of the array. - * @return Offset of the new field. - */ - public final int addDouble(int length) - { - return addField(MPI.DOUBLE, 8, length); - } - - /** - * Adds a struct field to this struct. - * @param struct Type of the field. - * @return Offset of the new field. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int addStruct(Struct struct) throws MPIException - { - return addStruct(struct, 1); - } - - /** - * Adds an array of structs to this struct. - * @param struct Type of the array. - * @param length Length of the array. - * @return Offset of the new field. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int addStruct(Struct struct, int length) throws MPIException - { - struct.commit(); - return addField(struct, struct.extent, length); - } - - /** - * Adds a field of the specified data type. - * @param type Data type. - * @return Offset of the new field. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int addData(Datatype type) throws MPIException - { - return addData(type, 1); - } - - /** - * Adds an array of the specified data type. - * @param type Data type. - * @param length Length of the array. - * @return Offset of the new field. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final int addData(Datatype type, int length) throws MPIException - { - return addField(type, type.getExtent() * type.baseSize, length); - } - - private boolean validType(int fieldOffset, int index, Datatype type) - { - int i = Arrays.binarySearch(offsets, fieldOffset); - return index >= 0 && index < lengths[i] && type == types[i]; - } - - private static class Field - { - private Object type; - private int offset, length; - - private Field(Object type, int offset, int length) - { - this.type = type; - this.offset = offset; - this.length = length; - } - - } // Field - - /** - * Base class for reading/writing data in a struct stored in a byte buffer. - */ - public abstract class Data - { - private ByteBuffer buffer; - private int offset; - - /** - * Gets the buffer where this struct data is stored. - *

The buffer can be used in {@code send}/{@code recv} operations. - * @return Buffer where the struct data is stored. - */ - public final ByteBuffer getBuffer() - { - return offset == 0 ? buffer : MPI.slice(buffer, offset); - } - - /** - * Gets the byte value of a field. - * @param field Offset of the field. - * @return Byte value. - */ - protected final byte getByte(int field) - { - assert validType(field, 0, MPI.BYTE) : typeMismatch; - return buffer.get(offset + field); - } - - /** - * Gets the byte value at the specified position of a byte array. - * @param field Offset of the byte array. - * @param index Index of the byte in the array. - * @return Byte value. - */ - protected final byte getByte(int field, int index) - { - assert validType(field, index, MPI.BYTE) : typeMismatch; - return buffer.get(offset + field + index); - } - - /** - * Puts a byte value in a field. - * @param field Offset of the field. - * @param v Byte value. - */ - protected final void putByte(int field, byte v) - { - assert validType(field, 0, MPI.BYTE) : typeMismatch; - buffer.put(offset + field, v); - } - - /** - * Puts a byte value at the specified position of a byte array. - * @param field Offset of the byte array. - * @param index Index of the byte in the array. - * @param v Byte value. - */ - protected final void putByte(int field, int index, byte v) - { - assert validType(field, index, MPI.BYTE) : typeMismatch; - buffer.put(offset + field + index, v); - } - - /** - * Gets the char value of a field. - * @param field Offset of the field. - * @return Char value. - */ - protected final char getChar(int field) - { - assert validType(field, 0, MPI.CHAR) : typeMismatch; - return buffer.getChar(offset + field); - } - - /** - * Gets the char value at the specified position of a char array. - * @param field Offset of the char array. - * @param index Index of the char in the array. - * @return Char value. - */ - protected final char getChar(int field, int index) - { - assert validType(field, index, MPI.CHAR) : typeMismatch; - return buffer.getChar(offset + field + index * 2); - } - - /** - * Puts a char value in a field. - * @param field Offset of the field. - * @param v Char value. - */ - protected final void putChar(int field, char v) - { - assert validType(field, 0, MPI.CHAR) : typeMismatch; - buffer.putChar(offset + field, v); - } - - /** - * Puts a char value at the specified position of a char array. - * @param field Offset of the char array. - * @param index Index of the char in the array. - * @param v Char value. - */ - protected final void putChar(int field, int index, char v) - { - assert validType(field, index, MPI.CHAR) : typeMismatch; - buffer.putChar(offset + field + index * 2, v); - } - - /** - * Gets the short value of a field. - * @param field Offset of the field. - * @return Short value. - */ - protected final short getShort(int field) - { - assert validType(field, 0, MPI.SHORT) : typeMismatch; - return buffer.getShort(offset + field); - } - - /** - * Gets the short value at the specified position of a short array. - * @param field Offset of the short array. - * @param index Index of the short in the array. - * @return Short value. - */ - protected final short getShort(int field, int index) - { - assert validType(field, index, MPI.SHORT) : typeMismatch; - return buffer.getShort(offset + field + index * 2); - } - - /** - * Puts a short value in a field. - * @param field Offset of the field. - * @param v Short value. - */ - protected final void putShort(int field, short v) - { - assert validType(field, 0, MPI.SHORT) : typeMismatch; - buffer.putShort(offset + field, v); - } - - /** - * Puts a short value at the specified position of a short array. - * @param field Offset of the short array. - * @param index Index of the short in the array. - * @param v Short value. - */ - protected final void putShort(int field, int index, short v) - { - assert validType(field, index, MPI.SHORT) : typeMismatch; - buffer.putShort(offset + field + index * 2, v); - } - - /** - * Gets the int value of a field. - * @param field Offset of the field. - * @return Int value. - */ - protected final int getInt(int field) - { - assert validType(field, 0, MPI.INT) : typeMismatch; - return buffer.getInt(offset + field); - } - - /** - * Gets the int value at the specified position of an int array. - * @param field Offset of the int array. - * @param index Index of the int in the array. - * @return Int value. - */ - protected final int getInt(int field, int index) - { - assert validType(field, index, MPI.INT) : typeMismatch; - return buffer.getInt(offset + field + index * 4); - } - - /** - * Puts an int value in a field. - * @param field Offset of the field. - * @param v Int value. - */ - protected final void putInt(int field, int v) - { - assert validType(field, 0, MPI.INT) : typeMismatch; - buffer.putInt(offset + field, v); - } - - /** - * Puts an int value at the specified position of an int array. - * @param field Offset of the int array. - * @param index Index of the int in the array. - * @param v Int value. - */ - protected final void putInt(int field, int index, int v) - { - assert validType(field, index, MPI.INT) : typeMismatch; - buffer.putInt(offset + field + index * 4, v); - } - - /** - * Gets the long value of a field. - * @param field Offset of the field. - * @return Long value. - */ - protected final long getLong(int field) - { - assert validType(field, 0, MPI.LONG) : typeMismatch; - return buffer.getLong(offset + field); - } - - /** - * Gets the long value at the specified position of a long array. - * @param field Offset of the long array. - * @param index Index of the long in the array. - * @return Long value. - */ - protected final long getLong(int field, int index) - { - assert validType(field, index, MPI.LONG) : typeMismatch; - return buffer.getLong(offset + field + index * 8); - } - - /** - * Puts a long value in a field. - * @param field Offset of the field. - * @param v Long value. - */ - protected final void putLong(int field, long v) - { - assert validType(field, 0, MPI.LONG) : typeMismatch; - buffer.putLong(offset + field, v); - } - - /** - * Puts a long value at the specified position of a long array. - * @param field Offset of the long array. - * @param index Index of the long in the array. - * @param v Long value. - */ - protected final void putLong(int field, int index, long v) - { - assert validType(field, index, MPI.LONG) : typeMismatch; - buffer.putLong(offset + field + index * 8, v); - } - - /** - * Gets the float value of a field. - * @param field Offset of the field. - * @return Float value. - */ - protected final float getFloat(int field) - { - assert validType(field, 0, MPI.FLOAT) : typeMismatch; - return buffer.getFloat(offset + field); - } - - /** - * Gets the float value at the specified position of a float array. - * @param field Offset of the float array. - * @param index Index of the float in the array. - * @return Float value. - */ - protected final float getFloat(int field, int index) - { - assert validType(field, index, MPI.FLOAT) : typeMismatch; - return buffer.getFloat(offset + field + index * 4); - } - - /** - * Puts a float value in a field. - * @param field Offset of the field. - * @param v Float value. - */ - protected final void putFloat(int field, float v) - { - assert validType(field, 0, MPI.FLOAT) : typeMismatch; - buffer.putFloat(offset + field, v); - } - - /** - * Puts a float value at the specified position of a float array. - * @param field Offset of the float array. - * @param index Index of the float in the array. - * @param v Float value. - */ - protected final void putFloat(int field, int index, float v) - { - assert validType(field, index, MPI.FLOAT) : typeMismatch; - buffer.putFloat(offset + field + index * 4, v); - } - - /** - * Gets the double value of a field. - * @param field Offset of the field. - * @return Double value. - */ - protected final double getDouble(int field) - { - assert validType(field, 0, MPI.DOUBLE) : typeMismatch; - return buffer.getDouble(offset + field); - } - - /** - * Gets the double value at the specified position of a double array. - * @param field Offset of the double array. - * @param index Index of the double in the array. - * @return Double value. - */ - protected final double getDouble(int field, int index) - { - assert validType(field, index, MPI.DOUBLE) : typeMismatch; - return buffer.getDouble(offset + field + index * 8); - } - - /** - * Puts a double value in a field. - * @param field Offset of the field. - * @param v Double value. - */ - protected final void putDouble(int field, double v) - { - assert validType(field, 0, MPI.DOUBLE) : typeMismatch; - buffer.putDouble(offset + field, v); - } - - /** - * Puts a double value at the specified position of a double array. - * @param field Offset of the double array. - * @param index Index of the double in the array. - * @param v Double value. - */ - protected final void putDouble(int field, int index, double v) - { - assert validType(field, index, MPI.DOUBLE) : typeMismatch; - buffer.putDouble(offset + field + index * 8, v); - } - - @SuppressWarnings("javadoc") - /** - * Gets the struct data of a field. - * @param struct Struct type. - * @param field Offset of the field. - * @return Struct data. - */ - protected final - D getData(S struct, int field) - { - Struct s = (Struct)struct; - assert validType(field, 0, s.datatype) : typeMismatch; - return s.newData(buffer, offset + field); - } - - @SuppressWarnings("javadoc") - /** - * Gets the struct data at the specified position of a struct array. - * @param struct Struct type. - * @param field Offset of the struct array. - * @param index Index of the struct in the array. - * @return Struct data. - */ - protected final - D getData(S struct, int field, int index) - { - Struct s = (Struct)struct; - assert validType(field, index, s.datatype) : typeMismatch; - return s.newData(buffer, offset + field + index * s.extent); - } - - /** - * Gets the buffer of a field. - *

The buffer can be used in {@code send}/{@code recv} operations. - * @param type Data type of the buffer. - * @param field Offset of the field. - * @return Buffer object. - */ - protected final ByteBuffer getBuffer(Datatype type, int field) - { - assert validType(field, 0, type) : typeMismatch; - int position = offset + field; - return position == 0 ? buffer : MPI.slice(buffer, position); - } - - /** - * Gets the buffer data at the specified position of a buffer array. - *

The buffer can be used in {@code send}/{@code recv} operations. - * @param type Data type of the buffer. - * @param field Offset of the buffer array. - * @param index Index of the buffer in the array. - * @return Buffer object. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - protected final ByteBuffer getBuffer(Datatype type, int field, int index) - throws MPIException - { - assert validType(field, index, type) : typeMismatch; - - int extent = type.getExtent() * type.baseSize, - position = offset + field + index * extent; - - return position == 0 ? buffer : MPI.slice(buffer, position); - } - - } // Data - -} // Struct diff --git a/ompi/mpi/java/java/UserFunction.java b/ompi/mpi/java/java/UserFunction.java deleted file mode 100644 index 2618b8b2040..00000000000 --- a/ompi/mpi/java/java/UserFunction.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ -/* - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - */ -/* - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -/* - * File : User_function.java - * Author : Xinying Li - * Created : Thu Apr 9 12:22:15 1998 - * Revision : $Revision: 1.4 $ - * Updated : $Date: 1999/09/13 16:14:30 $ - * Copyright: Northeast Parallel Architectures Center - * at Syracuse University 1998 - */ - -package mpi; - -import java.nio.*; - -/** - * Java equivalent of the {@code MPI_USER_FUNCTION}. - */ -public abstract class UserFunction -{ - /** - * User-defined function for a new {@code Op}. - * @param inVec array of values to combine with {@code inoutvec} elements - * @param inOutVec in-out array of accumulator locations - * @param count number of items in arrays - * @param datatype type of each item - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void call(Object inVec, Object inOutVec, int count, Datatype datatype) - throws MPIException - { - throw new UnsupportedOperationException("Not supported yet."); - } - - /** - * User-defined function for a new {@code Op}. - * @param in direct byte buffer to combine with {@code inOut} buffer - * @param inOut in-out direct byte buffer of accumulator locations - * @param count number of items in buffers - * @param datatype type of each item - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void call(ByteBuffer in, ByteBuffer inOut, int count, Datatype datatype) - throws MPIException - { - switch(datatype.baseType) - { - case Datatype.BYTE: - vCall(in, inOut, count, datatype); - break; - case Datatype.CHAR: - vCall(in.asCharBuffer(), inOut.asCharBuffer(), count, datatype); - break; - case Datatype.SHORT: - vCall(in.asShortBuffer(), inOut.asShortBuffer(), count, datatype); - break; - case Datatype.INT: - vCall(in.asIntBuffer(), inOut.asIntBuffer(), count, datatype); - break; - case Datatype.LONG: - vCall(in.asLongBuffer(), inOut.asLongBuffer(), count, datatype); - break; - case Datatype.FLOAT: - vCall(in.asFloatBuffer(), inOut.asFloatBuffer(), count, datatype); - break; - case Datatype.DOUBLE: - vCall(in.asDoubleBuffer(), inOut.asDoubleBuffer(), count, datatype); - break; - case Datatype.PACKED: - vCall(in, inOut, count, datatype); - break; - default: - throw new IllegalArgumentException("Unsupported datatype."); - } - } - - private void vCall(ByteBuffer in, ByteBuffer inOut, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - byte[] inVec = new byte[count * extent], - inOutVec = new byte[count * extent]; - - in.get(inVec); - inOut.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOut.clear(); - inOut.put(inOutVec); - } - - private void vCall(CharBuffer inBuf, CharBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - char[] inVec = new char[count * extent], - inOutVec = new char[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - - private void vCall(ShortBuffer inBuf, ShortBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - short[] inVec = new short[count * extent], - inOutVec = new short[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - - private void vCall(IntBuffer inBuf, IntBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - int[] inVec = new int[count * extent], - inOutVec = new int[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - - private void vCall(LongBuffer inBuf, LongBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - long[] inVec = new long[count * extent], - inOutVec = new long[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - - private void vCall(FloatBuffer inBuf, FloatBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - float[] inVec = new float[count * extent], - inOutVec = new float[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - - private void vCall(DoubleBuffer inBuf, DoubleBuffer inOutBuf, - int count, Datatype datatype) throws MPIException - { - int extent = datatype.getExtent(); - double[] inVec = new double[count * extent], - inOutVec = new double[count * extent]; - - inBuf.get(inVec); - inOutBuf.get(inOutVec); - call(inVec, inOutVec, count, datatype); - inOutBuf.clear(); - inOutBuf.put(inOutVec); - } - -} // UserFunction diff --git a/ompi/mpi/java/java/Version.java b/ompi/mpi/java/java/Version.java deleted file mode 100644 index 2194ce35a54..00000000000 --- a/ompi/mpi/java/java/Version.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2022 Cisco Systems, Inc. All rights reserved - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - * - * - * This file is almost a complete re-write for Open MPI compared to the - * original mpiJava package. Its license and copyright are listed below. - * See for more information. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * File : Version.java - * Author : Nathaniel Graham - * Created : Thu Jul 23 09:25 2015 - */ - -package mpi; - -/** - * Version and Subversion for MPI - */ -public final class Version -{ -private final int version; -private final int subVersion; - -protected Version(int version, int subVersion) -{ - this.version = version; - this.subVersion = subVersion; -} - -/** - * Gets the MPI version. - * @return MPI version - */ -public int getVersion() -{ - return version; -} - -/** - * Gets the MPI subversion. - * @return MPI subversion - */ -public int getSubVersion() -{ - return subVersion; -} - -} // Version diff --git a/ompi/mpi/java/java/Win.java b/ompi/mpi/java/java/Win.java deleted file mode 100644 index e9102f36c91..00000000000 --- a/ompi/mpi/java/java/Win.java +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana - * University Research and Technology - * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University - * of Tennessee Research Foundation. All rights - * reserved. - * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, - * University of Stuttgart. All rights reserved. - * Copyright (c) 2004-2005 The Regents of the University of California. - * All rights reserved. - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights - * reserved. - * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. - * $COPYRIGHT$ - * - * Additional copyrights may follow - * - * $HEADER$ - */ - -package mpi; - -import java.nio.*; - -/** - * This class represents {@code MPI_Win}. - */ -public final class Win implements Freeable -{ - private long handle; - public static final int WIN_NULL = 0; - public static final int FLAVOR_PRIVATE = 0; - public static final int FLAVOR_SHARED = 1; - - /** - * Java binding of {@code MPI_WIN_CREATE}. - * @param base initial address of window - * @param size size of window (buffer elements) - * @param dispUnit local unit size for displacements (buffer elements) - * @param info info object - * @param comm communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Win(Buffer base, int size, int dispUnit, Info info, Comm comm) - throws MPIException - { - if(!base.isDirect()) - throw new IllegalArgumentException("The buffer must be direct."); - - int baseSize; - - if(base instanceof ByteBuffer) - baseSize = 1; - else if(base instanceof CharBuffer || base instanceof ShortBuffer) - baseSize = 2; - else if(base instanceof IntBuffer || base instanceof FloatBuffer) - baseSize = 4; - else if(base instanceof LongBuffer || base instanceof DoubleBuffer) - baseSize = 8; - else - throw new AssertionError(); - - int sizeBytes = size * baseSize, - dispBytes = dispUnit * baseSize; - - handle = createWin(base, sizeBytes, dispBytes, info.handle, comm.handle); - } - - private native long createWin( - Buffer base, int size, int dispUnit, long info, long comm) - throws MPIException; - - /** - * Java binding of {@code MPI_WIN_ALLOCATE} and {@code MPI_WIN_ALLOCATE_SHARED}. - * @param size size of window (buffer elements) - * @param dispUnit local unit size for displacements (buffer elements) - * @param info info object - * @param comm communicator - * @param base initial address of window - * @param flavor FLAVOR_PRIVATE or FLAVOR_SHARED - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Win(int size, int dispUnit, Info info, Comm comm, Buffer base, int flavor) - throws MPIException - { - if(!base.isDirect()) - throw new IllegalArgumentException("The buffer must be direct."); - - int baseSize; - - if(base instanceof ByteBuffer) - baseSize = 1; - else if(base instanceof CharBuffer || base instanceof ShortBuffer) - baseSize = 2; - else if(base instanceof IntBuffer || base instanceof FloatBuffer) - baseSize = 4; - else if(base instanceof LongBuffer || base instanceof DoubleBuffer) - baseSize = 8; - else - throw new AssertionError(); - - int sizeBytes = size * baseSize, - dispBytes = dispUnit * baseSize; - - if(flavor == 0) { - handle = allocateWin(sizeBytes, dispBytes, info.handle, comm.handle, base); - } else if(flavor == 1) { - handle = allocateSharedWin(sizeBytes, dispBytes, info.handle, comm.handle, base); - } - } - - private native long allocateWin( - int size, int dispUnit, long info, long comm, Buffer base) - throws MPIException; - - private native long allocateSharedWin( - int size, int dispUnit, long info, long comm, Buffer base) - throws MPIException; - - /** - * Java binding of {@code MPI_WIN_CREATE_DYNAMIC}. - * @param info info object - * @param comm communicator - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Win(Info info, Comm comm) - throws MPIException - { - handle = createDynamicWin(info.handle, comm.handle); - } - - private native long createDynamicWin( - long info, long comm) - throws MPIException; - - private int getBaseType(Datatype orgType, Datatype targetType) - { - int baseType = orgType.baseType; - - if(baseType != targetType.baseType) - { - throw new IllegalArgumentException( - "Both datatype arguments must be constructed "+ - "from the same predefined datatype."); - } - - return baseType; - } - - /** - * Java binding of {@code MPI_WIN_ATTACH}. - * @param base initial address of window - * @param size size of window (buffer elements) - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void attach(Buffer base, int size) throws MPIException - { - MPI.check(); - if(!base.isDirect()) - throw new IllegalArgumentException("The buffer must be direct."); - - int baseSize; - - if(base instanceof ByteBuffer) - baseSize = 1; - else if(base instanceof CharBuffer || base instanceof ShortBuffer) - baseSize = 2; - else if(base instanceof IntBuffer || base instanceof FloatBuffer) - baseSize = 4; - else if(base instanceof LongBuffer || base instanceof DoubleBuffer) - baseSize = 8; - else - throw new AssertionError(); - - int sizeBytes = size * baseSize; - - attach(handle, base, sizeBytes); - } - - private native void attach(long win, Buffer base, int size) throws MPIException; - - /** - * Java binding of {@code MPI_WIN_DETACH}. - * @param base initial address of window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void detach(Buffer base) throws MPIException - { - MPI.check(); - if(!base.isDirect()) - throw new IllegalArgumentException("The buffer must be direct."); - - detach(handle, base); - } - - private native void detach(long win, Buffer base) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_GET_GROUP}. - * @return group of processes which share access to the window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Group getGroup() throws MPIException - { - MPI.check(); - return new Group(getGroup(handle)); - } - - private native long getGroup(long win) throws MPIException; - - /** - * Java binding of {@code MPI_PUT}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void put(Buffer origin, int orgCount, Datatype orgType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - put(handle, origin, orgCount, orgType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - getBaseType(orgType, targetType)); - } - - private native void put( - long win, Buffer origin, int orgCount, long orgType, - int targetRank, int targetDisp, int targetCount, long targetType, - int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_GET}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void get(Buffer origin, int orgCount, Datatype orgType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - get(handle, origin, orgCount, orgType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - getBaseType(orgType, targetType)); - } - - private native void get( - long win, Buffer origin, int orgCount, long orgType, - int targetRank, int targetDisp, int targetCount, long targetType, - int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_ACCUMULATE}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void accumulate(Buffer origin, int orgCount, Datatype orgType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType, Op op) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - accumulate(handle, origin, orgCount, orgType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - op, op.handle, getBaseType(orgType, targetType)); - } - - private native void accumulate( - long win, Buffer origin, int orgCount, long orgType, - int targetRank, int targetDisp, int targetCount, long targetType, - Op jOp, long hOp, int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_WIN_FENCE}. - * @param assertion program assertion - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void fence(int assertion) throws MPIException - { - MPI.check(); - fence(handle, assertion); - } - - private native void fence(long win, int assertion) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_START}. - * @param group group of target processes - * @param assertion program assertion - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void start(Group group, int assertion) throws MPIException - { - MPI.check(); - start(handle, group.handle, assertion); - } - - private native void start(long win, long group, int assertion) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_COMPLETE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void complete() throws MPIException - { - MPI.check(); - complete(handle); - } - - private native void complete(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_POST}. - * @param group group of origin processes - * @param assertion program assertion - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void post(Group group, int assertion) throws MPIException - { - MPI.check(); - post(handle, group.handle, assertion); - } - - private native void post(long win, long group, int assertion) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_WAIT}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void waitFor() throws MPIException - { - MPI.check(); - waitFor(handle); - } - - private native void waitFor(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_TEST}. - * @return true if success - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public boolean test() throws MPIException - { - MPI.check(); - return test(handle); - } - - private native boolean test(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_LOCK}. - * @param lockType either MPI.LOCK_EXCLUSIVE or MPI.LOCK_SHARED - * @param rank rank of locked window - * @param assertion program assertion - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void lock(int lockType, int rank, int assertion) throws MPIException - { - MPI.check(); - lock(handle, lockType, rank, assertion); - } - - private native void lock(long win, int lockType, int rank, int assertion) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_UNLOCK}. - * @param rank rank of window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void unlock(int rank) throws MPIException - { - MPI.check(); - unlock(handle, rank); - } - - private native void unlock(long win, int rank) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_SET_ERRHANDLER}. - * @param errhandler new MPI error handler for window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setErrhandler(Errhandler errhandler) throws MPIException - { - MPI.check(); - setErrhandler(handle, errhandler.handle); - } - - private native void setErrhandler(long win, long errhandler) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_GET_ERRHANDLER}. - * @return MPI error handler currently associated with window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Errhandler getErrhandler() throws MPIException - { - MPI.check(); - return new Errhandler(getErrhandler(handle)); - } - - private native long getErrhandler(long win); - - /** - * Java binding of the MPI operation {@code MPI_WIN_CALL_ERRHANDLER}. - * @param errorCode error code - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void callErrhandler(int errorCode) throws MPIException - { - callErrhandler(handle, errorCode); - } - - private native void callErrhandler(long handle, int errorCode) - throws MPIException; - - /** - * Create a new attribute key. - *

Java binding of the MPI operation {@code MPI_WIN_CREATE_KEYVAL}. - * @return attribute key for future access - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static int createKeyval() throws MPIException - { - MPI.check(); - return createKeyval_jni(); - } - - private static native int createKeyval_jni() throws MPIException; - - /** - * Frees an attribute key. - *

Java binding of the MPI operation {@code MPI_WIN_FREE_KEYVAL}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public static void freeKeyval(int keyval) throws MPIException - { - MPI.check(); - freeKeyval_jni(keyval); - } - - private static native void freeKeyval_jni(int keyval) throws MPIException; - - /** - * Stores attribute value associated with a key. - *

Java binding of the MPI operation {@code MPI_WIN_SET_ATTR}. - * @param keyval attribute key - * @param value attribute value - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setAttr(int keyval, Object value) throws MPIException - { - MPI.check(); - setAttr(handle, keyval, MPI.attrSet(value)); - } - - private native void setAttr(long win, int keyval, byte[] value) - throws MPIException; - - /** - * Retrieves attribute value by key. - *

Java binding of the MPI operation {@code MPI_WIN_GET_ATTR}. - * @param keyval attribute key - * @return attribute value or null if no attribute is associated with the key. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Object getAttr(int keyval) throws MPIException - { - MPI.check(); - Object obj = getAttr(handle, keyval); - return obj instanceof byte[] ? MPI.attrGet((byte[])obj) : obj; - } - - private native Object getAttr(long win, int keyval) throws MPIException; - - /** - * Deletes an attribute value associated with a key. - *

Java binding of the MPI operation {@code MPI_WIN_DELETE_ATTR}. - * @param keyval attribute key - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void deleteAttr(int keyval) throws MPIException - { - MPI.check(); - deleteAttr(handle, keyval); - } - - private native void deleteAttr(long win, int keyval) throws MPIException; - - /** - * Java binding of {@code MPI_WIN_FREE}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - @Override public void free() throws MPIException - { - MPI.check(); - handle = free(handle); - } - - private native long free(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_GET_INFO}. - * @return Info Info object associated with this window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Info getInfo() throws MPIException - { - MPI.check(); - return new Info(getInfo(handle)); - } - - private native long getInfo(long win) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_SET_INFO}. - * @param info the new info - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setInfo(Info info) throws MPIException - { - MPI.check(); - setInfo(handle, info.handle); - } - - private native void setInfo(long win, long info) - throws MPIException; - - /** - *

Java binding of the MPI operation {@code MPI_RPUT}. - * @param origin_addr initial address of origin buffer - * @param origin_count number of entries in origin buffer - * @param origin_datatype datatype of each entry in origin buffer - * @param target_rank rank of target - * @param target_disp displacement from start of window to target buffer - * @param target_count number of entries in target buffer - * @param target_datatype datatype of each entry in target buffer - * @return RMA request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request rPut(Buffer origin_addr, int origin_count, - Datatype origin_datatype, int target_rank, int target_disp, - int target_count, Datatype target_datatype) - throws MPIException - { - if(!origin_addr.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - Request req = new Request(rPut(handle, origin_addr, origin_count, - origin_datatype.handle, target_rank, target_disp, - target_count, target_datatype.handle, getBaseType(origin_datatype, target_datatype))); - req.addSendBufRef(origin_addr); - return req; - } - - private native long rPut(long win, Buffer origin_addr, int origin_count, - long origin_datatype, int target_rank, int target_disp, - int target_count, long target_datatype, int baseType) - throws MPIException; - - /** - * Java binding of {@code MPI_RGET}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @return RMA request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public final Request rGet(Buffer origin, int orgCount, Datatype orgType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - Request req = new Request(rGet(handle, origin, orgCount, orgType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - getBaseType(orgType, targetType))); - req.addRecvBufRef(origin); - return req; - } - - private native long rGet( - long win, Buffer origin, int orgCount, long orgType, - int targetRank, int targetDisp, int targetCount, long targetType, - int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_RACCUMULATE}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @param op reduce operation - * @return RMA request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public Request rAccumulate(Buffer origin, int orgCount, Datatype orgType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType, Op op) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - Request req = new Request(rAccumulate(handle, origin, orgCount, orgType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - op, op.handle, getBaseType(orgType, targetType))); - req.addSendBufRef(origin); - return req; - } - - private native long rAccumulate( - long win, Buffer origin, int orgCount, long orgType, - int targetRank, int targetDisp, int targetCount, long targetType, - Op jOp, long hOp, int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_GET_ACCUMULATE}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param resultAddr result buffer - * @param resultCount number of entries in result buffer - * @param resultType datatype of each entry in result buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public void getAccumulate(Buffer origin, int orgCount, Datatype orgType, - Buffer resultAddr, int resultCount, Datatype resultType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType, Op op) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - getAccumulate(handle, origin, orgCount, orgType.handle, - resultAddr, resultCount, resultType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - op, op.handle, getBaseType(orgType, targetType)); - } - - private native void getAccumulate( - long win, Buffer origin, int orgCount, long orgType, - Buffer resultAddr, int resultCount, long resultType, - int targetRank, int targetDisp, int targetCount, long targetType, - Op jOp, long hOp, int baseType) throws MPIException; - - /** - * Java binding of {@code MPI_RGET_ACCUMULATE}. - * @param origin origin buffer - * @param orgCount number of entries in origin buffer - * @param orgType datatype of each entry in origin buffer - * @param resultAddr result buffer - * @param resultCount number of entries in result buffer - * @param resultType datatype of each entry in result buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param targetCount number of entries in target buffer - * @param targetType datatype of each entry in target buffer - * @param op reduce operation - * @return RMA request - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public Request rGetAccumulate(Buffer origin, int orgCount, Datatype orgType, - Buffer resultAddr, int resultCount, Datatype resultType, - int targetRank, int targetDisp, int targetCount, - Datatype targetType, Op op) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - Request req = new Request(rGetAccumulate(handle, origin, orgCount, orgType.handle, - resultAddr, resultCount, resultType.handle, - targetRank, targetDisp, targetCount, targetType.handle, - op, op.handle, getBaseType(orgType, targetType))); - req.addRecvBufRef(origin); - return req; - } - - private native long rGetAccumulate( - long win, Buffer origin, int orgCount, long orgType, - Buffer resultAddr, int resultCount, long resultType, - int targetRank, int targetDisp, int targetCount, long targetType, - Op jOp, long hOp, int baseType) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_LOCK_ALL}. - * @param assertion program assertion - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void lockAll(int assertion) throws MPIException - { - MPI.check(); - lockAll(handle, assertion); - } - - private native void lockAll(long win, int assertion) - throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_UNLOCK_ALL}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void unlockAll() throws MPIException - { - MPI.check(); - unlockAll(handle); - } - - private native void unlockAll(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_SYNC}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void sync() throws MPIException - { - MPI.check(); - sync(handle); - } - - private native void sync(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_FLUSH}. - * @param targetRank rank of target window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void flush(int targetRank) throws MPIException - { - MPI.check(); - flush(handle, targetRank); - } - - private native void flush(long win, int targetRank) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_FLUSH_ALL}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void flushAll() throws MPIException - { - MPI.check(); - flushAll(handle); - } - - private native void flushAll(long win) throws MPIException; - - /** - * Java binding of {@code MPI_COMPARE_AND_SWAP}. - * @param origin origin buffer - * @param compareAddr compare buffer - * @param resultAddr result buffer - * @param targetType datatype of each entry in target buffer - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public void compareAndSwap(Buffer origin, Buffer compareAddr, Buffer resultAddr, - Datatype targetType, int targetRank, int targetDisp) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - compareAndSwap(handle, origin, compareAddr, resultAddr, - targetType.handle, targetRank, targetDisp); - } - - private native void compareAndSwap( - long win, Buffer origin, Buffer compareAddr, Buffer resultAddr, - long targetType, int targetRank, int targetDisp) throws MPIException; - - /** - * Java binding of {@code MPI_FETCH_AND_OP}. - * @param origin origin buffer - * @param resultAddr result buffer - * @param dataType datatype of entry in origin, result, and target buffers - * @param targetRank rank of target - * @param targetDisp displacement from start of window to target buffer - * @param op reduce operation - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public void fetchAndOp(Buffer origin, Buffer resultAddr, Datatype dataType, - int targetRank, int targetDisp, Op op) - throws MPIException - { - MPI.check(); - - if(!origin.isDirect()) - throw new IllegalArgumentException("The origin must be direct buffer."); - - fetchAndOp(handle, origin, resultAddr, dataType.handle, targetRank, - targetDisp, op, op.handle, getBaseType(dataType, dataType)); - } - - private native void fetchAndOp( - long win, Buffer origin, Buffer resultAddr, long targetType, int targetRank, - int targetDisp, Op jOp, long hOp, int baseType) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_FLUSH_LOCAL}. - * @param targetRank rank of target window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public void flushLocal(int targetRank) throws MPIException - { - MPI.check(); - flushLocal(handle, targetRank); - } - - private native void flushLocal(long win, int targetRank) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_FLUSH_LOCAL_ALL}. - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - - public void flushLocalAll() throws MPIException - { - MPI.check(); - flushLocalAll(handle); - } - - private native void flushLocalAll(long win) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_GET_NAME}. - * @return the name associated with this window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public String getName() throws MPIException - { - MPI.check(); - return getName(handle); - } - - private native String getName(long handle) throws MPIException; - - /** - * Java binding of the MPI operation {@code MPI_WIN_SET_NAME}. - * @param name the name to associate with this window - * @throws MPIException Signals that an MPI error of some sort has occurred. - */ - public void setName(String name) throws MPIException - { - MPI.check(); - setName(handle, name); - } - - private native void setName(long handle, String name) throws MPIException; - -} // Win diff --git a/ompi/op/op.c b/ompi/op/op.c index 3ace78f5933..8d986f17ff9 100644 --- a/ompi/op/op.c +++ b/ompi/op/op.c @@ -20,6 +20,7 @@ * Copyright (c) 2018-2025 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2026 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -401,25 +402,6 @@ ompi_op_t *ompi_op_create_user(bool commute, } -/* - * See lengthy comment in mpi/cxx/intercepts.cc for how the C++ MPI::Op - * callbacks work. - */ -void ompi_op_set_java_callback(ompi_op_t *op, void *jnienv, - void *object, int baseType) -{ - op->o_flags |= OMPI_OP_FLAGS_JAVA_FUNC; - /* The OMPI Java intercept was previously stored in - op->o_func.fort_fn by ompi_op_create_user(). So save that in - cxx.intercept_fn and put the user's fn in cxx.user_fn. */ - op->o_func.java_data.intercept_fn = - (ompi_op_java_handler_fn_t *) op->o_func.fort_fn; - op->o_func.java_data.jnienv = jnienv; - op->o_func.java_data.object = object; - op->o_func.java_data.baseType = baseType; -} - - /************************************************************************** * * Static functions diff --git a/ompi/op/op.h b/ompi/op/op.h index bf895d7c6f3..d5ab76f17cd 100644 --- a/ompi/op/op.h +++ b/ompi/op/op.h @@ -21,6 +21,7 @@ * Copyright (c) 2018-2025 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2021 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -72,15 +73,6 @@ typedef void (ompi_op_fortran_handler_fn_t)(const void *, void *, typedef void (ompi_op_fortran_handler_bc_fn_t)(const void *, void *, size_t *, MPI_Fint *); -/** - * Typedef for Java op functions intercept (used for user-defined - * MPI.Ops). - */ -typedef void (ompi_op_java_handler_fn_t)(const void *, void *, int *, - struct ompi_datatype_t **, - int baseType, - void *jnienv, void *object); - /* * Flags for MPI_Op */ @@ -88,8 +80,6 @@ typedef void (ompi_op_java_handler_fn_t)(const void *, void *, int *, #define OMPI_OP_FLAGS_INTRINSIC 0x0001 /** Set if the callback function is in Fortran */ #define OMPI_OP_FLAGS_FORTRAN_FUNC 0x0002 -/** Set if the callback function is in Java */ -#define OMPI_OP_FLAGS_JAVA_FUNC 0x0008 /** Set if the callback function is associative (MAX and SUM will both have ASSOC set -- in fact, it will only *not* be set if we implement some extensions to MPI, because MPI says that all @@ -162,14 +152,6 @@ struct ompi_op_t { ompi_op_fortran_handler_fn_t *fort_fn; /** Fortran handler function pointer - bigcount*/ ompi_op_fortran_handler_bc_fn_t *fort_fn_bc; - /** Java intercept function data */ - struct { - /* The OMPI C++ callback/intercept function */ - ompi_op_java_handler_fn_t *intercept_fn; - /* The Java run time environment */ - void *jnienv, *object; - int baseType; - } java_data; } o_func; /** 3-buffer functions, which is only for intrinsic ops. No need @@ -368,13 +350,6 @@ ompi_op_t *ompi_op_create_user(bool commute, bool bigcount, ompi_op_fortran_handler_fn_t func); -/** - * Mark an MPI_Op as holding a Java callback function, and cache that - * function in the MPI_Op. - */ -OMPI_DECLSPEC void ompi_op_set_java_callback(ompi_op_t *op, void *jnienv, - void *object, int baseType); - /** * Check to see if an op is intrinsic. * @@ -594,12 +569,6 @@ static inline void ompi_op_reduce(ompi_op_t * op, const void *source, op->o_func.fort_fn_bc(source, target, &full_count, &f_dtype); } return; - } else if (0 != (op->o_flags & OMPI_OP_FLAGS_JAVA_FUNC)) { - op->o_func.java_data.intercept_fn(source, target, &count, &dtype, - op->o_func.java_data.baseType, - op->o_func.java_data.jnienv, - op->o_func.java_data.object); - return; } if (0 == (op->o_flags & OMPI_OP_FLAGS_BIGCOUNT)) { op->o_func.c_fn(source, target, &count, &dtype); diff --git a/ompi/tools/ompi_info/param.c b/ompi/tools/ompi_info/param.c index f112bc5ed0c..54f313b68c8 100644 --- a/ompi/tools/ompi_info/param.c +++ b/ompi/tools/ompi_info/param.c @@ -16,6 +16,7 @@ * Copyright (c) 2015-2019 Intel, Inc. All rights reserved. * Copyright (c) 2018-2022 Amazon.com, Inc. or its affiliates. All Rights reserved. * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -108,7 +109,6 @@ void ompi_info_do_config(bool want_all) char *fortran_have_c_funloc; char *fortran_08_using_wrappers_for_choice_buffer_functions; char *fortran_build_sizeof; - char *java; char *heterogeneous; char *memprofile; char *memdebug; @@ -257,7 +257,6 @@ void ompi_info_do_config(bool want_all) fortran_usempif08_compliance = "The mpi_f08 module was not built"; } - java = OMPI_WANT_JAVA_BINDINGS ? "yes" : "no"; heterogeneous = OPAL_ENABLE_HETEROGENEOUS_SUPPORT ? "yes" : "no"; memprofile = OPAL_ENABLE_MEM_PROFILE ? "yes" : "no"; memdebug = OPAL_ENABLE_MEM_DEBUG ? "yes" : "no"; @@ -328,7 +327,8 @@ void ompi_info_do_config(bool want_all) fortran_usempif08_compliance); opal_info_out("Fort mpi_f08 subarrays", "bindings:use_mpi_f08:subarrays-supported", fortran_build_f08_subarrays); - opal_info_out("Java bindings", "bindings:java", java); + /* The Java bindings were removed in Open MPI v6.0.0. */ + opal_info_out("Java bindings", "bindings:java", "no"); opal_info_out("Wrapper compiler rpath", "compiler:all:rpath", WRAPPER_RPATH_SUPPORT); diff --git a/ompi/tools/wrappers/Makefile.am b/ompi/tools/wrappers/Makefile.am index 1d5b24a9372..0f5d4525862 100644 --- a/ompi/tools/wrappers/Makefile.am +++ b/ompi/tools/wrappers/Makefile.am @@ -15,6 +15,7 @@ # Copyright (c) 2014 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -40,9 +41,6 @@ endif # OPAL_INSTALL_BINARIES if OPAL_WANT_SCRIPT_WRAPPER_COMPILERS bin_SCRIPTS = ompi_wrapper_script -if OMPI_WANT_JAVA_BINDINGS -bin_SCRIPTS += mpijavac.pl -endif CLEANFILES += $(bin_SCRIPTS) install-exec-hook-always: @@ -57,10 +55,6 @@ if OMPI_HAVE_FORTRAN_COMPILER (cd $(DESTDIR)$(bindir); rm -f mpif77; $(LN_S) ompi_wrapper_script mpif77) (cd $(DESTDIR)$(bindir); rm -f mpif90; $(LN_S) ompi_wrapper_script mpif90) endif -if OMPI_WANT_JAVA_BINDINGS - (cp mpijavac.pl $(DESTDIR)$(bindir)) - (cd $(DESTDIR)$(bindir); chmod +x mpijavac.pl; rm -f mpijavac; $(LN_S) mpijavac.pl mpijavac) -endif uninstall-local-always: rm -f $(DESTDIR)$(bindir)/mpicc \ @@ -68,8 +62,7 @@ uninstall-local-always: $(DESTDIR)$(bindir)/mpicxx \ $(DESTDIR)$(bindir)/mpifort \ $(DESTDIR)$(bindir)/mpif77 \ - $(DESTDIR)$(bindir)/mpif90 \ - $(DESTDIR)$(bindir)/mpijavac + $(DESTDIR)$(bindir)/mpif90 if CASE_SENSITIVE_FS_AND_HAVE_CXX_COMPILER install-exec-hook: install-exec-hook-always @@ -85,10 +78,6 @@ else # OPAL_WANT_SCRIPT_WRAPPER_COMPILERS if OPAL_INSTALL_BINARIES -if OMPI_WANT_JAVA_BINDINGS -bin_SCRIPTS = mpijavac.pl -endif - nodist_ompidata_DATA = mpicc-wrapper-data.txt if OMPI_HAVE_CXX_COMPILER @@ -111,10 +100,6 @@ if OMPI_HAVE_FORTRAN_COMPILER (cd $(DESTDIR)$(bindir); rm -f mpif77$(EXEEXT); $(LN_S) opal_wrapper$(EXEEXT) mpif77$(EXEEXT)) (cd $(DESTDIR)$(bindir); rm -f mpif90$(EXEEXT); $(LN_S) opal_wrapper$(EXEEXT) mpif90$(EXEEXT)) endif -if OMPI_WANT_JAVA_BINDINGS - (cp mpijavac.pl $(DESTDIR)$(bindir)) - (cd $(DESTDIR)$(bindir); chmod +x mpijavac.pl; rm -f mpijavac; $(LN_S) mpijavac.pl mpijavac) -endif install-data-hook-always: if OMPI_HAVE_CXX_COMPILER @@ -139,9 +124,7 @@ uninstall-local-always: $(DESTDIR)$(pkgdatadir)/mpif90-wrapper-data.txt \ $(DESTDIR)$(pkgconfigdir)/ompi-f77.pc \ $(DESTDIR)$(pkgconfigdir)/ompi-f90.pc \ - $(DESTDIR)$(pkgconfigdir)/ompi-fort.pc \ - $(DESTDIR)$(bindir)/mpijavac \ - $(DESTDIR)$(bindir)/mpijavac.pl + $(DESTDIR)$(pkgconfigdir)/ompi-fort.pc if CASE_SENSITIVE_FS_AND_HAVE_CXX_COMPILER install-exec-hook: install-exec-hook-always diff --git a/ompi/tools/wrappers/mpijavac.pl.in b/ompi/tools/wrappers/mpijavac.pl.in deleted file mode 100644 index f8aeb747452..00000000000 --- a/ompi/tools/wrappers/mpijavac.pl.in +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env perl - -# WARNING: DO NOT EDIT THE mpijava.pl FILE AS IT IS GENERATED! -# MAKE ALL CHANGES IN mpijava.pl.in - -# Copyright (c) 2011-2013 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. - -use strict; - -# The main purpose of this wrapper compiler is to check for -# and adjust the Java class path to include the OMPI classes -# in mpi.jar. The user may have specified a class path on -# our cmd line, or it may be in the environment, so we have -# to check for both. We also need to be careful not to -# just override the class path as it probably includes classes -# they need for their application! It also may already include -# the path to mpi.jar, and while it doesn't hurt anything, we -# don't want to include our class path more than once to avoid -# user astonishment - -# Let the build system provide us with some critical values -my $my_compiler = "@JAVAC@"; -my $mpi_jar = "@OMPI_WRAPPER_LIBDIR@/mpi.jar"; -my $shmem_jar = "@OMPI_WRAPPER_LIBDIR@/shmem.jar"; - -# globals -my $showme_arg = 0; -my $verbose = 0; -my $my_arg; - -# Cannot use the usual GetOpts library as the user might -# be passing -options to the Java compiler! So have to -# parse the options ourselves to look for help and showme -my @save_args; -foreach $my_arg (@ARGV) { - if ($my_arg eq "-h" || - $my_arg eq "--h" || - $my_arg eq "-help" || - $my_arg eq "--help") { - print "Options: - --showme Show the wrapper compiler command without executing it - --verbose Show the wrapper compiler command *and* execute it - --help | -h This help list\n"; - exit(0); - } elsif ($my_arg eq "--showme") { - $showme_arg = 1; - } elsif ($my_arg eq "--verbose") { - $verbose = 1; - } else { - push(@save_args, $my_arg); - } -} - -# Create a place to save our argv array so we can edit any -# provide class path option -my @arguments = (); - -# Check the command line for a class path -my $cp_found = 0; -my $my_cp; -foreach $my_arg (@save_args) { - if (1 == $cp_found) { - $my_cp = $my_arg; - if (0 > index($my_arg, "mpi.jar")) { - # not found, so we add our path - if (rindex($my_arg, ":") == length($my_arg)-1) { - # already have a colon at the end - $my_cp = $my_cp . $mpi_jar; - } else { - # need to add the colon between paths - $my_cp = $my_cp . ":" . $mpi_jar; - } - } - if (0 > index($my_arg, "shmem.jar")) { - # not found, so we add our path - if (rindex($my_arg, ":") == length($my_arg)-1) { - # already have a colon at the end - $my_cp = $my_cp . $shmem_jar; - } else { - # need to add the colon between paths - $my_cp = $my_cp . ":" . $shmem_jar; - } - } - push(@arguments, $my_cp); - $cp_found = 2; - } else { - if (0 == $cp_found && ( - 0 <= index($my_arg, "-cp") || - 0 <= index($my_arg, "-classpath"))) - { - $cp_found = 1; - } - push(@arguments, $my_arg); - } -} - -# If the class path wasn't found on the cmd line, then -# we next check the class path in the environment, if it exists -if (2 != $cp_found && exists $ENV{'CLASSPATH'} && length($ENV{'CLASSPATH'}) > 0) { - $my_cp = $ENV{'CLASSPATH'}; - if(0 > index($my_cp, "mpi.jar")) { - # not found, so we add our path - if (rindex($my_cp, ":") == length($my_cp)-1) { - # already have a colon at the end - $my_cp = $my_cp . $mpi_jar; - } else { - # need to add the colon between paths - $my_cp = $my_cp . ":" . $mpi_jar; - } - } - if (0 > index($my_cp, "shmem.jar")) { - # not found, so we add our path - if (rindex($my_cp, ":") == length($my_cp)-1) { - # already have a colon at the end - $my_cp = $my_cp . $shmem_jar; - } else { - # need to add the colon between paths - $my_cp = $my_cp . ":" . $shmem_jar; - } - } - unshift(@arguments, $my_cp); - unshift(@arguments, "-cp"); - # ensure we mark that we "found" the class path - $cp_found = 1; -} - -# If the class path wasn't found in either location, then -# we have to insert it as the first argument -if (0 == $cp_found) { - unshift(@arguments, $mpi_jar . ":" . $shmem_jar); - unshift(@arguments, "-cp"); -} - -# Construct the command -my $returnCode = 0; -if ($showme_arg) { - print "$my_compiler @arguments\n"; -} else { - if ($verbose) { - print "$my_compiler @arguments\n"; - } - $returnCode = system $my_compiler, @arguments; -} -exit $returnCode; From 0a514743cf75cf73be6c3a262b37e751c66be1aa Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 17:48:42 -0400 Subject: [PATCH 098/230] Remove the unused Doxyfile Nothing in the tree uses Doxygen: configure does not search for it, no Makefile builds with it, and no script or CI references it. The file's only mention was the top-level Makefile.am EXTRA_DIST list, so it was merely bundled into release tarballs while never actually being used. It is also a Doxygen 1.3.4 (circa 2004) configuration; Open MPI's documentation is now built with Sphinx. Remove the Doxyfile and drop it from EXTRA_DIST. Signed-off-by: Jeff Squyres --- Doxyfile | 1099 --------------------------------------------------- Makefile.am | 3 +- 2 files changed, 2 insertions(+), 1100 deletions(-) delete mode 100644 Doxyfile diff --git a/Doxyfile b/Doxyfile deleted file mode 100644 index e8c88d33574..00000000000 --- a/Doxyfile +++ /dev/null @@ -1,1099 +0,0 @@ -# Doxyfile 1.3.4 -# -# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -# University Research and Technology -# Corporation. All rights reserved. -# Copyright (c) 2004-2005 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, -# University of Stuttgart. All rights reserved. -# Copyright (c) 2004-2005 The Regents of the University of California. -# All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Open MPI - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.1.1 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doxygen - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, -# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en -# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, -# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# This tag can be used to specify the encoding used in the generated output. -# The encoding is not always determined by the language that is chosen, -# but also whether or not the output is meant for Windows or non-Windows users. -# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES -# forces the Windows encoding (this is the default for the Windows binary), -# whereas setting the tag to NO uses a Unix-style encoding (the default for -# all platforms other than Windows). - -USE_WINDOWS_ENCODING = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will -# prepend the brief description of a member or function before the -# detailed description. Note: if both HIDE_UNDOC_MEMBERS and -# BRIEF_MEMBER_DESC are set to NO, the brief descriptions will be -# completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show -# all inherited members of a class in the documentation of that class -# as if those members were ordinary class members. Constructors, -# destructors and assignment operators of the base classes will not be -# shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of -# C sources only. Doxygen will then generate output that is more -# tailored for C. For instance, some of the names that are used will -# be different. The list of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of -# Java sources only. Doxygen will then generate output that is more -# tailored for Java. For instance, namespaces will be presented as -# packages, qualified scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a -# class will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = opal orte ompi - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc - -FILE_PATTERNS = *.c *.h *.cc *.dox - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = opal/event - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are -# excluded from the input. - -EXCLUDE_SYMLINKS = YES - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = static-modules.h *config*.h ompi_stdint.h ltdl.h - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output dir. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = YES - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -#PAPER_TYPE = a4wide -PAPER_TYPE = letter - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = YES - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = DOXYGEN - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the -# parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = doxygen/tagfile - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superceded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similiar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes that -# lay further from the root node will be omitted. Note that setting this option to -# 1 or 2 may greatly reduce the computation time needed for large code bases. Also -# note that a graph may be further truncated if the graph's image dimensions are -# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). -# If 0 is used for the depth value (the default), the graph is not depth-constrained. - -MAX_DOT_GRAPH_DEPTH = 0 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/Makefile.am b/Makefile.am index bff3c79c64f..49c6090a485 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ # Copyright (c) 2017-2022 Amazon.com, Inc. or its affiliates. All Rights reserved. # All Rights reserved. # Copyright (c) 2020 IBM Corporation. All rights reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -27,7 +28,7 @@ # be required. SUBDIRS = config contrib 3rd-party $(MCA_PROJECT_SUBDIRS) test docs DIST_SUBDIRS = config contrib 3rd-party $(MCA_PROJECT_DIST_SUBDIRS) test docs -EXTRA_DIST = README.md VERSION Doxyfile LICENSE autogen.pl AUTHORS +EXTRA_DIST = README.md VERSION LICENSE autogen.pl AUTHORS include examples/Makefile.include From 5828c547c661d8b1c57b0fb8696e53112b300a70 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sat, 13 Jun 2026 19:25:05 -0400 Subject: [PATCH 099/230] docs: add man pages for 4 implemented-but-undocumented MPI APIs MPI_T_cvar_get_index, MPI_T_pvar_get_index, MPI_T_category_get_index, and MPI_F_sync_reg are implemented and public in Open MPI but had no man pages, so they were missing from the rendered HTML documentation and the installed Unix man pages. They were surfaced by comparing the MPI Forum API metadata against the documented man3 pages. Add a man3 page for each in the usual style: the per-language bindings are generated from the MPI Forum metadata, and the descriptions follow the MPI standard. MPI_F_sync_reg is Fortran-only (no C binding and no ierror argument). Each new page is added to the OMPI_MAN3 install list and to the section-3 toctree (docs/man-openmpi/man3/index.rst). Signed-off-by: Jeff Squyres --- docs/Makefile.am | 6 +- docs/man-openmpi/man3/MPI_F_sync_reg.3.rst | 48 ++++++++++++++ .../man3/MPI_T_category_get_index.3.rst | 61 +++++++++++++++++ .../man3/MPI_T_cvar_get_index.3.rst | 62 ++++++++++++++++++ .../man3/MPI_T_pvar_get_index.3.rst | 65 +++++++++++++++++++ docs/man-openmpi/man3/index.rst | 4 ++ 6 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 docs/man-openmpi/man3/MPI_F_sync_reg.3.rst create mode 100644 docs/man-openmpi/man3/MPI_T_category_get_index.3.rst create mode 100644 docs/man-openmpi/man3/MPI_T_cvar_get_index.3.rst create mode 100644 docs/man-openmpi/man3/MPI_T_pvar_get_index.3.rst diff --git a/docs/Makefile.am b/docs/Makefile.am index 24a6d17740d..a30ac36e81f 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,6 +1,6 @@ # # Copyright (c) 2022 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2023-2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2023-2026 Jeffrey M. Squyres. All rights reserved. # Copyright (c) 2025 Triad National Security, LLC. All rights reserved. # # $COPYRIGHT$ @@ -194,6 +194,7 @@ OMPI_MAN3 = \ MPI_Errors.3 \ MPI_Exscan.3 \ MPI_Exscan_init.3 \ + MPI_F_sync_reg.3 \ MPI_Fetch_and_op.3 \ MPI_File_c2f.3 \ MPI_File_call_errhandler.3 \ @@ -459,10 +460,12 @@ OMPI_MAN3 = \ MPI_T_category_get_categories.3 \ MPI_T_category_get_cvars.3 \ MPI_T_category_get_events.3 \ + MPI_T_category_get_index.3 \ MPI_T_category_get_info.3 \ MPI_T_category_get_num.3 \ MPI_T_category_get_num_events.3 \ MPI_T_category_get_pvars.3 \ + MPI_T_cvar_get_index.3 \ MPI_T_cvar_get_info.3 \ MPI_T_cvar_get_num.3 \ MPI_T_cvar_handle_alloc.3 \ @@ -494,6 +497,7 @@ OMPI_MAN3 = \ MPI_T_finalize.3 \ MPI_T_init_thread.3 \ MPI_Topo_test.3 \ + MPI_T_pvar_get_index.3 \ MPI_T_pvar_get_info.3 \ MPI_T_pvar_get_num.3 \ MPI_T_pvar_handle_alloc.3 \ diff --git a/docs/man-openmpi/man3/MPI_F_sync_reg.3.rst b/docs/man-openmpi/man3/MPI_F_sync_reg.3.rst new file mode 100644 index 00000000000..678304bca23 --- /dev/null +++ b/docs/man-openmpi/man3/MPI_F_sync_reg.3.rst @@ -0,0 +1,48 @@ +.. _mpi_f_sync_reg: + + +MPI_F_sync_reg +============== + +.. include_body + +:ref:`MPI_F_sync_reg` |mdash| Prevent invalid register optimization of a Fortran buffer + +.. The following file was automatically generated +.. include:: ./bindings/mpi_f_sync_reg.rst + +INPUT/OUTPUT PARAMETERS +----------------------- +* ``buf``: Initial address of the buffer (choice). + +DESCRIPTION +----------- + +:ref:`MPI_F_sync_reg` has no executable statements; it exists only to prevent +a Fortran compiler from making invalid assumptions about the contents of a +buffer across an operation that the compiler cannot see. Passing *buf* to this +routine forces the compiler, when necessary, to flush a cached register copy +of the buffer back to memory, or to invalidate a cached register copy so that +the buffer is reloaded from memory on its next use. + +This is needed in Fortran code that aggressively optimizes register usage +around nonblocking or one-sided operations, whose completion |mdash| and +therefore whose effect on the buffer |mdash| is not visible to the compiler +from the surrounding code. + + +NOTES +----- + +This routine is provided only in the Fortran bindings; it has no C binding +because it would serve no purpose in C. It also has no *ierror* argument +because there is no operation that can fail. + +For example, after an :ref:`MPI_Wait` that completes a nonblocking receive +into *buf*, a call to ``MPI_F_sync_reg(buf)`` ensures that the compiler +reloads *buf* from memory rather than reusing a stale register copy that +predates the receive. + + +.. seealso:: + * :ref:`MPI_Wait` diff --git a/docs/man-openmpi/man3/MPI_T_category_get_index.3.rst b/docs/man-openmpi/man3/MPI_T_category_get_index.3.rst new file mode 100644 index 00000000000..e9849463531 --- /dev/null +++ b/docs/man-openmpi/man3/MPI_T_category_get_index.3.rst @@ -0,0 +1,61 @@ +.. _mpi_t_category_get_index: + + +MPI_T_category_get_index +======================== + +.. include_body + +:ref:`MPI_T_category_get_index` |mdash| Query the index of a category from its name + +.. The following file was automatically generated +.. include:: ./bindings/mpi_t_category_get_index.rst + +INPUT PARAMETERS +---------------- +* ``name``: Name of the category to query. + +OUTPUT PARAMETERS +----------------- +* ``cat_index``: Index of the category. + +DESCRIPTION +----------- + +:ref:`MPI_T_category_get_index` can be used to retrieve the index of a +category given its name. The *name* argument is provided by the caller as a +null-terminated string, and the matching index is returned in *cat_index*. +The returned index can then be passed to other MPI tool information interface +routines, such as :ref:`MPI_T_category_get_info`. + +This routine allows a tool to look up a category by name without iterating +over the entire set of categories. Because the number of categories exposed +by the implementation can change over time, this is both more convenient and +lower overhead than enumerating all of the categories to find a particular +one. + + +NOTES +----- + +Category names are implementation-specific. Looking a category up by name is +therefore not portable across MPI implementations, but may be the preferred +approach for a tool that targets Open MPI specifically. + + +ERRORS +------ + +:ref:`MPI_T_category_get_index` will fail if: + +* ``MPI_T_ERR_NOT_INITIALIZED``: The MPI Tools interface is not initialized. + +* ``MPI_T_ERR_INVALID``: ``name`` or ``cat_index`` is ``NULL``. + +* ``MPI_T_ERR_INVALID_NAME``: ``name`` does not match the name of any category + provided by the implementation at the time of the call. + + +.. seealso:: + * :ref:`MPI_T_category_get_info` + * :ref:`MPI_T_category_get_num` diff --git a/docs/man-openmpi/man3/MPI_T_cvar_get_index.3.rst b/docs/man-openmpi/man3/MPI_T_cvar_get_index.3.rst new file mode 100644 index 00000000000..b695f2ec882 --- /dev/null +++ b/docs/man-openmpi/man3/MPI_T_cvar_get_index.3.rst @@ -0,0 +1,62 @@ +.. _mpi_t_cvar_get_index: + + +MPI_T_cvar_get_index +==================== + +.. include_body + +:ref:`MPI_T_cvar_get_index` |mdash| Query the index of a control variable from its name + +.. The following file was automatically generated +.. include:: ./bindings/mpi_t_cvar_get_index.rst + +INPUT PARAMETERS +---------------- +* ``name``: Name of the control variable to query. + +OUTPUT PARAMETERS +----------------- +* ``cvar_index``: Index of the control variable. + +DESCRIPTION +----------- + +:ref:`MPI_T_cvar_get_index` can be used to retrieve the index of a control +variable given its name. The *name* argument is provided by the caller as a +null-terminated string, and the matching index is returned in *cvar_index*. +The returned index can then be passed to other MPI tool information +interface routines, such as :ref:`MPI_T_cvar_get_info`. Control variables in +Open MPI are the same as MCA parameters. + +This routine allows a tool to look up a control variable by name without +iterating over the entire set of control variables. Because the number of +control variables exposed by the implementation can change over time, this is +both more convenient and lower overhead than enumerating all of the variables +to find a particular one. + + +NOTES +----- + +Control variable names are implementation-specific. Looking a variable up by +name is therefore not portable across MPI implementations, but may be the +preferred approach for a tool that targets Open MPI specifically. + + +ERRORS +------ + +:ref:`MPI_T_cvar_get_index` will fail if: + +* ``MPI_T_ERR_NOT_INITIALIZED``: The MPI Tools interface is not initialized. + +* ``MPI_T_ERR_INVALID``: ``name`` or ``cvar_index`` is ``NULL``. + +* ``MPI_T_ERR_INVALID_NAME``: ``name`` does not match the name of any control + variable provided by the implementation at the time of the call. + + +.. seealso:: + * :ref:`MPI_T_cvar_get_info` + * :ref:`MPI_T_cvar_get_num` diff --git a/docs/man-openmpi/man3/MPI_T_pvar_get_index.3.rst b/docs/man-openmpi/man3/MPI_T_pvar_get_index.3.rst new file mode 100644 index 00000000000..6017e152346 --- /dev/null +++ b/docs/man-openmpi/man3/MPI_T_pvar_get_index.3.rst @@ -0,0 +1,65 @@ +.. _mpi_t_pvar_get_index: + + +MPI_T_pvar_get_index +==================== + +.. include_body + +:ref:`MPI_T_pvar_get_index` |mdash| Query the index of a performance variable from its name + +.. The following file was automatically generated +.. include:: ./bindings/mpi_t_pvar_get_index.rst + +INPUT PARAMETERS +---------------- +* ``name``: Name of the performance variable to query. +* ``var_class``: Class of the performance variable to query. + +OUTPUT PARAMETERS +----------------- +* ``pvar_index``: Index of the performance variable. + +DESCRIPTION +----------- + +:ref:`MPI_T_pvar_get_index` can be used to retrieve the index of a +performance variable given its name and class. The *name* and *var_class* +arguments are provided by the caller |mdash| *name* as a null-terminated +string |mdash| and the matching index is returned in *pvar_index*. A +performance variable is identified by the pair (*name*, *var_class*), so both +must be supplied. The returned index can then be passed to other MPI tool +information interface routines, such as :ref:`MPI_T_pvar_get_info`. + +This routine allows a tool to look up a performance variable by name without +iterating over the entire set of performance variables. Because the number of +performance variables exposed by the implementation can change over time, this +is both more convenient and lower overhead than enumerating all of the +variables to find a particular one. + + +NOTES +----- + +Performance variable names are implementation-specific. Looking a variable up +by name is therefore not portable across MPI implementations, but may be the +preferred approach for a tool that targets Open MPI specifically. + + +ERRORS +------ + +:ref:`MPI_T_pvar_get_index` will fail if: + +* ``MPI_T_ERR_NOT_INITIALIZED``: The MPI Tools interface is not initialized. + +* ``MPI_T_ERR_INVALID``: ``name`` or ``pvar_index`` is ``NULL``. + +* ``MPI_T_ERR_INVALID_NAME``: ``name`` does not match the name of any + performance variable of the specified *var_class* provided by the + implementation at the time of the call. + + +.. seealso:: + * :ref:`MPI_T_pvar_get_info` + * :ref:`MPI_T_pvar_get_num` diff --git a/docs/man-openmpi/man3/index.rst b/docs/man-openmpi/man3/index.rst index c746815fbf3..2cbd07ad1d5 100644 --- a/docs/man-openmpi/man3/index.rst +++ b/docs/man-openmpi/man3/index.rst @@ -108,6 +108,7 @@ MPI API manual pages (section 3) MPI_Error_string.3.rst MPI_Exscan.3.rst MPI_Exscan_init.3.rst + MPI_F_sync_reg.3.rst MPI_Fetch_and_op.3.rst MPI_File_c2f.3.rst MPI_File_call_errhandler.3.rst @@ -378,10 +379,12 @@ MPI API manual pages (section 3) MPI_T_category_get_categories.3.rst MPI_T_category_get_cvars.3.rst MPI_T_category_get_events.3.rst + MPI_T_category_get_index.3.rst MPI_T_category_get_info.3.rst MPI_T_category_get_num.3.rst MPI_T_category_get_num_events.3.rst MPI_T_category_get_pvars.3.rst + MPI_T_cvar_get_index.3.rst MPI_T_cvar_get_info.3.rst MPI_T_cvar_get_num.3.rst MPI_T_cvar_handle_alloc.3.rst @@ -407,6 +410,7 @@ MPI API manual pages (section 3) MPI_T_event_set_dropped_handler.3.rst MPI_T_finalize.3.rst MPI_T_init_thread.3.rst + MPI_T_pvar_get_index.3.rst MPI_T_pvar_get_info.3.rst MPI_T_pvar_get_num.3.rst MPI_T_pvar_handle_alloc.3.rst From 7c3dcab2cfe057bfd298f7b9299769ba3c39ccd2 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 15:04:32 -0400 Subject: [PATCH 100/230] AGENTS.md: add guidance on shared clones, testing, commits, naming Expand the AI-agent orientation notes with six additions: - A "Working in a shared repository" section: an agent may not be the only worker in a clone, so avoid repo-wide git commands (e.g. "git worktree prune", "git stash") that reach beyond its own working area. Creating a new branch to park work in progress is an allowed exception, as long as the name is unlikely to collide with others. - A note that portability is a core goal, that Linux and macOS are the primary development environments, and that containers (e.g. Docker on macOS) can help test the user-space behavior of other environments. - A reminder never to weaken or rewrite tests, or add new ones, just to accommodate buggy behavior; real bugs should be found, reported, and fixed instead. - Advice to keep incidental "drive-by" fixes as standalone commits so they can be reviewed separately from the main work. - A note that commits should land on the main and release branches only through pull requests, and never by pushing directly to those branches. - A note that the package's public name is always "Open MPI" in user-facing documentation, never the abbreviation "OMPI" (which is correct only as the internal project-layer name and symbol prefix). Signed-off-by: Jeff Squyres --- AGENTS.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b0ec197c541..43a579496f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -216,11 +216,29 @@ successfully. multiple hosts/specialized hardware — **do not assume you can run all of it locally, and don't report untested code as verified.** +**Test across environments when you can.** Portability across a wide +variety of environments is a core Open MPI goal. The primary development +environments are common Linux distributions and macOS, but the code is +expected to run far more widely. When container-based tooling is +available, it can be a practical way to reproduce, diagnose, and test +user-space behavior specific to an environment you aren't running +natively — for example, using Docker on macOS to exercise Linux +user-space code paths. (Containers don't replace real +network/hardware/launcher testing, but they're useful for OS and +user-space differences.) + **Add tests for new code.** Whenever practical, add unit tests under [`test/`](test/) that are wired into `make check` (and therefore run in CI). Prefer a `make check`-able test over a manual one-off so the coverage sticks and regressions are caught automatically. +**Never bend a test to accommodate a bug.** Do not weaken, skip, or +rewrite an existing test — and do not craft a new one — merely to make +buggy behavior pass. Tests encode intended behavior: when one fails, the +default assumption is that the code is wrong, not the test. If you find a +genuine bug in the code base, identify it, report it, and where +appropriate fix it — don't paper over it in the test suite. + ## Performance discipline Performance is paramount: short-message **latency** and large-message @@ -242,6 +260,21 @@ Concrete rules for hot paths: OPAL or in the hardware-specific component — not smeared across portable MPI logic. +## Working in a shared repository + +Don't assume you're the only agent (or person) using this clone. In +particular, if you're working in a **git worktree**, other worktrees may +be active against the same underlying repository at the same time. Avoid +repo-wide git commands that reach outside your own working area and can +disrupt others — for example, `git worktree prune`, or `git stash` +(which writes to the repository-wide stash ref shared by all worktrees). +Keep your git operations scoped to your own branch and worktree. + +As a narrow exception, creating a **new branch** when you need to park +work in progress (for example, instead of `git stash`) is fine. Just be +careful not to collide with branches that other agents or people may be +using in the same clone — pick a clearly-scoped, unlikely-to-clash name. + ## Contributing Authoritative process: @@ -256,16 +289,30 @@ honor: body explaining *why*. Open MPI does **not** use Conventional Commits (`feat:`/`fix:` prefixes) — write prose. Don't add AI tooling attribution. Wrap commit-message lines at around 75 characters. +- **Keep incidental fixes as their own commits.** Small "drive-by" bug + fixes you notice while working on something else are welcome, but it is + usually best to land them as standalone commits, separate from your + main change, so each can be evaluated and reviewed on its own. One + logical change per commit keeps history reviewable and easy to bisect. - **Branch flow:** land on `main` first via a GitHub pull request, then cherry-pick to the relevant release branch(es) `vMAJOR.MINOR.x` with a `(cherry picked from commit ...)` line at the end of the commit - message; use `git cherry-pick -x` to add it. Never commit features - directly to a release branch. See + message; use `git cherry-pick -x` to add it. Open MPI always lands + commits on `main` and release branches through pull requests; never + push directly to those branches. Never commit features directly to a + release branch. See [`docs/developers/git-github.rst`](docs/developers/git-github.rst). - **Update the docs and the changelog** when user-visible behavior changes: RST under [`docs/`](docs/), and a release-notes entry under [`docs/release-notes/changelog/`](docs/release-notes/changelog/) (`vMAJOR.MINOR.x.rst`). +- **In user-facing docs, the package's name is "Open MPI."** When + referring to this software package as a whole in user-facing + documentation, always write the formal name **Open MPI** — never the + abbreviation "OMPI". ("OMPI" is correct only as the internal name of + the middle project layer (OPAL → OMPI → OSHMEM) and its `ompi_` / + `OMPI_` symbol prefix — never as a public-facing name for the + package.) ## Repository map From 80cd3187c1ae24c86ecd5eb495d466bbed3cf7ae Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 12:38:50 -0400 Subject: [PATCH 101/230] Enable verbose output in community Jenkins build/test Add V=1 and VERBOSE=1 to MAKE_ARGS in the community Jenkins pr-builder.sh so all make invocations consistently use verbose Automake and test harness output. Verbose output makes CI logs far more useful when diagnosing failures: V=1 shows the full compiler/linker command lines instead of the terse Automake summaries, and VERBOSE=1 makes the test harness print each test's full output rather than just a pass/fail summary. Signed-off-by: Jeff Squyres --- .ci/community-jenkins/pr-builder.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/community-jenkins/pr-builder.sh b/.ci/community-jenkins/pr-builder.sh index cc43ad40701..166dc479fa3 100755 --- a/.ci/community-jenkins/pr-builder.sh +++ b/.ci/community-jenkins/pr-builder.sh @@ -3,6 +3,7 @@ # Copyright (c) 2022-2023 Amazon.com, Inc. or its affiliates. All rights # reserved. # Copyright (c) 2022-2023 Joe Downs. All rights reserved. +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -17,7 +18,7 @@ COMPILER= DISTCHECK=0 AUTOGEN_ARGS= CONFIGURE_ARGS= -MAKE_ARGS= +MAKE_ARGS="V=1 VERBOSE=1" MAKE_J="-j 8" PREFIX="${WORKSPACE}/install" MPIRUN_MODE=${MPIRUN_MODE:-runall} From c899c357d48584da1a1e789a1022fed601dd26f4 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Mon, 15 Jun 2026 14:32:42 -0600 Subject: [PATCH 102/230] F08: add some status accessors required for MPI 4.1 to mpi_f08. also add module interface procedures for mpi module Signed-off-by: Howard Pritchard Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../use-mpi-f08/Makefile.prototype_files | 6 +++ .../fortran/use-mpi-f08/status_get_error.c.in | 43 +++++++++++++++++++ .../use-mpi-f08/status_get_source.c.in | 43 +++++++++++++++++++ .../fortran/use-mpi-f08/status_get_tag.c.in | 43 +++++++++++++++++++ .../use-mpi-f08/status_set_elements.c.in | 6 +-- .../fortran/use-mpi-f08/status_set_error.c.in | 41 ++++++++++++++++++ .../use-mpi-f08/status_set_source.c.in | 41 ++++++++++++++++++ .../fortran/use-mpi-f08/status_set_tag.c.in | 41 ++++++++++++++++++ .../Makefile.prototype_files | 7 +++ .../mpi-ignore-tkr-interfaces.h.in | 13 ------ 10 files changed, 267 insertions(+), 17 deletions(-) create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_get_error.c.in create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_get_source.c.in create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_get_tag.c.in create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_set_error.c.in create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_set_source.c.in create mode 100644 ompi/mpi/fortran/use-mpi-f08/status_set_tag.c.in diff --git a/ompi/mpi/fortran/use-mpi-f08/Makefile.prototype_files b/ompi/mpi/fortran/use-mpi-f08/Makefile.prototype_files index 1bcd67acbbc..dfe4d70c7d4 100644 --- a/ompi/mpi/fortran/use-mpi-f08/Makefile.prototype_files +++ b/ompi/mpi/fortran/use-mpi-f08/Makefile.prototype_files @@ -160,7 +160,13 @@ prototype_files = \ session_iflush_buffer.c.in \ ssend_init_ts.c.in \ ssend_ts.c.in \ + status_get_error.c.in \ + status_get_source.c.in \ + status_get_tag.c.in \ status_set_elements.c.in \ + status_set_error.c.in \ + status_set_source.c.in \ + status_set_tag.c.in \ testany.c.in \ type_contiguous.c.in \ type_create_darray.c.in \ diff --git a/ompi/mpi/fortran/use-mpi-f08/status_get_error.c.in b/ompi/mpi/fortran/use-mpi-f08/status_get_error.c.in new file mode 100644 index 00000000000..317e7f7eb95 --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_get_error.c.in @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_get_error(STATUS status, INT_OUT err) +{ + int c_ierr; + int c_err; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *err = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, &c_err); + + if (MPI_SUCCESS == c_ierr) { + *err = OMPI_INT_2_FINT(c_err); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-f08/status_get_source.c.in b/ompi/mpi/fortran/use-mpi-f08/status_get_source.c.in new file mode 100644 index 00000000000..f322fd32543 --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_get_source.c.in @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_get_source(STATUS status, INT_OUT source) +{ + int c_ierr; + int c_source; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *source = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, &c_source); + + if (MPI_SUCCESS == c_ierr) { + *source = OMPI_INT_2_FINT(c_source); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-f08/status_get_tag.c.in b/ompi/mpi/fortran/use-mpi-f08/status_get_tag.c.in new file mode 100644 index 00000000000..3d9c3a5194d --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_get_tag.c.in @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_get_tag(STATUS status, INT_OUT tag) +{ + int c_ierr; + int c_tag; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *tag = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, &c_tag); + + if (MPI_SUCCESS == c_ierr) { + *tag = OMPI_INT_2_FINT(c_tag); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-f08/status_set_elements.c.in b/ompi/mpi/fortran/use-mpi-f08/status_set_elements.c.in index 0001700d391..f12eab26ca4 100644 --- a/ompi/mpi/fortran/use-mpi-f08/status_set_elements.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/status_set_elements.c.in @@ -12,7 +12,7 @@ * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2024-2025 Triad National Security, LLC. All rights + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights * reserved. * $COPYRIGHT$ * @@ -21,7 +21,7 @@ * $HEADER$ */ -PROTOTYPE VOID status_set_elements(STATUS status, DATATYPE datatype, +PROTOTYPE VOID status_set_elements(STATUS_INOUT status, DATATYPE datatype, COUNT count) { int c_ierr; @@ -38,8 +38,6 @@ PROTOTYPE VOID status_set_elements(STATUS status, DATATYPE datatype, c_ierr = @INNER_CALL@(&c_status, c_type, c_count); - /* If datatype is really being set, then that needs to be - converted.... */ if (MPI_SUCCESS == c_ierr) { PMPI_Status_c2f(&c_status, status); } diff --git a/ompi/mpi/fortran/use-mpi-f08/status_set_error.c.in b/ompi/mpi/fortran/use-mpi-f08/status_set_error.c.in new file mode 100644 index 00000000000..7d4658a564f --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_set_error.c.in @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_set_error(STATUS_INOUT status, INT err) +{ + int c_ierr; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, OMPI_FINT_2_INT(*err)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-f08/status_set_source.c.in b/ompi/mpi/fortran/use-mpi-f08/status_set_source.c.in new file mode 100644 index 00000000000..60fe2f22dd9 --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_set_source.c.in @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_set_source(STATUS_INOUT status, INT source) +{ + int c_ierr; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, OMPI_FINT_2_INT(*source)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-f08/status_set_tag.c.in b/ompi/mpi/fortran/use-mpi-f08/status_set_tag.c.in new file mode 100644 index 00000000000..373c17b9653 --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/status_set_tag.c.in @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2024-2026 Triad National Security, LLC. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +PROTOTYPE VOID status_set_tag(STATUS_INOUT status, INT tag) +{ + int c_ierr; + MPI_Status c_status; + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = @INNER_CALL@(&c_status, OMPI_FINT_2_INT(*tag)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.prototype_files b/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.prototype_files index 03f7fe313c9..546948fe5c8 100644 --- a/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.prototype_files +++ b/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.prototype_files @@ -18,4 +18,11 @@ prototype_files = \ session_detach_buffer.c.in \ session_flush_buffer.c.in \ session_iflush_buffer.c.in \ + status_get_error.c.in \ + status_get_source.c.in \ + status_get_tag.c.in \ + status_set_elements.c.in \ + status_set_error.c.in \ + status_set_source.c.in \ + status_set_tag.c.in \ type_get_value_index.c.in diff --git a/ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-interfaces.h.in b/ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-interfaces.h.in index 187fcbcf245..a0498c0f9a7 100644 --- a/ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-interfaces.h.in +++ b/ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-interfaces.h.in @@ -3862,19 +3862,6 @@ end subroutine MPI_Status_set_cancelled end interface -interface - -subroutine MPI_Status_set_elements(status, datatype, count, ierror) - include 'mpif-config.h' - integer, dimension(MPI_STATUS_SIZE), intent(inout) :: status - integer, intent(in) :: datatype - integer, intent(in) :: count - integer, intent(out) :: ierror -end subroutine MPI_Status_set_elements - -end interface - - interface subroutine MPI_Status_set_elements_x(status, datatype, count, ierror) From 4bf745cfce894ea6338e65ce0649a8ea5059d89a Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Tue, 16 Jun 2026 12:43:01 -0600 Subject: [PATCH 103/230] MPIF-H: add status accessor functions for mpif.h and back end of MPI F90. Related to https://github.com/open-mpi/ompi/issues/14020 Signed-off-by: Howard Pritchard --- ompi/mpi/fortran/mpif-h/Makefile.am | 6 ++ ompi/mpi/fortran/mpif-h/profile/Makefile.am | 6 ++ ompi/mpi/fortran/mpif-h/prototypes_mpi.h | 6 ++ ompi/mpi/fortran/mpif-h/status_get_error_f.c | 93 +++++++++++++++++++ ompi/mpi/fortran/mpif-h/status_get_source_f.c | 93 +++++++++++++++++++ ompi/mpi/fortran/mpif-h/status_get_tag_f.c | 93 +++++++++++++++++++ ompi/mpi/fortran/mpif-h/status_set_error_f.c | 91 ++++++++++++++++++ ompi/mpi/fortran/mpif-h/status_set_source_f.c | 91 ++++++++++++++++++ ompi/mpi/fortran/mpif-h/status_set_tag_f.c | 91 ++++++++++++++++++ 9 files changed, 570 insertions(+) create mode 100644 ompi/mpi/fortran/mpif-h/status_get_error_f.c create mode 100644 ompi/mpi/fortran/mpif-h/status_get_source_f.c create mode 100644 ompi/mpi/fortran/mpif-h/status_get_tag_f.c create mode 100644 ompi/mpi/fortran/mpif-h/status_set_error_f.c create mode 100644 ompi/mpi/fortran/mpif-h/status_set_source_f.c create mode 100644 ompi/mpi/fortran/mpif-h/status_set_tag_f.c diff --git a/ompi/mpi/fortran/mpif-h/Makefile.am b/ompi/mpi/fortran/mpif-h/Makefile.am index 6280e37cb8a..e439ef991cb 100644 --- a/ompi/mpi/fortran/mpif-h/Makefile.am +++ b/ompi/mpi/fortran/mpif-h/Makefile.am @@ -453,9 +453,15 @@ lib@OMPI_LIBMPI_NAME@_mpifh_la_SOURCES += \ start_f.c \ status_f082f_f.c \ status_f2f08_f.c \ + status_get_error_f.c \ + status_get_source_f.c \ + status_get_tag_f.c \ status_set_cancelled_f.c \ status_set_elements_f.c \ status_set_elements_x_f.c \ + status_set_error_f.c \ + status_set_source_f.c \ + status_set_tag_f.c \ testall_f.c \ testany_f.c \ test_cancelled_f.c \ diff --git a/ompi/mpi/fortran/mpif-h/profile/Makefile.am b/ompi/mpi/fortran/mpif-h/profile/Makefile.am index 88e495b56db..9a93ca47306 100644 --- a/ompi/mpi/fortran/mpif-h/profile/Makefile.am +++ b/ompi/mpi/fortran/mpif-h/profile/Makefile.am @@ -364,9 +364,15 @@ linked_files = \ pstart_f.c \ pstatus_f082f_f.c \ pstatus_f2f08_f.c \ + pstatus_get_error_f.c \ + pstatus_get_source_f.c \ + pstatus_get_tag_f.c \ pstatus_set_cancelled_f.c \ pstatus_set_elements_f.c \ pstatus_set_elements_x_f.c \ + pstatus_set_error_f.c \ + pstatus_set_source_f.c \ + pstatus_set_tag_f.c \ ptestall_f.c \ ptestany_f.c \ ptest_cancelled_f.c \ diff --git a/ompi/mpi/fortran/mpif-h/prototypes_mpi.h b/ompi/mpi/fortran/mpif-h/prototypes_mpi.h index 931d019dce7..39f0bd2160e 100644 --- a/ompi/mpi/fortran/mpif-h/prototypes_mpi.h +++ b/ompi/mpi/fortran/mpif-h/prototypes_mpi.h @@ -422,9 +422,15 @@ PN2(void, MPI_Start, mpi_start, MPI_START, (MPI_Fint *request, MPI_Fint *ierr)); PN2(void, MPI_Startall, mpi_startall, MPI_STARTALL, (MPI_Fint *count, MPI_Fint *array_of_requests, MPI_Fint *ierr)); PN2(void, MPI_Status_f082f, mpi_status_f082f, MPI_STATUS_F082F, (const MPI_F08_status *f08_status, MPI_Fint *f_status, MPI_Fint *ierr)); PN2(void, MPI_Status_f2f08, mpi_status_f2f08, MPI_STATUS_F2F08, (const MPI_Fint *f_status, MPI_F08_status *f08_status, MPI_Fint *ierr)); +PN2(void, MPI_Status_get_error, mpi_status_get_error, MPI_STATUS_GET_ERROR, (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr)); +PN2(void, MPI_Status_get_source, mpi_status_get_source, MPI_STATUS_GET_SOURCE, (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr)); +PN2(void, MPI_Status_get_tag, mpi_status_get_tag, MPI_STATUS_GET_TAG, (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr)); PN2(void, MPI_Status_set_cancelled, mpi_status_set_cancelled, MPI_STATUS_SET_CANCELLED, (MPI_Fint *status, ompi_fortran_logical_t *flag, MPI_Fint *ierr)); PN2(void, MPI_Status_set_elements, mpi_status_set_elements, MPI_STATUS_SET_ELEMENTS, (MPI_Fint *status, MPI_Fint *datatype, MPI_Fint *count, MPI_Fint *ierr)); PN2(void, MPI_Status_set_elements_x, mpi_status_set_elements_x, MPI_STATUS_SET_ELEMENTS_X, (MPI_Fint *status, MPI_Fint *datatype, MPI_Count *count, MPI_Fint *ierr)); +PN2(void, MPI_Status_set_error, mpi_status_set_error, MPI_STATUS_SET_ERROR, (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr)); +PN2(void, MPI_Status_set_source, mpi_status_set_source, MPI_STATUS_SET_SOURCE, (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr)); +PN2(void, MPI_Status_set_tag, mpi_status_set_tag, MPI_STATUS_SET_TAG, (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr)); PN2(void, MPI_Testall, mpi_testall, MPI_TESTALL, (MPI_Fint *count, MPI_Fint *array_of_requests, ompi_fortran_logical_t *flag, MPI_Fint *array_of_statuses, MPI_Fint *ierr)); PN2(void, MPI_Testany, mpi_testany, MPI_TESTANY, (MPI_Fint *count, MPI_Fint *array_of_requests, MPI_Fint *index, ompi_fortran_logical_t *flag, MPI_Fint *status, MPI_Fint *ierr)); PN2(void, MPI_Test, mpi_test, MPI_TEST, (MPI_Fint *request, ompi_fortran_logical_t *flag, MPI_Fint *status, MPI_Fint *ierr)); diff --git a/ompi/mpi/fortran/mpif-h/status_get_error_f.c b/ompi/mpi/fortran/mpif-h/status_get_error_f.c new file mode 100644 index 00000000000..3c644c76524 --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_get_error_f.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_GET_ERROR = ompi_status_get_error_f +#pragma weak pmpi_status_get_error = ompi_status_get_error_f +#pragma weak pmpi_status_get_error_ = ompi_status_get_error_f +#pragma weak pmpi_status_get_error__ = ompi_status_get_error_f + +#pragma weak PMPI_Status_get_error_f = ompi_status_get_error_f +#pragma weak PMPI_Status_get_error_f08 = ompi_status_get_error_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_GET_ERROR, + pmpi_status_get_error, + pmpi_status_get_error_, + pmpi_status_get_error__, + pompi_status_get_error_f, + (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr), + (status, err, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_GET_ERROR = ompi_status_get_error_f +#pragma weak mpi_status_get_error = ompi_status_get_error_f +#pragma weak mpi_status_get_error_ = ompi_status_get_error_f +#pragma weak mpi_status_get_error__ = ompi_status_get_error_f + +#pragma weak MPI_Status_get_error_f = ompi_status_get_error_f +#pragma weak MPI_Status_get_error_f08 = ompi_status_get_error_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_GET_ERROR, + mpi_status_get_error, + mpi_status_get_error_, + mpi_status_get_error__, + ompi_status_get_error_f, + (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr), + (status, err, ierr) ) +#else +#define ompi_status_get_error_f pompi_status_get_error_f +#endif +#endif + + +void ompi_status_get_error_f(MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + OMPI_SINGLE_NAME_DECL(err); + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *err = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_get_error(&c_status, OMPI_SINGLE_NAME_CONVERT(err)); + + if (MPI_SUCCESS == c_ierr) { + OMPI_SINGLE_INT_2_FINT(err); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/mpif-h/status_get_source_f.c b/ompi/mpi/fortran/mpif-h/status_get_source_f.c new file mode 100644 index 00000000000..e0a0f9eec22 --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_get_source_f.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_GET_SOURCE = ompi_status_get_source_f +#pragma weak pmpi_status_get_source = ompi_status_get_source_f +#pragma weak pmpi_status_get_source_ = ompi_status_get_source_f +#pragma weak pmpi_status_get_source__ = ompi_status_get_source_f + +#pragma weak PMPI_Status_get_source_f = ompi_status_get_source_f +#pragma weak PMPI_Status_get_source_f08 = ompi_status_get_source_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_GET_SOURCE, + pmpi_status_get_source, + pmpi_status_get_source_, + pmpi_status_get_source__, + pompi_status_get_source_f, + (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr), + (status, source, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_GET_SOURCE = ompi_status_get_source_f +#pragma weak mpi_status_get_source = ompi_status_get_source_f +#pragma weak mpi_status_get_source_ = ompi_status_get_source_f +#pragma weak mpi_status_get_source__ = ompi_status_get_source_f + +#pragma weak MPI_Status_get_source_f = ompi_status_get_source_f +#pragma weak MPI_Status_get_source_f08 = ompi_status_get_source_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_GET_SOURCE, + mpi_status_get_source, + mpi_status_get_source_, + mpi_status_get_source__, + ompi_status_get_source_f, + (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr), + (status, source, ierr) ) +#else +#define ompi_status_get_source_f pompi_status_get_source_f +#endif +#endif + + +void ompi_status_get_source_f(MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + OMPI_SINGLE_NAME_DECL(source); + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *source = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_get_source(&c_status, OMPI_SINGLE_NAME_CONVERT(source)); + + if (MPI_SUCCESS == c_ierr) { + OMPI_SINGLE_INT_2_FINT(source); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/mpif-h/status_get_tag_f.c b/ompi/mpi/fortran/mpif-h/status_get_tag_f.c new file mode 100644 index 00000000000..17e1d8c1603 --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_get_tag_f.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_GET_TAG = ompi_status_get_tag_f +#pragma weak pmpi_status_get_tag = ompi_status_get_tag_f +#pragma weak pmpi_status_get_tag_ = ompi_status_get_tag_f +#pragma weak pmpi_status_get_tag__ = ompi_status_get_tag_f + +#pragma weak PMPI_Status_get_tag_f = ompi_status_get_tag_f +#pragma weak PMPI_Status_get_tag_f08 = ompi_status_get_tag_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_GET_TAG, + pmpi_status_get_tag, + pmpi_status_get_tag_, + pmpi_status_get_tag__, + pompi_status_get_tag_f, + (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr), + (status, tag, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_GET_TAG = ompi_status_get_tag_f +#pragma weak mpi_status_get_tag = ompi_status_get_tag_f +#pragma weak mpi_status_get_tag_ = ompi_status_get_tag_f +#pragma weak mpi_status_get_tag__ = ompi_status_get_tag_f + +#pragma weak MPI_Status_get_tag_f = ompi_status_get_tag_f +#pragma weak MPI_Status_get_tag_f08 = ompi_status_get_tag_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_GET_TAG, + mpi_status_get_tag, + mpi_status_get_tag_, + mpi_status_get_tag__, + ompi_status_get_tag_f, + (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr), + (status, tag, ierr) ) +#else +#define ompi_status_get_tag_f pompi_status_get_tag_f +#endif +#endif + + +void ompi_status_get_tag_f(MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + OMPI_SINGLE_NAME_DECL(tag); + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + *tag = OMPI_INT_2_FINT(0); + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_get_tag(&c_status, OMPI_SINGLE_NAME_CONVERT(tag)); + + if (MPI_SUCCESS == c_ierr) { + OMPI_SINGLE_INT_2_FINT(tag); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/mpif-h/status_set_error_f.c b/ompi/mpi/fortran/mpif-h/status_set_error_f.c new file mode 100644 index 00000000000..7dbfdf1551e --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_set_error_f.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_SET_ERROR = ompi_status_set_error_f +#pragma weak pmpi_status_set_error = ompi_status_set_error_f +#pragma weak pmpi_status_set_error_ = ompi_status_set_error_f +#pragma weak pmpi_status_set_error__ = ompi_status_set_error_f + +#pragma weak PMPI_Status_set_error_f = ompi_status_set_error_f +#pragma weak PMPI_Status_set_error_f08 = ompi_status_set_error_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_SET_ERROR, + pmpi_status_set_error, + pmpi_status_set_error_, + pmpi_status_set_error__, + pompi_status_set_error_f, + (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr), + (status, err, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_SET_ERROR = ompi_status_set_error_f +#pragma weak mpi_status_set_error = ompi_status_set_error_f +#pragma weak mpi_status_set_error_ = ompi_status_set_error_f +#pragma weak mpi_status_set_error__ = ompi_status_set_error_f + +#pragma weak MPI_Status_set_error_f = ompi_status_set_error_f +#pragma weak MPI_Status_set_error_f08 = ompi_status_set_error_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_SET_ERROR, + mpi_status_set_error, + mpi_status_set_error_, + mpi_status_set_error__, + ompi_status_set_error_f, + (MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr), + (status, err, ierr) ) +#else +#define ompi_status_set_error_f pompi_status_set_error_f +#endif +#endif + + +void ompi_status_set_error_f(MPI_Fint *status, MPI_Fint *err, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_set_error(&c_status, OMPI_FINT_2_INT(*err)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/mpif-h/status_set_source_f.c b/ompi/mpi/fortran/mpif-h/status_set_source_f.c new file mode 100644 index 00000000000..36212412779 --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_set_source_f.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_SET_SOURCE = ompi_status_set_source_f +#pragma weak pmpi_status_set_source = ompi_status_set_source_f +#pragma weak pmpi_status_set_source_ = ompi_status_set_source_f +#pragma weak pmpi_status_set_source__ = ompi_status_set_source_f + +#pragma weak PMPI_Status_set_source_f = ompi_status_set_source_f +#pragma weak PMPI_Status_set_source_f08 = ompi_status_set_source_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_SET_SOURCE, + pmpi_status_set_source, + pmpi_status_set_source_, + pmpi_status_set_source__, + pompi_status_set_source_f, + (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr), + (status, source, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_SET_SOURCE = ompi_status_set_source_f +#pragma weak mpi_status_set_source = ompi_status_set_source_f +#pragma weak mpi_status_set_source_ = ompi_status_set_source_f +#pragma weak mpi_status_set_source__ = ompi_status_set_source_f + +#pragma weak MPI_Status_set_source_f = ompi_status_set_source_f +#pragma weak MPI_Status_set_source_f08 = ompi_status_set_source_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_SET_SOURCE, + mpi_status_set_source, + mpi_status_set_source_, + mpi_status_set_source__, + ompi_status_set_source_f, + (MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr), + (status, source, ierr) ) +#else +#define ompi_status_set_source_f pompi_status_set_source_f +#endif +#endif + + +void ompi_status_set_source_f(MPI_Fint *status, MPI_Fint *source, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_set_source(&c_status, OMPI_FINT_2_INT(*source)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} diff --git a/ompi/mpi/fortran/mpif-h/status_set_tag_f.c b/ompi/mpi/fortran/mpif-h/status_set_tag_f.c new file mode 100644 index 00000000000..7fe39301aa7 --- /dev/null +++ b/ompi/mpi/fortran/mpif-h/status_set_tag_f.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2005 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2011-2012 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Triad National Security, LLC. All rights reserved. + * + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include "ompi/mpi/fortran/mpif-h/bindings.h" +#include "ompi/mpi/fortran/base/constants.h" + +#if OMPI_BUILD_MPI_PROFILING +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak PMPI_STATUS_SET_TAG = ompi_status_set_tag_f +#pragma weak pmpi_status_set_tag = ompi_status_set_tag_f +#pragma weak pmpi_status_set_tag_ = ompi_status_set_tag_f +#pragma weak pmpi_status_set_tag__ = ompi_status_set_tag_f + +#pragma weak PMPI_Status_set_tag_f = ompi_status_set_tag_f +#pragma weak PMPI_Status_set_tag_f08 = ompi_status_set_tag_f +#else +OMPI_GENERATE_F77_BINDINGS (PMPI_STATUS_SET_TAG, + pmpi_status_set_tag, + pmpi_status_set_tag_, + pmpi_status_set_tag__, + pompi_status_set_tag_f, + (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr), + (status, tag, ierr) ) +#endif +#endif + +#if OPAL_HAVE_WEAK_SYMBOLS +#pragma weak MPI_STATUS_SET_TAG = ompi_status_set_tag_f +#pragma weak mpi_status_set_tag = ompi_status_set_tag_f +#pragma weak mpi_status_set_tag_ = ompi_status_set_tag_f +#pragma weak mpi_status_set_tag__ = ompi_status_set_tag_f + +#pragma weak MPI_Status_set_tag_f = ompi_status_set_tag_f +#pragma weak MPI_Status_set_tag_f08 = ompi_status_set_tag_f +#else +#if ! OMPI_BUILD_MPI_PROFILING +OMPI_GENERATE_F77_BINDINGS (MPI_STATUS_SET_TAG, + mpi_status_set_tag, + mpi_status_set_tag_, + mpi_status_set_tag__, + ompi_status_set_tag_f, + (MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr), + (status, tag, ierr) ) +#else +#define ompi_status_set_tag_f pompi_status_set_tag_f +#endif +#endif + + +void ompi_status_set_tag_f(MPI_Fint *status, MPI_Fint *tag, MPI_Fint *ierr) +{ + int c_ierr; + MPI_Status c_status; + + /* This seems silly, but someone will do it */ + + if (OMPI_IS_FORTRAN_STATUS_IGNORE(status)) { + c_ierr = MPI_SUCCESS; + } else { + PMPI_Status_f2c( status, &c_status ); + + c_ierr = PMPI_Status_set_tag(&c_status, OMPI_FINT_2_INT(*tag)); + + if (MPI_SUCCESS == c_ierr) { + PMPI_Status_c2f(&c_status, status); + } + } + if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); +} From e98c1989b5becd328364ff6be98c8a79c25ef987 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 19:10:26 -0400 Subject: [PATCH 104/230] opal/util: initialize opal_infosubscriber_t s_info in constructor infosubscriber_construct() initialized s_subscriber_table but left s_info uninitialized, while infosubscriber_destruct() releases s_info only when it is non-NULL. In normal use a subclass constructor (communicator, win, file) runs after this base constructor and sets s_info, masking the omission. A standalone OBJ_NEW(opal_infosubscriber_t) -- as exercised by the new opal_info_subscriber unit test -- has no subclass, so s_info held whatever the heap returned. On a platform where that memory was not zero (observed on riscv64) opal_infosubscribe_subscribe dereferenced the garbage pointer through opal_info_get and crashed. Initialize s_info to NULL in the constructor. Signed-off-by: Jeff Squyres --- opal/util/info_subscriber.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/opal/util/info_subscriber.c b/opal/util/info_subscriber.c index 3382612ac17..cb499b53e0f 100644 --- a/opal/util/info_subscriber.c +++ b/opal/util/info_subscriber.c @@ -18,6 +18,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2016-2018 IBM Corporation. All rights reserved. * Copyright (c) 2017-2018 Intel, Inc. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -76,6 +77,14 @@ static void infosubscriber_construct(opal_infosubscriber_t *obj) { OBJ_CONSTRUCT(&obj->s_subscriber_table, opal_hash_table_t); opal_hash_table_init(&obj->s_subscriber_table, 10); + + /* s_info is created lazily (see opal_infosubscribe_subscribe) and is + * released in the destructor only when non-NULL, so it must start out + * NULL. Subclasses (communicator, win, file) run after this base + * constructor; a standalone OBJ_NEW(opal_infosubscriber_t) has no + * subclass constructor, so without this it would be left uninitialized + * and dereferenced as a garbage pointer. */ + obj->s_info = NULL; } static void infosubscriber_destruct(opal_infosubscriber_t *obj) From a7095da9e53494d3633cfa464e7f7bbd87c95b3f Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 15:34:32 -0400 Subject: [PATCH 105/230] opal/util: fix opal_strerror returning NULL for unknown codes opal_strerror_int() defaulted its return value to OPAL_SUCCESS, so an errnum matched by no registered converter returned OPAL_SUCCESS with *str left at NULL. opal_strerror() then returned that NULL rather than formatting an "Unknown error" string, violating its documented contract that an unknown errnum yields a (non-NULL) overwritable buffer. The same path left opal_strerror_r() and opal_perror() formatting a NULL. Default the return value to OPAL_ERROR so an unmatched code is reported as unknown; a matching converter still sets the success return value. Signed-off-by: Jeff Squyres --- opal/util/error.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/opal/util/error.c b/opal/util/error.c index 7f8be1e5817..ea3ba8c4851 100644 --- a/opal/util/error.c +++ b/opal/util/error.c @@ -17,6 +17,7 @@ * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved. * Copyright (c) 2017 IBM Corporation. All rights reserved. * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -57,7 +58,14 @@ static converter_info_t converters[MAX_CONVERTERS] = {{0}}; static int opal_strerror_int(int errnum, const char **str) { - int i, ret = OPAL_SUCCESS; + /* Default to a non-success value so that an errnum matched by no + registered converter is reported as unknown by the callers + (opal_strerror/opal_strerror_r/opal_perror), which then format an + "Unknown error" string. Previously this defaulted to OPAL_SUCCESS, + leaving *str == NULL for unmatched codes and causing opal_strerror() + to return NULL -- violating its documented contract that an unknown + errnum yields a (non-NULL) overwritable buffer. */ + int i, ret = OPAL_ERROR; *str = NULL; for (i = 0; i < MAX_CONVERTERS; ++i) { From 06edc683a6b3401f5cc862341f5841020f6d3aa1 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 15:34:31 -0400 Subject: [PATCH 106/230] opal/util: fix opal_net_islocalhost matching 255.0.0.0 opal_net_islocalhost() tested whether the low 7 bits of the address's top byte matched 0x7F: 0x7F000000 == (0x7F000000 & ntohl(s_addr)) That mask only clears the high bit, so it also matches 255.x.x.x (0xFF & 0x7F == 0x7F), incorrectly reporting e.g. 255.0.0.0 as a localhost address. The documented contract (opal/util/net.h) is the 127.0.0.0/8 range only. Mask the full top byte (0xFF000000) so only 127.x.x.x matches. Signed-off-by: Jeff Squyres --- opal/util/net.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/opal/util/net.c b/opal/util/net.c index e53a0ddcf37..e74e778d0f1 100644 --- a/opal/util/net.c +++ b/opal/util/net.c @@ -20,6 +20,7 @@ * reserved. * Copyright (c) 2018 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -211,8 +212,11 @@ bool opal_net_islocalhost(const struct sockaddr *addr) case AF_INET: { const struct sockaddr_in *inaddr = (struct sockaddr_in *) addr; /* if it's in the 127. domain, it shouldn't be routed - (0x7f == 127) */ - if (0x7F000000 == (0x7F000000 & ntohl(inaddr->sin_addr.s_addr))) { + (0x7f == 127). Mask the full top byte (0xFF000000), not just + its low 7 bits (0x7F000000): the latter also matches 255.x.x.x + because 0xFF & 0x7F == 0x7F, incorrectly reporting 255.0.0.0 as + localhost. */ + if (0x7F000000 == (0xFF000000 & ntohl(inaddr->sin_addr.s_addr))) { return true; } return false; From c120d0d571f33c86da01b611fc45d58611646cf9 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 11:45:21 -0400 Subject: [PATCH 107/230] opal/class: fix opal_bitmap max_size units mismatch opal_bitmap_set_max_size() stores the cap in array elements (it divides the requested bit count by SIZE_OF_BASE_TYPE), and the internal growth logic in opal_bitmap_set_bit() already treats max_size as a count of array elements. However, the bounds checks in opal_bitmap_init() and opal_bitmap_set_bit() compared a bit count directly against max_size, mixing units. As a result, once a finite maximum was set, those functions rejected bit positions that were actually within the documented limit. For example, after opal_bitmap_set_max_size(bm, 64) (i.e. "at most 64 bits"), opal_bitmap_init(bm, 64) returned OPAL_ERR_BAD_PARAM, even though the header documents both arguments as being expressed in bits. Convert the requested size/bit to array elements before comparing against max_size in both functions. The only in-tree caller (ompi/attribute) sets the maximum to OMPI_FORTRAN_HANDLE_MAX (INT_MAX), for which the behavior is unchanged. Signed-off-by: Jeff Squyres --- opal/class/opal_bitmap.c | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/opal/class/opal_bitmap.c b/opal/class/opal_bitmap.c index 5d39dbc1933..80666dc5bb5 100644 --- a/opal/class/opal_bitmap.c +++ b/opal/class/opal_bitmap.c @@ -14,7 +14,7 @@ * Copyright (c) 2014 Intel, Inc. All rights reserved. * Copyright (c) 2015-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. + * Copyright (c) 2025-2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -62,32 +62,34 @@ int opal_bitmap_set_max_size(opal_bitmap_t *bm, int max_size) } /* - * Only if the caller wants to set the maximum size, - * we set it (in numbers of bits!), otherwise it is - * set to INT_MAX in the constructor. + * Store the cap in bits, matching the documented contract (see the + * header). When the caller does not set it, it is INT_MAX (set in + * the constructor). */ - bm->max_size = (int) (((size_t) max_size + SIZE_OF_BASE_TYPE - 1) / SIZE_OF_BASE_TYPE); + bm->max_size = max_size; return OPAL_SUCCESS; } int opal_bitmap_init(opal_bitmap_t *bm, int size) { + if ((size <= 0) || (NULL == bm)) { + return OPAL_ERR_BAD_PARAM; + } + /* - * Only if the caller set the maximum size before initializing, - * we test here (in numbers of bits!) - * By default, the max size is INT_MAX, set in the constructor. + * Enforce the optional maximum (in bits) on the requested size before + * rounding up to a whole number of array elements. bm->max_size is + * expressed in bits (see opal_bitmap_set_max_size()); by default it is + * INT_MAX, set in the constructor. */ - if ((size <= 0) || (NULL == bm) || (size > bm->max_size)) { + if (size > bm->max_size) { return OPAL_ERR_BAD_PARAM; } bm->array_size = (int) (((size_t) size + SIZE_OF_BASE_TYPE - 1) / SIZE_OF_BASE_TYPE); if (NULL != bm->bitmap) { free(bm->bitmap); - if (bm->max_size < bm->array_size) { - bm->max_size = bm->array_size; - } } bm->bitmap = (uint64_t *) malloc(bm->array_size * sizeof(uint64_t)); if (NULL == bm->bitmap) { @@ -100,9 +102,11 @@ int opal_bitmap_init(opal_bitmap_t *bm, int size) int opal_bitmap_set_bit(opal_bitmap_t *bm, int bit) { - int index, offset, new_size; + int index, offset, new_size, max_array_size; - if ((bit < 0) || (NULL == bm) || (bit > bm->max_size)) { + /* bm->max_size is the optional cap in bits; valid bit indices are + 0 .. max_size-1. */ + if ((bit < 0) || (NULL == bm) || (bit >= bm->max_size)) { return OPAL_ERR_BAD_PARAM; } @@ -116,8 +120,13 @@ int opal_bitmap_set_bit(opal_bitmap_t *bm, int bit) valid and we simply expand the bitmap */ new_size = index + 1; - if (new_size > bm->max_size) { - new_size = bm->max_size; + /* Clamp growth to the cap, converted from bits to array elements. + The bit-range check above already guarantees new_size stays + within this bound, but keep the clamp consistent with max_size. */ + max_array_size = (int) (((size_t) bm->max_size + SIZE_OF_BASE_TYPE - 1) + / SIZE_OF_BASE_TYPE); + if (new_size > max_array_size) { + new_size = max_array_size; } /* New size is just a multiple of the original size to fit in @@ -226,6 +235,22 @@ int opal_bitmap_find_and_set_first_unset_bit(opal_bitmap_t *bm, int *position) } (*position) += i * SIZE_OF_BASE_TYPE; + + /* + * The fast path above sets the first unset bit in word i directly, + * without consulting bm->max_size. When max_size is not a multiple of + * SIZE_OF_BASE_TYPE, the last allocated word can contain unset bits that + * lie beyond the cap, so this path can otherwise hand back (and set) a + * bit at/after max_size. If that happened the bitmap is full within its + * valid range [0, max_size): undo the speculative set and report it, + * matching opal_bitmap_set_bit() -- which the all-words-full grow path + * above already goes through. + */ + if (*position >= bm->max_size) { + bm->bitmap[i] &= ~(1UL << (*position - i * SIZE_OF_BASE_TYPE)); + return OPAL_ERR_BAD_PARAM; + } + return OPAL_SUCCESS; } From cefcc3aeba3f39944da9dd86045e742f62e45638 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 12:18:20 -0400 Subject: [PATCH 108/230] opal/class: fix opal_graph edge count on vertex removal opal_graph_remove_vertex() releases both the outgoing edges (via OBJ_RELEASE of the vertex's adjacency list) and the incoming edges (via delete_all_edges_conceded_to_vertex()), but neither path decremented graph->number_of_edges. As a result opal_graph_get_size() reported a stale, too-large edge count after a vertex was removed. Decrement number_of_edges for each incoming edge that is deleted, and by the number of outgoing edges when the adjacency list is released. Signed-off-by: Jeff Squyres --- opal/class/opal_graph.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/opal/class/opal_graph.c b/opal/class/opal_graph.c index aa4f787fd74..095d61cdf7a 100644 --- a/opal/class/opal_graph.c +++ b/opal/class/opal_graph.c @@ -14,6 +14,7 @@ * Copyright (c) 2016-2017 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2016 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -179,6 +180,8 @@ static void delete_all_edges_conceded_to_vertex(opal_graph_t *graph, opal_graph_ opal_list_remove_item(edge->in_adj_list->edges, (opal_list_item_t *) edge); /* distract this edge */ OBJ_RELEASE(edge); + /* keep the graph's edge count in sync */ + graph->number_of_edges--; } } } @@ -298,8 +301,11 @@ void opal_graph_remove_vertex(opal_graph_t *graph, opal_graph_vertex_t *vertex) adj_list = vertex->in_adj_list; /** * remove the adjscency list of this vertex from the graph and - * destruct it. + * destruct it. The outgoing edges of this vertex are released + * along with the adjacency list, so account for them in the graph's + * edge count. */ + graph->number_of_edges -= opal_list_get_size(adj_list->edges); opal_list_remove_item(graph->adjacency_list, (opal_list_item_t *) adj_list); OBJ_RELEASE(adj_list); /** From c728a0bc4fb8fed19c74206055f2c2827c7e8871 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 12:12:01 -0400 Subject: [PATCH 109/230] opal/util: fix opal_getcwd off-by-one buffer length check The buffer must hold the path string plus a NUL terminator, i.e. strlen(pwd) + 1 bytes. The check used "strlen(pwd) > size", so when strlen(pwd) == size it fell through to opal_string_copy(buf, pwd, size), which truncated the last character yet the function still returned OPAL_SUCCESS. Use ">=" so an exactly-too-small buffer correctly returns OPAL_ERR_TEMP_OUT_OF_RESOURCE. Signed-off-by: Jeff Squyres --- opal/util/opal_getcwd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/opal/util/opal_getcwd.c b/opal/util/opal_getcwd.c index da484e3eec0..6931fa13f4d 100644 --- a/opal/util/opal_getcwd.c +++ b/opal/util/opal_getcwd.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -83,9 +84,10 @@ int opal_getcwd(char *buf, size_t size) #endif /* If we got here, pwd is pointing to the result that we want to - give. Ensure the user's buffer is long enough. If it is, copy - in the value and be done. */ - if (strlen(pwd) > size) { + give. Ensure the user's buffer is long enough (it must hold the + string *and* a NUL terminator, so it needs strlen(pwd)+1 bytes). + If it is long enough, copy in the value and be done. */ + if (strlen(pwd) >= size) { /* if it isn't big enough, give them as much * of the basename as possible */ From c5cf89a4a4d8ca80a8aed13123eda37f26159ffa Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 12:12:02 -0400 Subject: [PATCH 110/230] opal/util: guard opal_dirname against NULL input opal_basename() returns NULL when passed a NULL filename, but opal_dirname() had no such guard: it passed the NULL straight to strdup()/strlen(), which is undefined behavior (typically a crash). Add the same bozo-case guard so the two functions behave consistently. Signed-off-by: Jeff Squyres --- opal/util/basename.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/opal/util/basename.c b/opal/util/basename.c index f5121156498..f425ea29434 100644 --- a/opal/util/basename.c +++ b/opal/util/basename.c @@ -13,6 +13,7 @@ * Copyright (c) 2014-2024 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Intel, Inc. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -103,6 +104,11 @@ char *opal_basename(const char *filename) char *opal_dirname(const char *filename) { + /* Check for the bozo case (mirrors opal_basename()) */ + if (NULL == filename) { + return NULL; + } + #if defined(HAVE_DIRNAME) || OPAL_HAVE_DIRNAME char *safe_tmp = strdup(filename), *result; if (NULL == safe_tmp) { From 2a3b54b545038b64cb96a70ceeff17821508c024 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 17:27:20 -0400 Subject: [PATCH 111/230] opal/util: fix opal_filename_to_uri reserved-char escaping The escaping loop in opal_filename_to_uri used a `k < strlen(filename) - 1` bound, dropping the last character of the filename whenever a reserved character was present (e.g. "/a;b/c" produced "file://host/a\;b/", losing the trailing 'c'). Iterate over every character instead. Also size the escape buffer for the worst case (every character escaped: 2 bytes plus the NUL terminator). The previous size relied on n, which counts reserved-character types present, not occurrences, so a filename with a repeated reserved character overflowed the allocation. Signed-off-by: Jeff Squyres --- opal/util/uri.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/opal/util/uri.c b/opal/util/uri.c index 233037ee246..3343076ead4 100644 --- a/opal/util/uri.c +++ b/opal/util/uri.c @@ -4,6 +4,7 @@ * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -73,9 +74,16 @@ char *opal_filename_to_uri(const char *filename, const char *hostname) } /* escape them if necessary */ if (0 < n) { - fn = (char *) malloc(strlen(filename) + n + 1); + /* Worst case: every character is escaped (backslash + character), + so allocate 2 bytes per character plus the NUL terminator. n + only records whether any reserved character is present -- it + counts reserved types, not occurrences, so it cannot size this + buffer safely when a reserved character repeats. */ + fn = (char *) malloc(2 * strlen(filename) + 1); i = 0; - for (k = 0; k < strlen(filename) - 1; k++) { + /* Iterate over every character of filename; a previous "- 1" bound + here dropped the last character whenever escaping was needed. */ + for (k = 0; k < strlen(filename); k++) { for (j = 0; j < strlen(uri_reserved_path_chars) - 1; j++) { if (filename[k] == uri_reserved_path_chars[j]) { fn[i] = '\\'; From fe26da337637e0e80fe7872acdcb281537767d09 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 12:12:01 -0400 Subject: [PATCH 112/230] opal/util: fix opal_string_copy out-of-bounds write for zero-length dest When opal_string_copy() was called with dest_len == 0 the copy loop never executed (i stayed 0) and the function then wrote dest[i - 1], i.e. dest[(size_t) -1], an out-of-bounds write. A zero-length destination buffer cannot hold even a NUL terminator, so there is nothing safe to write; return early in that case. This path is reachable, e.g., via opal_getcwd(buf, 0). Signed-off-by: Jeff Squyres --- opal/util/string_copy.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/opal/util/string_copy.c b/opal/util/string_copy.c index 531abb1f098..f4647a6a602 100644 --- a/opal/util/string_copy.c +++ b/opal/util/string_copy.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -28,6 +29,12 @@ void opal_string_copy(char *dest, const char *src, size_t dest_len) // obvious. assert(dest_len <= OPAL_MAX_SIZE_ALLOWED_BY_OPAL_STRING_COPY); + /* A zero-length destination buffer cannot hold even a NUL + terminator; there is nothing safe to write. */ + if (0 == dest_len) { + return; + } + for (i = 0; i < dest_len; ++i, ++src, ++new_dest) { *new_dest = *src; if ('\0' == *src) { From 11482212bac0f830ea984d593dc8024b9a25c431 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Sun, 14 Jun 2026 12:12:01 -0400 Subject: [PATCH 113/230] opal/util: fix opal_argv_delete argc on over-delete opal_argv_delete() already clamps the array work when num_to_delete runs past the end of the array (suffix_count is floored at 0 and the free loop is bounded by the element count), correctly truncating the array. But it then did "(*argc) -= num_to_delete" unconditionally, leaving *argc negative/garbage (e.g. -97) when more elements were requested for deletion than existed. Set *argc to the actual new array length instead, which is correct in both the normal and over-delete cases. Signed-off-by: Jeff Squyres --- opal/util/argv.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/opal/util/argv.c b/opal/util/argv.c index cc725db824b..382af733dd7 100644 --- a/opal/util/argv.c +++ b/opal/util/argv.c @@ -13,6 +13,7 @@ * Copyright (c) 2012 Los Alamos National Security, LLC. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * * $COPYRIGHT$ * @@ -492,8 +493,11 @@ int opal_argv_delete(int *argc, char ***argv, int start, int num_to_delete) *argv = tmp; } - /* adjust the argc */ - (*argc) -= num_to_delete; + /* Adjust argc to the actual new length of the array. "i" is the + index of the trailing NULL, i.e., the new element count. Using + this (rather than subtracting num_to_delete) keeps argc correct + even when num_to_delete runs past the end of the array. */ + *argc = i; return OPAL_SUCCESS; } From 16e19167afeceb52aabfe24c6ec70b2f7e4c9ba3 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 15 Jun 2026 00:28:42 -0400 Subject: [PATCH 114/230] fix(datatype): match only basic scalar types in ompi_datatype_match_size ompi_datatype_match_size() (used by MPI_Type_match_size) selected a predefined datatype by language + kind + size only. That let it return two kinds of bogus matches: - composite predefined types: e.g. MPI_Type_match_size(MPI_TYPECLASS_REAL, 8) could return MPI_2REAL (a pair of 4-byte reals) instead of a scalar real*8 -- same byte size, wrong type. - "unavailable" predefined types (size 0): a size-0 request would match one and be returned as success, handing back an unusable handle. Both are exposed by --disable-mpi-fortran, where the scalar Fortran intrinsic types are compiled as unavailable: a scalar lookup would either fall through to a composite (e.g. REAL/8 -> MPI_2REAL) or, for size 0, return an unavailable type. Require OPAL_DATATYPE_FLAG_BASIC so only basic scalar predefined types are eligible. This excludes both composite and unavailable types in one check: match_size now returns the correct scalar intrinsic when one exists and fails (MPI_ERR_ARG) otherwise -- including failing cleanly for every typeclass/size on a --disable-mpi-fortran build, per MPI-5.0 19.1. Also document this behavior on the MPI_Type_match_size man page. Signed-off-by: Jeff Squyres --- .../man3/MPI_Type_match_size.3.rst | 19 +++++++++++++++++++ ompi/datatype/ompi_datatype_match_size.c | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/man-openmpi/man3/MPI_Type_match_size.3.rst b/docs/man-openmpi/man3/MPI_Type_match_size.3.rst index 5670845b7f4..fb36aab07b2 100644 --- a/docs/man-openmpi/man3/MPI_Type_match_size.3.rst +++ b/docs/man-openmpi/man3/MPI_Type_match_size.3.rst @@ -41,6 +41,25 @@ suitable datatype. In C use the sizeof builtin instead of :ref:`MPI_Sizeof`. It is erroneous to specify a size not supported by the compiler. +NOTES +----- + +In Open MPI, *typeclass* always refers to a Fortran numeric intrinsic +type, and :ref:`MPI_Type_match_size` only ever returns an intrinsic +Fortran predefined datatype (for example, ``MPI_REAL8``, +``MPI_INTEGER4``, or ``MPI_COMPLEX8``) |mdash| regardless of whether it +is called from C or Fortran. It does not return C predefined datatypes +(such as ``MPI_DOUBLE``), nor composite predefined datatypes (such as +``MPI_2REAL`` or ``MPI_2INTEGER``), even when one of those happens to +have the requested *size*. + +Consequently, if Open MPI was built with ``--disable-mpi-fortran``, the +Fortran intrinsic datatypes are unavailable. In that case no datatype +can match any *typeclass* / *size* combination: every such request is +treated as a size not supported by the compiler, and the call fails with +error class ``MPI_ERR_ARG`` (subject to the relevant error handler). + + ERRORS ------ diff --git a/ompi/datatype/ompi_datatype_match_size.c b/ompi/datatype/ompi_datatype_match_size.c index ff48eeface8..6aefb33f6e5 100644 --- a/ompi/datatype/ompi_datatype_match_size.c +++ b/ompi/datatype/ompi_datatype_match_size.c @@ -13,6 +13,7 @@ * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2026 Stony Brook University. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -42,6 +43,16 @@ const ompi_datatype_t* ompi_datatype_match_size( size_t size, uint16_t datakind, datatype = (ompi_datatype_t*)opal_pointer_array_get_item(&ompi_datatype_f_to_c_table, i); + /* Only basic scalar predefined types are valid matches for a + * (typeclass, size) request. Requiring OPAL_DATATYPE_FLAG_BASIC + * skips two kinds of entries that would otherwise produce bogus + * matches: types that are unavailable in this build (e.g. the + * Fortran types in a --disable-mpi-fortran build, which have size 0 + * and would spuriously match a size-0 request), and composite + * predefined types (e.g. MPI_2REAL, a pair of REALs whose 8-byte + * size would otherwise be returned for a request of REAL/8). */ + if( (datatype->super.flags & OPAL_DATATYPE_FLAG_BASIC) != OPAL_DATATYPE_FLAG_BASIC ) + continue; if( (datatype->super.flags & OMPI_DATATYPE_FLAG_DATA_LANGUAGE) != datalang ) continue; if( (datatype->super.flags & OMPI_DATATYPE_FLAG_DATA_TYPE) != datakind ) From c46e33470c9490670118fce101809d52d76ee478 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 19:42:58 -0400 Subject: [PATCH 115/230] fix(sharedfp/sm): use a POSIX-portable leading-slash semaphore name The sm shared-file-pointer component creates the POSIX named semaphore that guards its shared offset with sem_open("OMPIO_", ...) -- a name with no leading slash. POSIX leaves the behavior of a named-semaphore name that does not begin with '/' implementation defined; Linux and macOS happen to accept it, but FreeBSD rejects it with EINVAL. Because sm has the highest default sharedfp priority it is selected for essentially every MPI_File_open(), and a failure in its file_open is fatal to the open, so MPI-IO File_open() returned MPI_ERR_OTHER for every file on FreeBSD. Emit a portable, leading-slash name ("/OMPIO_") on all platforms. Verified on FreeBSD 15 (the open now succeeds) and that Linux and macOS continue to work. Found while running the new ompi/test/file unit test on FreeBSD. Signed-off-by: Jeff Squyres --- ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c b/ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c index edc453a7add..0a1f0af9d78 100644 --- a/ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c +++ b/ompi/mca/sharedfp/sm/sharedfp_sm_file_open.c @@ -15,6 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2015-2021 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2016-2017 IBM Corporation. All rights reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -182,12 +183,18 @@ int mca_sharedfp_sm_file_open (struct ompi_communicator_t *comm, #if defined(HAVE_SEM_OPEN) + /* POSIX requires a named-semaphore name to begin with '/' (and to + contain no other '/'). Linux and macOS tolerate a missing leading + slash, but FreeBSD enforces POSIX: sem_open() of a name that does not + start with '/' fails with EINVAL. That made MPI_File_open() fail on + FreeBSD whenever the sm sharedfp component was selected (its default + priority is the highest), so always emit a leading-slash name. */ #if defined (__APPLE__) sm_data->sem_name = (char*) malloc( sizeof(char) * 32); - snprintf(sm_data->sem_name,31,"OMPIO_%s",filename_basename); + snprintf(sm_data->sem_name,31,"/OMPIO_%s",filename_basename); #else sm_data->sem_name = (char*) malloc( sizeof(char) * 253); - snprintf(sm_data->sem_name,252,"OMPIO_%s",filename_basename); + snprintf(sm_data->sem_name,252,"/OMPIO_%s",filename_basename); #endif // We're now done with filename_basename. Free it here so that we // don't have to keep freeing it in the error/return cases. From 5d71f112cd5d2023b55745a6cb8dad88ae6e34f9 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 22:32:31 -0400 Subject: [PATCH 116/230] fortran/use-mpi-f08: fix MPI_Buffer_detach C_PTR return and sentinel The mpi_f08 wrappers for MPI_Buffer_detach, MPI_Comm_detach_buffer, and MPI_Session_detach_buffer tested the wrong value when translating the C MPI_BUFFER_AUTOMATIC sentinel ((void *) 4) back to the Fortran sentinel. They compared the address of the user's C_PTR storage against MPI_BUFFER_AUTOMATIC instead of the pointer value the C library had written into that storage. As generated, the comparison was essentially never true, so the automatic-buffer translation never happened; and inside the (statically known) branch the code dereferenced (void *) 4, which GCC flagged as a -Wstringop-overflow write to address zero. MPI_Buffer_detach was additionally broken: it passed &buffer to the back-end call, so the detached buffer address landed in a local variable and was never returned to the user's TYPE(C_PTR) -- unlike the comm and session variants, which correctly pass buffer. Test the value written into the user's C_PTR (*(void **)buffer) and, in buffer_detach, pass buffer to the back-end call so the result reaches the caller. This fixes both the compiler warnings and the underlying incorrect behavior. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in | 5 +++-- ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in | 3 ++- ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in b/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in index 1769ca93a5f..5eaaac2ba60 100644 --- a/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in @@ -15,6 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -27,12 +28,12 @@ PROTOTYPE VOID buffer_detach(C_PTR_OUT buffer, COUNT size) int c_ierr; @COUNT_TYPE@ c_size; - c_ierr = @INNER_CALL@(&buffer, &c_size); + c_ierr = @INNER_CALL@(buffer, &c_size); if (NULL != ierr) *ierr = OMPI_INT_2_FINT(c_ierr); if (MPI_SUCCESS == c_ierr) { *size = (@COUNT_FINT_TYPE@)(c_size); - if (MPI_BUFFER_AUTOMATIC == buffer) { + if (MPI_BUFFER_AUTOMATIC == *((void **)buffer)) { *((void **)buffer) = OMPI_FORTRAN_BUFFER_AUTOMATIC_ADDR(); } } diff --git a/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in b/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in index e18728e4759..ace86e833d8 100644 --- a/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in @@ -15,6 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -35,7 +36,7 @@ PROTOTYPE VOID comm_detach_buffer(COMM comm, C_PTR_OUT buffer, COUNT size) if (MPI_SUCCESS == c_ierr) { *size = (@COUNT_FINT_TYPE@)(c_size); - if (MPI_BUFFER_AUTOMATIC == buffer) { + if (MPI_BUFFER_AUTOMATIC == *((void **)buffer)) { *((void **)buffer) = OMPI_FORTRAN_BUFFER_AUTOMATIC_ADDR(); } } diff --git a/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in b/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in index acaaa856386..c350d968266 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in @@ -15,6 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -35,7 +36,7 @@ PROTOTYPE VOID session_detach_buffer(SESSION session, C_PTR_OUT buffer, COUNT si if (MPI_SUCCESS == c_ierr) { *size = (@COUNT_FINT_TYPE@)(c_size); - if (MPI_BUFFER_AUTOMATIC == buffer) { + if (MPI_BUFFER_AUTOMATIC == *((void **)buffer)) { *((void **)buffer) = OMPI_FORTRAN_BUFFER_AUTOMATIC_ADDR(); } } From 561d0e3ca8330d32143379bd5116347eecd5befe Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 22:48:54 -0400 Subject: [PATCH 117/230] fortran/use-mpi-f08: translate MPI_BUFFER_AUTOMATIC in attach bindings The mpi_f08 wrappers for MPI_Buffer_attach, MPI_Comm_attach_buffer, and MPI_Session_attach_buffer passed the raw Fortran buffer base address straight to the back-end C routine. When the user passed the Fortran MPI_BUFFER_AUTOMATIC sentinel, the C library (which only recognizes its own (void *) 4 sentinel) treated the address of the Fortran sentinel variable as an ordinary user buffer, so automatic buffering was never engaged and the bogus region could be written. The older mpif-h bindings already guard against this with the OMPI_F2C_BUFFER_AUTOMATIC() macro, which maps the Fortran sentinel to the C sentinel and passes any other address through unchanged. Wrap the base address with the same macro in the three mpi_f08 attach wrappers so MPI_BUFFER_AUTOMATIC works end to end, matching the companion fix in the detach wrappers. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/buffer_attach_ts.c.in | 3 ++- ompi/mpi/fortran/use-mpi-f08/comm_attach_buffer_ts.c.in | 3 ++- ompi/mpi/fortran/use-mpi-f08/session_attach_buffer_ts.c.in | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/buffer_attach_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/buffer_attach_ts.c.in index 93e3b956d3b..e131768a195 100644 --- a/ompi/mpi/fortran/use-mpi-f08/buffer_attach_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/buffer_attach_ts.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -27,7 +28,7 @@ PROTOTYPE VOID buffer_attach(BUFFER_ASYNC x, COUNT size) @COUNT_TYPE@ c_size = (@COUNT_TYPE@)*size; if (OMPI_CFI_IS_CONTIGUOUS(x)) { - c_ierr = PMPI_Buffer_attach(OMPI_CFI_BASE_ADDR(x), c_size); + c_ierr = PMPI_Buffer_attach(OMPI_F2C_BUFFER_AUTOMATIC(OMPI_CFI_BASE_ADDR(x)), c_size); } else { c_ierr = MPI_ERR_BUFFER; OMPI_ERRHANDLER_INVOKE(MPI_COMM_SELF, c_ierr, FUNC_NAME); diff --git a/ompi/mpi/fortran/use-mpi-f08/comm_attach_buffer_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/comm_attach_buffer_ts.c.in index 75ec71d86b9..aadb7318cd7 100644 --- a/ompi/mpi/fortran/use-mpi-f08/comm_attach_buffer_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/comm_attach_buffer_ts.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -28,7 +29,7 @@ PROTOTYPE VOID comm_attach_buffer(COMM comm, BUFFER_ASYNC x, COUNT size) @COUNT_TYPE@ c_size = (@COUNT_TYPE@)*size; if (OMPI_CFI_IS_CONTIGUOUS(x)) { - c_ierr = PMPI_Comm_attach_buffer(c_comm, OMPI_CFI_BASE_ADDR(x), c_size); + c_ierr = PMPI_Comm_attach_buffer(c_comm, OMPI_F2C_BUFFER_AUTOMATIC(OMPI_CFI_BASE_ADDR(x)), c_size); } else { c_ierr = MPI_ERR_BUFFER; OMPI_ERRHANDLER_INVOKE(c_comm, c_ierr, FUNC_NAME); diff --git a/ompi/mpi/fortran/use-mpi-f08/session_attach_buffer_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/session_attach_buffer_ts.c.in index d3550eed9b9..b5917145c5c 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_attach_buffer_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/session_attach_buffer_ts.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -30,7 +31,7 @@ PROTOTYPE VOID session_attach_buffer(SESSION session, BUFFER_ASYNC x, COUNT size c_session = PMPI_Session_f2c(*session); if (OMPI_CFI_IS_CONTIGUOUS(x)) { - c_ierr = PMPI_Session_attach_buffer(c_session, OMPI_CFI_BASE_ADDR(x), c_size); + c_ierr = PMPI_Session_attach_buffer(c_session, OMPI_F2C_BUFFER_AUTOMATIC(OMPI_CFI_BASE_ADDR(x)), c_size); } else { c_ierr = MPI_ERR_BUFFER; OMPI_ERRHANDLER_INVOKE(c_session, c_ierr, FUNC_NAME); From 1ad5a9897f0a17e3348e1e42fcf9f3a54714667a Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 23:02:52 -0400 Subject: [PATCH 118/230] fortran/use-mpi-f08: add buffer attach/detach regression test Add a singleton-capable mpi_f08 test under test/simple that exercises MPI_Buffer_detach, MPI_Comm_detach_buffer, and MPI_Session_detach_buffer (with their attach counterparts) and checks two properties the bindings previously got wrong: - detach returns the attached buffer's address in the caller's TYPE(C_PTR); and - detaching an automatic buffer (MPI_BUFFER_AUTOMATIC) hands back the Fortran sentinel, never the C library's internal (void *) 4 sentinel. All operations are local, so the test runs as a singleton (no mpirun required). Wire it into the standalone test/simple Makefile. Signed-off-by: Jeff Squyres --- test/simple/Makefile | 8 +- test/simple/buffer_attach_detach_f08.f90 | 211 +++++++++++++++++++++++ 2 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 test/simple/buffer_attach_detach_f08.f90 diff --git a/test/simple/Makefile b/test/simple/Makefile index 5c763f878be..8a96bbf3049 100644 --- a/test/simple/Makefile +++ b/test/simple/Makefile @@ -5,7 +5,8 @@ PROGS = mpi_no_op mpi_barrier hello hello_nodename abort multi_abort comm_abort parallel_w8 parallel_w64 parallel_r8 parallel_r64 sio sendrecv_blaster early_abort \ debugger singleton_client_server intercomm_create spawn_tree init-exit77 mpi_info \ info_spawn server client ring binding badcoll attach xlib \ - no-disconnect nonzero interlib pinterlib add_host + no-disconnect nonzero interlib pinterlib add_host \ + buffer_attach_detach_f08 all: $(PROGS) @@ -23,6 +24,11 @@ xlib: xlib.c pinterlib: pinterlib.c $(CC) $(CFLAGS) $(CFLAGS_INTERNAL) $^ -o $@ -lpmix +# Fortran mpi_f08 test (no built-in .f90 rule) + +buffer_attach_detach_f08: buffer_attach_detach_f08.f90 + $(FC) $(FCFLAGS) $^ -o $@ + CC = mpicc CFLAGS = -g --openmpi:linkall CFLAGS_INTERNAL = -I../../.. -I../../../orte/include -I../../../opal/include diff --git a/test/simple/buffer_attach_detach_f08.f90 b/test/simple/buffer_attach_detach_f08.f90 new file mode 100644 index 00000000000..521f6c5fb6b --- /dev/null +++ b/test/simple/buffer_attach_detach_f08.f90 @@ -0,0 +1,211 @@ +! -*- f90 -*- +! +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. +! $COPYRIGHT$ +! +! Additional copyrights may follow +! +! $HEADER$ +! +! Regression test for the mpi_f08 buffer attach/detach bindings. +! +! This exercises MPI_Buffer_detach, MPI_Comm_detach_buffer, and +! MPI_Session_detach_buffer (and their attach counterparts) and +! verifies two things that the bindings previously got wrong: +! +! 1. detach must return, in the user's TYPE(C_PTR), the address of +! the buffer that was attached. MPI_Buffer_detach used to pass +! &buffer to the back-end call, so the detached address was +! dropped into a local variable and the caller's C_PTR was never +! updated. +! +! 2. when an automatic buffer (MPI_BUFFER_AUTOMATIC) is detached, the +! binding must hand back the *Fortran* sentinel address, not the C +! library's internal sentinel ((void *) 4). That requires the +! attach wrappers to translate the Fortran sentinel to the C +! sentinel (so the C library actually engages automatic mode) and +! the detach wrappers to translate the C sentinel back. +! +! Everything here is local (no communication), so the test runs fine +! as a singleton: ./buffer_attach_detach_f08 +! +! Exits non-zero if any check fails. + +program buffer_attach_detach_f08 + use, intrinsic :: iso_c_binding, only: c_ptr, c_loc, c_associated, & + c_null_ptr, c_intptr_t, c_int8_t + use mpi_f08 + implicit none + + integer, parameter :: BUFSIZE = 8192 + ! The C sentinel MPI_BUFFER_AUTOMATIC is ((void *) 4); the Fortran + ! binding must never expose that value to Fortran code. + integer(c_intptr_t), parameter :: C_BUFFER_AUTOMATIC = 4_c_intptr_t + + integer(c_int8_t), allocatable, target :: buf(:) + type(c_ptr) :: addr + integer :: isize, ierr, nerr + integer(c_intptr_t) :: ia_buf, ia_comm, ia_sess + type(MPI_Session) :: session + + nerr = 0 + + call MPI_Init(ierr) + call must("MPI_Init", ierr) + ! Let the buffer calls report errors via ierr instead of aborting. + call MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN, ierr) + call must("MPI_Comm_set_errhandler", ierr) + + allocate(buf(BUFSIZE)) + + ! ---------------------------------------------------------------- + ! Normal-buffer round trips: detach must return the attached + ! address. (This is the decisive check for the MPI_Buffer_detach + ! &buffer bug; the comm/session variants already returned the + ! address correctly and serve as regression guards.) + ! ---------------------------------------------------------------- + + addr = c_null_ptr + isize = -1 + call MPI_Buffer_attach(buf, BUFSIZE, ierr) + call must("MPI_Buffer_attach", ierr) + call MPI_Buffer_detach(addr, isize, ierr) + call must("MPI_Buffer_detach", ierr) + call expect_addr("MPI_Buffer_detach returns attached address", & + addr, c_loc(buf), nerr) + call expect_size("MPI_Buffer_detach returns attached size", & + isize, BUFSIZE, nerr) + + addr = c_null_ptr + isize = -1 + call MPI_Comm_attach_buffer(MPI_COMM_SELF, buf, BUFSIZE, ierr) + call must("MPI_Comm_attach_buffer", ierr) + call MPI_Comm_detach_buffer(MPI_COMM_SELF, addr, isize, ierr) + call must("MPI_Comm_detach_buffer", ierr) + call expect_addr("MPI_Comm_detach_buffer returns attached address", & + addr, c_loc(buf), nerr) + call expect_size("MPI_Comm_detach_buffer returns attached size", & + isize, BUFSIZE, nerr) + + call MPI_Session_init(MPI_INFO_NULL, MPI_ERRORS_RETURN, session, ierr) + call must("MPI_Session_init", ierr) + + addr = c_null_ptr + isize = -1 + call MPI_Session_attach_buffer(session, buf, BUFSIZE, ierr) + call must("MPI_Session_attach_buffer", ierr) + call MPI_Session_detach_buffer(session, addr, isize, ierr) + call must("MPI_Session_detach_buffer", ierr) + call expect_addr("MPI_Session_detach_buffer returns attached address", & + addr, c_loc(buf), nerr) + call expect_size("MPI_Session_detach_buffer returns attached size", & + isize, BUFSIZE, nerr) + + ! ---------------------------------------------------------------- + ! Automatic-buffer round trips: attach MPI_BUFFER_AUTOMATIC, then + ! detach. The returned address must be the Fortran sentinel -- a + ! real, non-null address that is NOT the C sentinel (void *) 4 -- + ! and must be identical across all three APIs. + ! ---------------------------------------------------------------- + + addr = c_null_ptr + call MPI_Buffer_attach(MPI_BUFFER_AUTOMATIC, BUFSIZE, ierr) + call must("MPI_Buffer_attach(AUTOMATIC)", ierr) + call MPI_Buffer_detach(addr, isize, ierr) + call must("MPI_Buffer_detach(AUTOMATIC)", ierr) + ia_buf = transfer(addr, ia_buf) + call expect_auto("MPI_Buffer_detach maps automatic sentinel", ia_buf, nerr) + + addr = c_null_ptr + call MPI_Comm_attach_buffer(MPI_COMM_SELF, MPI_BUFFER_AUTOMATIC, BUFSIZE, ierr) + call must("MPI_Comm_attach_buffer(AUTOMATIC)", ierr) + call MPI_Comm_detach_buffer(MPI_COMM_SELF, addr, isize, ierr) + call must("MPI_Comm_detach_buffer(AUTOMATIC)", ierr) + ia_comm = transfer(addr, ia_comm) + call expect_auto("MPI_Comm_detach_buffer maps automatic sentinel", ia_comm, nerr) + + addr = c_null_ptr + call MPI_Session_attach_buffer(session, MPI_BUFFER_AUTOMATIC, BUFSIZE, ierr) + call must("MPI_Session_attach_buffer(AUTOMATIC)", ierr) + call MPI_Session_detach_buffer(session, addr, isize, ierr) + call must("MPI_Session_detach_buffer(AUTOMATIC)", ierr) + ia_sess = transfer(addr, ia_sess) + call expect_auto("MPI_Session_detach_buffer maps automatic sentinel", ia_sess, nerr) + + if (ia_buf == ia_comm .and. ia_buf == ia_sess) then + print '(a)', "PASS: automatic sentinel address consistent across APIs" + else + print '(a)', "FAIL: automatic sentinel address differs across APIs" + nerr = nerr + 1 + end if + + call MPI_Session_finalize(session, ierr) + call must("MPI_Session_finalize", ierr) + + deallocate(buf) + + if (nerr == 0) then + print '(a)', "All mpi_f08 buffer attach/detach tests PASSED" + else + print '(a,i0,a)', "TEST FAILED: ", nerr, " check(s) failed" + end if + + call MPI_Finalize(ierr) + + if (nerr /= 0) then + error stop 1 + end if + +contains + + ! Abort on an unexpected MPI error return. + subroutine must(label, ie) + character(len=*), intent(in) :: label + integer, intent(in) :: ie + if (ie /= MPI_SUCCESS) then + print '(3a,i0)', "ERROR: ", label, " failed, ierr=", ie + call MPI_Abort(MPI_COMM_WORLD, 1) + end if + end subroutine must + + ! Check that a returned C_PTR matches the expected address. + subroutine expect_addr(label, got, want, ne) + character(len=*), intent(in) :: label + type(c_ptr), intent(in) :: got, want + integer, intent(inout) :: ne + if (c_associated(got, want)) then + print '(2a)', "PASS: ", label + else + print '(2a)', "FAIL: ", label + ne = ne + 1 + end if + end subroutine expect_addr + + ! Check that a detach returned the size that was attached. + subroutine expect_size(label, got, want, ne) + character(len=*), intent(in) :: label + integer, intent(in) :: got, want + integer, intent(inout) :: ne + if (got == want) then + print '(2a)', "PASS: ", label + else + print '(2a,i0)', "FAIL: ", label, got + ne = ne + 1 + end if + end subroutine expect_size + + ! Check that an automatic-detach result is the Fortran sentinel: + ! non-null, and not the C sentinel (void *) 4. + subroutine expect_auto(label, ia, ne) + character(len=*), intent(in) :: label + integer(c_intptr_t), intent(in) :: ia + integer, intent(inout) :: ne + if (ia /= 0_c_intptr_t .and. ia /= C_BUFFER_AUTOMATIC) then + print '(2a)', "PASS: ", label + else + print '(2a,i0)', "FAIL: ", label, ia + ne = ne + 1 + end if + end subroutine expect_auto + +end program buffer_attach_detach_f08 From 1c94319845ecb54f902946f0b36320ab6d6339e2 Mon Sep 17 00:00:00 2001 From: Howard Pritchard Date: Wed, 17 Jun 2026 11:49:33 -0600 Subject: [PATCH 119/230] MPI pack/unpack: fix type casting for size comparisons Replace inappropriate unsigned int casts with size_t in MPI_Pack and MPI_Unpack truncation checks, and remove unnecessary int cast in MPI_Pack_size. This ensures proper type compatibility when comparing sizes and avoids potential truncation issues with large message sizes. Fixes #14004 Signed-off-by: Howard Pritchard Co-authored-by: Claude --- ompi/mpi/c/pack.c.in | 2 +- ompi/mpi/c/pack_size.c.in | 2 +- ompi/mpi/c/unpack.c.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ompi/mpi/c/pack.c.in b/ompi/mpi/c/pack.c.in index 69a0bb358eb..18114c6d187 100644 --- a/ompi/mpi/c/pack.c.in +++ b/ompi/mpi/c/pack.c.in @@ -90,7 +90,7 @@ PROTOTYPE ERROR_CLASS pack(BUFFER inbuf, COUNT incount, DATATYPE datatype, /* Check for truncation */ opal_convertor_get_packed_size( &local_convertor, &size ); - if( (*position + size) > (unsigned int)outsize ) { /* we can cast as we already checked for < 0 */ + if( (*position + size) > (size_t)outsize ) { /* we can cast as we already checked for < 0 */ OBJ_DESTRUCT( &local_convertor ); return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_TRUNCATE, FUNC_NAME); } diff --git a/ompi/mpi/c/pack_size.c.in b/ompi/mpi/c/pack_size.c.in index f0931d00671..ffaac48d0cb 100644 --- a/ompi/mpi/c/pack_size.c.in +++ b/ompi/mpi/c/pack_size.c.in @@ -60,7 +60,7 @@ PROTOTYPE ERROR_CLASS pack_size(COUNT incount, DATATYPE datatype, COMM comm, incount, NULL, 0, &local_convertor ); opal_convertor_get_packed_size( &local_convertor, &length ); - *size = (int)length; + *size = length; OBJ_DESTRUCT( &local_convertor ); return MPI_SUCCESS; diff --git a/ompi/mpi/c/unpack.c.in b/ompi/mpi/c/unpack.c.in index 94055ceef94..3aa520c6524 100644 --- a/ompi/mpi/c/unpack.c.in +++ b/ompi/mpi/c/unpack.c.in @@ -97,7 +97,7 @@ PROTOTYPE ERROR_CLASS unpack(BUFFER inbuf, /* Check for truncation */ opal_convertor_get_packed_size( &local_convertor, &size ); - if( (*position + size) > (unsigned int)insize ) { + if( (*position + size) > (size_t)insize ) { OBJ_DESTRUCT( &local_convertor ); return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_TRUNCATE, FUNC_NAME); } From d1feb8435044e7c28826bbbff519c65c2599d79f Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 23:20:24 -0400 Subject: [PATCH 120/230] fortran/use-mpi-f08: use INTENT(OUT) for output size arguments The mpi_f08 wrappers for MPI_Buffer_detach, MPI_Comm_detach_buffer, MPI_Session_detach_buffer, and MPI_Type_size declared their output "size" argument with the COUNT prototype type, which generates INTEGER ..., INTENT(IN) -- even though the back-end wrapper writes the result through that argument. The MPI-5.0 mpi_f08 bindings specify INTENT(OUT) for these size arguments. Switch the prototype type to COUNT_OUT, which is already used for the same purpose by MPI_Get_count, MPI_Get_elements, and MPI_Pack_size. This changes only the generated Fortran INTENT (the C wrapper signature and body are byte-for-byte identical), bringing the declarations in line with the standard and removing a latent declaration mismatch that a conforming compiler could exploit. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in | 2 +- ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in | 2 +- ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in | 2 +- ompi/mpi/fortran/use-mpi-f08/type_size.c.in | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in b/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in index 5eaaac2ba60..db907a75228 100644 --- a/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/buffer_detach.c.in @@ -23,7 +23,7 @@ * $HEADER$ */ -PROTOTYPE VOID buffer_detach(C_PTR_OUT buffer, COUNT size) +PROTOTYPE VOID buffer_detach(C_PTR_OUT buffer, COUNT_OUT size) { int c_ierr; @COUNT_TYPE@ c_size; diff --git a/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in b/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in index ace86e833d8..ecd2cc576f6 100644 --- a/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/comm_detach_buffer.c.in @@ -23,7 +23,7 @@ * $HEADER$ */ -PROTOTYPE VOID comm_detach_buffer(COMM comm, C_PTR_OUT buffer, COUNT size) +PROTOTYPE VOID comm_detach_buffer(COMM comm, C_PTR_OUT buffer, COUNT_OUT size) { int c_ierr; MPI_Comm c_comm; diff --git a/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in b/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in index c350d968266..035c8d05147 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/session_detach_buffer.c.in @@ -23,7 +23,7 @@ * $HEADER$ */ -PROTOTYPE VOID session_detach_buffer(SESSION session, C_PTR_OUT buffer, COUNT size) +PROTOTYPE VOID session_detach_buffer(SESSION session, C_PTR_OUT buffer, COUNT_OUT size) { int c_ierr; MPI_Session c_session; diff --git a/ompi/mpi/fortran/use-mpi-f08/type_size.c.in b/ompi/mpi/fortran/use-mpi-f08/type_size.c.in index c71e3f9294d..b98f45ed141 100644 --- a/ompi/mpi/fortran/use-mpi-f08/type_size.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/type_size.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -21,7 +22,7 @@ * $HEADER$ */ -PROTOTYPE VOID type_size(DATATYPE type, COUNT size) +PROTOTYPE VOID type_size(DATATYPE type, COUNT_OUT size) { int c_ierr; MPI_Datatype c_type = PMPI_Type_f2c(*type); From 91ff5b83b19a29f2ccec672c902030ef3270995e Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Tue, 16 Jun 2026 23:48:34 -0400 Subject: [PATCH 121/230] fortran/use-mpi-f08: fix INTENT direction of several arguments Auditing the mpi_f08 bindings against the MPI standard parameter directions turned up five procedures whose Fortran INTENT did not match the standard: - MPI_Get_address: address is the returned address (OUT), not IN. - MPI_Unpack_external: outcount is the number of items to unpack, an input (IN), not OUT. - MPI_Win_allocate_shared: win is the newly created window (OUT), not IN -- every other window-creation routine already uses OUT. - MPI_Session_init: errhandler is the error handler to attach to the new session, an input (IN), not OUT. - MPI_Session_finalize: session is read and then set to MPI_SESSION_NULL (INOUT), not OUT -- matching every other handle-freeing routine. For the three template-generated bindings, switch the prototype type to the appropriate variant (AINT_OUT, COUNT, WIN_OUT); for the two hand-written session bindings, correct the INTENT directly. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/get_address_ts.c.in | 3 ++- ompi/mpi/fortran/use-mpi-f08/session_finalize_f08.F90 | 3 ++- ompi/mpi/fortran/use-mpi-f08/session_init_f08.F90 | 3 ++- ompi/mpi/fortran/use-mpi-f08/unpack_external_ts.c.in | 3 ++- ompi/mpi/fortran/use-mpi-f08/win_allocate_shared.c.in | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/get_address_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/get_address_ts.c.in index d672e8c1139..5a02209826c 100644 --- a/ompi/mpi/fortran/use-mpi-f08/get_address_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/get_address_ts.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -21,7 +22,7 @@ * $HEADER$ */ -PROTOTYPE VOID get_address(BUFFER_ASYNC x, AINT address) +PROTOTYPE VOID get_address(BUFFER_ASYNC x, AINT_OUT address) { int c_ierr; MPI_Aint c_address; diff --git a/ompi/mpi/fortran/use-mpi-f08/session_finalize_f08.F90 b/ompi/mpi/fortran/use-mpi-f08/session_finalize_f08.F90 index ef626258f0d..64ab388d880 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_finalize_f08.F90 +++ b/ompi/mpi/fortran/use-mpi-f08/session_finalize_f08.F90 @@ -7,6 +7,7 @@ ! and Technology (RIST). All rights reserved. ! Copyright (c) 2019 Triad National Security, LLC. All rights ! reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ #include "mpi-f08-rename.h" @@ -15,7 +16,7 @@ subroutine MPI_Session_finalize_f08(session,ierror) use :: mpi_f08_types, only : MPI_Session use :: ompi_mpifh_bindings, only : ompi_session_finalize_f implicit none - TYPE(MPI_Session), INTENT(OUT) :: session + TYPE(MPI_Session), INTENT(INOUT) :: session INTEGER, OPTIONAL, INTENT(OUT) :: ierror integer :: c_ierror diff --git a/ompi/mpi/fortran/use-mpi-f08/session_init_f08.F90 b/ompi/mpi/fortran/use-mpi-f08/session_init_f08.F90 index b9eee1338b1..2f01bd4b737 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_init_f08.F90 +++ b/ompi/mpi/fortran/use-mpi-f08/session_init_f08.F90 @@ -7,6 +7,7 @@ ! and Technology (RIST). All rights reserved. ! Copyright (c) 2019-2021 Triad National Security, LLC. All rights ! reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ #include "ompi/mpi/fortran/configure-fortran-output.h" @@ -18,7 +19,7 @@ subroutine MPI_Session_init_f08(info,errhandler,session,ierror) use :: ompi_mpifh_bindings, only : ompi_session_init_f implicit none TYPE(MPI_Info), INTENT(IN) :: info - TYPE(MPI_Errhandler), INTENT(OUT) :: errhandler + TYPE(MPI_Errhandler), INTENT(IN) :: errhandler TYPE(MPI_Session), INTENT(OUT) :: session INTEGER, OPTIONAL, INTENT(OUT) :: ierror integer :: c_ierror diff --git a/ompi/mpi/fortran/use-mpi-f08/unpack_external_ts.c.in b/ompi/mpi/fortran/use-mpi-f08/unpack_external_ts.c.in index 4852a43bada..6c7ce0ff446 100644 --- a/ompi/mpi/fortran/use-mpi-f08/unpack_external_ts.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/unpack_external_ts.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -23,7 +24,7 @@ PROTOTYPE VOID unpack_external(CHAR_ARRAY datarep, BUFFER x1, AINT_COUNT insize, AINT_COUNT_INOUT position, BUFFER x2, - COUNT_OUT outcount, DATATYPE datatype) + COUNT outcount, DATATYPE datatype) { int c_ierr; MPI_Datatype c_datatype, c_type = PMPI_Type_f2c(*datatype); diff --git a/ompi/mpi/fortran/use-mpi-f08/win_allocate_shared.c.in b/ompi/mpi/fortran/use-mpi-f08/win_allocate_shared.c.in index ff13c22d178..4c6ca8de1b7 100644 --- a/ompi/mpi/fortran/use-mpi-f08/win_allocate_shared.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/win_allocate_shared.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -23,7 +24,7 @@ PROTOTYPE VOID win_allocate_shared(AINT size, DISP disp_unit, INFO info, COMM comm, C_PTR_OUT baseptr, - WIN win) + WIN_OUT win) { int c_ierr; MPI_Info c_info; From 86c5eab768534b9bac5b7e3b6e6e9650ab45637b Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Wed, 17 Jun 2026 07:24:28 -0400 Subject: [PATCH 122/230] fortran/use-mpi-f08: use standard MPI parameter names The mpi_f08 binding generator took the Fortran dummy-argument names directly from the *.in PROTOTYPE lines. For the choice-buffer arguments those are generic internal names (x, x1, x2, ...) that the C back-end code refers to -- so they could not simply be renamed without breaking the back-end, and they did not match the names mandated by the MPI standard. Because the mpi_f08 dummy-argument names are part of the user-visible API (Fortran keyword arguments), this is a conformance problem: e.g. MPI_Send(buf=...) did not compile. Teach the Fortran generator to look up the standard F08 dummy-argument names from the pympistandard submodule (new --pympistd-dir option) and substitute them for the template names when emitting the Fortran subroutines and their BIND(C) interfaces. The C wrapper and the template bodies are untouched: the Fortran call passes the arguments to the C wrapper positionally, so the Fortran-visible name and the C-internal name are free to differ. When the prototype and the standard disagree on the number of arguments, the template names are kept rather than risk emitting a wrong name. Only the mpi_f08 module is affected; the C back-end and the mpi (f90) module are not. Wire $(top_srcdir)/3rd-party/pympistandard through the F90 and interface generation rules (VPATH-safe via abs_top_srcdir). Signed-off-by: Jeff Squyres --- ompi/mpi/bindings/bindings.py | 4 + ompi/mpi/bindings/ompi_bindings/fortran.py | 82 ++++++++++++++++++-- ompi/mpi/fortran/use-mpi-f08/Makefile.am | 3 +- ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am | 2 + 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/ompi/mpi/bindings/bindings.py b/ompi/mpi/bindings/bindings.py index 9fa858db93b..1dfd4c3377c 100644 --- a/ompi/mpi/bindings/bindings.py +++ b/ompi/mpi/bindings/bindings.py @@ -1,6 +1,7 @@ # Copyright (c) 2024-2025 Triad National Security, LLC. All rights # reserved. # +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -35,6 +36,9 @@ def main(): help='generate ts suffixes for appropriate routines') parser_fortran.add_argument('--fort-std', choices=('f90', 'f08'), help='fortran standard to use for fortran module and code generation') + parser_fortran.add_argument('--pympistd-dir', default=None, + help='path to the pympistandard submodule; when given, the generated ' + 'Fortran interfaces use the standard MPI dummy-argument names') # Handler for generating actual code subparsers_fortran = parser_fortran.add_subparsers() parser_code = subparsers_fortran.add_parser('code', help='generate binding code') diff --git a/ompi/mpi/bindings/ompi_bindings/fortran.py b/ompi/mpi/bindings/ompi_bindings/fortran.py index ea6253ef894..ada78106c5a 100644 --- a/ompi/mpi/bindings/ompi_bindings/fortran.py +++ b/ompi/mpi/bindings/ompi_bindings/fortran.py @@ -1,6 +1,7 @@ # Copyright (c) 2024-2026 Triad National Security, LLC. All rights # reserved. # +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -16,16 +17,57 @@ """ from collections import namedtuple import json +import os import re +import sys from ompi_bindings import consts, util from ompi_bindings.fortran_type import FortranType from ompi_bindings.parser import SourceTemplate +# Cache of {function_name_lower: [standard f08 dummy-argument names]} loaded +# from pympistandard. None means "not yet attempted"; an empty dict means +# "attempted but unavailable" (the generator then falls back to the names +# hard-coded in the *.in PROTOTYPE lines). +_STANDARD_F08_NAMES = None + + +def standard_f08_names(pympistd_dir): + """Load the standard MPI F08 dummy-argument names from pympistandard. + + The Open MPI templates use generic internal names (e.g. 'x', 'x1') for + the choice-buffer arguments; the C back-end code refers to those names. + The user-visible mpi_f08 interfaces, however, must use the parameter + names mandated by the MPI standard so that keyword arguments work. This + returns, per function, the ordered list of standard F08 dummy names + (excluding ierror), which the Fortran generator substitutes for the + template names -- without touching the C back-end. + """ + global _STANDARD_F08_NAMES + if _STANDARD_F08_NAMES is not None: + return _STANDARD_F08_NAMES + names = {} + if pympistd_dir: + src = os.path.join(pympistd_dir, 'src') + if os.path.isdir(src): + sys.path.insert(0, src) + import pympistandard as std + std.use_api_version(1) + for key, proc in std.PROCEDURES.items(): + f08 = getattr(proc.express, 'f08', None) + if f08 is None: + continue + names[key.lower()] = [p.name.lower() for p in f08.parameters + if p.name.lower() != consts.FORTRAN_ERROR_NAME] + _STANDARD_F08_NAMES = names + return names + + class FortranBinding: """Class for generating the binding for a single function.""" - def __init__(self, prototype, out, template=None, bigcount=False, needs_ts=False, gen_f90=False): + def __init__(self, prototype, out, template=None, bigcount=False, needs_ts=False, + gen_f90=False, f08_names=None): # Generate bigcount interface version self.bigcount = bigcount self.fn_name = template.prototype.name @@ -38,6 +80,16 @@ def __init__(self, prototype, out, template=None, bigcount=False, needs_ts=False self.parameters.append(param.construct(fn_name=self.fn_name, bigcount=bigcount, gen_f90=gen_f90)) + # For Fortran generation, replace the template's internal parameter + # names with the standard MPI F08 dummy-argument names. Only done + # when the count of standard names matches (i.e. the prototype and the + # standard agree on the number of non-ierror arguments); otherwise the + # template names are kept so a misaligned prototype never silently + # emits a wrong name. The C back-end (print_c_source) constructs its + # own FortranBinding without f08_names, so it is unaffected. + if f08_names is not None and len(f08_names) == len(self.parameters): + for param, std_name in zip(self.parameters, f08_names): + param.name = std_name def dump(self, *pargs, **kwargs): """Write to the output file.""" @@ -274,9 +326,10 @@ def print_c_source_header(out): out.dump('#include "bigcount.h"') -def print_binding(prototype, lang, out, bigcount=False, template=None, needs_ts=False, gen_f90=False): +def print_binding(prototype, lang, out, bigcount=False, template=None, needs_ts=False, gen_f90=False, f08_names=None): """Print the binding with or without bigcount.""" - binding = FortranBinding(prototype, out=out, bigcount=bigcount, template=template, needs_ts=needs_ts, gen_f90=gen_f90) + binding = FortranBinding(prototype, out=out, bigcount=bigcount, template=template, needs_ts=needs_ts, + gen_f90=gen_f90, f08_names=f08_names) if lang == 'fortran': binding.print_f_source() else: @@ -300,6 +353,11 @@ def generate_code(args, out): else: gen_f90 = True + # Standard F08 dummy-argument names are only applied to the F08 Fortran + # interfaces, never to the C back-end (whose body refers to the template's + # internal names) and not to the older mpi (f90) module. + std_names = standard_f08_names(args.pympistd_dir) if (args.lang == 'fortran' and not gen_f90) else {} + if args.lang == 'fortran': print_f_source_header(out) out.dump() @@ -312,10 +370,13 @@ def generate_code(args, out): out.dump() has_buffers = util.prototype_has_buffers(template.prototype) needs_ts = has_buffers and args.generate_ts_suffix - print_binding(template.prototype, args.lang, out, template=template, needs_ts=needs_ts, gen_f90=gen_f90) + f08_names = std_names.get('mpi_' + template.prototype.name.lower()) + print_binding(template.prototype, args.lang, out, template=template, needs_ts=needs_ts, + gen_f90=gen_f90, f08_names=f08_names) if util.prototype_has_bigcount(template.prototype) and gen_f90 == False: out.dump() - print_binding(template.prototype, args.lang, bigcount=True, out=out, template=template, needs_ts=needs_ts) + print_binding(template.prototype, args.lang, bigcount=True, out=out, template=template, + needs_ts=needs_ts, f08_names=f08_names) def generate_interface(args, out): @@ -330,16 +391,23 @@ def generate_interface(args, out): else: gen_f90 = True + # The interface specifications are part of the user-visible mpi_f08 + # module, so they use the standard MPI dummy-argument names too. The + # older mpi (f90) module is out of scope. + std_names = standard_f08_names(args.pympistd_dir) if not gen_f90 else {} + for template in templates: ext_name = util.ext_api_func_name(template.prototype.name) out.dump(f'interface {ext_name}') has_buffers = util.prototype_has_buffers(template.prototype) needs_ts = has_buffers and args.generate_ts_suffix - binding = FortranBinding(template.prototype, template=template, needs_ts=needs_ts, gen_f90=gen_f90, out=out) + f08_names = std_names.get('mpi_' + template.prototype.name.lower()) + binding = FortranBinding(template.prototype, template=template, needs_ts=needs_ts, + gen_f90=gen_f90, out=out, f08_names=f08_names) binding.print_interface() if util.prototype_has_bigcount(template.prototype) and gen_f90 == False: out.dump() binding_c = FortranBinding(template.prototype, out=out, template=template, - needs_ts=needs_ts, bigcount=True) + needs_ts=needs_ts, bigcount=True, f08_names=f08_names) binding_c.print_interface() out.dump(f'end interface {ext_name}') diff --git a/ompi/mpi/fortran/use-mpi-f08/Makefile.am b/ompi/mpi/fortran/use-mpi-f08/Makefile.am index b098db3485d..e88f90f961b 100644 --- a/ompi/mpi/fortran/use-mpi-f08/Makefile.am +++ b/ompi/mpi/fortran/use-mpi-f08/Makefile.am @@ -15,7 +15,7 @@ # reserved. # Copyright (c) 2020 Sandia National Laboratories. All rights reserved. # Copyright (c) 2022 IBM Corporation. All rights reserved. -# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2025-2026 Jeffrey M. Squyres. All rights reserved. # # $COPYRIGHT$ # @@ -445,6 +445,7 @@ api_f08_generated.F90: $(template_files) --output $(abs_builddir)/$@ \ fortran \ $(gen_ts) \ + --pympistd-dir $(abs_top_srcdir)/3rd-party/pympistandard \ code \ --lang fortran \ --prototype-files $(template_files) diff --git a/ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am b/ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am index 39a80c2f76f..e438093a427 100644 --- a/ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am +++ b/ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am @@ -13,6 +13,7 @@ # Copyright (C) 2024-2026 Triad National Security, LLC. All rights # reserved. # +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -93,6 +94,7 @@ mpi-f08-interfaces-generated.h: $(template_files) --output $(abs_builddir)/$@ \ fortran \ $(gen_ts) \ + --pympistd-dir $(abs_top_srcdir)/3rd-party/pympistandard \ --fort-std f08 \ interface \ --prototype-files $(template_files) From aafa1ce4cced86bc35f8f5d329d7c4c19697a082 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Wed, 17 Jun 2026 07:24:37 -0400 Subject: [PATCH 123/230] fortran/use-mpi-f08: fix INTENT of the MPI_Testany index argument The testany.c.in template declared the index argument with the INT type (INTENT(IN)), but index is an output -- MPI_Testany returns the index of the completed request. The MPI standard specifies INTEGER, INTENT(OUT). Use the INDEX_OUT prototype type (INTEGER, INTENT(OUT)), which has the same C parameter as INT, so only the Fortran INTENT changes. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/testany.c.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/testany.c.in b/ompi/mpi/fortran/use-mpi-f08/testany.c.in index 3ca6be546d4..00be762e1ca 100644 --- a/ompi/mpi/fortran/use-mpi-f08/testany.c.in +++ b/ompi/mpi/fortran/use-mpi-f08/testany.c.in @@ -14,6 +14,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024-2025 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -21,7 +22,7 @@ * $HEADER$ */ -PROTOTYPE VOID testany(INT count, REQUEST_ARRAY_INOUT array_of_requests:count, INT indx, +PROTOTYPE VOID testany(INT count, REQUEST_ARRAY_INOUT array_of_requests:count, INDEX_OUT indx, LOGICAL_OUT flag, STATUS_OUT status) { MPI_Request *c_req; From e0adfc44d33cdfd79c32883a9fecc64f9f9c33ee Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Wed, 17 Jun 2026 07:24:46 -0400 Subject: [PATCH 124/230] fortran/use-mpi-f08: use standard parameter names in hand-written bindings Three hand-written mpi_f08 bindings used dummy-argument names that do not match the MPI standard: - MPI_Pready_list: partitions -> array_of_partitions - MPI_Session_get_info: info -> info_used - MPI_Win_get_info: info -> info_used (the explicit interface already used info_used; the implementation lagged) Because mpi_f08 dummy-argument names are part of the API (keyword arguments), rename them in both the implementations (*_f08.F90) and the explicit interfaces (mpi-f08-interfaces.h.in) so they agree with the standard. Signed-off-by: Jeff Squyres --- ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h.in | 9 +++++---- ompi/mpi/fortran/use-mpi-f08/pready_list_f08.F90 | 7 ++++--- ompi/mpi/fortran/use-mpi-f08/session_get_info_f08.F90 | 7 ++++--- ompi/mpi/fortran/use-mpi-f08/win_get_info_f08.F90 | 7 ++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h.in b/ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h.in index e2ec132302d..39a2c1c7800 100644 --- a/ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h.in +++ b/ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h.in @@ -13,6 +13,7 @@ ! Copyright (c) 2021-2023 Triad National Security, LLC. All rights ! reserved. ! Copyright (c) 2025 UT-Battelle, LLC. All rights reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ ! ! This file provides the interface specifications for the MPI Fortran @@ -52,11 +53,11 @@ end subroutine MPI_Pready_f08 end interface MPI_Pready interface MPI_Pready_list -subroutine MPI_Pready_list_f08(length,partitions,request,ierror) +subroutine MPI_Pready_list_f08(length,array_of_partitions,request,ierror) use :: mpi_f08_types, only : MPI_Request implicit none INTEGER, INTENT(IN) :: length - INTEGER, DIMENSION(*), INTENT(IN) :: partitions + INTEGER, DIMENSION(*), INTENT(IN) :: array_of_partitions TYPE(MPI_Request), INTENT(IN) :: request INTEGER, OPTIONAL, INTENT(OUT) :: ierror end subroutine MPI_Pready_list_f08 @@ -135,11 +136,11 @@ end subroutine MPI_Session_get_errhandler_f08 end interface MPI_Session_get_errhandler interface MPI_Session_get_info -subroutine MPI_Session_get_info_f08(session, info, ierror) +subroutine MPI_Session_get_info_f08(session, info_used, ierror) use :: mpi_f08_types, only : MPI_Session, MPI_Info implicit none TYPE(MPI_Session), INTENT(IN) :: session - TYPE(MPI_Info), INTENT(OUT) :: info + TYPE(MPI_Info), INTENT(OUT) :: info_used INTEGER, OPTIONAL, INTENT(OUT) :: ierror end subroutine MPI_Session_get_info_f08 end interface MPI_Session_get_info diff --git a/ompi/mpi/fortran/use-mpi-f08/pready_list_f08.F90 b/ompi/mpi/fortran/use-mpi-f08/pready_list_f08.F90 index f021e107cf2..78a735b2874 100644 --- a/ompi/mpi/fortran/use-mpi-f08/pready_list_f08.F90 +++ b/ompi/mpi/fortran/use-mpi-f08/pready_list_f08.F90 @@ -6,22 +6,23 @@ ! Copyright (c) 2018 Research Organization for Information Science ! and Technology (RIST). All rights reserved. ! Copyright (c) 2020 Sandia National Laboratories. All rights reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ #include "mpi-f08-rename.h" #include "ompi/mpi/fortran/configure-fortran-output.h" -subroutine MPI_Pready_list_f08(length,partitions,request,ierror) +subroutine MPI_Pready_list_f08(length,array_of_partitions,request,ierror) use :: mpi_f08_types, only : MPI_Datatype, MPI_Comm, MPI_Request use :: ompi_mpifh_bindings, only : ompi_pready_list_f implicit none INTEGER, INTENT(IN) :: length - INTEGER, dimension(*), INTENT(IN) :: partitions + INTEGER, dimension(*), INTENT(IN) :: array_of_partitions TYPE(MPI_Request), INTENT(IN) :: request INTEGER, OPTIONAL, INTENT(OUT) :: ierror integer :: c_ierror - call ompi_pready_list_f(length,partitions,request%MPI_VAL,c_ierror) + call ompi_pready_list_f(length,array_of_partitions,request%MPI_VAL,c_ierror) if (present(ierror)) ierror = c_ierror end subroutine MPI_Pready_list_f08 diff --git a/ompi/mpi/fortran/use-mpi-f08/session_get_info_f08.F90 b/ompi/mpi/fortran/use-mpi-f08/session_get_info_f08.F90 index a1abe6dfdb5..34bb4d2155e 100644 --- a/ompi/mpi/fortran/use-mpi-f08/session_get_info_f08.F90 +++ b/ompi/mpi/fortran/use-mpi-f08/session_get_info_f08.F90 @@ -7,20 +7,21 @@ ! and Technology (RIST). All rights reserved. ! Copyright (c) 2019-2022 Triad National Security, LLC. All rights ! reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ #include "mpi-f08-rename.h" -subroutine MPI_Session_get_info_f08(session, info, ierror) +subroutine MPI_Session_get_info_f08(session, info_used, ierror) use :: mpi_f08_types, only : MPI_Session, MPI_Info use :: ompi_mpifh_bindings, only : ompi_session_get_info_f implicit none TYPE(MPI_Session), INTENT(IN) :: session - TYPE(MPI_Info), INTENT(OUT) :: info + TYPE(MPI_Info), INTENT(OUT) :: info_used INTEGER, OPTIONAL, INTENT(OUT) :: ierror integer :: c_ierror - call ompi_session_get_info_f(session%MPI_VAL, info%MPI_VAL, c_ierror) + call ompi_session_get_info_f(session%MPI_VAL, info_used%MPI_VAL, c_ierror) if (present(ierror)) ierror = c_ierror end subroutine MPI_Session_get_info_f08 diff --git a/ompi/mpi/fortran/use-mpi-f08/win_get_info_f08.F90 b/ompi/mpi/fortran/use-mpi-f08/win_get_info_f08.F90 index 23c5387e772..1bdc73bf19c 100644 --- a/ompi/mpi/fortran/use-mpi-f08/win_get_info_f08.F90 +++ b/ompi/mpi/fortran/use-mpi-f08/win_get_info_f08.F90 @@ -2,20 +2,21 @@ ! ! Copyright (c) 2015-2020 Research Organization for Information Science ! and Technology (RIST). All rights reserved. +! Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ #include "mpi-f08-rename.h" -subroutine MPI_Win_get_info_f08(win,info,ierror) +subroutine MPI_Win_get_info_f08(win,info_used,ierror) use :: mpi_f08_types, only : MPI_Win, MPI_Info use :: ompi_mpifh_bindings, only : ompi_win_get_info_f implicit none TYPE(MPI_Win), INTENT(IN) :: win - TYPE(MPI_Info), INTENT(OUT) :: info + TYPE(MPI_Info), INTENT(OUT) :: info_used INTEGER, OPTIONAL, INTENT(OUT) :: ierror integer :: c_ierror - call ompi_win_get_info_f(win%MPI_VAL,info%MPI_VAL,c_ierror) + call ompi_win_get_info_f(win%MPI_VAL,info_used%MPI_VAL,c_ierror) if (present(ierror)) ierror = c_ierror end subroutine MPI_Win_get_info_f08 From 05a94cc7016a02337498ef0f3a82fea911dc7a54 Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Wed, 17 Jun 2026 07:25:29 -0400 Subject: [PATCH 125/230] fortran/use-mpi-f08: validate mpi_f08 interfaces against the standard Add a check, run during "make check", that the mpi_f08 interfaces agree with the MPI standard on parameter names, types, and intents, so the bindings cannot silently drift from the standard. check_f08_names.py loads the pympistandard metadata and compares it against the mpi_f08 sources. It is run in two places so that both code paths are covered: - use-mpi-f08/Makefile.am checks the implementations -- the generated api_f08_generated.F90 and the hand-written *_f08.F90 files. - mod/Makefile.am checks the user-visible interface specifications -- mpi-f08-interfaces-generated.h and mpi-f08-interfaces.h -- which are generated by a separate code path from the implementations. The check deliberately ignores things the standard leaves to the implementation: choice buffers (rendered with Open MPI's ignore-TKR macro), arguments whose standard F08 intent is unspecified (e.g. a status argument that must accept MPI_STATUS_IGNORE), and large-count (_c) procedures the standard does not provide an F08 binding for. If pympistandard is not checked out, the check is skipped instead of failing. Both checks run via check-local (VPATH-safe: hand-written sources and pympistandard from the source tree, generated files from the build directory) and fail "make check" on any mismatch. Signed-off-by: Jeff Squyres --- ompi/mpi/Makefile.am | 3 +- ompi/mpi/bindings/check_f08_names.py | 311 +++++++++++++++++++ ompi/mpi/fortran/use-mpi-f08/Makefile.am | 17 + ompi/mpi/fortran/use-mpi-f08/mod/Makefile.am | 12 + 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 ompi/mpi/bindings/check_f08_names.py diff --git a/ompi/mpi/Makefile.am b/ompi/mpi/Makefile.am index 80ae278fde2..f740b22a9cf 100644 --- a/ompi/mpi/Makefile.am +++ b/ompi/mpi/Makefile.am @@ -12,7 +12,7 @@ # Copyright (c) 2006-2018 Cisco Systems, Inc. All rights reserved. # Copyright (c) 2015 Research Organization for Information Science # and Technology (RIST). All rights reserved. -# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# Copyright (c) 2025-2026 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -24,6 +24,7 @@ EXTRA_DIST += \ mpi/fortran/configure-fortran-output-bottom.h \ mpi/help-mpi-api.txt \ mpi/bindings/bindings.py \ + mpi/bindings/check_f08_names.py \ mpi/bindings/ompi_bindings/consts.py \ mpi/bindings/ompi_bindings/c.py \ mpi/bindings/ompi_bindings/c_type.py \ diff --git a/ompi/mpi/bindings/check_f08_names.py b/ompi/mpi/bindings/check_f08_names.py new file mode 100644 index 00000000000..65cb18beecf --- /dev/null +++ b/ompi/mpi/bindings/check_f08_names.py @@ -0,0 +1,311 @@ +# Copyright (c) 2026 Jeffrey M. Squyres. All rights reserved. +# +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +"""Validate the Open MPI mpi_f08 interfaces against the MPI standard. + +The mpi_f08 module is the only Fortran binding whose dummy-argument +*names* are part of the user-visible contract (keyword arguments). This +script loads the MPI Forum's pympistandard metadata and checks that every +mpi_f08 procedure's dummy arguments agree with the standard on three +things: + + * name -- the dummy-argument name (case-insensitive) + * intent -- INTENT(IN|OUT|INOUT) + * type -- the declared Fortran type + +It is intended to be run at build time over the generated Fortran source +(api_f08_generated.F90 and the interface headers) plus the hand-written +*_f08.F90 files, and exits non-zero -- failing the build -- if any +mpi_f08 interface has drifted from the standard. Only the mpi_f08 +module is in scope; the C back-end and the older mpi (f90) module are +not checked. + +Things the standard deliberately leaves to the implementation are not +flagged: + + * choice buffers (standard type 'TYPE(*), ...'); Open MPI renders + these with its own ignore-TKR macro and may attach INTENT(IN). + * any argument whose standard F08 intent is unspecified (None), e.g. + a TYPE(MPI_Status) argument that must also accept MPI_STATUS_IGNORE. + * a large-count (_c) procedure that the standard does not provide an + F08 binding for. +""" + +import argparse +import os +import re +import sys + + +# Automake-style result colors (PASS=green, FAIL=red, SKIP=blue), matching +# Automake's color-tests palette. +_STATUS_COLOR = {'PASS': '\033[0;32m', 'FAIL': '\033[0;31m', 'SKIP': '\033[1;34m'} +_COLOR_RESET = '\033[m' + + +def _use_color(): + """Colorize like Automake: AM_COLOR_TESTS=always forces it; otherwise a TTY.""" + setting = os.environ.get('AM_COLOR_TESTS', '') + if setting == 'always': + return True + if setting == 'no' or os.environ.get('NO_COLOR'): + return False + return sys.stdout.isatty() + + +def emit_status(status, label, reason=None): + """Print an Automake-style ':