// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see .
#include
#include
#include
#include
#ifdef _USING_FCGI_
#include "fcgi_stdio.h"
#endif
#ifdef SIM
#include
#else
#include "sched_config.h"
#include "sched_msgs.h"
#endif
#include "edf_sim.h"
using std::vector;
#define SUMMARY 0
// show candidate decision
#define WORKLOAD 1
// show workload
#define DETAIL 2
// show every step of simulation
static void log_msg(int level, const char* format, ...) {
#ifdef SIM
#else
switch(level) {
case SUMMARY:
if (!config.debug_send) return;
break;
case WORKLOAD:
if (!config.debug_edf_sim_workload) return;
break;
case DETAIL:
if (!config.debug_edf_sim_detail) return;
break;
}
#endif
va_list va;
va_start(va, format);
#ifdef SIM
vfprintf(stderr, format, va);
#else
log_messages.vprintf(MSG_DEBUG, format, va);
#endif
va_end(va);
}
bool lessthan_deadline(const IP_RESULT& p1, const IP_RESULT& p2) {
if (p1.computation_deadline < p2.computation_deadline) return true;
return false;
}
// run an EDF simulation, marking which results will miss
// their deadlines and when
//
void mark_edf_misses (int ncpus, vector& ip_results){
vector::iterator ipp_it;
double booked_to[128];
int j;
log_msg(DETAIL, "mark_edf_misses\n");
// keeps track of when each cpu is next free
//
for (j=0; j r.computation_deadline) {
r.misses_deadline = true;
r.estimated_completion_time = booked_to[lowest_booked_cpu];
log_msg(DETAIL, " %s misses_deadline; est completion %.2f\n",
r.name, booked_to[lowest_booked_cpu]/3600
);
} else {
r.misses_deadline = false;
log_msg(DETAIL, " %s makes deadline; est completion %.2f\n",
r.name, booked_to[lowest_booked_cpu]/3600
);
// if result doesn't miss its deadline,
// then the estimated_completion_time is of no use
}
}
}
// For each ip_result, compute computation_deadline from report_deadline,
// and determine if the deadline would be missed by simulating EDF
//
void init_ip_results(
double work_buf_min,
int ncpus,
vector& ip_results
){
unsigned int i;
log_msg(DETAIL,
"init_ip_results; work_buf_min %.2f ncpus %d:\n",
work_buf_min/3600, ncpus
);
for (i=0; i REQUEST_HANDLER_WORK_SEND::find_sendable_test_results (
vector test_results,
int ncpus,
vector ipp_results,
double cpu_pessimism_factor // = 1 by default
) {
//test results to send
vector sendable_test_results;
vector::iterator test_results_it;
sort(test_results.begin(), test_results.end(), lessthan_deadline);
// see if each test result can be added to the work queue without
// causing deadline misses or deadline miss delays
//
for (test_results_it = test_results.begin();
test_results_it != test_results.end();
test_results_it++
) {
bool failed = result_cause_deadline_miss_or_delay(
(*test_results_it).computation_deadline*cpu_pessimism_factor,
(*test_results_it).cpu_time_remaining,
ncpus,
ipp_results
);
if (!failed){
// add sendable result to work queue, copying by value, so that we
// can evaluate what happens if we add more new results to the queue
//
ipp_results.push_back(*test_results_it);
sendable_test_results.push_back (*test_results_it);
}
}
return (sendable_test_results);
}
#endif
// Return false if
// 1) the candidate result X would cause another result Y to miss its deadline
// (which Y would not have otherwise missed)
// 2) X causes another result Y to miss its deadline by more than
// it otherwise would have, or
// 3) X would miss its deadline
//
bool check_candidate (
IP_RESULT& candidate,
int ncpus,
vector ip_results // passed by value (copy)
) {
double booked_to[128]; // keeps track of when each cpu is free
int j;
log_msg(DETAIL, "check_candidate %s: dl %.2f cpu %.2f\n",
candidate.name, candidate.computation_deadline/3600,
candidate.cpu_time_remaining/3600
);
for (j=0; j computation_deadline AND
// result would not have missed deadline to begin with
//
if (booked_to[lowest_booked_cpu] > r.computation_deadline
&& !r.misses_deadline
) {
log_msg(SUMMARY,
" cand. fails; %s now misses deadline: %.2f > %.2f\n",
r.name, booked_to[lowest_booked_cpu]/3600,
r.computation_deadline/3600
);
return false;
}
// check a late result (i.e., one that would have missed its
// deadline) // would be made even later
//
if (r.misses_deadline
&& booked_to[lowest_booked_cpu] > r.estimated_completion_time
){
log_msg(SUMMARY,
" cand. fails; late result %s would be returned even later\n",
r.name
);
return false;
}
}
log_msg(SUMMARY, " candidate succeeds\n");
return true;
}
#if 0
int main() {
vector ip_results;
double work_buf_min = 0;
double cpu_pessimism_factor = 1;
int ncpus = 1;
bool flag;
ip_results.push_back(IP_RESULT("R1", 5, 3));
ip_results.push_back(IP_RESULT("R2", 5, 3));
init_ip_results(work_buf_min, ncpus, ip_results);
IP_RESULT c1 = IP_RESULT("C1", 10, 1);
if (check_candidate(c1, ncpus, ip_results)) {
printf("adding %s\n", c1.name);
ip_results.push_back(c1);
}
IP_RESULT c2 = IP_RESULT("C2", 7, 2);
if (check_candidate(c2, ncpus, ip_results)) {
printf("adding %s\n", c2.name);
ip_results.push_back(c2);
}
}
#endif