Bug 562791 Added RTA functions for Coop-Pre, Coop-NonPre-Pre environment

Change-Id: Ic8f4a05beddaafa958df1eaa50214e75f8050d57
Signed-off-by: The Bao Bui <Zerovnb@gmail.com>
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/NPandPRTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/NPandPRTA.java
index f161deb..4d3dc9d 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/NPandPRTA.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/NPandPRTA.java
@@ -75,7 +75,7 @@
 		/*Initialize variable to compare previous and current iteration in the formula*/

 		BigDecimal temp = BigDecimal.valueOf(2.0);

 

-		CPURta rtaia = new CPURta(this.model); 

+		CPURta rtaia = new CPURta(this.model);

 		List<Task> groupTaskList = groupTask(thisTask, ia);

 		List<Task> sortedTaskList = rtaia.taskSorting(groupTaskList);

 

@@ -152,6 +152,132 @@
 	}

 

 	/**

+	 * Calculate task's response time with C-P mixed environment (Cooperative + Preemptive)

+	 * Formula = classic RTA + max_{k of type C and in lp(i)} c_k.

+	 * In easy explaination: classic response time + blocking time caused by lower priority task, 

+	 * the blocking time equal the longest execution time of runnable inside 1 task(task have bunch of runnables, we use the longest one) 

+	 * @param thisTask

+	 * @param ia

+	 * @param executionCase

+	 * @return

+	 */

+	public Time getCooperativeTaskRTA(Task thisTask, int[] ia, TimeType executionCase) {

+		//Adding decimal Format for better visual checking when debugging

+		//ie 6000000000 ps -> 6,000,000,000 ps 

+		DecimalFormat df = new DecimalFormat("#,###.##");

+		final Logger log = Logger.getLogger(NPandPRTA.class);

+		EList<Task> listTask = this.model.getSwModel().getTasks();

+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+		Time blockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+		Time taskClassicRTA = getClassicRTA(thisTask, ia, executionCase);

+		CPURta rtaia = new CPURta(this.model);

+

+		List<Task> sortedTaskList = rtaia.taskSorting(groupTask(thisTask, ia));

+

+		//Reverse the order from highest -> lowest to the opposite lowest -> highest

+		Collections.reverse(sortedTaskList);

+		List<Task> lowerPriorityTaskList = new ArrayList<>();

+

+		/*Loop through all the task in the sorted Task list and add them to lowerPriorityTaskList until we see thisTask

+		 * I have reversed the order of the task list above so we will capture all task with lower priority via top down iteration

+		 */

+		for (Task task : sortedTaskList) {

+			int taskIndex = listTask.indexOf(task);

+			int preempTypeValue = this.preemptionTypeArray[taskIndex];

+			//add task to our list if it has lower priority and is cooperative (preempTypeValue = 2 )

+			if (!task.equals(thisTask) && preempTypeValue == 2) {

+				lowerPriorityTaskList.add(task);

+			}

+			//Get out of the loop when we met thisTask in the sorted task list

+			//Without this, lowerPriorityTaskList may add the task with higher priority

+			else if (task.equals(thisTask)) {

+				break;

+			}

+		}

+

+

+		/**

+		 * if there is no cooperative task with lower priority allocate to the processor 

+		 */

+		if (lowerPriorityTaskList.isEmpty()) {

+			//blockingTime = 0 initially

+			result = result.add(blockingTime);

+			log.debug(df.format(blockingTime.getValue()) + " ps - cooperative blocking time, no blocking");

+		}

+		/**

+		 * adding blocking time of lower priority task with non-preemptive mode (take the longest among our list)

+		 */

+		else {

+			for (Task task : lowerPriorityTaskList) {

+				Time currentBlockingTime = getLongestRunnableExecutionTime(task, ia, executionCase);

+				//Compare to find the longer one when iterate

+				if (blockingTime.compareTo(currentBlockingTime) <= 0) {

+					blockingTime = currentBlockingTime;

+				}

+				log.debug(df.format(currentBlockingTime.getValue()) + " ps - Lower priority task [" + task.getName() + "] cooperative blockingTime");

+			}

+			//add blocking time when we have find the maximum execution time among 

+			result = result.add(blockingTime);

+			log.debug(df.format(blockingTime.getValue()) + " ps - Final cooperative blocking time: ");

+		}

+		//final result should be RTA = blockingTime + classicRTA(task)

+		result = result.add(taskClassicRTA);

+

+		BigDecimal thisTaskPeriodInBigDec = new BigDecimal(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(thisTask)));

+		if (result.getValue().compareTo(thisTaskPeriodInBigDec.toBigInteger()) > 0) {

+			log.error("!!! UNSCHEDULABLE !!!");

+			log.error("Response time of task [" + thisTask.getName() + "] is bigger than its period, return 0 for RT ");

+			log.error(df.format(result.getValue()) + " > " + df.format(thisTaskPeriodInBigDec));

+			//result is 0

+			result.setValue(BigInteger.ZERO);

+			return result;

+		}

+		log.debug(df.format(result.getValue()) + "ps - Task [" + thisTask.getName() + "] C-P environment response time :");

