0

I am trying to implement the KThread.join() method in nachos OS. My sample code fragment is as follows:

private KThread toJoin = null;
public void join() {
Lib.debug(dbgThread, "Joining to thread: " + toString());

Lib.assertTrue(this != currentThread);


    Lib.assertTrue(toJoin == null);
    boolean intStatus = Machine.interrupt().disable();

   if (status != statusFinished) 
   {
       toJoin = KThread.currentThread();
       KThread.sleep();
   }
   Machine.interrupt().restore(intStatus);
}

public static void finish() {
Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());

Machine.interrupt().disable();

Machine.autoGrader().finishingCurrentThread();

Lib.assertTrue(toBeDestroyed == null); // what is being done in this line?
toBeDestroyed = currentThread;

     if (currentThread.toJoin != null)   
     {
       currentThread.toJoin.ready(); ////what is being done in this line?
     }
currentThread.status = statusFinished;

sleep();
}

My questions is If I create a parent thread and inside it I create a child and call child.join() method, then what will happen to the parent thread? According to me It will go to sleep until the child thread has finished it's task. Am I right? I have some more questions on this:

  1. when will the finish() method will be called? Is it called for both the parent and child thread?
  2. Inside the finish() method what is actually being done in the lines I have commented out?
user5520111
  • 23
  • 3
  • 9

1 Answers1

0

Gonna be upfront, I don't remember much about this class. The way I remember it working is the child would call join, then the parent would have to finish before the child resumes.

To answer your questions:

  1. The finish method is called after the process assigned to that thread has completed and the thread is going to be destroyed.
  2. The first line you commented out checks to make sure there are no other threads waiting to be destroyed. (I'm assuming the reason for this is we want to give threads who are waiting to be destroyed priority in the Queue, but I don't remember 100%). The second line adds the thread trying waiting to join back into the ready queue so it will take a turn running because we called the sleep method on it in the join() method.

    public void join() {
        Lib.debug(dbgThread, "Joining to thread: " + toString());
    
       Lib.assertTrue(this != currentThread);
        // Entering a critical Section
        Machine.interrupt().disable();
        // Check if the queue has been instantiated
        if(joinerQueue == null){
            // Instantiate it
            joinerQueue = ThreadedKernel.scheduler.newThreadQueue(true);
        }
        // Check if the thread is finished
        if (status == statusFinished) {
            return;
        }
        else {
            // We give joinerQueue the lock of this in order to transfer the priority of this thread
            joinerQueue.acquire(this);
            // we are adding the currentThread to the joinerQueue
            joinerQueue.waitForAccess(currentThread);
            // We sleep the currentThread because we need to wait until this thread finishes
            // When this thread finishes we will wake up in the finish() method
            currentThread.sleep();
        }
        Machine.interrupt().enable();
    }
    
    public static void finish() {
        Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());
        // Critical Section
        Machine.interrupt().disable();
        // Get the threads which are waiting for the currentThread to finish
        ThreadQueue currentQueue = currentThread.joinerQueue;
        // if currentQueue is not null, means there are threads waiting to join
        if(currentQueue != null) {
            // Get the first thread from the queue
            KThread curThread = currentQueue.nextThread();
            // While there are more threads, ready them up
            while ( curThread != null ) {
                curThread.ready();
                currentThread.joinerQueue.acquire(curThread);
                // Get the next thread to ready up
                curThread = currentQueue.nextThread();
            }
        }
    
        Machine.autoGrader().finishingCurrentThread();
    
        Lib.assertTrue(toBeDestroyed == null);
        toBeDestroyed = currentThread;
    
        currentThread.status = statusFinished;
    
        sleep();
    }
    
Thomas L
  • 33
  • 1
  • 1
  • 6