Open main menu

lensowiki β

Changes

Computer Science/162/proj1

429 bytes added, 03:51, 20 February 2023
m
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--;
==Priority Scheduler==
===Implementation===
;New state variables
* {{c|PriorityQueue.holder}} - this ThreadState corresponds to the holder of 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, or any of the queues in the waitQueue flag themselves as dirty.
* {{c|PriorityQueue.effective}} - the cached highest of the effective priorities in the waitQueue. This value is invalidated while dirty is true.
The idea here is that Threads keep track * {{c|ThreadState.myResources}} - collection of the PriorityQueues corresponding to both that signify the Locks or other resources that they are currently holding and those that they want to hold. We can do this via hooking PriorityQueue's waitForAccess, acquire, and nextThread. Once we have this, every time a thread tries to wait on a queue, or takes control of a queue, we can tell that queue that its overall effective priority may have changed, and it can in, turn tell the thread that currently holds the resource that one .* {{c|ThreadState.waitingOn}} - collection of the PriorityQueues it holds may have had its priority changed. That holder can in turn tell the same corresponding to the PriorityQueues resources that it is waiting on, and so on. Eventually a this thread holding a resource that everyone needs, has attempted to acquire but with a low priority will be marked for priority recalculationcould notAt this point recalculation is simple* {{c|ThreadState. The effective}} - the cached effective priority of a this thread is the maximum of its own actual priority and the priorities of all the PriorityQueues that it currently holds. The effective priority of a PriorityQueue this value is the maximum effective priority of all the threads waiting on it (if the queue invalidated when dirty is supposed to donate priority), and so on and so forth in this mutually recursive manner. ;New state variablestrue*'''PriorityQueue''' – {{c|ThreadState holder, ArrayList<ThreadState> waitQueue, int effective, boolean .dirty}}<br />*- set to true when this thread'''ThreadState''' – {{c|int effectives priority is changed, boolean or when one of the queues in myResources flags itself as dirty, HashSet<PriorityQueue> myResources, WaitingOn}}<br />.
;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 does calls {{c|setDirty() }} on this thread.* {{c|ThreadState.setDirty()}}* :Sets the {{c|dirty }} flag on this thread, then calls {{c|setDirty()}} on each of the PriorityQueues {{c|PriorityQueue}}s that the thread is waiting for, does setDirty on them. 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, otherwise recalculates by returning the max of the effective priorities of the PriorityQueues {{c|PriorityQueue}}s in {{c|myResources}}.
===Testing===
===Pseudocode===
;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;
ThreadState {public void setPriority(int priority) set non-donated priority to the argument setDirty();
public int getPriorityvoid setDirty() if already dirty return non-donated priority. public int getEffectivePriority() if ( dirty) { effective = non-donated prioritytrue; for each PriorityQueue of the PriorityQueues pq that I am currently holdingwaiting on, effective = MAX(effective, pq.getEffectivePriority) } return effective;setDirty
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(); }
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==
In addition, each thread has a local variable to keep track of which island the person is currently on.
;Basic ideaImplementation overview
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. 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