Finished Part 1 and 2 with naive testing

master
ginger88895 2019-04-01 22:28:24 +08:00
parent 33ebdf5cfd
commit a7b419fbb1
8 changed files with 129 additions and 26 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -20,8 +20,9 @@ public class Condition2 {
* lock whenever it uses <tt>sleep()</tt>,
* <tt>wake()</tt>, or <tt>wakeAll()</tt>.
*/
public Condition2(Lock conditionLock) {
this.conditionLock = conditionLock;
public Condition2(Lock conditionLock)
{
this.conditionLock = conditionLock;
}
/**
@ -30,29 +31,48 @@ public class Condition2 {
* current thread must hold the associated lock. The thread will
* automatically reacquire the lock before <tt>sleep()</tt> returns.
*/
public void sleep() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
public void sleep()
{
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
conditionLock.release();
conditionLock.acquire();
conditionLock.release();
boolean intStatus=Machine.interrupt().disable();
waitQueue.waitForAccess(KThread.currentThread());
KThread.sleep();
Machine.interrupt().restore(intStatus);
conditionLock.acquire();
}
/**
* Wake up at most one thread sleeping on this condition variable. The
* current thread must hold the associated lock.
*/
public void wake() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
public void wake()
{
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
boolean intStatus=Machine.interrupt().disable();
KThread a=waitQueue.nextThread();
if(a!=null) a.ready();
Machine.interrupt().restore(intStatus);
}
/**
* Wake up all threads sleeping on this condition variable. The current
* thread must hold the associated lock.
*/
public void wakeAll() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
public void wakeAll()
{
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
boolean intStatus=Machine.interrupt().disable();
while(true)
{
KThread a=waitQueue.nextThread();
if(a!=null) a.ready();
else break;
}
Machine.interrupt().restore(intStatus);
}
private Lock conditionLock;
private ThreadQueue waitQueue=ThreadedKernel.scheduler.newThreadQueue(true);
}

View File

@ -193,6 +193,10 @@ public class KThread {
currentThread.status = statusFinished;
currentThread.condLock.acquire();
currentThread.joinCondition.wakeAll();
currentThread.condLock.release();
sleep();
}
@ -277,6 +281,14 @@ public class KThread {
Lib.assertTrue(this != currentThread);
if(status==statusFinished) return;
else
{
condLock.acquire();
joinCondition.sleep();
condLock.release();
}
}
/**
@ -381,30 +393,98 @@ public class KThread {
Lib.assertTrue(this == currentThread);
}
private static class PingTest implements Runnable {
PingTest(int which) {
this.which = which;
}
public void run() {
for (int i=0; i<5; i++) {
System.out.println("*** thread " + which + " looped "
+ i + " times");
currentThread.yield();
}
}
private static class PingTest implements Runnable
{
PingTest(int which,KThread other)
{
this.which=which;
this.other=other;
}
public void run()
{
if(other!=null) other.join();
if(other!=null) other.join();
for(int i=0;i<5;i++)
{
System.out.println("*** thread " + which + " looped " + i + " times");
currentThread.yield();
}
}
private int which;
private int which;
private KThread other;
}
private static class Condition2Test implements Runnable
{
Condition2Test(int id)
{
this.id=id;
this.wakeMode=-1;
}
Condition2Test(int id,int wakeMode)
{
this.id=id;
this.wakeMode=wakeMode;
}
public void run()
{
if(id==0)
{
for(int i=0;;i++)
{
if(i%100==0)
{
cond2Lock.acquire();
if(wakeMode==0) cond2.wake();
else cond2.wakeAll();
cond2Lock.release();
}
System.out.println("Main: "+i);
currentThread.yield();
}
}
else
{
for(int i=0;;i++)
{
cond2Lock.acquire();
cond2.sleep();
cond2Lock.release();
System.out.println("Thread "+id+" awakened! i="+i);
currentThread.yield();
}
}
}
private int id;
private int wakeMode;
private static Lock cond2Lock=new Lock();
private static Condition2 cond2=new Condition2(cond2Lock);
}
/**
* Tests whether this module is working.
*/
public static void selfTest() {
Lib.debug(dbgThread, "Enter KThread.selfTest");
new KThread(new PingTest(1)).setName("forked thread").fork();
new PingTest(0).run();
//new KThread(new PingTest(1)).setName("forked thread").fork();
//Test for KThread2.join()
/*
KThread t1=new KThread(new PingTest(1,null)).setName("forked thread");
t1.fork();
new PingTest(0,t1).run();
*/
//Test for Condition2
new KThread(new Condition2Test(1)).fork();
new KThread(new Condition2Test(2)).fork();
new KThread(new Condition2Test(3)).fork();
new KThread(new Condition2Test(4)).fork();
new Condition2Test(0,1).run();
}
private static final char dbgThread = 't';
@ -444,4 +524,7 @@ public class KThread {
private static KThread currentThread = null;
private static KThread toBeDestroyed = null;
private static KThread idleThread = null;
public Lock condLock=new Lock();
private Condition joinCondition=new Condition(condLock);
}