home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.pdx.edu
/
2014.02.ftp.ee.pdx.edu.tar
/
ftp.ee.pdx.edu
/
pub
/
users
/
Harry
/
Blitz
/
OSProject
/
p4
/
Main.c
< prev
next >
Wrap
Text File
|
2007-09-19
|
16KB
|
473 lines
code Main
-- This is code for testing the ThreadManage, ProcessManager and FrameManager
----------------------------- Main ---------------------------------
function main ()
/*
var th0, th1, th2: ptr to Thread
proc0, proc1, proc2, proc3: ptr to ProcessControlBlock
*/
-- Initialization for testing code
uniqueNumberLock.Init ()
-- Initialize the Thread Scheduler
InitializeScheduler ()
-- Initialize the ProcessManager
processManager = new ProcessManager
processManager.Init ()
-- Initialize the ThreadManager
threadManager = new ThreadManager
threadManager.Init ()
-- Initialize the FrameManager
frameManager = new FrameManager
frameManager.Init ()
-- THE FOLLOWING CODE MAY BE USEFUL DURING TESTING, SO YOU MAY WISH TO
-- UNCOMMENT AND USE ALL OR PART OF IT. HOWEVER, FOR YOUR FINAL RUN,
-- PLEASE USE THIS FILE EXACTLY AS DISTRIBUTED.
/*
-- Print the initial state
print ("\n==================== INITIAL STATE ====================\n\n")
threadManager.Print ()
print ("\n=========================================================\n\n")
-- Allocate some threads
print ("\n***** Allocating some threads *****\n\n")
th0 = threadManager.GetANewThread()
th1 = threadManager.GetANewThread()
th2 = threadManager.GetANewThread()
-- Rreturn one of the threads
print ("***** Returning one thread *****\n\n")
threadManager.FreeThread (th1)
-- Print the new state
print ("\n==================== NEW STATE ====================\n\n")
threadManager.Print ()
print ("\n=========================================================\n\n")
-- Return the other threads
threadManager.FreeThread (th0)
threadManager.FreeThread (th2)
-- Print the initial state
print ("\n==================== INITIAL STATE ====================\n\n")
processManager.Print ()
print ("\n\n")
frameManager.Print ()
print ("\n=========================================================\n\n")
-- Allocate some processes
print ("***** Allocating some processes *****\n\n")
proc0 = processManager.GetANewProcess()
proc1 = processManager.GetANewProcess()
proc2 = processManager.GetANewProcess()
proc3 = processManager.GetANewProcess()
-- Allocate some frames
print ("***** Allocating some frames *****\n\n")
frameManager.GetNewFrames(&proc2.addrSpace, 3)
frameManager.GetNewFrames(&proc1.addrSpace, 2)
frameManager.GetNewFrames(&proc0.addrSpace, 5)
frameManager.GetNewFrames(&proc3.addrSpace, 1)
-- Return one of the processes and return its frames
print ("***** Returning one process and its frames *****\n\n")
frameManager.ReturnAllFrames(&proc1.addrSpace)
processManager.FreeProcess (proc1)
-- Rreturn one of the threads
print ("***** Returning one thread *****\n\n")
threadManager.FreeThread (th1)
-- Print the new state
print ("\n==================== NEW STATE ====================\n\n")
processManager.Print ()
print ("\n\n")
frameManager.Print ()
print ("\n=========================================================\n\n")
-- Return the other processes and their frames
frameManager.ReturnAllFrames(&proc0.addrSpace)
processManager.FreeProcess (proc0)
frameManager.ReturnAllFrames(&proc2.addrSpace)
processManager.FreeProcess (proc2)
frameManager.ReturnAllFrames(&proc3.addrSpace)
processManager.FreeProcess (proc3)
*/
-- Run more thorough tests.
RunThreadManagerTests ()
RunProcessManagerTests ()
RunFrameManagerTests ()
RuntimeExit ()
endFunction
----------------------------- GetUniqueNumber ---------------------------------
--
-- This function returns a different number each time it is called. It is passed
-- the number of unique numbers required, in "count". Normally, count is 1.
-- If several unique numbers are needed, it can be called with a larger "count";
-- In this case, the numbers
-- ret, ret+1, ret+2, ... ret+count-1
-- will all be unique numbers that can be used.
--
var uniqueNumberLock: Mutex = new Mutex
nextUnique: int = 1
function GetUniqueNumber (count: int) returns int
var i: int
uniqueNumberLock.Lock ()
i = nextUnique
nextUnique = nextUnique + count
uniqueNumberLock.Unlock ()
return i
endFunction
----------------------------- Misc ---------------------------------
--
-- These are used by various testing functions.
--
const NUM_THREADS = 20
WAIT_TIME = 10
NUMBER_ITERATIONS = 20
var allDone: Semaphore = new Semaphore
freeze: Semaphore = new Semaphore
----------------------------- RunThreadManagerTests ---------------------------------
--
-- This function tests the ThreadManager. It creates a bunch of threads
-- (NUM_THREADS) and starts each thread running. Each thread will execute
-- the "TestThreadManager" function. The main thread will then wait until all
-- the threads complete. To control this, there is a single Semaphore "allDone".
-- Each TestThreadManager thread signals it and the main thread will wait
-- for NUM-THREAD times, i.e., until all threads have finished.
--
-- Each TestThreadManager does basically this:
-- loop NUMBER_ITERATIONS times
-- call GetANewThread
-- wait
-- call FreeThread
-- wait
-- endLoop
--
function RunThreadManagerTests ()
var i: int
th: ptr to Thread
allDone.Init (0)
freeze.Init (0)
uniqueNumberLock.Init ()
nextUnique = 1
print ("\n\n***** THREAD-MANAGER TEST *****\n\n")
for i = 1 to NUM_THREADS
th = alloc Thread
th.Init ("TestThreadManager")
th.Fork (TestThreadManager, i)
endFor
-- Wait for all the testing threads to complete.
-- (Make sure you see the completion message!)
for i = 1 to NUM_THREADS
allDone.Down ()
endFor
if GetUniqueNumber (1) != NUM_THREADS * NUMBER_ITERATIONS + 1
FatalError ("Concurrency control failure (1)")
endIf
print ("\n\n***** THREAD-MANAGER TEST COMPLETED SUCCESSFULLY *****\n\n")
endFunction
----------------------------- TestThreadManager ---------------------------------
--
-- This function is the main function for a thread which will test the
-- ThreadManager. It will request and return Thread objects. First, it
-- grabs a unique number and stuffs it in the Thread. Later, it makes sure that
-- the number is unchanged. It could only have changed if some other tester
-- was allowed to access this Thread object before this tester returned it.
--
function TestThreadManager (myID: int)
var i, j, e: int
th: ptr to Thread
-- printIntVar ("Thread started", myID)
for i = 1 to NUMBER_ITERATIONS
printInt (myID)
e = GetUniqueNumber (1)
th = threadManager.GetANewThread ()
th.regs[0] = e
for j = 1 to WAIT_TIME+i
currentThread.Yield ()
endFor
if e != th.regs[0]
FatalError ("Concurrency control failure (2)")
endIf
printChar ('.')
threadManager.FreeThread (th)
for j = 1 to WAIT_TIME-i
currentThread.Yield ()
endFor
endFor
allDone.Up ()
freeze.Down ()
endFunction
----------------------------- RunProcessManagerTests ---------------------------------
--
-- This function tests the ProcessManager. It creates a bunch of tester threads
-- (NUM_THREADS) and starts each thread running. Each tester thread will execute
-- the "TestProcessManager" function. The main thread will then wait until all
-- the testers complete. To control this, there is a single Semaphore "allDone".
-- Each TestProcessManager thread signals it and the main thread will wait
-- for NUM-THREAD times, i.e., until all tester threads have finished.
--
-- Each TestProcessManager does basically this:
-- loop NUMBER_ITERATIONS times
-- call GetANewProcess
-- wait
-- call FreeProcess
-- wait
-- endLoop
--
function RunProcessManagerTests ()
var i: int
th: ptr to Thread
allDone.Init (0)
freeze.Init (0)
uniqueNumberLock.Init ()
nextUnique = 1
print ("\n\n***** PROCESS-MANAGER TEST *****\n\n")
for i = 1 to NUM_THREADS
th = alloc Thread
th.Init ("TestProcessManager")
th.Fork (TestProcessManager, i)
endFor
-- Wait for all the testing threads to complete.
-- (Make sure you see the completion message!)
for i = 1 to NUM_THREADS
allDone.Down ()
endFor
if GetUniqueNumber (1) != NUM_THREADS * NUMBER_ITERATIONS + 1
FatalError ("Concurrency control failure (1)")
endIf
print ("\n\n***** PROCESS-MANAGER TEST COMPLETED SUCCESSFULLY *****\n\n")
endFunction
----------------------------- TestProcessManager ---------------------------------
--
-- This function is the main function for a thread which will test the
-- ProcessManager. It will request and return ProcessControlBlocks. First, it
-- grabs a unique number and stuffs it in the PCB. Later, it makes sure that
-- the number is unchanged. It could only have changed if some other tester
-- was also allowed to access this ProcessContolBlock before this tester
-- returned it.
--
function TestProcessManager (myID: int)
var i, j, e: int
pcb: ptr to ProcessControlBlock
-- printIntVar ("Thread started", myID)
for i = 1 to NUMBER_ITERATIONS
printInt (myID)
e = GetUniqueNumber (1)
pcb = processManager.GetANewProcess ()
pcb.exitStatus = e
for j = 1 to WAIT_TIME+i
currentThread.Yield ()
endFor
if e != pcb.exitStatus
FatalError ("Concurrency control failure (2)")
endIf
printChar ('.')
processManager.FreeProcess (pcb)
for j = 1 to WAIT_TIME-i
currentThread.Yield ()
endFor
endFor
allDone.Up ()
freeze.Down ()
endFunction
----------------------------- RunFrameManagerTests ---------------------------------
--
-- This function tests the FrameManager. It creates one thread
-- for each ProcessControlBlock. Each thread will execute
-- the "TestFrameManager" function. The main thread will then wait until all
-- the threads complete. To control this, there is a single Semaphore "allDone2".
-- Each TestFrameManager thread signals it and the main thread will wait
-- for NUM-THREAD times, i.e., until all threads have finished.
-- We also keep track of how many times each frame is used and print this
-- data (as a histogram) after all the threads have finished.
--
const WAIT_TIME2 = 5
NUMBER_ITERATIONS_2 = 5
var allDone2: Semaphore = new Semaphore
histogram: array [NUMBER_OF_PHYSICAL_PAGE_FRAMES] of int =
new array of int {NUMBER_OF_PHYSICAL_PAGE_FRAMES of 0 }
function RunFrameManagerTests ()
var i,j : int
th: ptr to Thread
allDone2.Init (0)
freeze.Init (0)
print ("\n\n***** FRAME-MANAGER TEST *****\n\n")
for i = 1 to MAX_NUMBER_OF_PROCESSES
th = alloc Thread
th.Init ("TestFrameManager")
th.Fork (TestFrameManager, i)
endFor
-- Wait for all the testing threads to complete.
-- (Make sure you see the completion message!)
for i = 1 to MAX_NUMBER_OF_PROCESSES
allDone2.Down ()
endFor
print ("\n\nHere is a histogram showing how many times each frame was used:\n")
for i = 0 to NUMBER_OF_PHYSICAL_PAGE_FRAMES-1
print (" ")
printInt (i)
print (": ")
for j = 0 to histogram[i]
printChar ('*')
endFor
nl ()
endFor
print ("\n\n***** FRAME-MANAGER TEST COMPLETED SUCCESSFULLY *****\n\n")
endFunction
----------------------------- TestFrameManager ---------------------------------
--
-- This function is the main function for a thread which will test the
-- FrameManager.
--
-- Each TestFrameManager does basically this:
-- get a PCB
-- loop NUMBER_ITERATIONS_2 times
-- for sz = 1, 2, 3, ... MAX
-- call GetNewFrames to get "sz" frames
-- check to make sure the pageTable looks good
-- and store some data in the frames
-- wait
-- check to make sure the data we stored is still
-- in the frames
-- call ReturnAllFrames
-- wait
-- endFor
-- endLoop
--
function TestFrameManager (myID: int)
var i, j, newData, sz: int
pcb: ptr to ProcessControlBlock
-- printIntVar ("Thread started", myID)
pcb = processManager.GetANewProcess ()
for i = 1 to NUMBER_ITERATIONS_2
for sz = 1 to MAX_PAGES_PER_VIRT_SPACE-1
printInt (myID)
newData = GetUniqueNumber (sz)
frameManager.GetNewFrames (&pcb.addrSpace, sz)
CheckAddrSpace (&pcb.addrSpace, sz, newData)
for j = 1 to WAIT_TIME+i
currentThread.Yield ()
endFor
printChar ('.')
CheckAddrSpace2 (&pcb.addrSpace, sz, newData)
frameManager. ReturnAllFrames (&pcb.addrSpace)
for j = 1 to WAIT_TIME-i
currentThread.Yield ()
endFor
endFor
endFor
allDone2.Up ()
processManager.FreeProcess (pcb)
freeze.Down ()
endFunction
----------------------------- CheckAddrSpace ---------------------------------
--
-- This function is passed a pointer to an address space. It checks to make
-- sure that it looks good. It also stores some data in each of the frames.
--
function CheckAddrSpace (addrSpace: ptr to AddrSpace, n: int, uniq: int)
var i, frameAddr, frameNumber: int
if addrSpace.numberOfPages != n
FatalError ("addrSpace.numberOfPages is wrong")
endIf
for i = 0 to n-1
frameAddr = addrSpace.ExtractFrameAddr (i)
frameNumber = (frameAddr - PHYSICAL_ADDRESS_OF_FIRST_PAGE_FRAME) / PAGE_SIZE
-- printIntVar ("frameNumber", frameNumber)
if frameNumber < 0 ||
frameNumber >= NUMBER_OF_PHYSICAL_PAGE_FRAMES ||
frameAddr % PAGE_SIZE != 0
FatalError ("Bad frame number in some addr space")
endIf
histogram[frameNumber] = histogram[frameNumber] + 1
if addrSpace.ExtractUndefinedBits (i) != 0 ||
addrSpace.IsDirty (i) ||
addrSpace.IsReferenced (i) ||
! addrSpace.IsWritable (i) ||
! addrSpace. IsValid (i)
FatalError ("Problems with bits in some page table entry")
endIf
* (frameAddr asPtrTo int) = uniq + i
endFor
endFunction
----------------------------- CheckAddrSpace2 ---------------------------------
--
-- This function is passed a pointer to an address space. It checks to make
-- sure that the data we stored in the frame earlier is still there. The only
-- way it might have gotten corrupted is if some other thread also used this
-- frame.
--
function CheckAddrSpace2 (addrSpace: ptr to AddrSpace, n: int, uniq: int)
var i, frameAddr, frameNumber: int
if addrSpace.numberOfPages != n
FatalError ("addrSpace.numberOfPages is wrong")
endIf
for i = 0 to n-1
frameAddr = addrSpace.ExtractFrameAddr (i)
frameNumber = (frameAddr - PHYSICAL_ADDRESS_OF_FIRST_PAGE_FRAME) / PAGE_SIZE
-- printIntVar ("frameNumber", frameNumber)
if frameNumber < 0 ||
frameNumber >= NUMBER_OF_PHYSICAL_PAGE_FRAMES ||
frameAddr % PAGE_SIZE != 0
FatalError ("Bad frame number in some addr space")
endIf
if * (frameAddr asPtrTo int) != uniq + i
FatalError ("Data corruption, indicating that frame was shared")
endIf
endFor
endFunction
endCode