Toms deadlock.c

From Education

Jump to: navigation, search
#include <mpi.h>
#include <stdio.h>
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 0 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);
}
SC Education sites