Changes
→Testing
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.
Finally, we repeated the same procedure, but intermingled the creation of speakers and listeners via .fork(), such that listeners would start listening before all the speakers were queued up.
Third, we used testing functions: MassSpeaker and MassListener are designed to be run by a single thread each. These runnables, will iterate until a given limit, and on each iteration, there is a 50% chance that a speak (or listen) is called. After each iteration, the thread yields to the opposite thread to do the same. Debug statements will display what threads are doing at each iteration and how messages are being exchanged. With this we can generate large amounts of calls with randomized orders between two threads, and will be able to verify all speaks are received by a listen.
A second set of runnables, MassTSpeaker and MassTListener, are designed to fork off several threads themselves, with each of these forked threads performing a single speak or listen. These forked threads are also executed with 50% chance on each iteration to provide random ordering. We can also verify if all threads are correctly paired off in this more complex situation.
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.