Smreks
Smreks

Reputation: 327

C - Linux - Pthreads and Semaphore

I am having trouble trying to implement semaphores with pthreads. The scenario that I am trying to program are rats in a maze. Where rats are threads and the maze consists of rooms connected to each other. The rats have to traverse through each room with each room having a different capacity and wait time before a rat can move on. I was able to implement it with a while loop and let the threads sit and spin while waiting for a spot to free up but I need to achieve the objective with semaphores. Here's what I have:

sem_t psem, csem;

void EnterRoom(int iRat, int iRoom) {

    time_t currentTime;

    currentTime = time(NULL);

    RoomVB[iRoom][iRat].tEntry = currentTime - startTime;
    RoomVB[iRoom][iRat].iRat = iRat;
    VisitorCount[iRoom]++;
    sleep(roomArray[iRoom].delay);
}

void LeaveRoom(int iRat, int iRoom) {

    time_t currentTime;

    currentTime = time(NULL);

    VisitorCount[iRoom]--;
    RoomVB[iRoom][iRat].tDep = currentTime - startTime;
}

void *rat(void *ratID) {

    if (sem_init(&csem, 0, 0) < 0) {
        perror("sem_init");
        exit(1);
    }

    int id;

    id = (int)ratID;

    int i;

    for (i = 0; i < numOfRooms; i++) {

    /*while (VisitorCount[i] >= roomArray[i].capacity) {

    }*/

    if (sem_init(&psem, 0, roomArray[i].capacity) < 0) {
        perror("sem_init");
        exit(1);
        }


    sem_wait(&psem);
    EnterRoom(id, i);
    sem_post(&csem);

    sem_wait(&csem);
    LeaveRoom(id, i);
    sem_post(&psem);

    }

    return NULL;

}

As you can see I commented out the while loop. I had to incorporate additional information like the time it it takes for a rat to travel through rooms in a 2D array.

Error result:

Rat 0 completed maze in 5 seconds.
Rat 1 completed maze in 5 seconds.
Rat 2 completed maze in 5 seconds.
Room 0 [3 1]: 0 0 1; 1 0 1; 2 0 1; 
Room 1 [2 2]: 0 1 3; 1 1 3; 2 1 3; 
Room 2 [1 2]: 0 3 5; 1 3 5; 2 3 5; 
Total traversal time: 15 seconds, compared to ideal time: 15 seconds.

Correct result (achieved with loop):

Rat 0 completed maze in 7 seconds.
Rat 1 completed maze in 5 seconds.
Rat 2 completed maze in 9 seconds.
Room 0 [3 1]: 0 0 1; 1 0 1; 2 0 1; 
Room 1 [2 2]: 0 1 3; 1 1 3; 2 3 5; 
Room 2 [1 2]: 0 5 7; 1 3 5; 2 7 9; 
Total traversal time: 21 seconds, compared to ideal time: 15 seconds.

I assume I need two semaphores with the producer semaphore being initially set to n - which is the capacity of each room. Any ideas how I fix it so it works as it should?

Upvotes: 0

Views: 1551

Answers (1)

caf
caf

Reputation: 239011

You can't have each thread re-initialise the same two shared semaphores simultaneously. The semaphores all need to be initialised up-front, before your rats start running.

The easiest way to solve this will be to have one semaphore for each room, initialised to the capacity of that room (store the sempahore in the roomArray element for that room). Then, just have the rat wait on the semaphore when it enters the room, and post the semaphore when it exits the room.

Upvotes: 1

Related Questions