Open main menu

lensowiki β

Changes

Computer Science/162/proj1

5,025 bytes added, 03:51, 20 February 2023
m
===Implementation===
;New state variables
{{c|KThread}} has a new state variable {{c|joinedOnMe}}, a {{c|ThreadQueue}}., and {{c|isJoined}}, a {{c|boolean}}
;Implementation details
}</pre>}}
==WaitUntil{{c|waitUntil()}}==
===Implementation===
;New state variables
Alarm has a new instance variable, {{c|waitingThreads}}, which is a Java {{c|PriorityQueue }} of waiting threads with the target wake time as their priority. It also contains a new inner class named waitingThread{{c|WaitingThread}}, which contains a reference to a {{c|KThread }} and its associated {{c|wakeTime}}. The {{c|PriorityQueue waitingThreads }} will be populated with instances of this inner class.
;Implementation details
* {{c|waitUntil() }} creates a new instance of {{c|waitingThread}}, which will associate the currentThread current thread with the give given time argument. It will then add this {{c|waitingThread }} instance to the {{c|PriorityQueue }} and put the current thread to sleep. This method is atomic. * {{c|timerInterrupt() peek }} peeks at the first {{c|WaitingThread }} in the {{c|waitQueue }} and check checks if its associated wake time is less than or equal to the current time. If it is, this method will pop the {{c|WaitingThread }} off the {{c|waitQueue }} and wake the associated thread. This process is repeated until the wake time of the first {{c|WaitingThread }} is greater than the current time.
===Testing===
* Have the timer interrupt print a debug statement, and have timed threads print the times they go to sleep and when they have woken up. Verify that they wake up relatively close to their expected exit wake time.
* Make sure threads called with illegal times return immediately. Test threads that go to sleep chronologically in order (1, 500, 1050) as well as threads that go to sleep with the same times (50, 50) and threads that go to sleep in reverse order (500, 250). Verify they all wake up when they are supposed to.
Re-enable interrupts;
}</pre>}}
 
