#include #include void Usage(char *msg, char *prog); void Send(int rank, int size, int msgLen, int mode, char modeChar); void Recv(int rank, int size, int msgLen); void checkParameters(int *msgLen, int *order, int *mode, int argc, char **argv, int size, char orderChar, char modeChar); #define MAX_ARRAY_LENGTH 800000 #define modeB 0 #define modeR 1 #define modeS 2 #define modeV 3 #define orderR 0 #define orderS 1 #define orderA 2 #define tag 42 /* * compile -> mpicc -o deadlock deadlock.c * run -> mpirun -np 2 deadlock S 10 S * */ int main(int argc, char **argv) { int mode = -1, order=2; int size, rank, msgLen; char orderChar, modeChar; int *buffer; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); orderChar = *(argv[1]); modeChar = *(argv[3]); checkParameters(&msgLen, &order, &mode, argc, argv, size, orderChar, modeChar); if (mode == modeB) { buffer = (int *)malloc(MPI_BSEND_OVERHEAD + msgLen*sizeof(int)); MPI_Buffer_attach(buffer, MPI_BSEND_OVERHEAD + msgLen); } if ((order != orderR) && (rank || (order == orderS))) { Send(rank,size,msgLen, mode, modeChar); Recv(rank,size,msgLen); } else { Recv(rank,size,msgLen); Send(rank,size,msgLen, mode, modeChar); } MPI_Finalize(); return(0); } void Recv(int rank, int size, int msgLen) { MPI_Status status; int retVal, buffer_in[MAX_ARRAY_LENGTH]; fprintf(stderr,"\n%d/%d: receiving %d\n", rank, size, msgLen); retVal = MPI_Recv(buffer_in, MAX_ARRAY_LENGTH, MPI_INT, 1-rank, tag, MPI_COMM_WORLD, &status); fprintf(stderr, "%d/%d: received %d\n", rank, size, retVal); } void Send(int rank, int size, int msgLen, int mode, char modeChar) { MPI_Status status; int retVal, buffer_out[MAX_ARRAY_LENGTH]; fprintf(stderr,"\n%d/%d: sending %d in mode %c\n", rank, size, msgLen, modeChar); switch (mode) { case modeB: retVal = MPI_Bsend(buffer_out, msgLen, MPI_INT, 1-rank, tag, MPI_COMM_WORLD); break; case modeR: retVal = MPI_Rsend(buffer_out, msgLen, MPI_INT, 1-rank, tag, MPI_COMM_WORLD); break; case modeS: retVal = MPI_Ssend(buffer_out, msgLen, MPI_INT, 1-rank, tag, MPI_COMM_WORLD); break; case modeV: retVal = MPI_Send(buffer_out, msgLen, MPI_INT, 1-rank, tag, MPI_COMM_WORLD); break; } fprintf(stderr, "%d/%d: sent %d\n", rank, size, retVal); } void checkParameters(int *msgLen, int *order, int *mode, int argc, char **argv, int size, char orderChar, char modeChar) { char errbuf[200]; if (size != 2) { sprintf(errbuf, "wrong number of processes (%d)", size); Usage(errbuf, argv[0]); } if (argc < 3) { sprintf(errbuf, "wrong number of arguments (%d)", argc); Usage(errbuf, argv[0]); } switch (orderChar) { case 's': case 'S': *order = orderS; break; case 'R': case 'r': *order = orderR; break; case 'A': case 'a': *order = orderA; break; default: sprintf(errbuf, "unrecognized order=%c", orderChar); Usage(errbuf, argv[0]); } if (!sscanf(argv[2], "%d", msgLen) || *msgLen < 1 || *msgLen > MAX_ARRAY_LENGTH) { sprintf(errbuf, "msgLen out of bounds=%s", argv[2]); Usage(errbuf, argv[0]); } switch (modeChar) { case 'B': case 'b': *mode = modeB; break; case 'R': case 'r': *mode = modeR; break; case 'S': case 's': *mode = modeS; break; case 'V': case 'v': *mode = modeV; break; default: sprintf(errbuf, "unrecognized mode=%c", modeChar); Usage(errbuf, argv[0]); } } void Usage(char *msg, char *prog) { printf("\n%s\nUsage: %s order msgLen mode\n", msg, prog); printf("\twhere\n"); printf("\t\torder is R(receive first), S(send first), or A(alternate)\n"); printf("\t\tmsgLen can be 1 to %d\n", MAX_ARRAY_LENGTH); printf("\t\tmode is B(Buffered), R(Ready), S(Synchronous), or V(Standard)\n"); exit(1); }