performance/semaphore.c

///////////////////////////////////////////////////////////////////////////////
// Filename: semaphore.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: measure how fast semaphore operations are
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/01 13:49:41 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/sem.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


const int SEM_MODE = 0666;           // SEM_R | SEM_A;  // read and alter



// 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( NUMBER_REPEAT > SEMVMX)
        error.panic("SEMVMX too small, reduce NUMBER_REPEAT!");
#endif

    // create semaphore

    int semid = semget(IPC_PRIVATE, 1, SEM_MODE);
    if(semid == -1)
        error.system("semget error");


    // set to initial value

#ifdef linux
    semun initial_value;
#else
    union semun {
        int val;
        struct semid_ds *buf;
        ushort *array;
    } initial_value;
#endif

    initial_value.val = 0;

    if( semctl(semid, 0, SETVAL, initial_value) == -1)
        error.system("semctl error");


    // initialize default values

    struct sembuf op;
    op.sem_num = 0;     // member number (we only have number 0)
    op.sem_op  = 1;     // inc
    op.sem_flg = 0;     // no flags


    measurement mes(argv[0], "mes", 4);


    // do measurements without undo


    // start timer
    mes.start(-1, NUMBER_REPEAT, "Measuring semop() +1 operations without undo");

    for(i=0; i < NUMBER_REPEAT; i++)
    {
        if( semop(semid, &op, 1) == -1)
            error.system("semop error");
    }

    // end timer
    mes.end();


    // now do the reverse..

    op.sem_op = -1;     // dec

    // start timer
    mes.start(-1, NUMBER_REPEAT, "Measuring semop() -1 operations without undo");

    for(i=0; i < NUMBER_REPEAT; i++)
    {
        if( semop(semid, &op, 1) == -1)
            error.system("semop error");
    }

    // end timer
    mes.end();



    // do measurements with undo

    op.sem_op  = 1;         // inc
    op.sem_flg = SEM_UNDO;  // remeber change if program crashes or exit()s

    // start timer
    mes.start(-1, NUMBER_REPEAT, "Measuring semop() +1 operations with undo");

    for(i=0; i < NUMBER_REPEAT; i++)
    {
        if( semop(semid, &op, 1) == -1)
            error.system("semop error");
    }

    // end timer
    mes.end();


    // now do the reverse..

    op.sem_op = -1;     // dec

    // start timer
    mes.start(-1, NUMBER_REPEAT, "Measuring semop() -1 operations with undo");

    for(i=0; i < NUMBER_REPEAT; i++)
    {
        if( semop(semid, &op, 1) == -1)
            error.system("semop error");
    }

    // end timer
    mes.end();



    // destroy semaphore    

#ifdef linux
    union semun nop;
#else
    int nop=0;
#endif

    if(semctl(semid, 0, IPC_RMID, nop) == -1)
        error.system("semctl error");


    mes.writeout_logfile(false, true, true);    // use cout for output


    return(EXIT_SUCCESS);
}