+

+		return result;

+	}

+

+	/**

+	 * Calculate the execution time of longest/biggest runnable within task.

+	 * @param thisTask

+	 * @param ia

+	 * @param executionCase

+	 * @return

+	 */

+	private Time getLongestRunnableExecutionTime(Task thisTask, int[] ia, TimeType executionCase) {

+		final Logger log = Logger.getLogger(NPandPRTA.class);

+		//set up decimal format for debugging

+		DecimalFormat df = new DecimalFormat("#,###.##");

+

+		final int currentIndex = this.model.getSwModel().getTasks().indexOf(thisTask); //get index of the task in the array

+		final int PUI = ia[currentIndex]; // get the index of processing unit

+		final List<ProcessingUnit> pul = CommonUtils.getPUs(this.model);

+		final ProcessingUnit pu = pul.get(PUI);

+

+		//comparing value to get the longer one 

+		Time longest = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+

+		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(thisTask, null);

+		RTARuntimeUtil rtautil = new RTARuntimeUtil();

+		//In case a task doesn't invoke any runnable, better be careful than be sorry 

+		if (!runnableList.isEmpty()) {

+			for (Runnable r : runnableList) {

+				Time runnableTime = rtautil.getExecutionTimeForRTARunnable(r, pu, executionCase);

+				if (longest.compareTo(runnableTime) <= 0) {

+					longest = runnableTime;

+				}

+			}

+		}

+

+		if (runnableList.isEmpty()) {

+			log.error("!!!The task [" + thisTask.getName() + "] is doing nothing, no runnable called");

+		}

+

+		log.debug(df.format(longest.getValue()) + " ps - Longest runnable of task [" + thisTask.getName() + "]");

+		return longest;

+	}

+

+	/**

 	 * Calculation uses classic RTA + max(max_{j of type NP and in lp(i)} C_j}

 	 * basically just add a blocking time (the longest execution time of tasks) among task within the same processor

 	 * @param thisTask

@@ -168,7 +294,8 @@
 		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

 		Time blockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

 		Time taskClassicRTA = getClassicRTA(thisTask, ia, executionCase);

-		CPURta rtaia = new CPURta(this.model); 

+		CPURta rtaia = new CPURta(this.model);

+

 		List<Task> sortedTaskList = rtaia.taskSorting(groupTask(thisTask, ia));

 

 		//Reverse the order from highest -> lowest to the opposite lowest -> highest

@@ -211,7 +338,7 @@
 				if (blockingTime.compareTo(currentBlockingTime) <= 0) {

 					blockingTime = currentBlockingTime;

 				}

-				log.debug(df.format(currentBlockingTime.getValue()) + " ps - Lower priority task [" + task.getName() + "] blockingTime");

+				log.debug(df.format(currentBlockingTime.getValue()) + " ps - Lower priority task [" + task.getName() + "] Non-Preemptive blocking Time");

 			}

 			//add blocking time when we have find the maximum execution time among 

 			result = result.add(blockingTime);

@@ -236,6 +363,134 @@
 

 

 	/**

+	 * Calculation uses classic RTA + max(max_{j of type NP and in lp(i)} C_j; max_{k of type C and in lp(i)} c_k.

+	 * basically just add a blocking time 

+	 * (choose the longest time, task A will be block by another task (B/C/D) depends on each's execution time 

+	 * or each's runnable's execution time) among tasks within the same processor depend on each's preemption mode  

+	 * @param thisTask

+	 * @param ia

+	 * @param executionCase

+	 * @return

+	 */

