noman13 0 Newbie Poster

Hi guys,
I need help with this code, I am trying to figure out how can I add semaphores to this code in order to have just one at a time accessing the shared memory.

Thanks,

/* elevator.c
	The elevator process starts a people process which runs
	independently, except that the processes share some memory.
	The elevator runs up and down, stopping when it has people
	to pick up or let off at a floor. The people process
	occasionally brings a new person into the system at a randomly
	chosen floor, letting the elevator know whether that person is
	going up or down.
*/
/* Program has major problem - access to shared memory needs to be
   one at a time - add semaphores later. */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <signal.h>

#define FLOORS (5)
#define ELEVATOR_SPEED (3)
void elevator();
void people();

struct shared_info {
	int going_up[FLOORS];
	int going_down[FLOORS];
	int total_number;
};

struct shared_info * people_data; /* data shared by parent and child */ 
int shared_memory_id;

void handle(int sig)
{
	/* Remove the shared memory segment from the system. */
	shmctl(shared_memory_id, IPC_RMID, NULL);
	exit(0);
}

void main(void)
{
	int floor;
	pid_t fork_return;

	/* Get and attach the shared memory segment. */
	shared_memory_id = shmget(IPC_PRIVATE, sizeof(struct shared_info),
		0600);
	if (shared_memory_id < 0) {
		perror("Cannot get shared memory");
		exit(1);
	}
	
	/* Ensure that shared memory segment gets removed when
	   we go away. */
	signal(SIGINT, handle);
	signal(SIGQUIT, handle);

	people_data = (struct shared_info *) shmat( shared_memory_id,
			0, 0);
	if((void *)people_data < (void *) 0){
		perror("Cannot attach shared memory");
		exit(1);
	}

	/* Initialize people_data to no people in system. */
	for( floor = 0; floor < FLOORS; floor++){
		(people_data -> going_up)[floor] = 0;
		(people_data -> going_down)[floor] = 0;
		people_data -> total_number = 0;
	}
	

	/* fork the people process */
	fork_return = fork();

	switch(fork_return){
		case 0:	people();
		case -1: perror("Cannot fork child");
			 exit(1);
		default: elevator();
	}
}

void elevator()
{
	/* Number of people on elevator wanting to get off at each floor. */
	int getting_off[FLOORS];
	int total_on_board;

	/* Elevator's current direction. */
#define UP (1)
#define DOWN (0)
	int direction = UP;

	/* Elevator's current floor. */
	int floor = 0;
	int new_on;
	int i;
	int flag1, flag2;

	for(i = 0; i < FLOORS; i++)
		getting_off[i] = 0;
	/* Seed random numbers */
	srand(getpid());

	printf("Elevator starting.\n");
	while( 1)
	{
		/* If no one wants to go anywhere... */
		if( total_on_board == 0 && people_data -> total_number == 0){
			/* Just sleep a bit and try again. */
			sleep(1);
		}
		else {
						
								
			/* Let people going in our direction on. */
			if( direction == UP) 
			{
				new_on = (people_data -> going_up)[floor];
				(people_data -> going_up)[floor] -= new_on;
				people_data -> total_number -= new_on;
				total_on_board += new_on;
				/* Random destination for each person. */
				for( i = 0; i < new_on; i++)
					getting_off[ floor +
						rand()%(FLOORS - floor - 1) 
						+ 1]++;
			
			}
			else
			{
									
				new_on = (people_data -> going_down)[floor];
				(people_data -> going_down)[floor] -= new_on;
				people_data -> total_number -= new_on;
				total_on_board += new_on;
				/* Random destination for each person. */
				for( i = 0; i < new_on; i++)
					getting_off[ floor -
						rand()%( floor ) - 1]++;
			}
			if( new_on)
				printf("%d %s got on at floor %d.\n",
					new_on, 
					new_on > 1 ? "people" : "person", 
					floor);

			/* If nothing is going to happen in the direction
			   we are going, then change direction. */
			flag1 = 0;
			flag2 = 0;
			if(direction == UP){
				for(i = floor; i < FLOORS; i++)
				   if(getting_off[i] || 
				      people_data -> going_up[i] ||
				      people_data -> going_down[i])
				   {
					flag1 = 1;
					break;
				   }
				if( !flag1 )
				   direction = DOWN;
			}
			else{
				for(i = floor; i >= 0; i--)
				   if(getting_off[i] || 
				      people_data -> going_up[i] ||
				      people_data -> going_down[i])
				   {
					flag2 = 1;
					break;
				   }
				if( !flag2 )
				   direction = UP;
			}
	

			/* Travel to next floor. */
			/* Elevator is not instantaneous. */
			if( flag1 || flag2) {
				sleep(ELEVATOR_SPEED);
				direction == UP ? floor++ : floor--;

				if( floor == FLOORS - 1)
					direction = DOWN;
				if( floor == 0)
					direction = UP;

			/* If anyone wants off here, let them off. */
				if( getting_off[floor])
					printf("Elevator lets %d off at floor %d.\n",
					getting_off[floor], floor);
				people_data -> total_number -= getting_off[floor];
				getting_off[floor] = 0;


			}
		}
	}
}

void people()
{
	int floor;
	srand( getpid());
	while(1)
	{
		/* Sleep a while */
		sleep( rand() % 10 );
		/* Generate a new person. */
		if( rand() % 2 == 0){
			/* Going down. */
			floor = rand() % (FLOORS - 1) + 1;
			people_data -> going_down[ floor ] ++;
			printf("New person going down at floor %d.\n", floor);
		}
		else {
			floor = rand() % (FLOORS - 1);
			(people_data -> going_up)[ floor ]++;
			printf("New person going up at floor %d.\n", floor);
		}
		people_data -> total_number++;
	}
}

<< moderator edit: added code tags: [code][/code] >>

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.