Skip to content

Instantly share code, notes, and snippets.

@stetro
Created June 1, 2012 13:02
Show Gist options
  • Save stetro/2851989 to your computer and use it in GitHub Desktop.
Save stetro/2851989 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>
#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!"
#define FORK_ERROR "fork() konnte keinen Kindprozess erzeugen!"
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;
unsigned short marker[1];
sem_id = semget (IPC_PRIVATE, 1, IPC_CREAT|0644); /*anlegen*/
if(sem_id == -1)
{
fprintf(stderr,"Fehler bei Semaphore !\n");
return EXIT_FAILURE;
}
marker[0] = 1;
semctl(sem_id, 1, SETALL, marker);
/* PIDs der Kindprozesse*/
int pid[2];
/* Shared Memorys generieren und bei Fehlern aussteigen*/
double *area,id;
int *sperr_fuer_kind,id_sperr;
id = shmget( IPC_PRIVATE, 2*sizeof(double),0600);
if(id == -1)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
id_sperr = shmget( IPC_PRIVATE , sizeof(int),0600);
if(id_sperr == -1)
{
fprintf(stderr,SHM_ERROR);
return EXIT_FAILURE;
}
area = (double*)shmat(id,0,0);
if(area == NULL)
{
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;
}
/* 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)
{
semop(sem_id,&enter,1); /* Eintritt in kritischen Bereich*/
if(*sperr_fuer_kind == 1 && *area > 0){
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/
continue;
}
if(*area > 0)
{
*area -= FUSS_A;
}else{break;}
*sperr_fuer_kind = 1;
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/
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)
{
semop(sem_id,&enter,1); /* Eintritt in kritischen Bereich*/
if(*sperr_fuer_kind == 2 && *area > 0){
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/
continue;
}
if(*area > 0)
{
*area -= FUSS_B;
}else{break;}
*sperr_fuer_kind = 2;
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/
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