2 * Copyright 1993 Jeff Hollingsworth. All rights reserved.
7 static char Copyright[] = "@(#) Copyright (c) 1993 Jeff Hollingsowrth\
10 static char rcsid[] = "@(#) $Header: /home/jaw/CVSROOT_20081103/CVSROOT/core/paradynd/src/metricFocusNode.C,v 1.6 1994/03/26 19:31:36 hollings Exp $";
14 * metric.C - define and create metrics.
16 * $Log: metricFocusNode.C,v $
17 * Revision 1.6 1994/03/26 19:31:36 hollings
18 * Changed sample time to be consistant.
20 * Revision 1.5 1994/03/24 16:41:59 hollings
21 * Moved sample aggregation to lib/util (so paradyn could use it).
23 * Revision 1.4 1994/03/01 21:23:58 hollings
24 * removed unused now variable.
26 * Revision 1.3 1994/02/24 04:32:34 markc
27 * Changed header files to reflect igen changes. main.C does not look at the number of command line arguments now.
29 * Revision 1.2 1994/02/01 18:46:52 hollings
30 * Changes for adding perfConsult thread.
32 * Revision 1.1 1994/01/27 20:31:28 hollings
33 * Iinital version of paradynd speaking dynRPC igend protocol.
35 * Revision 1.17 1994/01/20 17:47:16 hollings
36 * moved getMetricValue to this file.
38 * Revision 1.16 1993/12/15 21:02:42 hollings
41 * Revision 1.15 1993/12/13 19:55:16 hollings
44 * Revision 1.14 1993/10/19 15:27:54 hollings
45 * AST based mini-tramp code generator.
47 * Revision 1.13 1993/10/07 19:42:43 jcargill
48 * Added true combines for global instrumentation
50 * Revision 1.12 1993/10/01 21:29:41 hollings
51 * Added resource discovery and filters.
53 * Revision 1.11 1993/09/03 18:36:16 hollings
54 * removed extra printfs.
56 * Revision 1.10 1993/09/03 16:01:56 hollings
57 * removed extra printf.
59 * Revision 1.9 1993/09/03 15:45:51 hollings
60 * eat the first sample from an aggregate to get a good start interval time.
62 * Revision 1.8 1993/08/20 22:00:51 hollings
63 * added getMetricValue for controller.
64 * moved insertInstrumentation for predicates to before pred users.
66 * Revision 1.7 1993/08/16 16:24:50 hollings
67 * commented out elapsedPauseTime because of CM-5 problems with node processes.
68 * removed many debugging printfs.
70 * Revision 1.6 1993/08/11 01:52:12 hollings
71 * chages for new build before use mode.
73 * Revision 1.5 1993/07/13 18:28:30 hollings
74 * new include file syntax.
76 * Revision 1.4 1993/06/24 16:18:06 hollings
79 * Revision 1.3 1993/06/22 19:00:01 hollings
82 * Revision 1.2 1993/06/08 20:14:34 hollings
83 * state prior to bc net ptrace replacement.
85 * Revision 1.1 1993/03/19 22:45:45 hollings
95 #include "rtinst/h/rtinst.h"
96 #include "rtinst/h/trace.h"
97 #include "util/h/aggregateSample.h"
102 #include "dyninstP.h"
106 #include "dyninstRPC.SRVR.h"
109 extern int metricCount;
110 extern int metResPairsEnabled;
111 extern HTable<metric> metricsUsed;
112 extern HTable<resourceList> fociUsed;
115 HTable<metricInstance> midToMiMap;
117 metricList globalMetricList;
118 extern struct _metricRec DYNINSTallMetrics[];
119 extern process *nodePseudoProcess;
121 // used to indicate the mi is no longer used.
124 metricDefinitionNode::metricDefinitionNode(process *p)
126 memset(this, '\0', sizeof(metricDefinitionNode));
130 sample.lastSampleEnd = 0.0;
131 sample.lastSampleStart = 0.0;
134 float metricDefinitionNode::getMetricValue()
137 List<metricDefinitionNode*> curr;
141 for (curr = components; *curr; curr++) {
142 total += (*curr)->getMetricValue();
146 return((*data)->getMetricValue());
149 metricDefinitionNode::metricDefinitionNode(metric m,
150 List<metricDefinitionNode*> parts)
153 memset(this, '\0', sizeof(metricDefinitionNode));
158 inform = FALSE; // change this latter.
160 for (; *parts; parts++) {
161 (*parts)->aggregators.add(this);
162 valueList.add(&(*parts)->sample);
166 metricInstance buildMetricInstRequest(resourceList l, metric m)
175 process *proc = NULL;
176 resourcePredicate *pred;
177 struct _metricRec *curr;
178 process **instProcessList;
179 resource complexPredResource;
180 resourcePredicate *complexPred;
181 List<metricDefinitionNode*> parts;
182 metricDefinitionNode *mn;
183 AstNode *predInstance = NULL;
185 if (!processList.count()) return(NULL);
187 /* first find the named metric */
188 for (i=0; i < metricCount; i++) {
189 curr = &DYNINSTallMetrics[i];
195 if (curr != m) return(NULL);
198 // check that the predicates are valid.
200 for (pred = curr->definition.predicates; pred->namePrefix; pred++) {
201 for (i=0; i < l->count; i++) {
204 /* test predicate for this resource */
205 if (!strcmp(pred->namePrefix, r->parent->info.fullName) ||
206 !strcmp(pred->namePrefix, r->info.fullName)) {
210 if (i== l->count) continue;
212 if (!strcmp(pred->namePrefix, r->info.fullName)) {
213 // null refinement skip it .
216 if (pred->type == invalidPredicate) {
222 * Identify if one or all processes should be inst.
226 for (i=0; i < l->count; i++) {
228 /* HACK for process for now */
229 if (!strcmp("/Process", r->parent->info.fullName)) {
230 proc = (process *) r->handle;
232 /* HACK for machine for now */
233 if (!strcmp("/Machine", r->parent->info.fullName)) {
234 tid = (int) r->handle;
239 instProcessList = (process **) xcalloc(sizeof(process *), 2);
240 if (!tid || (proc->thread == tid)) {
241 instProcessList[0] = proc;
243 } else if (nodePseudoProcess) {
244 instProcessList = (process **) xcalloc(sizeof(process *), 3);
245 instProcessList[0] = nodePseudoProcess;
246 instProcessList[1] = nodePseudoProcess->parent;
248 count = processList.count();
249 instProcessList = (process **) xcalloc(sizeof(process *), count+1);
250 for (pl = processList,count = 0; proc = *pl; pl++) {
251 /* HACK for machine for now */
252 if (!tid || (proc->thread == tid)) {
253 instProcessList[count++] = proc;
258 /* check all proceses are in an ok state */
259 if (!isApplicationPaused()) {
263 for (count=0; proc = instProcessList[count]; count++) {
264 mn = new metricDefinitionNode(proc);
270 * iterate through possible predicates.
271 * Predicates must be the outer loop so predicates are
272 * created in the correct order.
276 for (pred = curr->definition.predicates; pred->namePrefix; pred++) {
277 for (i=0; i < l->count; i++) {
280 /* test predicate for this resource */
281 if (!strcmp(pred->namePrefix, r->parent->info.fullName) ||
282 !strcmp(pred->namePrefix, r->info.fullName)) {
286 if (i== l->count) continue;
290 if (!strcmp(pred->namePrefix, r->info.fullName)) {
291 // null refinement skip it .
295 assert(pred->type != invalidPredicate);
296 if (pred->type == nullPredicate) {
298 } else if (pred->type == simplePredicate) {
299 predInstance = pred->creator(mn, r->info.name, predInstance);
302 printf("Error two complex predicates in a single metric\n");
305 complexPredResource = r;
307 printf("Error predicate before complex in list\n");
315 if (covered != l->count) {
316 printf("unable to find a predicate\n");
321 * now the base metric with the built-up trigger.
326 * complex preds replace base definitions.
329 (void) complexPred->creator(mn,
330 complexPredResource->info.name, predInstance);
332 curr->definition.baseFunc(mn, predInstance);
336 // currMi->proc = proc;
341 if (parts.count() > 1) {
342 ret = new metricDefinitionNode(m, parts);
356 List<metricDefinitionNode*> allMIs;
359 * See if we can find the requested metric instance.
360 * Currently this is only used to cache structs built for cost requests
361 * which are then instantuadted. This could be used as a general system
362 * to request find sub-metrics that are already defined and use them to
363 * reduce cost. This would require adding the componenets of an aggregate
364 * into the allMIs list since searching tends to be top down, not bottom
365 * up. This would also require adding a ref count to many of the structures
366 * so they only get deleted when we are really done with them.
370 metricInstance createMetricInstance(resourceList l, metric m)
373 metricDefinitionNode *mi;
374 List<metricDefinitionNode*> curr;
376 // first see if it already defined.
377 for (curr = allMIs; *curr; curr++) {
378 if ((*curr)->match(l, m)) break;
380 if (*curr) return(*curr);
382 // not found, build it.
383 mi = buildMetricInstRequest(l, m);
385 if (mi) allMIs.add(mi, (void *) mi->id);
389 int startCollecting(resourceList l, metric m)
392 extern void printResourceList(resourceList);
394 mi = createMetricInstance(l, m);
397 // cost = mi->cost();
398 // printf("*** metric cost = %f\n", cost);
400 mi->insertInstrumentation();
403 printf("enable of %s for RL =", getMetricName(m));
404 printResourceList(l);
407 // collect some stats.
408 metResPairsEnabled++;
409 fociUsed.addUnique(l, (void *) l);
410 metricsUsed.addUnique(m, (void *) m);
415 float guessCost(resourceList l , metric m)
420 mi = createMetricInstance(l, m);
421 if (!mi) return(0.0);
427 Boolean metricDefinitionNode::insertInstrumentation()
429 List<instReqNode*> req;
430 List<dataReqNode*> dp;
431 List<metricDefinitionNode*> curr;
433 if (inserted) return(True);
437 for (curr = components; *curr; curr++) {
438 (*curr)->insertInstrumentation();
441 for (dp = data; *dp; dp++) {
442 (*dp)->insertInstrumentation(this);
444 for (req = requests; *req; req++) {
445 (*req)->insertInstrumentation();
451 float metricDefinitionNode::cost()
455 List<instReqNode*> req;
456 List<metricDefinitionNode*> curr;
460 for (curr = components; *curr; curr++) {
461 nc = (*curr)->cost();
462 if (nc > ret) ret = nc;
465 for (req = requests; *req; req++) {
466 ret += (*req)->cost();
472 void metricDefinitionNode::disable()
474 List<dataReqNode*> dp;
475 List<instReqNode*> req;
476 metricDefinitionNode *mi;
477 List<metricDefinitionNode*> curr;
479 if (!inserted) return;
483 /* disable components of aggregate metrics */
484 for (curr = components; mi = *curr; curr++) {
488 for (dp = data; *dp; dp++) {
491 for (req = requests; *req; req++) {
497 metricDefinitionNode::~metricDefinitionNode()
499 List<instReqNode*> req;
500 List<dataReqNode*> dp;
501 metricDefinitionNode *mi;
502 List<metricDefinitionNode*> curr;
505 /* delete components of aggregate metrics */
506 for (curr = components; mi = *curr; curr++) {
510 for (dp = data; *dp; dp++) {
513 for (req = requests; *req; req++) {
519 void metricDefinitionNode::updateValue(time64 wallTime,
522 timeStamp sampleTime;
523 struct sampleInterval ret;
524 List<metricDefinitionNode*> curr;
525 // extern timeStamp elapsedPauseTime;
527 // sampleTime = (wallTime - elapsedPauseTime) / 1000000.0;
528 // commented out elapsedPauseTime because we don't currently stop CM-5
529 // node processes. (brought it back jkh 11/9/93).
530 sampleTime = wallTime / 1000000.0;
531 assert(value >= -0.01);
533 if (met->info.style == EventCounter) {
534 // only use delta from last sample.
535 assert(value + 0.0001 >= sample.value);
536 value -= sample.value;
537 sample.value += value;
540 ret = sample.newValue(valueList, sampleTime, value);
542 for (curr = aggregators; *curr; curr++) {
543 (*curr)->updateAggregateComponent(this, sampleTime, value);
547 * must do this after all updates are done, because it may turn off this
550 if (inform && ret.valid) {
551 /* invoke call backs */
552 tp->sampleDataCallbackFunc(0, id, ret.start, ret.end, ret.value);
556 void metricDefinitionNode::updateAggregateComponent(metricDefinitionNode *curr,
557 timeStamp sampleTime,
560 struct sampleInterval ret;
562 ret = sample.newValue(valueList, sampleTime, value);
564 tp->sampleDataCallbackFunc(0, id, ret.start, ret.end, ret.value);
568 void processSample(traceHeader *h, traceSample *s)
570 metricDefinitionNode *mi;
571 extern int samplesDelivered;
573 mi = midToMiMap.find((void *) s->id.id);
575 // printf("sample %d not for a valid metric instance\n", s->id.id);
579 // printf("sample id %d at time %f = %f\n", s->id.id, now, s->value);
580 mi->updateValue(h->wall, s->value);
584 metricList getMetricList()
586 if (!globalMetricList) {
587 globalMetricList = (metricList)
588 xcalloc(sizeof(struct _metricListRec), 1);
589 globalMetricList->elements = DYNINSTallMetrics;
590 globalMetricList->count = metricCount;
592 return(globalMetricList);
595 metric findMetric(char *name)
601 metrics = getMetricList();
602 for (i=0, met = metrics->elements; i < metrics->count; i++, met++) {
603 if (!strcmp(met->info.name, name)) {
610 char *getMetricName(metric m)
612 return(m->info.name);
615 metricInfo *getMetricInfo(metric m)
620 metric getMetric(metricInstance mi)
626 * functions to operate on inst request graph.
629 instReqNode::instReqNode(process *iProc,
642 Boolean instReqNode::insertInstrumentation()
644 instance = addInstFunc(proc, point, ast, when, order);
645 if (instance) return(True);
650 void instReqNode::disable()
652 deleteInst(instance);
656 instReqNode::~instReqNode()
661 float instReqNode::cost()
667 unitCost = ast->cost();
668 frequency = getPointFrequency(point);
669 value = unitCost * frequency;
674 dataReqNode::dataReqNode(dataObjectType iType,
682 initialValue = iInitialValue;
688 float dataReqNode::getMetricValue()
692 if (type == intCounter) {
693 ret = getIntCounterValue((intCounterHandle*) instance);
694 } else if (type == timer) {
695 ret = getTimerValue((timerHandle*) instance);
704 void *dataReqNode::getInferriorPtr()
707 timerHandle *timerInst;
708 intCounterHandle *counterInst;
710 if (type == intCounter) {
711 counterInst = (intCounterHandle *) instance;
713 param = (void *) counterInst->counterPtr;
717 } else if (type == timer) {
718 timerInst = (timerHandle *) instance;
720 param = (void *) timerInst->timerPtr;
730 timerHandle *dataReqNode::createTimerInstance()
734 ret = createTimer(proc, tType, report);
738 intCounterHandle *dataReqNode::createCounterInstance()
740 intCounterHandle *ret;
742 ret = createIntCounter(proc, initialValue, report);
746 void dataReqNode::insertInstrumentation(metricDefinitionNode *mi)
748 if (type == intCounter) {
749 intCounterHandle *ret;
750 ret = createCounterInstance();
751 instance = (void *) ret;
753 midToMiMap.add(mi, (void *) id.id);
756 ret = createTimerInstance();
757 instance = (void *) ret;
759 midToMiMap.add(mi, (void *) id.id);
763 void dataReqNode::disable()
768 if (!instance) return;
770 found = midToMiMap.remove((void *) id.id);
771 assert(found == True);
773 /* make sure it is gone =-- debugging code */
774 mi = midToMiMap.find((void *) id.id);
778 freeTimer((timerHandle *) instance);
779 } else if (type == intCounter) {
780 freeIntCounter((intCounterHandle *) instance);
787 dataReqNode::~dataReqNode()