aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenmon/xenbaked.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xenmon/xenbaked.c')
-rw-r--r--tools/xenmon/xenbaked.c267
1 files changed, 164 insertions, 103 deletions
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 945a5c47f9..3789f20c84 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -95,6 +95,8 @@ int dom0_flips = 0;
_new_qos_data *new_qos;
_new_qos_data **cpu_qos_data;
+int global_cpu;
+uint64_t global_now;
// array of currently running domains, indexed by cpu
int *running = NULL;
@@ -678,7 +680,7 @@ const struct argp parser_def =
};
-const char *argp_program_version = "xenbaked v1.3";
+const char *argp_program_version = "xenbaked v1.4";
const char *argp_program_bug_address = "<rob.gardner@hp.com>";
@@ -715,16 +717,117 @@ int main(int argc, char **argv)
return ret;
}
+void qos_init_domain(int domid, int idx)
+{
+ int i;
+
+ memset(&new_qos->domain_info[idx], 0, sizeof(_domain_info));
+ new_qos->domain_info[idx].last_update_time = global_now;
+ // runnable_start_time[idx] = 0;
+ new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
+ new_qos->domain_info[idx].in_use = 1;
+ new_qos->domain_info[idx].blocked_start_time = 0;
+ new_qos->domain_info[idx].id = domid;
+ if (domid == IDLE_DOMAIN_ID)
+ sprintf(new_qos->domain_info[idx].name, "Idle Task%d", global_cpu);
+ else
+ sprintf(new_qos->domain_info[idx].name, "Domain#%d", domid);
+
+ for (i=0; i<NSAMPLES; i++) {
+ new_qos->qdata[i].ns_gotten[idx] = 0;
+ new_qos->qdata[i].ns_allocated[idx] = 0;
+ new_qos->qdata[i].ns_waiting[idx] = 0;
+ new_qos->qdata[i].ns_blocked[idx] = 0;
+ new_qos->qdata[i].switchin_count[idx] = 0;
+ new_qos->qdata[i].io_count[idx] = 0;
+ }
+}
+
+void global_init_domain(int domid, int idx)
+{
+ int cpu;
+ _new_qos_data *saved_qos;
+
+ saved_qos = new_qos;
+
+ for (cpu=0; cpu<NCPU; cpu++) {
+ new_qos = cpu_qos_data[cpu];
+ qos_init_domain(domid, idx);
+ }
+ new_qos = saved_qos;
+}
+
+
+// give index of this domain in the qos data array
+int indexof(int domid)
+{
+ int idx;
+ xc_dominfo_t dominfo[NDOMAINS];
+ int xc_handle, ndomains;
+ extern void qos_kill_thread(int domid);
+
+ if (domid < 0 || domid >= NDOMAINS) { // shouldn't happen
+ if (domid != IDLE_DOMAIN_ID) {
+ printf("bad domain id: %d\r\n", domid);
+ return 0;
+ }
+ }
+
+ for (idx=0; idx<NDOMAINS; idx++)
+ if ( (new_qos->domain_info[idx].id == domid) && new_qos->domain_info[idx].in_use)
+ return idx;
+
+ // not found, make a new entry
+ for (idx=0; idx<NDOMAINS; idx++)
+ if (new_qos->domain_info[idx].in_use == 0) {
+ global_init_domain(domid, idx);
+ return idx;
+ }
+
+ // call domaininfo hypercall to try and garbage collect unused entries
+ xc_handle = xc_interface_open();
+ ndomains = xc_domain_getinfo(xc_handle, 0, NDOMAINS, dominfo);
+ xc_interface_close(xc_handle);
+
+ // for each domain in our data, look for it in the system dominfo structure
+ // and purge the domain's data from our state if it does not exist in the
+ // dominfo structure
+ for (idx=0; idx<NDOMAINS; idx++) {
+ int domid = new_qos->domain_info[idx].id;
+ int jdx;
+
+ for (jdx=0; jdx<ndomains; jdx++) {
+ if (dominfo[jdx].domid == domid)
+ break;
+ }
+ if (jdx == ndomains) // we didn't find domid in the dominfo struct
+ if (domid != IDLE_DOMAIN_ID) // exception for idle domain, which is not
+ // contained in dominfo
+ qos_kill_thread(domid); // purge our stale data
+ }
+
+ // look again for a free slot
+ for (idx=0; idx<NDOMAINS; idx++)
+ if (new_qos->domain_info[idx].in_use == 0) {
+ global_init_domain(domid, idx);
+ return idx;
+ }
+
+ // still no space found, so bail
+ fprintf(stderr, "out of space in domain table, increase NDOMAINS\r\n");
+ exit(2);
+}
+
int domain_runnable(int domid)
{
- return new_qos->domain_info[ID(domid)].runnable;
+ return new_qos->domain_info[indexof(domid)].runnable;
}
void update_blocked_time(int domid, uint64_t now)
{
uint64_t t_blocked;
- int id = ID(domid);
+ int id = indexof(domid);
if (new_qos->domain_info[id].blocked_start_time != 0) {
if (now >= new_qos->domain_info[id].blocked_start_time)
@@ -734,7 +837,7 @@ void update_blocked_time(int domid, uint64_t now)
new_qos->qdata[new_qos->next_datapoint].ns_blocked[id] += t_blocked;
}
- if (domain_runnable(id))
+ if (domain_runnable(domid))
new_qos->domain_info[id].blocked_start_time = 0;
else
new_qos->domain_info[id].blocked_start_time = now;
@@ -773,7 +876,7 @@ void qos_update_thread(int cpu, int domid, uint64_t now)
uint64_t last_update_time, start;
int64_t time_since_update, run_time = 0;
- id = ID(domid);
+ id = indexof(domid);
n = new_qos->next_datapoint;
last_update_time = new_qos->domain_info[id].last_update_time;
@@ -851,7 +954,7 @@ void qos_update_all(uint64_t now, int cpu)
for (i=0; i<NDOMAINS; i++)
if (new_qos->domain_info[i].in_use)
- qos_update_thread(cpu, i, now);
+ qos_update_thread(cpu, new_qos->domain_info[i].id, now);
}
@@ -866,69 +969,37 @@ void qos_update_thread_stats(int cpu, int domid, uint64_t now)
}
-void qos_init_domain(int cpu, int domid, uint64_t now)
-{
- int i, id;
-
- id = ID(domid);
-
- if (new_qos->domain_info[id].in_use)
- return;
-
-
- memset(&new_qos->domain_info[id], 0, sizeof(_domain_info));
- new_qos->domain_info[id].last_update_time = now;
- // runnable_start_time[id] = 0;
- new_qos->domain_info[id].runnable_start_time = 0; // invalidate
- new_qos->domain_info[id].in_use = 1;
- new_qos->domain_info[id].blocked_start_time = 0;
- new_qos->domain_info[id].id = id;
- if (domid == IDLE_DOMAIN_ID)
- sprintf(new_qos->domain_info[id].name, "Idle Task%d", cpu);
- else
- sprintf(new_qos->domain_info[id].name, "Domain#%d", domid);
-
- for (i=0; i<NSAMPLES; i++) {
- new_qos->qdata[i].ns_gotten[id] = 0;
- new_qos->qdata[i].ns_allocated[id] = 0;
- new_qos->qdata[i].ns_waiting[id] = 0;
- new_qos->qdata[i].ns_blocked[id] = 0;
- new_qos->qdata[i].switchin_count[id] = 0;
- new_qos->qdata[i].io_count[id] = 0;
- }
-}
-
// called when a new thread gets the cpu
void qos_switch_in(int cpu, int domid, uint64_t now, unsigned long ns_alloc, unsigned long ns_waited)
{
- int id = ID(domid);
+ int idx = indexof(domid);
- new_qos->domain_info[id].runnable = 1;
+ new_qos->domain_info[idx].runnable = 1;
update_blocked_time(domid, now);
- new_qos->domain_info[id].blocked_start_time = 0; // invalidate
- new_qos->domain_info[id].runnable_start_time = 0; // invalidate
- //runnable_start_time[id] = 0;
-
- new_qos->domain_info[id].start_time = now;
- new_qos->qdata[new_qos->next_datapoint].switchin_count[id]++;
- new_qos->qdata[new_qos->next_datapoint].ns_allocated[id] += ns_alloc;
- new_qos->qdata[new_qos->next_datapoint].ns_waiting[id] += ns_waited;
+ new_qos->domain_info[idx].blocked_start_time = 0; // invalidate
+ new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
+ //runnable_start_time[idx] = 0;
+
+ new_qos->domain_info[idx].start_time = now;
+ new_qos->qdata[new_qos->next_datapoint].switchin_count[idx]++;
+ new_qos->qdata[new_qos->next_datapoint].ns_allocated[idx] += ns_alloc;
+ new_qos->qdata[new_qos->next_datapoint].ns_waiting[idx] += ns_waited;
qos_update_thread_stats(cpu, domid, now);
- set_current(cpu, id);
+ set_current(cpu, domid);
// count up page flips for dom0 execution
- if (id == 0)
+ if (domid == 0)
dom0_flips = 0;
}
// called when the current thread is taken off the cpu
void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
{
- int id = ID(domid);
+ int idx = indexof(domid);
int n;
- if (!is_current(id, cpu)) {
+ if (!is_current(domid, cpu)) {
// printf("switching out domain %d but it is not current. gotten=%ld\r\n", id, gotten);
}
@@ -943,18 +1014,18 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
n = new_qos->next_datapoint;
#if 0
- new_qos->qdata[n].ns_gotten[id] += gotten;
+ new_qos->qdata[n].ns_gotten[idx] += gotten;
if (gotten > new_qos->qdata[n].ns_passed)
printf("inconsistency #257, diff = %lld\n",
gotten - new_qos->qdata[n].ns_passed );
#endif
- new_qos->domain_info[id].ns_oncpu_since_boot += gotten;
- new_qos->domain_info[id].runnable_start_time = now;
+ new_qos->domain_info[idx].ns_oncpu_since_boot += gotten;
+ new_qos->domain_info[idx].runnable_start_time = now;
// runnable_start_time[id] = now;
- qos_update_thread_stats(cpu, id, now);
+ qos_update_thread_stats(cpu, domid, now);
// process dom0 page flips
- if (id == 0)
+ if (domid == 0)
if (dom0_flips == 0)
new_qos->qdata[n].flip_free_periods++;
}
@@ -963,23 +1034,30 @@ void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten)
// when thread is already asleep
void qos_state_sleeping(int cpu, int domid, uint64_t now)
{
- int id = ID(domid);
+ int idx;
- if (!domain_runnable(id)) // double call?
+ if (!domain_runnable(domid)) // double call?
return;
- new_qos->domain_info[id].runnable = 0;
- new_qos->domain_info[id].blocked_start_time = now;
- new_qos->domain_info[id].runnable_start_time = 0; // invalidate
- // runnable_start_time[id] = 0; // invalidate
+ idx = indexof(domid);
+ new_qos->domain_info[idx].runnable = 0;
+ new_qos->domain_info[idx].blocked_start_time = now;
+ new_qos->domain_info[idx].runnable_start_time = 0; // invalidate
+ // runnable_start_time[idx] = 0; // invalidate
qos_update_thread_stats(cpu, domid, now);
}
+// domain died, presume it's dead on all cpu's, not just mostly dead
void qos_kill_thread(int domid)
{
- new_qos->domain_info[ID(domid)].in_use = 0;
+ int cpu;
+
+ for (cpu=0; cpu<NCPU; cpu++) {
+ cpu_qos_data[cpu]->domain_info[indexof(domid)].in_use = 0;
+ }
+
}
@@ -987,30 +1065,33 @@ void qos_kill_thread(int domid)
// when thread is already runnable
void qos_state_runnable(int cpu, int domid, uint64_t now)
{
- int id = ID(domid);
+ int idx;
+
qos_update_thread_stats(cpu, domid, now);
- if (domain_runnable(id)) // double call?
+ if (domain_runnable(domid)) // double call?
return;
- new_qos->domain_info[id].runnable = 1;
+
+ idx = indexof(domid);
+ new_qos->domain_info[idx].runnable = 1;
update_blocked_time(domid, now);
- new_qos->domain_info[id].blocked_start_time = 0; /* invalidate */
- new_qos->domain_info[id].runnable_start_time = now;
+ new_qos->domain_info[idx].blocked_start_time = 0; /* invalidate */
+ new_qos->domain_info[idx].runnable_start_time = now;
// runnable_start_time[id] = now;
}
void qos_count_packets(domid_t domid, uint64_t now)
{
- int i, id = ID(domid);
+ int i, idx = indexof(domid);
_new_qos_data *cpu_data;
for (i=0; i<NCPU; i++) {
cpu_data = cpu_qos_data[i];
- if (cpu_data->domain_info[id].in_use) {
- cpu_data->qdata[cpu_data->next_datapoint].io_count[id]++;
+ if (cpu_data->domain_info[idx].in_use) {
+ cpu_data->qdata[cpu_data->next_datapoint].io_count[idx]++;
}
}
@@ -1019,77 +1100,57 @@ void qos_count_packets(domid_t domid, uint64_t now)
}
-int domain_ok(int cpu, int domid, uint64_t now)
-{
- if (domid == IDLE_DOMAIN_ID)
- domid = NDOMAINS-1;
- if (domid < 0 || domid >= NDOMAINS) {
- printf("bad domain id: %d\r\n", domid);
- return 0;
- }
- if (new_qos->domain_info[domid].in_use == 0)
- qos_init_domain(cpu, domid, now);
- return 1;
-}
-
-
void process_record(int cpu, struct t_rec *r)
{
uint64_t now;
-
new_qos = cpu_qos_data[cpu];
rec_count++;
now = ((double)r->cycles) / (opts.cpu_freq / 1000.0);
+ global_now = now;
+ global_cpu = cpu;
+
log_event(r->event);
switch (r->event) {
case TRC_SCHED_SWITCH_INFPREV:
// domain data[0] just switched out and received data[1] ns of cpu time
- if (domain_ok(cpu, r->data[0], now))
- qos_switch_out(cpu, r->data[0], now, r->data[1]);
+ qos_switch_out(cpu, r->data[0], now, r->data[1]);
// printf("ns_gotten %ld\n", r->data[1]);
break;
case TRC_SCHED_SWITCH_INFNEXT:
// domain data[0] just switched in and
// waited data[1] ns, and was allocated data[2] ns of cpu time
- if (domain_ok(cpu, r->data[0], now))
- qos_switch_in(cpu, r->data[0], now, r->data[2], r->data[1]);
+ qos_switch_in(cpu, r->data[0], now, r->data[2], r->data[1]);
break;
case TRC_SCHED_DOM_ADD:
- if (domain_ok(cpu, r->data[0], now))
- qos_init_domain(cpu, r->data[0], now);
+ (void) indexof(r->data[0]);
break;
case TRC_SCHED_DOM_REM:
- if (domain_ok(cpu, r->data[0], now))
- qos_kill_thread(r->data[0]);
+ qos_kill_thread(r->data[0]);
break;
case TRC_SCHED_SLEEP:
- if (domain_ok(cpu, r->data[0], now))
- qos_state_sleeping(cpu, r->data[0], now);
+ qos_state_sleeping(cpu, r->data[0], now);
break;
case TRC_SCHED_WAKE:
- if (domain_ok(cpu, r->data[0], now))
- qos_state_runnable(cpu, r->data[0], now);
+ qos_state_runnable(cpu, r->data[0], now);
break;
case TRC_SCHED_BLOCK:
- if (domain_ok(cpu, r->data[0], now))
- qos_state_sleeping(cpu, r->data[0], now);
+ qos_state_sleeping(cpu, r->data[0], now);
break;
case TRC_MEM_PAGE_GRANT_TRANSFER:
- if (domain_ok(cpu, r->data[0], now))
- qos_count_packets(r->data[0], now);
+ qos_count_packets(r->data[0], now);
break;
default: