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);
}