#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include "my_shm.h"
#include "my_sem.h"
#define NO_ACTION -1
#define CREATE_SHM 0
#define GET_SHM 1
#define NUMBER_OF_SEM 3
#define ELEMENT 0
#define SPACE 1
#define START 2
int main (int argc, char *argv[])
{
int ipc_key, shm_size, action, cr, sem_number, sem_values[NUMBER_OF_SEM], data, max_data;
if (argc != 5)
{
fprintf (stderr, "\nUsage: shm.test <IPC key (shm and sem)> <SHM size> <action> <max data>");
fprintf (stderr, "\n -- if 'IPC key' is equal to -1, then the system choose the IPC keys");
fprintf (stderr, "\n -- 'action' could be 'create' or 'get'");
fprintf (stderr, "\n");
return 1;
}
ipc_key = atoi(argv[1]);
shm_size = atoi(argv[2]);
sem_number = NUMBER_OF_SEM;
max_data = atoi(argv[4]);
action = NO_ACTION;
if (strcmp(argv[3], "create") == 0) { action = CREATE_SHM; }
if (strcmp(argv[3], "get") == 0) { action = GET_SHM; }
if (action == NO_ACTION)
{
fprintf (stderr, "\nInvalid action (must be 'create' or 'get')\n");
return 1;
}
switch (action)
{
case CREATE_SHM:
{
fprintf (stdout, "\nProductor: Create Shared Memory Segment\n"); fflush (stdout);
cr = create_shared_memory_segment ((key_t)ipc_key, shm_size);
switch (cr)
{
case CREATE_SHM_ALREADY_CREATED:
fprintf (stderr, "\nCan not create SHM: already created\n");
return 1;
case CREATE_SHM_ERROR:
fprintf (stderr, "\nCan not create SHM: system error - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\nProductor: Create set of semaphores\n"); fflush (stdout);
cr = create_semaphore_set ((key_t)ipc_key+1, sem_number);
switch (cr)
{
case CREATE_SEMAPHORE_CREATE_ERROR:
fprintf (stderr, "\nCan not create SEM - %s\n", strerror(errno));
return 1;
case CREATE_SEMAPHORE_SET_VAL_ERROR:
fprintf (stderr, "\nCan not set SEM values - %s\n", strerror(errno));
return 1;
}
}; break;
case GET_SHM:
{
fprintf (stdout, "\nConsumer: Get Shared Memory Segment\n"); fflush (stdout);
cr = get_shared_memory_segment_sys_id ((key_t)ipc_key, shm_size);
switch (cr)
{
case GET_SHM_ALREADY_GET:
fprintf (stderr, "\nCan not get SHM's id: already get\n");
return 1;
case GET_SHM_ERROR:
fprintf (stderr, "\nCan not get SHM's id: system error - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\nConsumer: Get set of semaphores\n"); fflush (stdout);
cr = get_semaphore_set ((key_t)ipc_key+1, 2);
switch (cr)
{
case GET_SEM_ALREADY_GET:
fprintf (stderr, "\nCan not get SEM - The process already got the semaphores\n");
return 1;
case GET_SEM_ERROR:
fprintf (stderr, "\nError while getting set of semaphores - %d - %s\n", errno, strerror(errno));
return 1;
}
}; break;
}
if (attache_shared_memory_segment() == (SHM_addr)-1)
{
fprintf (stderr, "\nError while attaching the SHM - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\n");
fprintf (stdout, "\nProcess ID is: %d", (int)getpid());
fprintf (stdout, "\nSHM system ID is: %d", get_shared_memory_segment_id());
fprintf (stdout, "\nSHM bind address is: %0X", (unsigned int)attache_shared_memory_segment());
fprintf (stdout, "\nAttachemant number is: %d", (int)(get_shm_info()->shm_nattch));
fprintf (stdout, "\n");
memset ((void*)get_shm_address(), 0, shm_size);
if (action == CREATE_SHM)
{
fprintf (stdout, "\nProductor: Set ELEMENT value to 0");
fprintf (stdout, "\nProductor: Set SPACE value to 1");
fprintf (stdout, "\nProductor: Set START value to 0 and take it => I should go to sleep");
fflush (stdout);
sem_values[ELEMENT] = 0;
sem_values[SPACE] = 1;
sem_values[START] = 0;
cr = set_semaphore_values (sem_values);
switch(cr)
{
case SET_SEM_VALUES_SEM_NOT_CREATED:
fprintf (stderr, "\nProductor: Error while setting semaphores' values - Semaphores not created\n");
return 1;
case SET_SEM_VALUES_SET_ERROR:
fprintf (stderr, "\nProductor: Error while setting semaphores' values - %s\n", strerror(errno));
return 1;
}
if (take_sem(START) == -1)
{
fprintf (stderr, "\nProductor: Error while tacking START - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\nProductor (%d): I have START!", (int)getpid());
fflush (stdout);
}
if (action == GET_SHM)
{
fprintf (stdout, "\nConsumer: Set START to 1, this should awake the productor ...\n");
fflush (stdout);
cr = set_semaphore_value (1, START);
switch(cr)
{
case SET_SEM_VALUES_SEM_NOT_CREATED:
fprintf (stderr, "\nConsumer: Error while setting START to 1 - Semaphores not get\n");
return 1;
case SET_SEM_VALUES_SET_ERROR:
fprintf (stderr, "\nConsumer: Error while setting START to 1 - %s\n", strerror(errno));
return 1;
}
}
data = 0;
while(data != -1)
{
if (action == CREATE_SHM)
{
if (take_sem(SPACE) == -1)
{
fprintf (stderr, "\nProductor: Error while tacking PLACE - %s\n", strerror(errno));
return 1;
}
if (data > max_data) { data = -1; }
memcpy ((void*)get_shm_address(), (void*)&data, sizeof(int));
sleep (1);
if (release_sem(ELEMENT) == -1)
{
fprintf (stderr, "\nProductor: Error while releasing ELEMENT - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\nProductor: %d", data);
fflush(stdout);
if (data != -1) { data++; }
}
if (action == GET_SHM)
{
if (take_sem(ELEMENT) == -1)
{
fprintf (stderr, "\nConsumer: Error while getting ELEMENT - %s\n", strerror(errno));
return 1;
}
memcpy ((void*)&data, (void*)get_shm_address(), sizeof(int));
if (release_sem(SPACE) == -1)
{
fprintf (stderr, "\nConsumer: Error while releasing PLACE - %s\n", strerror(errno));
return 1;
}
fprintf (stdout, "\nConsumer: %d", data);
fflush(stdout);
}
}
if (action == CREATE_SHM)
{
fprintf (stdout, "\nProductor: exit now\n\n");
if (set_shm_auto_destroy() == -1)
{
fprintf (stderr, "\nProductor: Error while setting SHM into auto-destry mode - %s\n", strerror(errno));
return 1;
}
if (detache_shm() == -1)
{
fprintf (stderr, "\nProductor: Error while detaching SHM - %s\n", strerror(errno));
return 1;
}
if (release_sem(START) == -1)
{
fprintf (stderr, "\nProductor: Error while releasing START - %s\n", strerror(errno));
return 1;
}
return 0;
}
if (action == GET_SHM)
{
if (take_sem(START) == -1)
{
fprintf (stderr, "\nConsumer: Error while tacking START - %s\n", strerror(errno));
return 1;
}
if (destroy_semaphore_set() == -1)
{
fprintf (stderr, "\nConsumer: Error while destroying the set of semaphores - %s\n", strerror(errno));
return 1;
}
if (detache_shm() == -1)
{
fprintf (stderr, "\nConsumer: Error while detaching SHM - %s\n", strerror(errno));
return 1;
}
}
return 0;
}