1,277
edits
Changes
→Communicator: formatting + copyedit
==Communicator==
===Implementation===
;New state variablesWe add new state variables (a lock, four counters, and two condition variables): . {{c|<pre>Lock lock = new Lock()int activeSpeakers= 0int waitingSpeakers= 0int activeListeners= 0int waitingListeners= 0Condition speakers
Condition listeners
Condition return</pre>}} * The first lone speaker or listener will be counted as ''active'', or in the process of exchanging a message and returning, and will sleep on the {{c|return }} condition variable until its counterpart wakes it up so that they can both return. * A second thread performing the same action as a currently active thread will be counted as ''waiting'', and be put to sleep on its respective condition variable. Otherwise, it will check if there is an ''active '' thread of its counterpart action waiting on the {{c|return }} condition variable. If there isn’tisn't, it will attempt to wake waiting threads of its counterpart action prior to going to sleep on the return condition variable. If there is a counterpart ''active '' thread, it will wake it up and they both will return. Prior to returning, a the counterpart action will also attempt to wake sleeping ''waiting '' threads of its type.* Any interjecting threads that execute in between an exchange of message will be stopped by the ''active '' counters, which do not decrement until BOTH '''both''' counterparts in the exchange have returned.
===Testing===
Our original solution exhibited non-deterministic behavior, so after rewriting it, we decided to stress it exceptionally to make sure that it was working correctly. We tested our communicator in three main ways.
First, we set up a manual sequence of {{c|speak() }} and {{c|listen() }} actions on different threads and executed them in a particular order, verifying that the resulting sequence of messages was correct, monitored via print statements to the console
Second, we set off a random number of speakers, followed by a random number of listeners, and verified that the limiting resource was completely used up, i.e. that a matching number of speakers and listeners returned and that this was equal to the smaller of numbers of created speakers/listeners.
The latter two tests were run with up to 500 threads of speakers and listeners each (with a temporary override on the number of max threads in Nachos) and the number of listen and speak operations was analyzed via script. The speakers and listeners would print statements while executing code, which allowed us to perform this analysis.
===Pseudocode==={|| style="vertical-align: top;"| speak(int word) {
Acquire the lock;
while (There is an active speaker) {
}
}
listen() {
Acquire the lock;
}
}
|}
==Priority Scheduler==