boolean flag[2]; /* flag[0]=flag[1]=false */ int turn=0;
i
=0 or 1,
j
==1-i
.
while (1) { flag[i]=true; if (flag[j] && (turn==j)) { flag[i]=false; while (turn==j); flag[i]=true; } /* critical section */ flag[i]=false; turn=j; /* remainder section */ }
boolean flag[2]; /* flag[0]=flag[1]=false */ int turn=0;
i
=0 or 1,
j
==1-i
.
while (1) { flag[i]=true; while (flag[j] && (turn==j)); /* critical section */ flag[i]=false; turn=j; /* remainder section */ }
wait
:
wait(S1); C--; if (C<0) { signal(S1); wait(S2); } else { signal(S1); }
signal
:
wait(S1); C++; if (C<=0) { signal(S2); } signal(S1);
wait
:
wait(S1); C--; signal(S1); if (C<0) { wait(S2); signal(S1); }
signal
:
wait(S1); C++; if (C<=0) { signal(S2); } else { signal(S1); }
csci4534.allocator.MainSimulator
. This simulator keeps
track of a set of simulated processes and multi-instance resources, as
processes and resources are created and terminated/deleted, and
processes request and release resource instances. For example,
after you complete this task,
allocate.bat BankersAllocator np np np np nr:2 nr:2 nr:1 a:0:1:2 a:2:1:1:2:1 a:3:1:1 a:1:0:2 a:0:0:2 a:1:1:2 r:0:0:1 xp:0 a:1:1:2 xr:0will perform the following simulation and report the following output:
csci4534.allocator.Allocator
interface,
csci4534.allocator.BankersAllocator
in this case, and
reports its name. You will only implement this single allocator in
this programming task, and you are given no other allocator
implementation. This is why you cannot get the output in the following
steps if you execute the above command-line before you complete this
task.
Allocator: csci4534.allocator.BankersAllocator
csci4534.allocator.Process
interface;
BankersAllocator
creates an instance of the
csci4534.allocator.BankersProcess
class. The simulator
then assigns an arbitrary internal integer ID to this instance, and
reports it on the screen, presumably 0 in this case. When applicable,
the process ID is supplied as the first argument to other operations.
Creating process: 0
Creating process: 1 Creating process: 2 Creating process: 3
csci4534.allocator.Resource
interface;
BankersAllocator
creates an instance of the
csci4534.allocator.BankersResource
class. Do not be
confused by the multiple but distinct meanings of the word
instance here: there are instances of Java classes, and there
are instances of resources managed by the allocator. In this case, the
simulator asks the allocator to create a single Java object; that
single object must implement Resource
; that single object
must also represent a resource that has two instances available for
allocation initially (the number of instances is given to the
allocator); the allocator produces a single Java object whose class is
BankersResource
. The simulator then assigns an arbitrary
internal integer ID to this object, and reports it on the screen,
presumably 0 in this case.
Creating resource with 2 instances: 0
Creating resource with 2 instances: 1 Creating resource with 1 instances: 2
csci4534.allocator.Request
object, which identifies the
relevant process and resource(s) via the Process
and
Resource
implementations the allocator created above; the
allocator does not see the IDs used by the simulator. For each
resource that is part of a request, a Request
object
contains a csci4534.allocator.ResourceCount
object,
pairing a Resource
object with the number of requested
resource instances.
When the allocator processes the request, the simulator reports its response. In this case, the request is granted because the resource instances are available, and the allocation would not violate the allocator's fairness (a.k.a. no starvation) policy.
Allocation request [0;(1,2)]: granted
Allocation request [2;(1,1)(2,1)]: enqueued
Allocation request [3;(1,1)]: enqueued
Allocation request [1;(0,2)]: granted
Allocation request [0;(0,2)]: enqueued
csci4534.allocator.AllocatorException
, signifying that
not only can't the request be granted, but it also can't be enqueued
because doing so would immediately bring the system into a deadlocked
state. The simulator simply displays the exception.
Allocation request [1;(1,2)]: csci4534.allocator.AllocatorException: Deadlock will occur if process is enqueued
Request
instance; but the simulator calls a different
method of the allocator than the one it calls for resource
allocation. The allocator throws an AllocatorException
,
signifying that a process that has a pending request cannot take any
direct de/allocation action. That is because such processes are in the
waiting state, and do not receive CPU time to take further action. In
other words, our attempt supplied an invalid input which the allocator
recognized as such.
Release [0;(1,2)]: csci4534.allocator.AllocatorException: Process has pending request
Now that resource instances have become available, some of the pending
requests may be able to proceed. So the allocator may dequeue and
grant pending requests from the queue, depending on its fairness
policy. The allocator does this whenever resource instances become
available, whether by process deletion (xp
command) or
successful resource release (r
command). The simulator
receives this list of granted requests, and displays them. In this
case, process 2 receives 1 instance of resource 1, and 1 instance of
resource 2; and process 3 receives 1 instance of resource 1.
Deleting process 0: done Dequeued: [2;(1,1)(2,1)] Dequeued: [3;(1,1)]
Allocation request [1;(1,2)]: enqueued
AllocatorException
. In other words, our attempt supplied
an invalid input that the allocator recognized it as such. Resource 0
is not deleted. This is analogous to requesting Windows to delete a
file currently open by some application, and being told that the
operation cannot be completed.
Deleting resource 0: csci4534.allocator.AllocatorException: The resource is in active use
Resources: ID: 0; Available: 0 ID: 1; Available: 0 ID: 2; Available: 0 Processes: ID: 1; Allocations: (0,2) ID: 2; Allocations: (2,1)(1,1) ID: 3; Allocations: (1,1) Allocator request queue: [1;(1,2)]
Allocator
, Process
, and
Resource
(the three interfaces you have to implement),
along with the rest of the provided code. For most classes, it might
be convenient to read first the HTML documentation produced from the
code's javadoc comments (by running jdoc.bat
). The HTML
documentation doesn't cover everything (e.g. it doesn't cover in-line
comments or private methods), but it's more readable.
After you have finished studying the provided code, get ready to fill-in the provided stub classes with your allocator implementation. As you form your plan of attack, keep in mind the following:
make.bat
to build your
code.
BankersProcess
and BankersResource
be pure
data containers (e.g. BankersResource
holds the number of
total resource instances and BankersProcess
holds the
process allocations), keeping all algorithms within
BankersAllocator
. Or, you can have a top-down design
where BankersProcess
and BankersResource
perform computations on their data only, and
BankersAllocator
treats their methods as helpers. The
choice is yours to make between the above or any other design
alternatives. Whatever your choice, though, the final code structure
should be reasonable and well-commented.
[2 points] Implement
csci4534.allocator.Vector
.
[18 points] Compose a minimal implementation of the
allocator in BankersAllocator
and its helpers
BankersProcess
and BankersResource
. Such an
implementation maintains correctly the queue of pending requests, the
list of active processes, the list of active resources, their
respective allocations, etc. Also, all allocator methods are correctly
implemented. For example, the release of a resource and the deletion
of a process should trigger the granting of the proper pending
requests. However, do not worry at this point about deadlocks,
robustness, or fairness.
[20 points] Add deadlock detection to your implementation via the banker's algorithm variant of section 8.6.2 of your textbook.
[10 points] Improve your implementation to make it robust. It is critical that you make no assumptions regarding the arguments to your methods, except that no arguments will
Process
argument may receive null
, or a process created by
another allocator. Again, these are examples; it is up to you
to determine the complete list of possible invalid inputs or invalid
states you may encounter. Be sure to throw instances of
AllocationException
with a descriptive message whenever
your allocator detects any misuse of its methods. Real OS resource
allocators have to be extremely robust given their pivotal role in the
reliable operation of a computer system.
[10 points] Add a fairness policy to your implementation. That is, a process that issues a pending request will not be forever bypassed by other processes which make later allocation requests for the same resource(s). Document your policy in detail with in-line comments. For a fairness policy to receive full marks, it should be not only fair, but it should also achieve good resource utilization: allowing a single allocation at a time across all processes and resources guarantees fairness but it's not at all efficient. Of course, its implementation should also be correct.
[1 point] How much time did you spend on this section?