- Parallelize a presented segment of code using PThread primatives, being sure to highlight concerns with
1. .resource conflicts,
2. order dependencies, and
3.deadlock conditions. The above can be simplified - wherever there is a pthread_mutex_unlock() followed immediately by a pthread_mutex_lock() of the same mutex, the unlock/lock pair can be removed.
This program is supposed to synchronize several threads of "visitors" and "cars".
Visitors wander around for a random amount of time until they decide to go on a car ride.
If they are first in line for a car ride and a car is available they take a ride,
else they must wait till they are first in line or a car comes back.
If there are no visitors in line the cars wait in order until a visitor wants to go on a ride.
pthread_mutex_t c_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex protecting c_line and cars_out */
pthread_mutex_t v_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex protecting v_line */
pthread_cond_t c_cond[TOTALCARS]; /* condition variables for waiting for c_state[i] to change from VISITORS to another value */
pthread_cond_t v_cond[TOTALVISITORS]; /* condition variables for visitor waiting to be first in line or ejected from a car */
pthread_cond_t v_car_cond = PTHREAD_COND_INITIALIZER; /* Condition variable for a visitor first in line, but waiting for a car. */
pthread_mutex_t sc[TOTALCARS]; /* one mutex per car, sc[i] protects c_state[i] */
int main(){
int i;
void *status;
pthread_t c[TOTALCARS];
pthread_t v[TOTALVISITORS];
srand(time(NULL));
printf("Jurassic Park is open, cars are being prepped for passengers\n"); mutex init if multiple, cond init if multiple, thread creation
for (i = 0; i < TOTALCARS; i++){
pthread_mutex_init(&sc[i], NULL);
pthread_cond_init(&c_cond[i], NULL);
}
for (i = 0; i < TOTALVISITORS; i++){
pthread_cond_init(&v_cond[i], NULL);
}
for (i = 0; i < TOTALCARS; i++){
c_state[i] = TOTALVISITORS;
pthread_create(&c[i], NULL, car, (void *)i);
}
for (i = 0; i < TOTALVISITORS; i++){
pthread_create(&v[i], NULL, visitor, (void *)i);
}
for (i = 0; i < TOTALVISITORS; i++){
pthread_join(v[i], &status);
}
museum_empty++;
printf("All visitors have left Jurassic Park\n");
for (i = 0; i < TOTALCARS; i++){
pthread_mutex_lock(&sc[i]);
c_state[i] = -1;
pthread_cond_signal(&c_cond[i]);
pthread_mutex_unlock(&sc[i]);
}
for (i = 0; i < TOTALCARS; i++){
pthread_join(c[i], &status);
}
printf("Jurrasic Park is closed, all cars have been parked\n");
pthread_exit(NULL);
return 0;
}
// For each car
void *car(void *i)
{
int c_id = (int) i;// Current car id
int v_id;
while (museum_empty != 1) { // Museum is open
/1* join end of car queue */ c_line[c_id]
pthread_mutex_lock(&c_mutex);
c_line[c_id] = set_car_place_in_line();
if (c_line[c_id] == 1)
pthread_cond_signal(&v_car_cond);
printf("Car %d is ready for a passenger and is %d in line %d of %d cars are out\n", c_id, c_line[c_id], cars_out, TOTALCARS);
pthread_mutex_unlock(&c_mutex);
/2* wait until occupied */ c_state[c_id]
pthread_mutex_lock(&sc[c_id]);
while ( (v_id = c_state[c_id]) == TOTALVISITORS ) {
pthread_cond_wait(&c_cond[c_id], &sc[c_id]);
}
pthread_mutex_unlock(&sc[c_id]);
if(museum_empty == 1){
break;
}
pthread_mutex_lock(&c_mutex);// casrs_out
cars_out++;
printf("Visitor %d is riding in car %d %d of %d cars are out --\n", v_id, c_id, cars_out, TOTALCARS);
pthread_mutex_unlock(&c_mutex);
/3* visitor is on car ride for random amount of time */
sleep(rand()%5);
printf("Visitor %d is done riding in car %d\n", v_id, c_id);
/4* eject visitor from car */
pthread_mutex_lock(&sc[c_id]);//c_state
c_state[c_id] = TOTALVISITORS;
pthread_cond_signal(&v_cond[v_id]);
pthread_mutex_unlock(&sc[c_id]);
pthread_mutex_lock(&c_mutex); // casrs_out
cars_out--;
pthread_mutex_unlock(&c_mutex);
}
return NULL;
}
// For each visitor
void *visitor(void *i)
{
int v_id = (int) i;
int next_v;
int j = 0;
int car;
while (j < RIDES) {
if (j == 0) {
printf("Visitor %d entered museum and is wandering around\n", v_id);
} else {
printf("Visitor %d got back from ride and is wandering around\n", v_id);
}
sleep(rand()%3); /* visitor is wandering */
/1* join end of visitor queue */ // v_line
pthread_mutex_lock(&v_mutex);
v_line[v_id] = set_visitor_place_in_line();
printf("Visitor %d is %d in line for a ride\n", v_id, v_line[v_id]);
/2* wait until first in line */ //v_line
while (v_line[v_id] != 1) {
pthread_cond_wait(&v_cond[v_id], &v_mutex);
}
pthread_mutex_unlock(&v_mutex);
/3* wait until there is a car free */
pthread_mutex_lock(&c_mutex);
while ((car = get_next_car()) == TOTALCARS) {
pthread_cond_wait(&v_car_cond, &c_mutex);
}
/4* remove car from car queue */ //c_line
move_car_line();
pthread_mutex_unlock(&c_mutex);
/5* remove self from visitor queue */ //v_line
pthread_mutex_lock(&v_mutex);
move_passenger_line();
next_v = get_next_passenger();
if (next_v < TOTALVISITORS)
pthread_cond_signal(&v_cond[next_v]);
pthread_mutex_unlock(&v_mutex);
/6* occupy car */
pthread_mutex_lock(&sc[car]);//c_state
c_state[car] = v_id;
pthread_cond_signal(&c_cond[car]);
/7* wait until not in car anymore */
/* NOTE: This test must be against v_id and *not* VISITORS, because the car could have been
* subsequently occupied by another visitor before we are woken. */
while(c_state[car] == v_id) {
pthread_cond_wait(&v_cond[v_id], &sc[car]);
}
pthread_mutex_unlock(&sc[car]);
j++;
}
printf("Visitor %d leaving museum.\n", v_id);
return NULL;
}
|
No comments:
Post a Comment