package javax.safetycritical;
/**
* This class is a two dimension set, which contains pairs of clock and process.
* The infrastructure will use this class to model the wait set and lock set.
*/
class PriorityQueueForLockAndWait {
int[] queue;
int tail;
int queueSize;
PriorityQueueForLockAndWait(int size) {
queue = new int[size];
tail = -1;
queueSize = 0;
makeEmptyQueue(queue);
}
private void makeEmptyQueue(int[] set) {
for (int i = 0; i < set.length; i++)
set[i] = -999;
}
/**
* Add a relation between the lock and the process into the set.
*
* @param target
* The lock associate with the process
* @param process
* The process
*/
protected void addProcess(Object monitor, ScjProcess process) {
vm.ClockInterruptHandler.instance.disable();
if (tail < queue.length - 1) {
tail++;
int index = tail;
// find the place in the set for this process
for (int i = 0; i < tail; i++) {
ScjProcess temp = getScjProcess(queue[i]);
if (temp == null)
throw new IllegalArgumentException("1");
if (ManagedSchedMethods.getPriorityParameter(process.getTarget()).getPriority()
> ManagedSchedMethods.getPriorityParameter(temp.getTarget()).getPriority()) {
index = i;
break;
}
}
// reserve the place in the set for this process
if (index != tail) {
for (int i = tail; i > index; i--) {
queue[i] = queue[i - 1];
}
}
// add the index of the process into the set and set the required lock
process.monitorLock = monitor;
queue[index] = process.index;
queueSize++;
} else {
throw new IndexOutOfBoundsException("set: too small");
}
//print();
vm.ClockInterruptHandler.instance.enable();
}
/**
* Get the first process who needs to lock.
* Rules:
* 1. The highest priority process who needs the lock will be returned.
* 2. If there are more than one processes who have the same priority, then FIFO.
*
* @param target
* The lock
* @return The process who needs to lock.
*/
protected /*synchronized*/ ScjProcess getNextProcess(Object monitor) {
for (int i = 0; i <= tail; i++) {
ScjProcess process = getScjProcess(queue[i]);
if (process.monitorLock == monitor) {
process.monitorLock = null;
reorderSet(i);
queueSize--;
return process;
}
}
return null;
}
public /*synchronized*/ void removeProcess(ScjProcess process) {
for (int i = 0; i <= tail; i++) {
if (queue[i] == process.index) {
reorderSet(i);
process.monitorLock = null;
queueSize--;
}
}
}
private void reorderSet(int index) {
for (int i = index; i <= tail - 1; i++) {
queue[i] = queue[i + 1];
}
queue[tail] = -999;
tail--;
}
private ScjProcess getScjProcess(int processIdx) {
if (processIdx == -999) {
return null;
}
if (processIdx == -2) {
return PriorityScheduler.instance().outerMostSeqProcess;
}
if (processIdx == -1) {
return ScjProcess.idleProcess;
}
int missionIndex = processIdx / 20;
int scjProcessIndex = processIdx % 20;
return Mission.getScjProcess(missionIndex, scjProcessIndex);
}
/**
* For testing purpose.
*/
public void print() {
devices.Console.println("queue size = " + (tail + 1));
// for (int i = 0; i <= tail; i++) {
// ScjProcess temp = getScjProcess(queue[i]);
// if (temp != null)
// devices.Console.println(temp.print());
// }
for (int i = 0; i < queue.length; i++) {
devices.Console.print("[ " + queue[i] + " ] ");
}
devices.Console.println("");
}
}