{{c|<pre>timerInterrupt(){
Wake a waiting listener;
}
Sleep as an active speakerwaiting to return;
AS--;
AL--;
Wake a waiting speaker;
}
Sleep as an active listenerwaiting to return;
AL--;
AS--;
===Implementation===
;New state variables
*'''PriorityQueue''' – {{c|PriorityQueue.holder}} - this ThreadState corresponds to the holderof the resource signified by the * {{c|PriorityQueue.waitQueue}} - an ArrayList of ThreadStates waiting on this resource. Unsorted.* {{c|PriorityQueue.dirty}} - set to true when a new thread is added to the queue, ArrayList<ThreadState> or any of the queues in the waitQueue, int flag themselves as dirty.* {{c|PriorityQueue.effective}} - the cached highest of the effective, boolean priorities in the waitQueue. This value is invalidated while dirtyis true. * {{c|ThreadState.myResources}}<br />- collection of PriorityQueues that signify the Locks or other resources that this thread currently holds.*'''{{c|ThreadState''' – .waitingOn}} - collection of PriorityQueues corresponding to resources that this thread has attempted to acquire but could not.* {{c|int ThreadState.effective}} - the cached effective, boolean priority of this thread. this value is invalidated when dirty is true* {{c|ThreadState.dirty}} - set to true when this thread's priority is changed, HashSet<PriorityQueue> or when one of the queues in myResources, WaitingOn}}<br />flags itself as dirty.
;Implementation overviewThe idea here is that {{c|Thread}}s keep track of the {{c|PriorityQueue.holder - this ThreadState corresponds }}s corresponding to both the holder of the resource signified by the PriorityQueueresources that they are currently holding and those that they want to hold.waitQueue - an ArrayList of ThreadStates waiting on We can do this resource. Unsorted.via hooks in {{c|PriorityQueue.dirty - set to true when a new thread is added to the queue}}'s {{c|waitForAccess()}}, {{c|acquire}}, or any of the queues in the waitQueue flag themselves as dirty.PriorityQueue.effective - the cached highest of the effective priorities in the waitQueue. This value is invalidated while dirty is trueand {{c|nextThread}} methods.
ThreadState.myResources - collection Once we have this, every time a thread tries to wait on a queue, or takes control of PriorityQueues a queue, we can tell the queue that signify its overall effective priority may have changed, and it can, in turn, tell the Locks or other resources thread that this thread currently holds.ThreadState.waitingOn - collection the resource that one of PriorityQueues corresponding to resources that this thread has attempted to acquire but could not.ThreadState.effective - the cached effective {{c|PriorityQueue}}s it holds may have had its priority of this threadchanged. this value That holder can in turn tell the same to the {{c|PriorityQueue}}s that it is invalidated when dirty is trueThreadStatewaiting on, and so forth.dirty - set to true when this Eventually a thread's , which is holding a resource that everyone needs, but has a low priority is changed, or when one of the queues in myResources flags itself as dirtywill be marked for priority recalculation and thus priority escalation.
At this point, recalculation is simple. The effective priority of a thread is the maximum of its own actual priority and the priorities of all the {{c|PriorityQueue}}s that it currently holds. The effective priority of a {{c|PriorityQueue}} is the maximum effective priority of all the threads waiting on it (if the queue is supposed to donate priority), and so on and so forth in a mutually recursive manner.
;Implementation details
* {{c|PriorityQueue.nextThread()}}* :This method retrieves and removes the highest priority thread off the Priority-Time {{c|ArrayList}}. It then flags the previous holder of this resource as {{c|dirty}}, and removes the queue from that holder's resource list. It then sets the retrieved thread to this queue's new {{c|holder}}, and flags that thread as {{c|dirty }} as well.* {{c|PriorityQueue.acquire(KThread thread)}}* :Sets the {{c|holder }} of this queue to the specified thread, bypassing the queue. Resets previous {{c|holder }} and sets {{c|dirty }} flags as in {{c|nextThread()}}.* {{c|PriorityQueue.pickNextThread()}}* :Simply retrieves the highest priority thread off this queue.* {{c|PriorityQueue.setDirty()}}:Set this queue's {{c|dirty}} flag, and calls {{c|setDirty}} on the current holder of this thread.* {{c|PriorityQueue.getEffectivePriority()}}* :If this queue is "{{c|dirty"}}, returns the maximum of each of the ThreadStates{{c|ThreadState}}s{{c|.getEffectivePriority() }} in this queue. Those calls in turn become mutually recursive when they call {{c|getEffectivePriority ()}} on the {{c|PriorityQueues }} in their myResrouces{{c|myResources}}.* {{c|ThreadState.setPriority() }}:This method will change the actual priority of the thread associated with the {{c|ThreadState}}. It then calls {{c|setDirty()}} on this thread. The effective priority * {{c|ThreadState.setDirty()}}:Sets the {{c|dirty}} flag on this thread, then calls {{c|setDirty()}} on each of lastThread must also be by difference between current threads priority and new prioritythe {{c|PriorityQueue}}s that the thread is waiting for. Mutually recursive. *{{c|ThreadState.getEffectivePriority}}:Like the analogue of this function in {{c|PriorityQueue}}, returns the (cached) priority if this thread is not {{c|dirty}}; otherwise, recalculates by returning the max of the effective priorities of the {{c|PriorityQueue}}s in {{c|myResources}}.
===Testing===
* Instantiate new threads and set their priorities in decreasing order. Have the threads state their priorities as they execute and verify that they were run in decreasing order according to their priorities.
* Verify donation works by creating a high priority thread and joining it to a low priority thread with a high priority thread already queued.
* Create complex set of interdependent threads and multiple locks, verify that execution order is correct.
===Pseudocode===
FIXME;PriorityQueue{{c|<pre>public void waitForAccess(KThread thread) add this thread to my waitQueue thread.waitForAccess(this) public void acquire(KThread thread) if I have a holder and I transfer priority, remove myself from the holder's resource list thread.acquire(this) public KThread nextThread() if I have a holder and I transfer priority, remove myself from the holder's resource list if waitQueue is empty, return null ThreadState firstThread = pickNextThread(); remove firstThread from waitQueue firstThread.acquire(this); return firstThread public int getEffectivePriority() if I do not transfer priority, return minimum priority if (dirty) effective = minimum priority; for each ThreadState t in waitQueue effective = MAX(effective, t.getEffectivePriority()) dirty = false; return effective;  public void setDirty() if I do not transfer priority, there is no need to recurse, return dirty = true; if I have a holder, holder.setDirty() protected ThreadState pickNextThread() ThreadState ret = null for each ThreadState ts in waitQueue if ret is null OR ts has higher priority/time ranking than ret set ret to ts return ret;</pre>}} ;ThreadState{{c|<pre>public int getPriority() return non-donated priority. public int getEffectivePriority() if (dirty) { effective = non-donated priority for each PriorityQueue pq that I am currently holding effective = MAX(effective, pq.getEffectivePriority) } return effective; public void setPriority(int priority) set non-donated priority to the argument setDirty();  public void setDirty() if already dirty return dirty = true; for each of the PriorityQueues pq I am waiting on, pq.setDirty public void waitForAccess(PriorityQueue waitQueue) add the waitQueue to my waitingOn list if the waitQueue was previously in myResources, remove it and set its holder to null. if waitQueue has a holder, set the queue to dirty to signify possible change in the queue's effective priority public void acquire(PriorityQueue waitQueue) add waitQueue to myResources list if waitQueue was in my waitingOn list, remove it setWaitQueue's holder to me setDirty();</pre>}}
==Boat.java==
===Implementation===
Algorithm for solving boat problem (high level):
If there are no children on Molokai or if there are no adults left on Oahu, two children from Oahu will pilot over and one will return to Molokai. If there is a child on Molokai, an adult will pilot over to Molokai and the child will bring the boat back to Oahu. This process, carried to completion eventually results in all of the adults and children on Molokai.
 
