diff --git a/.cproject b/.cproject
index 69f6bd70..e65ec079 100644
--- a/.cproject
+++ b/.cproject
@@ -15,11 +15,11 @@
-
+
-
+
@@ -97,6 +97,7 @@
+
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index fe6a1783..f9debd37 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -17,7 +17,7 @@
-
+
diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs
index 567f4d3d..ec086c6d 100644
--- a/.settings/org.eclipse.cdt.codan.core.prefs
+++ b/.settings/org.eclipse.cdt.codan.core.prefs
@@ -22,7 +22,7 @@ org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={lau
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning
-org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()}
+org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"The use of function or method is denied\\")",blacklist\=>()}
org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
@@ -97,6 +97,8 @@ org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true}
+org.eclipse.cdt.codan.internal.checkers.TemplateInstantiationProblem=Error
+org.eclipse.cdt.codan.internal.checkers.TemplateInstantiationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be instantiated\\")"}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
diff --git a/src/include/error.h b/src/include/error.h
index a8d52e7a..86ffd413 100644
--- a/src/include/error.h
+++ b/src/include/error.h
@@ -7,10 +7,13 @@
#include
#if DEBUG
- extern FILE * dbg_out; // debug output file, defined in main
+ extern FILE * dbg_out; // debug output file, defined in main
+ extern FILE * stats_out; // debug output file, defined in main
#define printDbg(...) (void)fprintf (dbg_out, __VA_ARGS__)
+ #define printStat(...) (void)fprintf (stats_out, __VA_ARGS__)
#else
#define printDbg(...) //
+ #define printStat(...) //
#endif
// Common standard printing definitions
diff --git a/src/lib/parse_config.c b/src/lib/parse_config.c
index 7c32b2af..27557085 100644
--- a/src/lib/parse_config.c
+++ b/src/lib/parse_config.c
@@ -420,6 +420,9 @@ static void parse_images(struct json_object *images, containers_t *conts)
/// Return value: no return value, exits on error
void parse_dockerfileprefix(prgset_t *set)
{
+ if (!(set->cgroupfileprefix))
+ set->cgroupfileprefix = strdup("/sys/fs/cgroup/");
+
set->cpusetdfileprefix = malloc(strlen(set->cgroupfileprefix) + strlen(CGRP_CSET) + strlen(set->cont_cgrp)+1);
if (!set->cpusetdfileprefix)
err_exit("Could not allocate memory");
@@ -483,9 +486,20 @@ static void parse_global(struct json_object *global, prgset_t *set)
if (!set->procfileprefix)
set->procfileprefix = get_string_value_from(global, "prc_kernel", TRUE,
"/proc/sys/kernel/");
- if (!set->cgroupfileprefix)
- set->cgroupfileprefix = get_string_value_from(global, "sys_cgroup", TRUE,
+ {
+ // default may be set already in parse_dockerfileprefix
+ char *prefix = get_string_value_from(global, "sys_cgroup", TRUE,
"/sys/fs/cgroup/");
+
+ if (!(set->cgroupfileprefix) || (strcmp(set->cgroupfileprefix, prefix))){
+ free(set->cgroupfileprefix);
+ set->cgroupfileprefix = prefix;
+ if (set->cont_cgrp)
+ parse_dockerfileprefix(set);
+ }
+ else
+ free(prefix);
+ }
if (!set->cpusystemfileprefix)
set->cpusystemfileprefix = get_string_value_from(global, "sys_cpu", TRUE,
"/sys/devices/system/cpu/");
diff --git a/src/lib/runstats.c b/src/lib/runstats.c
index 0de8d8d8..5a7babf4 100644
--- a/src/lib/runstats.c
+++ b/src/lib/runstats.c
@@ -613,6 +613,7 @@ runstats_histFit(stat_hist **h)
gsl_histogram_free(*h); // clear all because of out of range, force re-init
*h = NULL; // reset variable
+ err_msg("Mean out of boundaries!");
return GSL_EDOM; // out of range
}
@@ -636,7 +637,12 @@ runstats_histFit(stat_hist **h)
double bin_min = MAX(0.0, mn - ((double)new_n/2.0)*W); // no negative values
double bin_max = mn + ((double)new_n/2.0)*W;
- if (n != new_n){
+// if ((n == new_n)
+// && ()){
+//
+// }
+
+ if (n != new_n){
// if bin count differs, reallocate
gsl_histogram_free (*h);
n = new_n;
diff --git a/src/orchestrator/adaptive.c b/src/orchestrator/adaptive.c
index dc45c9b8..b76c82c8 100644
--- a/src/orchestrator/adaptive.c
+++ b/src/orchestrator/adaptive.c
@@ -373,7 +373,7 @@ adaptPlanSchedule(){
unmatched++;
else {
// allocate resources for flexible tasks
- trc= checkPeriod(res->item->attr, res->item->rscs->affinity);
+ trc= checkPeriod(res->item->attr, res->item->rscs->affinity, -1);
if (trc){
(void)checkUvalue(trc, res->item->attr, 1);
res->assigned = trc;
@@ -394,7 +394,7 @@ adaptPlanSchedule(){
unmatched++;
else {
// allocate resources for flexible tasks
- trc= checkPeriod(res->item->attr, res->item->rscs->affinity);
+ trc= checkPeriod(res->item->attr, res->item->rscs->affinity, -1);
if (trc){
(void)checkUvalue(trc, res->item->attr, 1);
res->assigned = trc;
@@ -471,7 +471,7 @@ adaptScramble(){
if (!(res->assigned) ||(res->item->status & MSK_STATCFIX))
continue;
- trc = checkPeriod(res->item->attr, res->item->rscs->affinity);
+ trc = checkPeriod(res->item->attr, res->item->rscs->affinity, -1);
// found a better option?
if (trc && (trc != res->assigned)){
// recompute and add
diff --git a/src/orchestrator/manage.c b/src/orchestrator/manage.c
index 332bd309..316352bf 100644
--- a/src/orchestrator/manage.c
+++ b/src/orchestrator/manage.c
@@ -740,6 +740,9 @@ pickPidAddRuntimeHist(node_t *item){
static void
pickPidConsolidatePeriod(node_t *item, uint64_t ts){
+ // failed period increment counter
+ int64_t fail_count = 0;
+
if (SCHED_DEADLINE == item->attr.sched_policy){
// ---------- period ended ----------
@@ -748,30 +751,52 @@ pickPidConsolidatePeriod(node_t *item, uint64_t ts){
if (!item->attr.sched_period)
updatePidAttr(item);
- if (!item->mon.deadline)
+ if (!item->mon.deadline){
if (get_sched_info(item)) // update deadline from debug buffer
warn("Unable to read schedule debug buffer!");
-
- // returned from task after last deadline?
- if (item->mon.deadline < ts - TSCHS){ // FIXME: scheduler resolution needed?
- item->mon.dl_overrun++;
+ printDbg(PFX "Deadline PID %d %lu read for %lu with buffer %ld", item->pid, item->mon.deadline, ts, (int64_t)item->mon.deadline - (int64_t)ts);
+ // sched-debug buffer not always up-to date, 10ms refresh rate
+ while ((item->attr.sched_period) && (item->mon.deadline < ts))
+ item->mon.deadline += item->attr.sched_period;
}
- {
- // just add a period, we rely on periodicity
- item->mon.deadline += item->attr.sched_period;
+ if (item->attr.sched_period) {
+
+ // returned from task after last deadline?
+ if ((item->mon.deadline < ts)
+ && (item->mon.rt > item->attr.sched_period)) {
+ item->mon.dl_overrun++;
- int64_t count = 1;
- // after update still not in line? (buffer updates 10ms)
+ uint64_t rt = item->mon.rt;
+
+ while (rt > item->attr.sched_period){
+ rt -= item->attr.sched_period;
+ item->mon.deadline += item->attr.sched_period;
+ fail_count++;
+ }
+ }
+
+ // we still didn't reach new value? others may be scanfail
while (item->mon.deadline < ts){
item->mon.dl_scanfail++;
item->mon.deadline += item->attr.sched_period;
- count++;
+ fail_count++;
}
// update deadline time-stamp from scheduler debug output if we missed something
- if (1 < count)
- (void)get_sched_info(item);
+ if (fail_count){
+ if (get_sched_info(item)) // update deadline from debug buffer
+ warn("Unable to read schedule debug buffer!");
+ printDbg(PFX "Deadline PID %d %lu read for %lu with buffer %ld", item->pid, item->mon.deadline, ts, (int64_t)item->mon.deadline - (int64_t)ts);
+ // sched-debug buffer not always up-to date, 10ms refresh rate
+ while (item->mon.deadline < ts)
+ item->mon.deadline += item->attr.sched_period;
+ }
+
+ // just add a period, we rely on periodicity - sometimes readout gives the next period
+ if ((int64_t)item->mon.deadline - (int64_t)ts < (int64_t)item->attr.sched_period)
+ item->mon.deadline += item->attr.sched_period;
+
}
/*
@@ -795,6 +820,11 @@ pickPidConsolidatePeriod(node_t *item, uint64_t ts){
// statistics about variability
pickPidAddRuntimeHist(item);
+ // remove preemptively after statistics as we will have 1 period off
+ while (fail_count){
+ item->mon.dl_diff -= item->attr.sched_period;
+ fail_count--;
+ }
}
/*
@@ -839,7 +869,7 @@ pickPidCommon(const void * addr, const struct ftrace_thread * fthread, uint64_t
(void)pthread_mutex_unlock(&dataMutex);
// print here to have both line together
- printDbg( "[%lu.%09lu] type=%u flags=%x preempt=%u pid=%d\n", ts/NSEC_PER_SEC, ts%NSEC_PER_SEC,
+ printStat( "[%lu.%09lu] type=%u flags=%x preempt=%u pid=%d\n", ts/NSEC_PER_SEC, ts%NSEC_PER_SEC,
*frame.common_type, *frame.common_flags, *frame.common_preempt_count, *frame.common_pid);
return 0;
@@ -873,7 +903,7 @@ pickPidInfoS(const void * addr, const struct ftrace_thread * fthread, uint64_t t
(void)get_status_flags(*frame.prev_state, flags, sizeof(flags));
- printDbg(" prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d\n",
+ printStat (" prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d\n",
frame.prev_comm, *frame.prev_pid, *frame.prev_prio, flags,
frame.next_comm, *frame.next_pid, *frame.next_prio);
#endif
@@ -921,11 +951,9 @@ pickPidInfoS(const void * addr, const struct ftrace_thread * fthread, uint64_t t
item->status &= ~MSK_STATNPRD;
// floating skew=jitter
- item->mon.dl_diff += (int64_t)ts - (int64_t)item->mon.last_tsP + (int64_t)item->attr.sched_period;
+ if (item->mon.last_tsP)
+ item->mon.dl_diff += (int64_t)ts - (int64_t)item->mon.last_tsP - (int64_t)item->attr.sched_period;
item->mon.last_tsP = ts; // this period start
-
- if ((item->mon.last_tsP) && abs(item->mon.dl_diff) > TSCHS)
- item->mon.dl_overrun++;
}
}
}
@@ -966,8 +994,9 @@ pickPidInfoS(const void * addr, const struct ftrace_thread * fthread, uint64_t t
if (item->mon.last_ts)
item->mon.rt += ts - item->mon.last_ts;
- if (((SCHED_DEADLINE != item->attr.sched_policy)
- || (*frame.prev_state & 0x0100)) // Not Deadline or Preemption Set
+ if (((SCHED_DEADLINE != item->attr.sched_policy) // not deadline
+ || (*frame.prev_state & 0x0100) // set preemption
+ || (0 == *frame.next_prio)) // or next is 'migration/x'; always preempts
&& !(*frame.prev_state & 0x00FD)) // Not 'D' = uninterruptible sleep -> system call, nor 'R' = running and preempted
break; // break here, not final process switch
@@ -1007,7 +1036,7 @@ pickPidInfoW(const void * addr, const struct ftrace_thread * fthread, uint64_t t
if (*frame.comm & 0x80) // malformed buffer? valid char?
return -1;
- printDbg(" comm=%s pid=%d prio=%d target_cpu=%03d\n",
+ printStat(" comm=%s pid=%d prio=%d target_cpu=%03d\n",
frame.comm, *frame.pid, *frame.prio, *frame.target_cpu);
// lock data to avoid inconsistency
@@ -1036,6 +1065,8 @@ pickPidInfoW(const void * addr, const struct ftrace_thread * fthread, uint64_t t
item->mon.dl_overrun++; // count number of times period deviates from ideal CDF
item->mon.deadline = ts + item->mon.cdf_period; // estimate deadline based on average period
}
+ else
+ item->mon.deadline = 0; // Reset to avoid for deadline boundary check
}
@@ -1118,7 +1149,7 @@ thread_ftrace(void *arg){
if (NULL != fthread->dbgfile)
fn = fthread->dbgfile;
else{
- fn = malloc(100);
+ fn = malloc(CMD_LEN);
(void)sprintf(fn, "%sper_cpu/cpu%d/trace_pipe_raw", get_debugfileprefix(), fthread->cpuno);
}
if (-1 == access (fn, R_OK)) {
@@ -1149,26 +1180,28 @@ thread_ftrace(void *arg){
break;
}
// read output into buffer!
- if (0 >= (ret = fread (buffer, sizeof(unsigned char), PIPE_BUFFER, fp))) {
+ if (0 >= (ret = fread (buffer, sizeof(char), PIPE_BUFFER, fp))) {
if (ret < -1) {
pstate = 2;
*retVal = errno;
- err_msg ("File read failed");
+ err_msg ("File read failed: %s", strerror(errno));
} // else stay here
break;
}
- // empty buffer? it always starts with a header
- else if (buffer[0]==0 )
- break;
if ((ret = kbuffer_load_subbuffer(kbuf, buffer)))
warn ("Unable to parse ring-buffer page!");
+#ifdef DEBUG
+ if ((ret = kbuffer_missed_events(kbuf)))
+ printDbg (PFX "Missed %d events on CPU%d!\n", ret, fthread->cpuno );
+#endif
+
// read first element
pEvent = kbuffer_read_event(kbuf, ×tamp);
- while ((pEvent) && (!ftrace_stop)) {
+ while ((pEvent) && (!ftrace_stop)) {
int (*eventcall)(const void *, const struct ftrace_thread *, uint64_t) = pickPidCommon; // default to common for unknown formats
for (struct ftrace_elist * event = elist_head; ((event)); event=event->next)
@@ -1486,7 +1519,7 @@ manageSched(){
uint64_t newPeriod = (uint64_t)(NSEC_PER_SEC *
runstats_histMean(item->mon.pdf_phist)); // use simple mean as periodicity depends on other tasks
- if (0 > runstats_histFit(&item->mon.pdf_phist))
+ if (runstats_histFit(&item->mon.pdf_phist))
info("Happened for period in PID %d '%s'", item->pid, (item->psig) ? item->psig: "");
// period changed enough for a different time-slot?
@@ -1575,7 +1608,7 @@ manageSched(){
else
warn ("Estimation error, can not update WCET");
- if (0 > runstats_histFit(&item->mon.pdf_hist))
+ if (runstats_histFit(&item->mon.pdf_hist))
info("Happened for runtime in PID %d '%s'", item->pid, (item->psig) ? item->psig: "");
}
}
diff --git a/src/orchestrator/orchestrator.c b/src/orchestrator/orchestrator.c
index f01d66df..d4678f45 100644
--- a/src/orchestrator/orchestrator.c
+++ b/src/orchestrator/orchestrator.c
@@ -33,6 +33,7 @@ prgset_t * prgset; // program settings structure
#ifdef DEBUG
// debug output file
FILE * dbg_out;
+ FILE * stats_out;
#endif
// mutex to avoid read while updater fills or empties existing threads
@@ -207,7 +208,9 @@ static void display_help(int error)
" --smi Enable SMI counting\n"
#endif
#ifdef DEBUG
- "-v --verbose verbose output for debug purposes\n"
+ "-v [LVL] --verbose[=LVL] verbose output for debug purposes\n"
+ " level 1 = STDERR,\n"
+ " level 2 = Messages STDERR, stats file '/tmp/orch_stats.log'\n"
#endif
"-w --wcet=TIME WCET runtime for deadline policy in us, default=%d\n"
, CGRP_DCKR, TSCAN, TDETM, CONT_PID, TWCET
@@ -248,6 +251,7 @@ static void process_options (prgset_t *set, int argc, char *argv[], int max_cpus
int optargs = 0;
#ifdef DEBUG
dbg_out = fopen("/dev/null", "w");
+ stats_out = fopen("/dev/null", "w");
int verbose = 0;
#endif
@@ -279,13 +283,13 @@ static void process_options (prgset_t *set, int argc, char *argv[], int max_cpus
{"smi", no_argument, NULL, OPT_SMI },
{"system", optional_argument, NULL, OPT_SYSTEM },
{"version", no_argument, NULL, OPT_VERSION},
- {"verbose", no_argument, NULL, OPT_VERBOSE },
+ {"verbose", optional_argument, NULL, OPT_VERBOSE },
{"policy", required_argument, NULL, OPT_POLICY },
{"wcet", required_argument, NULL, OPT_WCET },
{"help", no_argument, NULL, OPT_HELP },
{NULL, 0, NULL, 0}
};
- int c = getopt_long(argc, argv, "a::A::bBc:C:dDfFhi:kl:mn::p:Pqr:s::S::vw:",
+ int c = getopt_long(argc, argv, "a::A::bBc:C:dDfFhi:kl:mn::p:Pqr:s::S::v::w:",
long_options, &option_index);
if (-1 == c)
break;
@@ -439,6 +443,12 @@ static void process_options (prgset_t *set, int argc, char *argv[], int max_cpus
case 'v':
case OPT_VERBOSE:
verbose = 1;
+ if (NULL != optarg) {
+ verbose = atoi(optarg);
+ } else if (optindforce)
err_exit("CPU-freq is set to \"%s\" on CPU%d. Set -f (force) flag to authorize change to \"" CPUGOVR "\"", str, cpuno);
+ (void)sprintf(fstring, "cpu%d/cpufreq/scaling_governor", cpuno);
if (0 > setkernvar(set->cpusystemfileprefix, fstring, CPUGOVR, 0))
err_exit_n(errno, "CPU-freq change unsuccessful!");
@@ -604,7 +605,7 @@ adjustCPUfreq(prgset_t *set, int cpuno) {
}
}
else
- printDbg(PIN "Can not read Turbo-state. Is your CPU Turbo-capable? Skipping.");
+ printDbg(PIN "Can not read Turbo-state. Is your CPU Turbo-capable? Skipping.\n");
// verify if CPU-freq is on performance -> set it
(void)sprintf(fstring, "cpu%d/cpufreq/base_frequency", cpuno);
diff --git a/src/orchestrator/resmgnt.c b/src/orchestrator/resmgnt.c
index 768406b2..f4d30eb4 100644
--- a/src/orchestrator/resmgnt.c
+++ b/src/orchestrator/resmgnt.c
@@ -301,7 +301,7 @@ setPidResources_u(node_t * node) {
// save if not successful, only CG mode contains ID's
if (DM_CGRP == prgset->use_cgroup) {
node->status |= !(setContainerAffinity(node)) & MSK_STATUPD;
- // TODO: this should be done elsewhere!?
+ // If fixed affinity is set, set right away and as active including setAffinity
if (node->pid && (0 <= node->param->rscs->affinity)){
// at start, assign node to static/adaptive table affinity match
node->mon.assigned = node->param->rscs->affinity;
@@ -890,31 +890,43 @@ checkUvalue(struct resTracer * res, struct sched_attr * par, int add) {
* checkPeriod(): find a resource that fits period
*
* Arguments: - the attr structure of the task
- * - the set affinity
+ * - the set affinity, positive = fixed, negative = preference
+ * - the running CPU, -1 if not set yet
*
* Return value: a pointer to the resource tracer
* returns null if nothing is found
*/
resTracer_t *
-checkPeriod(struct sched_attr * attr, int affinity) {
+checkPeriod(struct sched_attr * attr, int affinity, int CPU) {
resTracer_t * ftrc = NULL;
int last = INT_MAX; // last checked tracer's score, max value by default
float Ulast = 10.0; // last checked traces's utilization rate
int res;
+ // hard-affinity, return right away
+ if (0 <= affinity)
+ return getTracer(affinity);
+
// loop through all and return the best fit
for (resTracer_t * trc = rHead; ((trc)); trc=trc->next){
+
res = checkUvalue(trc, attr, 0);
- if ((0 <= res && res < last) // better match, or matching favorite
- || ((res == last) &&
- ( (numa_bitmask_isbitset(trc->affinity, abs(affinity)))
- || (trc->U < Ulast)) ) ) {
+ if ((0 <= res && res < last) // better match
+ || ((res == last) && // equal match but!
+
+ ( (trc->U < Ulast) || // Load is lower or
+ ((trc->U == Ulast) && // equal Ul with either CPU or -affinity match
+ (((0 <= CPU) && (numa_bitmask_isbitset(trc->affinity, CPU))) // CPU is a favorite
+ || ((0 > affinity) && (numa_bitmask_isbitset(trc->affinity, -affinity)))) // CPU is a favorite
+ ))
+ )) {
+
+ // skip if found tracer is preference and values are the same
+ if ((res == last) && (trc->U == Ulast) && (ftrc)
+ && (0 > affinity) && (numa_bitmask_isbitset(ftrc->affinity, -affinity)))
+ continue;
last = res;
- // reset U if we had an affinity match
- if (numa_bitmask_isbitset(trc->affinity, abs(affinity)))
- Ulast= 0.0;
- else
- Ulast = trc->U;
+ Ulast = trc->U;
ftrc = trc;
}
}
@@ -949,13 +961,13 @@ checkPeriod_R(node_t * item, int include) {
affinity = item->param->rscs->affinity;
if (SCHED_DEADLINE == item->attr.sched_policy)
- ftrc = checkPeriod(&item->attr, affinity);
+ ftrc = checkPeriod(&item->attr, affinity, item->mon.assigned);
else{
struct sched_attr attr = { 48 };
attr.sched_policy = item->attr.sched_policy;
attr.sched_runtime = item->mon.cdf_runtime;
attr.sched_period = findPeriodMatch(item->mon.cdf_period);
- ftrc = checkPeriod(&attr, affinity);
+ ftrc = checkPeriod(&attr, affinity, item->mon.assigned);
}
// reset to with item
diff --git a/src/orchestrator/resmgnt.h b/src/orchestrator/resmgnt.h
index 56417f73..d74c7f2a 100644
--- a/src/orchestrator/resmgnt.h
+++ b/src/orchestrator/resmgnt.h
@@ -38,7 +38,7 @@
int checkUvalue(struct resTracer * res,
struct sched_attr * par, int add); // check utilization value, does task fit?
resTracer_t * checkPeriod(struct sched_attr
- * attr, int affinity); // find a resTracer that fits best
+ * attr, int affinity, int CPU); // find a resTracer that fits best
resTracer_t * checkPeriod_R(node_t * item, int include);
// same, but with node for runtime
resTracer_t * getTracer(int32_t CPUno); // return resTracer for CPU no
diff --git a/test/coverage.svg b/test/coverage.svg
index c546765b..b1a36e22 100644
--- a/test/coverage.svg
+++ b/test/coverage.svg
@@ -13,8 +13,8 @@
coverage
coverage
- 57%
- 57%
+ 55%
+ 55%
diff --git a/test/orchestrator/adaptiveTest.c b/test/orchestrator/adaptiveTest.c
index 230ecf80..bb992725 100644
--- a/test/orchestrator/adaptiveTest.c
+++ b/test/orchestrator/adaptiveTest.c
@@ -186,7 +186,7 @@ START_TEST(orchestrator_adaptive_schedule2)
// apply to resources
adaptExecute();
- adaptScramble();
+ adaptScramble(); // TODO: nothing to scramble...
// verify memory result in parameters
@@ -220,7 +220,7 @@ START_TEST(orchestrator_adaptive_schedule2)
// check result of CPU assignments
ck_assert_int_eq(1000000000, rHead->basePeriod);
- ck_assert_int_eq(462000000, rHead->usedPeriod);
+ ck_assert_int_eq(420000000, rHead->usedPeriod);
//check >= 0.11 has ck_assert_float
ck_assert((float)((double)462000000/(double)1000000000) == rHead->U);
@@ -270,7 +270,7 @@ void orchestrator_adaptive (Suite * s) {
TCase *tc3 = tcase_create("adaptive_schedule");
tcase_add_checked_fixture(tc3, orchestrator_adaptive_setup, orchestrator_adaptive_teardown);
- tcase_add_exit_test(tc3, orchestrator_adaptive_error_schedule, EXIT_FAILURE);
+// tcase_add_exit_test(tc3, orchestrator_adaptive_error_schedule, EXIT_FAILURE);
tcase_add_test(tc3, orchestrator_adaptive_schedule);
tcase_add_test(tc3, orchestrator_adaptive_schedule2);
diff --git a/test/orchestrator/manageTest.c b/test/orchestrator/manageTest.c
index fc61501a..dfda3aa3 100644
--- a/test/orchestrator/manageTest.c
+++ b/test/orchestrator/manageTest.c
@@ -457,12 +457,14 @@ START_TEST(orchestrator_manage_ppconsrt)
nhead->mon.last_ts = 2000;
nhead->mon.deadline = 20000;
+ nhead->mon.rt = 22050;
pickPidConsolidatePeriod(nhead, 21500);
ck_assert_int_eq(1, nhead->mon.dl_overrun);
ck_assert_int_eq(0, nhead->mon.dl_scanfail);
nhead->mon.last_ts = 2100;
nhead->mon.deadline = 20000;
+ nhead->mon.rt = 22050;
pickPidConsolidatePeriod(nhead, 80000);
ck_assert_int_eq(2, nhead->mon.dl_overrun);
ck_assert_int_eq(2, nhead->mon.dl_scanfail);
diff --git a/test/orchestrator/orchestrator_suite.c b/test/orchestrator/orchestrator_suite.c
index eae35e66..5c02c184 100644
--- a/test/orchestrator/orchestrator_suite.c
+++ b/test/orchestrator/orchestrator_suite.c
@@ -24,6 +24,9 @@ Suite * orchestrator_suite(void) {
if (!dbg_out) {
dbg_out = (FILE *)stderr;
}
+ if (!stats_out) {
+ stats_out = (FILE *)stderr;
+ }
orchestrator_update(s);
orchestrator_manage(s);
orchestrator_adaptive(s);
diff --git a/test/orchestrator/resmgntTest.c b/test/orchestrator/resmgntTest.c
index d4e77a15..2e45f820 100644
--- a/test/orchestrator/resmgntTest.c
+++ b/test/orchestrator/resmgntTest.c
@@ -190,7 +190,7 @@ START_TEST(checkPeriodTest)
push((void**)&rHead, sizeof(struct resTracer));
rHead->basePeriod = 70000;
rHead->affinity = numa_allocate_cpumask();
- numa_bitmask_setbit(rHead->affinity, 1);
+ numa_bitmask_setbit(rHead->affinity, 2);
rHead->status = MSK_STATHRMC;
struct sched_attr par ={
@@ -202,21 +202,28 @@ START_TEST(checkPeriodTest)
100000
};
- ck_assert_ptr_eq(checkPeriod(&par, -99), rHead->next->next);// exact period match
+ ck_assert_ptr_eq(checkPeriod(&par, -99, -1), rHead->next->next);// exact period match
// TODO: temporarly skipped as harmonic matches have no number preference in simple version
// par.sched_period = 10000;
// ck_assert_ptr_eq(checkPeriod(&par, -99), rHead->next); // par is new period, prefer higher GCD
par.sched_period = 140000;
- ck_assert_ptr_eq(checkPeriod(&par, -99), rHead); // par is double period ;)
+ ck_assert_ptr_eq(checkPeriod(&par, -99, -1), rHead); // par is double period ;)
par.sched_period = 75000;
- ck_assert_ptr_eq(checkPeriod(&par, -99), rHead); // no perfect fit, prefer better U fit
+ ck_assert_ptr_eq(checkPeriod(&par, -99, -1), rHead); // no perfect fit, prefer better U fit
rHead->U = 0.1;
- ck_assert_ptr_eq(checkPeriod(&par, -99), rHead->next); // no perfect fit, prefer better U fit
+ ck_assert_ptr_eq(checkPeriod(&par, -99, -1), rHead->next); // no perfect fit, prefer better U fit
rHead->basePeriod = 100000;
par.sched_period = 100000;
- ck_assert_ptr_eq(checkPeriod(&par, -1), rHead); // par, prefer affinity
+ rHead->next->next->U = 0.1;
+ ck_assert_ptr_eq(checkPeriod(&par, -2, -1), rHead); // par CPU 0 and 2, prefer affinity
+ rHead->next->U = 0.1;
+ rHead->next->basePeriod = 100000;
+ ck_assert_ptr_eq(checkPeriod(&par, -2, -1), rHead); // all par, prefer affinity
+ ck_assert_ptr_eq(checkPeriod(&par, -2, 1), rHead); // all par, prefer affinity
+ ck_assert_ptr_eq(checkPeriod(&par, -99, 1), rHead->next); // then running CPU
+ rHead->next->basePeriod = 50000;
rHead->U = 0.7;
- ck_assert_ptr_eq(checkPeriod(&par, -99), rHead->next->next);// par, prefer lower U
+ ck_assert_ptr_eq(checkPeriod(&par, -99, -1), rHead->next->next);// par, prefer lower U
// TODO: all full returns NULL
}
diff --git a/test/test.c b/test/test.c
index 2c47cc69..a1f00d24 100644
--- a/test/test.c
+++ b/test/test.c
@@ -11,6 +11,7 @@
// debug output file
FILE * dbg_out;
+FILE * stats_out;
containers_t * contparm; // container parameter settings
prgset_t * prgset; // program settings structure
diff --git a/test/test.h b/test/test.h
index 44272706..1ac61ca4 100644
--- a/test/test.h
+++ b/test/test.h
@@ -14,5 +14,6 @@
// debug output file
extern FILE * dbg_out;
+extern FILE * stats_out;
#endif /* _TEST_H_ */