performance/message.c

///////////////////////////////////////////////////////////////////////////////
// Filename: message.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: measure how long it takes to send/receive SYSV IPC messages
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/02 02:30:17 muellerg: created
//
///////////////////////////////////////////////////////////////////////////////


// Feature test switches ///////////////////////////// Feature test switches //
    /* NONE */



// System headers /////////////////////////////////////////// System headers //

#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>


// Local headers ///////////////////////////////////////////// Local headers //

#include "../common.h"



// Macros /////////////////////////////////////////////////////////// Macros //
    /* NONE */



// File scope objects /////////////////////////////////// File scope objects //

const int NUMBER_REPEAT = 10000;        // how often for measurements

#ifndef MSGMAX
#define MSGMAX 2048
#endif

const int size_max = MSGMAX;            // maximum size of messages

const int MSG_MODE = 0666; // MSG_R | MSG_W;        // read and write

const int measure_max = 32;             // maximum number of measurements



// External variables, functions, and classes ///////////// External objects //
    /* NONE */



// Signal catching functions ///////////////////// Signal catching functions //
    /* NONE */



// Structures, unions, and class definitions /////////////////// Definitions //
    /* NONE */



// Functions and class implementation /// Functions and class implementation //
    /* NONE */



// Main /////////////////////////////////////////////////////////////// Main //


int
main(int argc, char *argv[])
{
    error.set_program_name(argv[0]);    

    int i;


    // do some performance measurements

    // check size

#ifdef linux
    if( size_max > MSGMAX)
        error.panic("MSGMAX too small, reduce size_max!");
#endif

    // create message queue

    int msgid = msgget(IPC_PRIVATE, MSG_MODE);
    if(msgid == -1)
        error.system("msgget error");


    synchronization_init();

    // get buffer which we can work

    struct msgbuf *buffer = (struct msgbuf *)malloc(size_max+4);
                             // +4 for long at beginning of buffer
    if(!buffer)
        error.panic("out of memory");

    // set type (priority)
    buffer->mtype = 1;      // has to be positive

    
    pid_t childpid;
    int size;

    childpid = fork();
    if(childpid == -1)
        error.system("fork error");

    if(childpid == 0)
    {
        // child, will receive data from parent

        for(size = 1; size <= size_max; size*=2)
        {
            for(i = 0; i < NUMBER_REPEAT; i++)
            {
                if( msgrcv(msgid, buffer, size_max+4, 0, 0) == -1)
                    error.system("msgrcv error");
            }
        }

        synchronization_signal_parent(getppid());
    }
    else
    {
        // parent, will send data to child

        measurement mes(argv[0], "write", measure_max);

        for(size = 1; size <= size_max; size*=2)
        {
            // start timer
            mes.start(size, NUMBER_REPEAT);

            for(i = 0; i < NUMBER_REPEAT; i++)
            {
                if( msgsnd(msgid, buffer, size, 0) == -1)
                    error.system("msgsnd error");
            }

            // end timer
            mes.end();
        }


        // wait till child has read all data
        synchronization_wait();

        mes.writeout_logfile(true, true, true);     // use cout as output file
        mes.writeout_plain_logfile(true, false);    // and write gnuplot data file

        // destroy message queue    

        if(msgctl(msgid, IPC_RMID, NULL) == -1)
            error.system("msgctl error");
    }

    if(buffer)
        free(buffer);

    return(EXIT_SUCCESS);
}