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 @@ 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_ */