#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <pthread.h> #include <semaphore.h> sem_t semaphore; sem_t nap; sem_t takeoff; pthread_t plane[45]; int regions[6] = {0, 0, 0, 0, 0, 0}; void* routine(void* arg){ void* arg1 = arg; for(int i = 0; i < 2; i ++){ //thread will enter to try and perform the task outlined in the assignment //properly cast the arg into an so that every plane is identified with a number ID int planeid = *(int*) arg; char idMessage[14]; sprintf(idMessage, "[%s Plane #%2i %s]",planeid<15?"Large":"Small",planeid,i==1?"Arrival":"Departure"); //try and fly //branch based on plane size if(planeid < 15){ //pick a time that the plane will ide in terminal and sleep int largetime = (rand()%10000) + 1; printf("%s idle in the %s Sleeping for %i microseconds!\n",idMessage,i==0?"terminal.":"air",largetime); usleep(largetime); //set of regions denoted 0-1 //0 is 1,4,6 //1 is 2,3,5 //pick which region to taxi to int bigset = (rand()%2); //pick set and do something based on which region was picked switch(bigset){ case 0: printf("%s going to region 1,4,6\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[0] == 0 && regions[3] == 0 && regions[5] == 0){ //take off if every section of region is empty printf("%s on section 1,4,6!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[0]=1; regions[3]=1; regions[5]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 1,4,6 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 1,4,6 is unblocked!\n", idMessage); goto RETRY; } //begin taking off //1 is up, 0 is down int direction = (rand()%2); if( direction == 0)/*decreasing order*/{ //staring in 6 printf("%s I am in zone 6 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[0]=0; regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); } else if(direction == 1)/*increasing order*/{ //starting in 1 //everything here is the same as the prior section, just different region order printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 6 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[0]=0; regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[0]=0; regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); //start over } break; case 1: printf("%s going to taxi to region 2,3,5\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY2: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[1] == 0 && regions[2] == 0 && regions[4] == 0){ //take off if every section of region is empty printf("%s taking off on section 2,3,5!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[1]=1; regions[2]=1; regions[4]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 2,3,5 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 2,3,5 is unblocked!\n", idMessage); goto RETRY2; } //begin taking off //1 is up, 0 is down int direction1 = (rand()%2); if( direction1 == 0)/*decreasing order*/{ //staring in 5 printf("%s I am in zone 5 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[1]=0; regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); } else if(direction1 == 1)/*increasing order*/{ //starting in 2 //everything here is the same as the prior section, just different region order printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 5 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[1]=0; regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[1]=0; regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%10 + 1); //start over } break; } } //SMALL if(planeid >= 15){ int smalltime = (rand()%10000) + 1; printf("%s idle in the %s Sleeping for %i microseconds!\n",idMessage,i==0?"terminal.":"air",smalltime); usleep(smalltime); //set of regions denoted 0-5 //0 is 1,2 //1 is 3,4 //2 is 1,4 //3 is 2,3 //4 is 3,5 //5 is 4,6 int smallset = (rand()%6); //pick set switch(smallset){ case 0: printf("%s going to taxi to region 1,2\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY3: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[0] == 0 && regions[1] == 0){ //take off if every section of region is empty // printf("[%s Plane #%i]taking off on section 1,2!\n", planeid); printf("%s taking off on section 1,2!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[0]=1; regions[1]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 1,2 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 1,2 is unblocked!\n", idMessage); goto RETRY3; } //begin taking off //1 is up, 0 is down int smalldirection = (rand()%2); if( smalldirection == 0)/*decreasing order*/{ //staring in 2 printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[0]=0; regions[1]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection == 1)/*increasing order*/{ //starting in 1 //everything here is the same as the prior section, just different region order printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[0]=0; regions[1]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[0]=0; regions[1]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; case 1: printf("%s going to taxi to region 3,4\n", idMessage); // printf("Plane of type %s with ID# %i is going to taxi to region 3,4\n", "SMALL", planeid); //check availability of the picked region //dealing with global vars now, so lock the region RETRY4: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[2] == 0 && regions[3] == 0 ){ //take off if every section of region is empty printf("%s taking off on section 3,4!\n", idMessage); // printf("[%s Plane #%i]taking off on section 3,4!\n", planeid); //mark region sections as occupied so other planes cannot enter regions[2]=1; regions[3]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 3,4 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 3, 4 is unblocked!\n", idMessage); goto RETRY4; } //begin taking off //1 is up, 0 is down int smalldirection1 = (rand()%2); if( smalldirection1 == 0)/*decreasing order*/{ //staring in 4 printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[2]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection1 == 1)/*increasing order*/{ //starting in 3 //everything here is the same as the prior section, just different region order printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[2]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[2]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; case 2: // printf("Plane of type %s with ID# %i is going to taxi to region 1,4\n", "SMALL", planeid); printf("%s going to taxi to region 1,4\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY5: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[0] == 0 && regions[3] == 0 ){ //take off if every section of region is empty // printf("[%s Plane #%i]taking off on section 1,4!\n", planeid); printf("%s taking off on section 1,4!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[0]=1; regions[3]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 1,4 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 1,4 is unblocked!\n", idMessage); goto RETRY5; } //begin taking off //1 is up, 0 is down int smalldirection2 = (rand()%2); if( smalldirection2 == 0)/*decreasing order*/{ //staring in 4 printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[0]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection2 == 1)/*increasing order*/{ //starting in 1 //everything here is the same as the prior section, just different region order printf("%s I am in zone 1 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[0]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[0]=0; regions[3]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; case 3: // printf("Plane of type %s with ID# %i is going to taxi to region 2,3\n", "SMALL", planeid); printf("%s going to taxi to region 2,3\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY6: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[1] == 0 && regions[2] == 0 ){ //take off if every section of region is empty // printf("[%s Plane #%i]taking off on section 2,3!\n", planeid); printf("%s taking off on section 2,3!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[1]=1; regions[2]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 2,3 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 2,3 is unblocked!\n", idMessage); goto RETRY6; } //begin taking off //1 is up, 0 is down int smalldirection3 = (rand()%2); if( smalldirection3 == 0)/*decreasing order*/{ //staring in 3 printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[1]=0; regions[2]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection3 == 1)/*increasing order*/{ //starting in 2 //everything here is the same as the prior section, just different region order printf("%s I am in zone 2 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[1]=0; regions[2]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[1]=0; regions[2]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; case 4: // printf("Plane of type %s with ID# %i is going to taxi to region 3,5\n", "SMALL", planeid); printf("%s going to taxi to region 3,5\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY7: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[2] == 0 && regions[4] == 0 ){ //take off if every section of region is empty // printf("[%s Plane #%i]taking off on section 3,5!\n", planeid); printf("%s taking off on section 3,5!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[2]=1; regions[4]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 3,5 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 3,5 is unblocked!\n", idMessage); goto RETRY7; } //begin taking off //1 is up, 0 is down int smalldirection4 = (rand()%2); if( smalldirection4 == 0)/*decreasing order*/{ //staring in 5 printf("%s I am in zone 5 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection4 == 1)/*increasing order*/{ //starting in 3 //everything here is the same as the prior section, just different region order printf("%s I am in zone 3 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 5 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[2]=0; regions[4]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; case 5: // printf("Plane of type %s with ID# %i is going to taxi to region 4,6\n", "SMALL", planeid); printf("%s going to taxi to region 4,6\n", idMessage); //check availability of the picked region //dealing with global vars now, so lock the region RETRY8: sem_wait(&semaphore); //double lock so that if the region is unavalable, the nap semaphore won't unlock until it is if( regions[3] == 0 && regions[5] == 0 ){ //take off if every section of region is empty // printf("[%s Plane #%i]taking off on section 4,6!\n", planeid); printf("%s taking off on section 4,6!\n", idMessage); //mark region sections as occupied so other planes cannot enter regions[3]=1; regions[5]=1; //unlock both semaphors so other planes can try to take off sem_post(&semaphore); } else{ //if a plan enters the semaphor region and cannot begin takeoff, it comes here to wait for &nap to increment with a different post printf("%s Region 4,6 is blocked! Sleeping until available\n", idMessage); sem_post(&semaphore); sem_wait(&nap); printf("%s awoken because region 4,6 is unblocked!\n", idMessage); goto RETRY8; } //begin taking off //1 is up, 0 is down int smalldirection5 = (rand()%2); if( smalldirection5 == 0)/*decreasing order*/{ //staring in 6 printf("%s I am in zone 6 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); //again mutating global vars so lock the crit region sem_wait(&takeoff); regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else if(smalldirection5 == 1)/*increasing order*/{ //starting in 4 //everything here is the same as the prior section, just different region order printf("%s I am in zone 4 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am in zone 6 now\n", idMessage); sleep( rand() % 5 ); printf("%s I am %s now\n", idMessage, i==0?"in the air":" on the ground"); sem_wait(&takeoff); regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } else{ printf("Something went wrong\n"); //reset region if something broke sem_wait(&takeoff); regions[3]=0; regions[5]=0; //clear nap int check; sem_getvalue(&nap, &check); if( check == 0 ){sem_post(&nap);} sem_post(&takeoff); //sleep for fairness sleep( rand()%3 + 1); } break; } } //to prevent starving, sleep //start over once you land } routine(arg1); } void seed_helper(){ //Open seed file FILE *fp; char seed[5]; fp = fopen("seed.txt", "r"); //getting seed from file fscanf(fp, "%s", seed); int intseed = atoi(seed); //seed srand srand((unsigned) intseed); //close file fclose(fp); } int main(){ //ensure seed.txt is used seed_helper(); //initialize seaphore sem_init(&semaphore, 0, 1); sem_init(&nap, 0, 1); sem_init(&takeoff, 0, 1); printf("Planes will continue to fly at their leisure until you kill the program with ctrl+c. Program will continue after 5 seconds. Happy Fyling!\n"); //sleep to allow user time to read sleep(5); //create threads, each thread will be a plane //small plane labeled 0 //large plane labeled 1 int numplanes = 45; for(int i = 0; i<numplanes; i++){ int* a = malloc(sizeof(int)); *a = i; if( pthread_create(&plane[i], NULL, &routine, a) != 0){ perror("Failed to create Thread\n"); } } //join for(int j=0; j<numplanes; j++){ if( pthread_join(plane[j], NULL) != 0){ return -1; } } //destroy semaphore sem_destroy(&takeoff); sem_destroy(&nap); sem_destroy(&semaphore); return 0; }