****************************************************************** ***************** Assignment #6 for CS341 ********************* ***** Due Tuesday 12/11/01 ***** ****************************************************************** The purpose of this assignment is to add multi-tasking/multi-threading to tkisem. This allows more than one program to run concurrently similar to Linux or any other modern operating system. This switching between tasks/threads has been done in two major ways in the past: (1) cooperatively where each task/thread voluntarily yields control with an explicit trap invocation (2) preemption by an external event like a timer In tkisem a timer device exists, so the 2nd way can be followed. However, input from the keyboard will cause a thread to call the thread scheduler which in turn will suspend the calling thread and resume another thread. The timer acts just like any other trap - although in this case it is of the implicit or involuntary variety known as an interrupt. The main part of the assignment is to write the timer interrupt handler in the supervisor part of tkisem. It will effectively switch from one thread of user execution to another; this is also known as context switching. Besides the context switcher, some thread management functions are desirable. For this assignment, only a minimum number of these will be necessary. create_thread() must be available to add a thread to the system and start_multi() must be available to kick off the timer and begin this whole multi-threading business. These two should be implemented as explicit traps. Create_thread() sets up one single thread. It will take the starting address of the new thread as its first and only argument. Now any system has a limit on the number of threads (or processes) it can reasonably handle. Because tkisem is so slow, this should be something small - so make it 10. create_thread() should check that the limit is not exceeded returning -1 if it fails. The other trap, start_multi(), merely starts the multi-threading. It takes no arguments. It should simply get the timer going and do a context switch to the first thread's starting address. Note: it might be wise to re-use timer code by jumping to the restoration part in the timer code, since the timer interrupt handler is the context switcher. Also note that the flow of execution will not return to the point just after the invocation of start_multi() unless an error occurs. (The possible errors are starting without having some threads to run and starting when the system has already been started.) Finally, if a thread terminates by thread #0, it should not usually cause the entire system system to halt - instead, that thread should merely be taken out of the switching loop. Only when it is the last thread to stop (or if multi-threading was never started) should trap #0 stop the entire system. The section of user code that sets up and starts the threads might look something like this: ... set main, %o0 ta create_thread ... set main, %o0 ta create_thread ... set main, %o0 ta create_thread ... set main, %o0 ta create_thread ... ta start_multi ! execution should not return here main: ! the separate threads can all start here, ! note that they can all share the same user code ... ta 0 One test program for your system will use the circle GX routine and trap #7 (used in assignment #5). It will make four threads each of which will be drawing circles in its own quadrant of the screen. This user program will be provided, but your thread system should work with any properly written multi-threading program so you are encouraged to test it with your own test programs. In addition to drawing its circle, a thread should be able to input an integer from the keyboard. The integer can range between 0 and n. Here's what should happen if the user types j when thread i (henceforth Ti) is running. (a) Ti calls the scheduler/context switcher with parameter j. (b) The scheduler suspends Ti (saving its state). The scheduler resumes Tj and it executes until its "quantum" runs out or it is interrupted by a keystroke, whichever occurs earlier. In the latter case, Tj will be followed by T((j+1) mod 4) upon completion. Extra Credit - in order to get the project to a more reasonable size, non-leaf procedure calls in the user code will not be permitted. This way, the context switcher only needs to deal with one register window. It will be extra credit if the context switcher handles non-leaf procedures. ------------------------------------------------------------------------------ What to turn in: (1) modified supervisor code ("isem_rom.s" and "isem_vec.s") It must contain: - trap #7 from the previous assignment - trap # for create_thread() - trap # for start_multi() - timer interrupt code for context switching - modified trap #0 for generalized halting (2) the identity of the traps chosen for create_thread() and start_multi(), e.g. 8 and 9 ------------------------------------------------------------------------------