Here is the code written to run under the thread manager:
#include
#include "threads.h"
void test_thread( int n )
{
int j;
for (j = 0;j < 10; j++) {
thread_relinquish();
puts( (char *)n );
}
}
int main()
{
thread_manager_init();
thread_startup_report(); /***********/
thread_launch( 4000, test_thread, (int)"x" );
thread_launch( 4000, test_thread, (int)"y" );
thread_manager_start();
/* control never reaches this point */
}
This does not produce the same output as the pure UNIX version for a number
of reasons:
- The Unix version uses preemptive scheduling. Therefore, if process
switches occur, they occur at random. The thread version is not preemptive
and thread context switches occur deterministically.
- The time-slice used by the UNIX scheduler is long enough that it is
likely that one of the UNIX processes in the example can run to completion
without any context switching. The thread version forces context switching
with each line of output.
- The puts() routine is part of the stream package in the C library,
operating at a level well above the level of the UNIX kernel. The stream
package maintains a buffer for each stream used by a process, and this buffer
does not necessarily write to the output device until it is full. Therefore,
given the small volume of output produced by each process in this example,
it is possible that no output will be sent to the terminal until the process
terminates, forcing buffered output to be flushed. Thus, even if there is
frequent context switching in the UNIX version, the outputs from the processes
may be completely sorted! In contrast, the thread version has no private
buffering for each thread, so the outputs will be interleaved to exactly
reflect all context switching within the application.