Skip to content

Instantly share code, notes, and snippets.

@stetro
Forked from stetro/pisspott2.c
Created June 4, 2012 15:16
Show Gist options
  • Save stetro/2868994 to your computer and use it in GitHub Desktop.
Save stetro/2868994 to your computer and use it in GitHub Desktop.
Piss Pott Ohne Raceconditions mit Semaphoren
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#define MAXCOUNT ((FUSS_B+FUSS_A)*17)
#define FUSS_B 15.51337
#define FUSS_A 13.13123
#define SHM_ERROR "Shared Memory konnte nicht erstellt werden!\n"
#define FORK_ERROR "fork() konnte keinen Kindprozess erzeugen!\n"
#define SEM_ERROR "Fehler bei Semaphore !\n"
int main(int argc, char * argv[])
{
/* Hilfsvariablen*/
int i, sleep_time;
if(argc <= 1)
{
fprintf(stderr,"Zeit in us angeben !\n");
return EXIT_FAILURE;
}
sleep_time = strtol(argv[1],NULL,10);
/* Semaphore initialisieren*/
int sem_id,sem_check;
unsigned short marker[1];
sem_id = semget (IPC_PRIVATE, 1, IPC_CREAT|0644); /*anlegen*/
if(sem_id == -1)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
marker[0] = 1;
sem_check=semctl(sem_id, 1, SETALL, marker);
if(sem_check < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
/* PIDs der Kindprozesse*/
int pid[2];
/*Shared Memory fuer IPS*/
int *sperr_fuer_kind,id_sperr,id;
id_sperr = shmget( IPC_PRIVATE, sizeof(int),0600);
if(id_sperr == -1)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
sperr_fuer_kind = (int*)shmat(id_sperr,0,0);
if(sperr_fuer_kind == NULL)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
/*Shared Memory fuer PissPott*/
double *area;
id = shmget( IPC_PRIVATE, sizeof(double),0600);
if(id == -1)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
area = (double*)shmat(id,0,0);
if(area == NULL)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
/* Semaphore Strukturen zum sperren und freigeben*/
struct sembuf enter, leave;
enter.sem_num = 0; /* Semaphor 0 in der Gruppe*/
enter.sem_op = -1; /* blockieren*/
enter.sem_flg = SEM_UNDO;
leave.sem_num = 0; /* Semaphor 0 in der Gruppe*/
leave.sem_op = 1; /* freigeben*/
leave.sem_flg = SEM_UNDO;
/* Bereich zuruecksetzen*/
*area = MAXCOUNT;
*sperr_fuer_kind = 0;
/* 1 Kindprozesse erzeugen*/
pid[0] = fork();
if(pid[0] == -1)
{
fprintf(stderr,FORK_ERROR);
return EXIT_FAILURE;
}
if(pid[0] == 0) /* KIND 1*/
{
while(1)
{
/*KRITISCHER BEREICH BETRETEN*/
if( semop(sem_id,&enter,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
if(*sperr_fuer_kind == 1 && *area > 0){
/*KRITISCHER BEREICH VERLASSEN*/
if( semop(sem_id,&leave,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
continue;
}
if(*area > 0)
{
*area -= FUSS_A;
}else{break;}
*sperr_fuer_kind = 1;
/*KRITISCHER BEREICH VERLASSEN*/
if( semop(sem_id,&leave,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
printf("POTT - %lf\n",*area);
fflush(stdout);
usleep(sleep_time);
}
return EXIT_SUCCESS;
}
else
{
/* 2 Kindprozesse erzeugen*/
pid[1] = fork();
if(pid[1] == -1)
{
fprintf(stderr,FORK_ERROR);
return EXIT_FAILURE;
}
if(pid[1] == 0) /* KIND 2*/
{
while(1)
{
/*KRITISCHER BEREICH BETRETEN*/
if( semop(sem_id,&enter,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
if(*sperr_fuer_kind == 2 && *area > 0){
/*KRITISCHER BEREICH VERLASSEN*/
if( semop(sem_id,&leave,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
continue;
}
if(*area > 0)
{
*area -= FUSS_B;
}else{break;}
*sperr_fuer_kind = 2;
/*KRITISCHER BEREICH VERLASSEN*/
if( semop(sem_id,&leave,1) < 0)
{
fprintf(stderr,SEM_ERROR);
return EXIT_FAILURE;
}
printf("PISS - %lf\n",*area);
fflush(stdout);
usleep(sleep_time);
}
return EXIT_SUCCESS;
}
/* VATER wartet auf alle Kinder*/
for(i=0;i<2;i++)
{
waitpid(*(pid+i),NULL,0);
}
}
/* Semaphore freigeben*/
semctl(sem_id, 0, IPC_RMID);
/* ENDE*/
/* return EXIT_SUCCESS;*/
if(*area < 0.1 && *area > -0.1)
{
/* Shared Memory loesen*/
shmdt(area);
shmdt(sperr_fuer_kind);
shmctl(id, IPC_RMID, 0);
shmctl(id_sperr, IPC_RMID, 0);
printf("OK\n");
return EXIT_SUCCESS;
}
else
{
/* Shared Memory loesen*/
shmdt(area);
shmdt(sperr_fuer_kind);
shmctl(id, IPC_RMID, 0);
shmctl(id_sperr, IPC_RMID, 0);
printf("Nicht OK\n");
return EXIT_FAILURE;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment