From ccdbbeb97932acf458724fa2e6026f16ebbb7b87 Mon Sep 17 00:00:00 2001 From: p-w-rs Date: Wed, 5 Oct 2022 10:55:49 -0500 Subject: [PATCH] stuff --- 05-JurrasicPark/README.md | 201 +++++++++++++++++- 05-JurrasicPark/assets/parkvars.png | Bin 0 -> 1777702 bytes 05-JurrasicPark/assets/sum.png | Bin 0 -> 630633 bytes Examples/concurrency/con1 | Bin 50216 -> 50216 bytes Examples/concurrency/con2 | Bin 50208 -> 50208 bytes .../con2.dSYM/Contents/Resources/DWARF/con2 | Bin 10427 -> 10423 bytes Examples/concurrency/con3 | Bin 50208 -> 50208 bytes .../con3.dSYM/Contents/Resources/DWARF/con3 | Bin 10426 -> 10422 bytes Examples/concurrency/con4 | Bin 50256 -> 50256 bytes .../con4.dSYM/Contents/Resources/DWARF/con4 | Bin 10446 -> 10442 bytes Examples/concurrency/con_dekkers | Bin 50280 -> 50280 bytes .../Contents/Resources/DWARF/con_dekkers | Bin 10549 -> 10543 bytes Examples/concurrency/mutex1 | Bin 50424 -> 50424 bytes .../Contents/Resources/DWARF/mutex1 | Bin 10630 -> 10626 bytes Examples/concurrency/mutex2 | Bin 50424 -> 50424 bytes .../Contents/Resources/DWARF/mutex2 | Bin 10678 -> 10672 bytes Examples/concurrency/mutex3 | Bin 50424 -> 50424 bytes .../Contents/Resources/DWARF/mutex3 | Bin 10675 -> 10669 bytes Examples/concurrency/prod_cons1 | Bin 50656 -> 50656 bytes .../Contents/Resources/DWARF/prod_cons1 | Bin 11139 -> 11130 bytes Examples/concurrency/prod_cons2 | Bin 51016 -> 51016 bytes Examples/concurrency/prod_cons2.c | 26 ++- .../Contents/Resources/DWARF/prod_cons2 | Bin 11415 -> 11449 bytes Examples/concurrency/race | Bin 50152 -> 50152 bytes Examples/concurrency/race.c | 14 +- .../race.dSYM/Contents/Resources/DWARF/race | Bin 10323 -> 10319 bytes Examples/concurrency/sem1 | Bin 50408 -> 50408 bytes .../sem1.dSYM/Contents/Resources/DWARF/sem1 | Bin 10495 -> 10491 bytes Examples/concurrency/sem2 | Bin 50408 -> 50408 bytes .../sem2.dSYM/Contents/Resources/DWARF/sem2 | Bin 10541 -> 10535 bytes Examples/concurrency/sem_list1 | Bin 50376 -> 50376 bytes .../Contents/Resources/DWARF/sem_list1 | Bin 10633 -> 10635 bytes Examples/concurrency/sem_list2 | Bin 50632 -> 0 bytes Examples/concurrency/sem_list2.c | 10 +- .../sem_list2.dSYM/Contents/Info.plist | 20 -- .../Contents/Resources/DWARF/sem_list2 | Bin 10833 -> 0 bytes 36 files changed, 228 insertions(+), 43 deletions(-) create mode 100644 05-JurrasicPark/assets/parkvars.png create mode 100644 05-JurrasicPark/assets/sum.png delete mode 100755 Examples/concurrency/sem_list2 delete mode 100644 Examples/concurrency/sem_list2.dSYM/Contents/Info.plist delete mode 100644 Examples/concurrency/sem_list2.dSYM/Contents/Resources/DWARF/sem_list2 diff --git a/05-JurrasicPark/README.md b/05-JurrasicPark/README.md index 413dc15..c5c0b7a 100644 --- a/05-JurrasicPark/README.md +++ b/05-JurrasicPark/README.md @@ -1,5 +1,204 @@ -## Introduction +# Introduction For this lab you will use threads, semaphores, and mutexes to implement a simulation of an ASCII art Jurassic Park! +# Motivation + +Contemporary operating systems are built around the concept of processes or tasks. Tasks may or may not be related, may or may not affect the state of another task, but usually always need to share resources in a protected, prioritized, and equitable manner. + +Jurassic Park is an inter-process communication and synchronization problem between multiple tasks. Visitors to the park want to first get a ticket, visit the park museum, take a ride on a park tour car to see the dinosaurs, and then visit the gift shop before leaving the park. Since the park is on a limited budget, drivers must perform double duty when not sleeping; selling tickets to the park visitors and driving the tour cars through the park. Visitors, drivers, and cars are represents by concurrent tasks while an additional task is used to display the park status every second. + +Attempting to coordinate the park activities without bringing about any race conditions is typical of many queuing problems. A poorly implemented solution could lead to the inter-process communication problems of starvation and deadlock. For example, the driver could end up waiting to sell a ticket to a visitor while a loaded tour car could be waiting for a driver, resulting in deadlock. Alternatively, visitors may not decide to take a tour car ride in an orderly manner, leading to process starvation as some visitors never get the chance for a ride even though they have been waiting in line. + +Jurassic Park is not unlike real world simulation and control problems such as found in airports, supply houses, traffic systems, oil tank farms, etc. Each requires multitasking roles involving inter-process coordination and communication. Like the classical dining philosophers and sleeping barber problems, the Jurassic Park exercise demonstrates what problems can occur in a multitasking, multi-user environment when many tasks are competing for the same resources. + +# Project Description + +Visitors arrive at the Jurassic Park at random times over a period of 60 seconds. (Only 20 visitors may be in the park at any one time - OSHA requirements!) Upon entering the park, a visitor gets in line to purchase a ticket. After obtaining a ticket from a driver, the visitor gets in the museum line. (Again, a limited number of visitors are allowed in the museum as well as the gift shop.) After visiting the museum, the visitor gets in the tour car line to wait until invited to board a tour car. As a visitor boards a tour car, he returns his ticket. When the touring car is filled with visitors (3) and a driver, the car enters Jurassic Park and follows a guided tour path through the park. When the tour car completes the ride and pulls into the unloading station, the visitors debark and move to the gift shop line, the driver goes back to sleep awaiting new duties, and the tour car pulls forward to be loaded again. After visiting the gift shop, the visitor exits the park. + +# Requirments + +The following are important guidelines for completing the Jurassic Park assignment: + +1. 60 visitors must pass successfully thru the park. +Add a delta clock to your operating system. +2. Create 3 thread routines (visitor, driver, car) and a thread for each park visitor (NUM_VISITORS), driver (NUM_DRIVERS), and tour car (NUM_CARS) running thosse routines. +3. Update the park data structure variables appropriately as visitor, driver, and car states change. The park is displayed using the park data struct every second by the jurassicTask task in park.c. +4. Visitors should stand in lines for a random time before requesting a ticket, entrance to the museum or gift shop, or getting into a tour car (1-3 seconds). +5. Use resource semaphores (counting) to control access to the park, the number of tickets available, and the number of people allowed in the gift shop and museum. +6. Use mutex semaphores (binary) to protect any critical sections of code within your implementation, such as when acquiring a driver to buy a ticket or drive a tour car, accessing global data, or sampling the state of a semaphore. +7. Use semaphores (binary) to synchronize and communicate events between tasks, such as to awaken a driver, signal data is valid, signal a mode change, etc. +8. Use at least two sem_trywait(...) functions in your simulation. +9. Park critical code must be protected by the parkMutex mutex. +10. The park simulation also creates a "lostVisitor" task which sums critical variables in the park to detect any lost visitors. Beware! +11. You are to implement a fair algorithm that prevents deadlock and starvation rather than detect them. + +# Some IPC ideas may or may not want to use + +Inter-Process Communication (IPC) refers to the exchange of data among two or more threads in one or more processes. Among others, IPC techniques involve synchronization (events and semaphores), shared memory (globals), message passing (pipes and message queues), sockets, and remote procedure calls (RPC). The method of IPC used may vary based on the bandwidth and latency of communication between the threads, and the type of data being communicated. For Jurassic Park, use semaphores and shared memory as follows: + +Semaphores are considered events and are usually one of the following types: + +1. **Resource semaphores**. Typically counting, these semaphores are used to control access to the park, the number of tickets available, and the number of people allowed in the gift shop and museum. +```c +//global variables +sem_t tickets; + +//some local thread routine +{ +// create MAX_TICKETS tickets using counting semaphore +sem_init(&tickets, 0, MAX_TICKETS); + +// buy a ticket (consume) +sem_wait(tickets); + +// resell ticket (produce) +sem_post(tickets); +} +``` + +2. **Mutex semaphores**. Typically binary, these semaphores are used to protect critical sections of code within your implementation, such as when updating the delta clock, acquiring a driver to buy a ticket or drive a tour car, accessing global data, or sampling the state of a semaphore. +```c +// need ticket, wait for driver (mutex) +pthread_mutex_lock(&needDriverMutex); +{ + // signal need ticket (signal, put hand up) +} +pthread_mutex_unlock(&needDriverMutex); +// release driver (mutex) +``` + +3. **Signal semaphores**. Typically binary, these semaphores are used to synchronize and communicate events between tasks, such as to awaken a driver, signal data is valid, signal a mode change, etc. For example, the following code signals the need for a ticket (needTicket), signals a driver to wakeup (wakeupDriver), waits for a ticket to be printed (ticketReady), and then signals to buy the ticket (buyTicket). The task indicates it no longer needs a ticket by consuming the needTicket semaphore. +```c +// only 1 visitor at a time requests a ticket +pthread_mutex_lock(&getTicketMutex); +{ + // signal need ticket (produce, put hand up) + sem_post(&needTicket); + + // wakeup a driver (produce) + sem_post(&wakeupDriver); + + // wait for driver to obtain ticket (consume) + sem_wait(&ticketReady); + + // put hand down (consume, driver awake, ticket ready) + sem_wait(&needTicket); + + // buy ticket (produce, signal driver ticket taken) + sem_post(&buyTicket); +} +// done (produce) +pthread_mutex_unlock(&getTicketMutex); +``` + +4. Shared memory can be implemented using C global memory when protected with mutex semaphores. +```c +randomWait(60); +pthread_mutex_lock(&parkMutex); +myPark.numOutsidePark++; +pthread_mutex_unlock(&parkMutex); +``` + +# Interfacing with "jurassicTask" + +The jurassicTask task fills tour cars with passengers when a car is in the loading position, moves tour cars one position forward (if possible) around the park, randomly chooses a route at the route cross roads, and displays the status of Jurassic Park every second. The display is generated from the following C struct variables defined in the **park.h** file: + +```c +typedef struct +{ + int numOutsidePark; // # outside of park + int numInPark; // # in park (P=#) + int numTicketsAvailable; // # left to sell (T=#) + int numRidesTaken; // # of tour rides taken (S=#) + int numExitedPark; // # who have exited the park + int numInTicketLine; // # in ticket line + int numInMuseumLine; // # in museum line + int numInMuseum; // # in museum + int numInCarLine; // # in tour car line + int numInCars; // # in tour cars + int numInGiftLine; // # in gift shop line + int numInGiftShop; // # in gift shop + int drivers[NUM_DRIVERS]; // driver state (-1=T, 0=z, 1=A, 2=B, etc.) + CAR cars[NUM_CARS]; // cars in park +} JPARK; +``` + +Your visitor, driver, and tour car tasks need to update the appropriate variables at the appropriate times. The following global signal semaphores are defined in **park.c**: + +```c +pthread_mutex_t fillSeat[NUM_CARS]; // (signal) seat ready to fill +pthread_mutex_t seatFilled[NUM_CARS]; // (wait) passenger seated +pthread_mutex_t rideOver[NUM_CARS]; // (signal) ride over +``` + +All car tasks should + +1. for each car (and seat in the car), + - wait (fillSeat) to be filled, seat by seat, when the car is in loading position, + - get a passenger from the tour car waiting line, + - get a driver for car (if last seat) + - signal (seatFilled) that seat has been filled, +2. wait for a signal (rideOver) that the ride is over, +3. and release passenger and driver (allow driver to go back to sleep.) + +For example, to fill a seat in tour car carID, wait for available seat ready (fillSeat[carID]), then find a visitor from the tour car waiting line, and then signal (seatFilled[carID]) that you are ready for the next seat. (Communication with the park is indicated by /\*...\*/.) + +```c +pthread_mutex_lock(&fillSeat[carID]); /*wait for available seat*/ + +sem_post(&getPassenger); // signal for visitor +sem_wait(&seatTaken); // wait for visitor to reply + +//... save passenger ride over semaphore ... + +sem_post(&passengerSeated); // signal visitor in seat + +// if last passenger, get driver +{ + pthread_mutex_lock(&needDriverMutex); + + // wakeup attendant + sem_post(&wakeupDriver); + + //... save driver ride over semaphore ... + + // got driver (mutex) + pthread_mutex_unlock(&needDriverMutex); +} + +pthread_mutex_unlock(&seatFilled[carID]); /*signal ready for next seat*/ + + +pthread_mutex_lock(&rideOver[myID]); /*if car full, wait until ride over*/ + +//... release passengers and driver ... +``` + +In summary: + +![sum](/assets/sum.png) + +Park variables correspond to the park display as follows: + +![park](/assets/parkvars.png) + + +# Suggested Steps to Implementing the Jurassic Park Project + +1. Develop the car task. + - Design car functionality and Jurassic Park interface. (Don't worry about passengers yet.) + - Implement design and integrate with park and Jurassic Park. + - Validate correct car behaviour. +2. Develop the visitor task. + - Design visitor functionality and car task interface. + - Implement design and integrate with park and car tasks. (Don't worry about tickets yet.) + - Use rand and sleep to vary visitor time in all lines, museum, and gift shop. + - Observe correct visitor behavior as a visitor moves through the park. +3. Develop the driver task. + - Design driver functionality and interface with visitor and car tasks. + - Implement design and integrate with other park, visitor, and car tasks. (Now is the time to worry about ticket sales and driver duties.) + - Add ticket sales and driver responsibilities. + - When a driver is awakened, use the sem_trywait() function to determine if a driver or a ticket seller is needed. + diff --git a/05-JurrasicPark/assets/parkvars.png b/05-JurrasicPark/assets/parkvars.png new file mode 100644 index 0000000000000000000000000000000000000000..26aa19aacd3ce3cf475d24bab2ed1f97e2d682e5 GIT binary patch literal 1777702 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