;New state variables (all shared)
{{c|<pre>lock = new Lock()
In addition, each thread has a local variable to keep track of which island the person is currently on.
;Basic ideaImplementation overviewIf there are no children on Molokai or if there are no adults left on Oahu, two children from Oahu will pilot over and one will return to Molokai. If there is a child on Molokai, an adult will pilot over to Molokai and the child will bring the boat back to Oahu. This process, carried to completion eventually results in all of the adults and children on Molokai. Each thread will attempt to acquire the lock (which essentially represents control over the boat). If the thread can perform one of the tasks fitting for the current state of the world, it executes it. Otherwise, it will go to sleep on the condition variable corresponding to its current role and location.
;Algorithm Implementation details
Each child will begin running on Oahu and try to acquire the lock.
==Design questions==
;Why is it fortunate that we did not ask you to implement priority donation for semaphores?
:Be damned Currently, each time a thread acquires a lock or calls {{c|join()}}, we know who is currently holding the resource. This allows us to donate priority to this single resource if I knowa higher-priority thread begins waiting on it. With semaphores, this is not possible for initial values greater than 1, because the last thread to successfully "acquire" the semaphore will not necessarily be the one with the lowest priority. The implementation would need to change to keep track of all threads that are actually using the semaphore currently and thus be able to determine which of those has the lowest priority and needs to "receive" a donation. Anyone?
;A student proposes to solve the boats problem by use of a counter, AdultsOnOahu. Since this number isn't known initially, it will be started at zero, and incremented by each adult thread before they do anything else. Is this solution likely to work? Why or why not?
:No, because there is no way of enforcing the fact that everyone will increment it before they do anything else.
1,277
edits