+	public Time getMixedPreempRTA(Task thisTask, int[] ia, TimeType executionCase) {

+		//Adding decimal Format for better visual checking when debugging

+		//ie 6000000000 ps -> 6,000,000,000 ps 

+		DecimalFormat df = new DecimalFormat("#,###.##");

+		final Logger log = Logger.getLogger(NPandPRTA.class);

+		EList<Task> listTask = this.model.getSwModel().getTasks();

+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+		Time nonPreempBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+		Time coopBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+		Time taskClassicRTA = getClassicRTA(thisTask, ia, executionCase);

+		CPURta rtaia = new CPURta(this.model);

+

+		List<Task> sortedTaskList = rtaia.taskSorting(groupTask(thisTask, ia));

+

+		//Reverse the order from highest -> lowest to the opposite lowest -> highest

+		Collections.reverse(sortedTaskList);

+		List<Task> npLowerPriorityTaskList = new ArrayList<>();

+		List<Task> coopLowerPriorityTaskList = new ArrayList<>();

+

+

+		/*Loop through all the task in the sorted Task list and add them to lowerPriorityTaskList until we see thisTask

+		 * I have reversed the order of the task list above so we will capture all task with lower priority via top down iteration

+		 * lowest -> highest prio

+		 */

+		for (Task task : sortedTaskList) {

+			int taskIndex = listTask.indexOf(task);

+			int preempTypeValue = this.preemptionTypeArray[taskIndex];

+			//add task to our list if it has lower priority and is non-preemptive (preempTypeValue = 1 )

+			if (!task.equals(thisTask) && preempTypeValue == 1) {

+				npLowerPriorityTaskList.add(task);

+			}

+

+			//add task to the list if has lower priority and in cooperative (preempTypeValue = 2 )

+			else if (!task.equals(thisTask) && preempTypeValue == 2) {

+				coopLowerPriorityTaskList.add(task);

+			}

+			//Get out of the loop when we met thisTask in the sorted task list

+			//Without this, lowerPriorityTaskList may add the task with higher priority

+			else if (task.equals(thisTask)) {

+				break;

+			}

+		}

+

+

+		/**

+		 * if there is no non-preemptive task with lower priority allocate to the processor 

+		 */

+		if (npLowerPriorityTaskList.isEmpty()) {

+			//blockingTime = 0 initially

+			result = result.add(nonPreempBlockingTime);

+			log.debug(df.format(nonPreempBlockingTime.getValue()) + " ps - Non-preemptive blocking time, no blocking");

+		}

+

+		/**

+		 * if there is no cooperative task with lower priority in the same processor

+		 */

+		if (coopLowerPriorityTaskList.isEmpty()) {

+			//coop blocking time  = 0

+			result = result.add(coopBlockingTime);

+			log.debug(df.format(coopBlockingTime.getValue()) + " ps - Cooperative blocking time, no blocking");

+		}

+

+

+		/**

+		 * adding blocking time of lower priority task with non-preemptive mode and cooperative

+		 * Take the longer blocking time among the 2

+		 * Only block if there either/both task in our task lists (coop + np)

+		 */

+		if (!npLowerPriorityTaskList.isEmpty() || !coopLowerPriorityTaskList.isEmpty()) {

+			for (Task task : npLowerPriorityTaskList) {

+				int taskIndex = listTask.indexOf(task);

+				Time currentBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

+

+				/**

+				 * 1 task can only have either np or coop preemption mode anyway

+				 */

+				if (this.preemptionTypeArray[taskIndex] == 1) {

+					currentBlockingTime = getExecutionTime(task, ia, executionCase);

+				}

+				else if (this.preemptionTypeArray[taskIndex] == 2) {

+					currentBlockingTime = getLongestRunnableExecutionTime(thisTask, ia, executionCase);

+				}

+

+				/**

+				 * after the above we will have the time that [thisTask] is blocked by [task] potentially

+				 * We only need to loop through all task in [listTask] to find which [task] block [thisTask] the longest

+				 * 

+				 */

+

+				//Compare to find the longer one when iterate

+				if (nonPreempBlockingTime.compareTo(currentBlockingTime) <= 0) {

+					nonPreempBlockingTime = currentBlockingTime;

+				}

+				log.debug(df.format(currentBlockingTime.getValue()) + " ps - Lower priority task [" + task.getName() + "] blockingTime");

+			}

+			//add blocking time when we have find the maximum execution time among 

+			result = result.add(nonPreempBlockingTime);

+			log.debug(df.format(nonPreempBlockingTime.getValue()) + " ps - Final Non-preemptive/coop blocking time: ");

+		}

+		//final result should be RTA = blockingTime + classicRTA(task)

+		result = result.add(taskClassicRTA);

+

+

+		BigDecimal thisTaskPeriodInBigDec = new BigDecimal(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(thisTask)));

+		if (result.getValue().compareTo(thisTaskPeriodInBigDec.toBigInteger()) > 0) {

+			log.error("!!! UNSCHEDULABLE !!!");

+			log.error("Response time of task [" + thisTask.getName() + "] is bigger than its period, return 0 for RT ");

+			log.error(df.format(result.getValue()) + " > " + df.format(thisTaskPeriodInBigDec));

+			//result is 0

+			result.setValue(BigInteger.ZERO);

+			return result;

+		}

+		log.debug(df.format(result.getValue()) + "ps - Task [" + thisTask.getName() + "] NP environment response time :");

+

+		return result;

+	}

+

+

+	/**

 	 * this function will get PURE execution time via calculate execution time of task's runnables

 	 * @param thisTask

 	 * @param ia

@@ -248,7 +503,7 @@
 		final List<ProcessingUnit> pul = CommonUtils.getPUs(this.model);

 		final ProcessingUnit pu = pul.get(PUI);

 		RTARuntimeUtil rtautil = new RTARuntimeUtil();

-		

+

 		/* The list of runnables of the given task */

 		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(thisTask, null);

 

@@ -308,8 +563,8 @@
 		final List<Task> stepOneTaskList = new ArrayList<>();

 		final EList<Task> taskList = this.model.getSwModel().getTasks();

 		final int currentIndex = this.model.getSwModel().getTasks().indexOf(thisTask);

-		

-		CPURta rtaia = new CPURta(this.model); 

+

+		CPURta rtaia = new CPURta(this.model);

 		final int PUI = ia[currentIndex];

 		for (int i = 0; i < ia.length; i++) {

 			if (PUI == ia[i]) {

@@ -318,9 +573,8 @@
 		}

 

 		return rtaia.taskSorting(stepOneTaskList);

-		

-	}

 

+	}

 

 

 }