performance/memory.c
///////////////////////////////////////////////////////////////////////////////
// Filename: memory.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: measure the throughput of memory in normal memory and shared
//          memory
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/17 02:33:04 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/shm.h>
// Local headers ///////////////////////////////////////////// Local headers //
#include "../common.h"
// Macros /////////////////////////////////////////////////////////// Macros //
// #define READMEMORY 1 
                        /* most compilers fool this test, as they optimize
                           the operations so that the results are not
                           meaningful. The assembler source code was
                           checked that this is not the case for the write */
// File scope objects /////////////////////////////////// File scope objects //
const int NUMBER_REPEAT = 100;          // how often to do measurements
const int SHM_SIZE = 1024*1024;         // shared and normal memory size, 1 MB
const int SHM_MODE = (SHM_R | SHM_W);   // user read/write
// 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 //
/*
 * perform measurements with memory pointed to by ptr
 */
void writememory(char *ptr, char *prgname, char *comment)
{
    register long *mem;
    register long i = 0;
    register long value = 0;
    measurement mes(prgname, "write", NUMBER_REPEAT);
    int numberoftimes = SHM_SIZE/(sizeof(long) * 64);
    // make sure that memory is attached and eventually partly cached
    for(char *p=ptr; i < SHM_SIZE; i++)
        p[i]=255;   
#ifdef READMEMORY
    cout << "\nWrite to memory" << endl;
#endif
    for(int n=0; n < NUMBER_REPEAT; n++)
    {
        mem = (long *)ptr;
        mes.start(-1, 0, comment);
        // a little bit of loop unrolling
        // this writes 256 bytes if sizeof(long) is 4 bytes
    
        for(i=0; i < numberoftimes; i++)
        {
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
        }
        mes.end();
    }
    mes.writeout_histogram(true);
#ifdef READMEMORY
    measurement mes2(prgname, "read", NUMBER_REPEAT);
    
    cout << "\nRead from memory" << endl;
    for(int n=0; n < NUMBER_REPEAT; n++)
    {
        mem = (long *)ptr;
        mes2.start(-1, 0, comment);
        // a little bit of loop unrolling
        // this reads 256 bytes if sizeof(long) is 4 bytes
    
        for(i=0; i < numberoftimes; i++)
        {
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
        }
        mes2.end();
    }
    mes2.writeout_histogram(true);
#endif /* READMEMORY */
}
// Main /////////////////////////////////////////////////////////////// Main //
int
main(int argc, char *argv[])
{
    error.set_program_name(argv[0]);    
    cout << "This program measures the throughput of normal and shared memory."
         << "\nAll measurements are done " << NUMBER_REPEAT << " times with "
         << "memory regions\nof the size " << SHM_SIZE << " bytes.\n" << endl;
    // two measurements: one in normal memory, one in shared
    // normal memory
    char *mem= new char[SHM_SIZE];
    writememory(mem, argv[0], "Normal Memory:");
    delete[] mem;
    cout << endl;
    // shared memory
    int shmid;  
    char *shmptr;
    // get shared memory region
    if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) == -1)
        error.system("shmget error");
    if ((shmptr = (char *)shmat(shmid, 0, 0)) == (char *)-1)
        error.system("shmat error");
    writememory(shmptr, argv[0], "Shared memory:");         
    // destroy shared memory region
    if (shmdt(shmptr) == -1)
        error.system("shmdt error");
        
    if (shmctl(shmid, IPC_RMID, 0) == -1)
        error.system("shmctl error");
    return(EXIT_SUCCESS);
}