Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions one-sided/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


CC=mpicc
CFLAGS=-Wall -g -O0

PROGS=test_mpi_win_shared_query

all: $(PROGS)

test_mpi_win_shared_query: test_mpi_win_shared_query.c
$(CC) test_mpi_win_shared_query.c $(CFLAGS) -o test_mpi_win_shared_query


clean:
rm -f *.o $(PROGS)
7 changes: 7 additions & 0 deletions one-sided/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash -e

echo "============================="
echo "Testing: MPI_Win_shared_query"
echo "============================="
mpirun --np 2 ./test_mpi_win_shared_query

112 changes: 112 additions & 0 deletions one-sided/test_mpi_win_shared_query.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include <mpi.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

void test_shared_memory(MPI_Win win, MPI_Comm comm, int *local_mem, int shared_size, const char *test_name) {
int ret = MPI_SUCCESS;
int rank, size;
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);

// Configure the window to return errors instead of aborting
MPI_Win_set_errhandler(win, MPI_ERRORS_RETURN);
if (rank != 0) {
do {
// Query the shared memory of rank 0
int *baseptr;
MPI_Aint queried_size;
int disp_unit;
ret = MPI_Win_shared_query(win, 0, &queried_size, &disp_unit, &baseptr);
if (ret != MPI_SUCCESS) {
printf("%s: rank %d: MPI_Win_shared_query failed with error code %d\n", test_name, rank, ret);
ret = MPI_ERR_OTHER;
break;
}

if (baseptr == NULL) {
printf("%s: rank %d: MPI_Win_shared_query returned NULL\n", test_name, rank);
if (queried_size != 0) {
printf("%s: rank %d: Expected zero size but got %zu\n", test_name, rank, queried_size);
}
ret = MPI_ERR_NO_MEM;
break;
}

if (queried_size != shared_size) {
printf("%s: rank %d: Queried size mismatch: expected %d, got %zu\n", test_name, rank, shared_size, queried_size);
Comment on lines +31 to +38
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format specifier %zu is used for MPI_Aint queried_size, but MPI_Aint is not guaranteed to be the same type as size_t. Use %ld with a cast to long or check the MPI implementation's recommended format specifier for MPI_Aint.

Suggested change
printf("%s: rank %d: Expected zero size but got %zu\n", test_name, rank, queried_size);
}
ret = MPI_ERR_NO_MEM;
break;
}
if (queried_size != shared_size) {
printf("%s: rank %d: Queried size mismatch: expected %d, got %zu\n", test_name, rank, shared_size, queried_size);
printf("%s: rank %d: Expected zero size but got %ld\n", test_name, rank, (long)queried_size);
}
ret = MPI_ERR_NO_MEM;
break;
}
if (queried_size != shared_size) {
printf("%s: rank %d: Queried size mismatch: expected %d, got %ld\n", test_name, rank, shared_size, (long)queried_size);

Copilot uses AI. Check for mistakes.

Comment on lines +31 to +38
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format specifier %zu is used for MPI_Aint queried_size, but MPI_Aint is not guaranteed to be the same type as size_t. Use %ld with a cast to long or check the MPI implementation's recommended format specifier for MPI_Aint.

Suggested change
printf("%s: rank %d: Expected zero size but got %zu\n", test_name, rank, queried_size);
}
ret = MPI_ERR_NO_MEM;
break;
}
if (queried_size != shared_size) {
printf("%s: rank %d: Queried size mismatch: expected %d, got %zu\n", test_name, rank, shared_size, queried_size);
printf("%s: rank %d: Expected zero size but got %ld\n", test_name, rank, (long)queried_size);
}
ret = MPI_ERR_NO_MEM;
break;
}
if (queried_size != shared_size) {
printf("%s: rank %d: Queried size mismatch: expected %d, got %ld\n", test_name, rank, shared_size, (long)queried_size);

Copilot uses AI. Check for mistakes.

ret = MPI_ERR_SIZE;
break;
}

// Write data to the shared memory
baseptr[rank] = 42;

} while (false);
}

int *ret_vals = (int *)malloc(size * sizeof(int));
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check after malloc. If malloc fails and returns NULL, the subsequent MPI_Gather call will cause undefined behavior.

Suggested change
int *ret_vals = (int *)malloc(size * sizeof(int));
int *ret_vals = (int *)malloc(size * sizeof(int));
if (ret_vals == NULL) {
printf("%s: rank %d: malloc for ret_vals failed\n", test_name, rank);
ret = MPI_ERR_NO_MEM;
// Use MPI_Gather with a NULL recvbuf only on non-root, or skip entirely
// To avoid undefined behavior, we return early
return;
}

Copilot uses AI. Check for mistakes.

MPI_Gather(&ret, 1, MPI_INT, ret_vals, 1, MPI_INT, 0, comm);
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak: ret_vals is allocated but never freed. Add free(ret_vals) after the MPI_Gather operation and result processing.

Copilot uses AI. Check for mistakes.


if (rank == 0) {
int valid_procs = size - 1; // Exclude rank 0
bool all_success = true;
for (int i = 1; i < size; ++i) {
if (ret_vals[i] != MPI_SUCCESS) {
valid_procs--;
continue; // Skip ranks that had errors
}
// Check if the data was written correctly
if (local_mem[i] != 42) {
all_success = false;
printf("%s: rank 0: Data verification failed at %d!\n", test_name, i);
}
}
if (all_success && valid_procs > 0) {
printf("%s: rank 0: all data written correctly!\n", test_name);
}
}
}

int main(int argc, char *argv[]) {
MPI_Init(&argc, &argv);

int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

int shared_size;
int shared_rank;
MPI_Comm comm_shared;
MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &comm_shared);
MPI_Comm_rank(comm_shared, &shared_rank);
MPI_Comm_size(comm_shared, &shared_size);

// Test with MPI_Win_allocate_shared
MPI_Win win_shared;
int *shared_mem_shared = NULL;
int win_size = size*sizeof(int);
MPI_Win_allocate_shared(shared_rank == 0 ? sizeof(int)*shared_size : 0, sizeof(int), MPI_INFO_NULL, comm_shared, &shared_mem_shared, &win_shared);
test_shared_memory(win_shared, comm_shared, shared_mem_shared, sizeof(int)*shared_size, "MPI_Win_allocate_shared");
MPI_Win_free(&win_shared);

// Test with MPI_Win_allocate
MPI_Win win_allocate;
int *shared_mem_allocate = NULL;
MPI_Win_allocate(rank == 0 ? win_size : 0, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &shared_mem_allocate, &win_allocate);
test_shared_memory(win_allocate, MPI_COMM_WORLD, shared_mem_allocate, win_size, "MPI_Win_allocate");
MPI_Win_free(&win_allocate);

// Test with MPI_Win_create
MPI_Win win_create;
int* local_mem = (int*)malloc(sizeof(int) * win_size);
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check after malloc. If malloc fails and returns NULL, the subsequent MPI_Win_create call may cause undefined behavior.

Suggested change
int* local_mem = (int*)malloc(sizeof(int) * win_size);
int* local_mem = (int*)malloc(sizeof(int) * win_size);
if (local_mem == NULL) {
fprintf(stderr, "Error: malloc failed for local_mem in MPI_Win_create test\n");
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}

Copilot uses AI. Check for mistakes.

MPI_Win_create(rank == 0 ? local_mem : NULL, rank == 0 ? win_size : 0, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &win_create);
test_shared_memory(win_create, MPI_COMM_WORLD, local_mem, win_size, "MPI_Win_create");
MPI_Win_free(&win_create);
free(local_mem);

MPI_Finalize();
return 0;
}