Added pause_time metric.
[dyninst.git] / paradynd / src / metricDefs-cm5.C
1 /*
2  *  Copyright 1993 Jeff Hollingsworth.  All rights reserved.
3  *
4  */
5
6 #ifndef lint
7 static char Copyright[] = "@(#) Copyright (c) 1993 Jeff Hollingsowrth\
8     All rights reserved.";
9
10 static char rcsid[] = "@(#) $Header: /home/jaw/CVSROOT_20081103/CVSROOT/core/paradynd/src/Attic/metricDefs-cm5.C,v 1.5 1994/04/11 23:25:24 hollings Exp $";
11 #endif
12
13 /*
14  * metric.C - define and create metrics.
15  *
16  * $Log: metricDefs-cm5.C,v $
17  * Revision 1.5  1994/04/11 23:25:24  hollings
18  * Added pause_time metric.
19  *
20  * Revision 1.4  1994/03/25  23:00:44  hollings
21  * Made active_processes a sampledFunction.
22  *
23  * Revision 1.3  1994/02/03  23:29:44  hollings
24  * Corrected metric type for active_processes.
25  *
26  * Revision 1.2  1994/02/01  18:46:54  hollings
27  * Changes for adding perfConsult thread.
28  *
29  * Revision 1.1  1994/01/27  20:31:30  hollings
30  * Iinital version of paradynd speaking dynRPC igend protocol.
31  *
32  * Revision 1.10  1993/12/13  19:55:26  hollings
33  * support duplicate functions with the same name in a single binary.
34  *
35  * Revision 1.9  1993/11/01  22:51:15  hollings
36  * fixed per procedure waiting time.
37  *
38  * Revision 1.8  1993/10/19  15:27:54  hollings
39  * AST based mini-tramp code generator.
40  *
41  * Revision 1.7  1993/10/04  21:43:09  hollings
42  * corrected per procedure cpu time metric.
43  *
44  * Revision 1.6  1993/10/01  21:29:41  hollings
45  * Added resource discovery and filters.
46  *
47  * Revision 1.5  1993/08/20  22:02:16  hollings
48  * added perProcedureCalls
49  *
50  * Revision 1.4  1993/08/11  01:49:07  hollings
51  * chages for predicated cost model (build the inst before using it).
52  *
53  * Revision 1.3  1993/07/13  18:28:49  hollings
54  * new include file syntax.
55  * fixed procedure call defintion for number of points.
56  *
57  * Revision 1.2  1993/06/22  19:00:01  hollings
58  * global inst state.
59  *
60  * Revision 1.1  1993/06/08  20:14:34  hollings
61  * Initial revision
62  *
63  * Revision 1.1  1993/03/19  22:45:45  hollings
64  * Initial revision
65  *
66  *
67  */
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <assert.h>
71 #include <string.h>
72
73 #include "rtinst/h/rtinst.h"
74 #include "rtinst/h/trace.h"
75 #include "symtab.h"
76 #include "process.h"
77 #include "inst.h"
78 #include "dyninstP.h"
79 #include "metric.h"
80 #include "ast.h"
81
82 extern metricDefinitionNode *pauseTimeNode;
83
84 AstNode *defaultProcedurePredicate(metricDefinitionNode *mn, char *funcName,
85     AstNode *pred)
86 {
87     int i;
88     function *func;
89     dataReqNode *dataPtr;
90     AstNode *enterNode, *leaveNode;
91
92     func = findFunction(mn->proc->symbols, funcName);
93     if (!func) {
94         /* no such function in this process */
95         // 0 predicate if always false.
96         return(new AstNode(Constant, 0));
97     }
98
99     dataPtr = mn->addIntCounter(0, False);
100
101     enterNode = createPrimitiveCall("setCounter", dataPtr, 1);
102     leaveNode = createPrimitiveCall("setCounter", dataPtr, 0);
103
104     if (pred) {
105         enterNode = createIf(pred, enterNode);
106         leaveNode = createIf(pred, leaveNode);
107     }
108
109     for (; func; func=func->sibling) {
110         for (i = 0; i < func->callCount; i++) {
111             if (callsUserFuncP(func->calls[i])) {
112                 mn->addInst(func->calls[i], leaveNode,
113                     callPreInsn, orderLastAtPoint);
114                 mn->addInst(func->calls[i], enterNode,
115                     callPostInsn, orderFirstAtPoint);
116             }
117         }
118         mn->addInst(func->funcEntry, enterNode, callPreInsn, orderLastAtPoint);
119
120         mn->addInst(func->funcReturn, leaveNode, callPreInsn,orderFirstAtPoint);
121     }
122     return(new AstNode(DataValue, dataPtr));
123 }
124
125 AstNode *defaultProcessPredicate(metricDefinitionNode *mn, char *process,
126     AstNode *pred)
127 {
128     abort();
129 }
130
131
132 void createProcCalls(metricDefinitionNode *mn, AstNode *pred)
133 {
134     function *func;
135     AstNode *newCall;
136     dataReqNode *counter;
137
138     counter = mn->addIntCounter(0, True);
139     newCall = createPrimitiveCall("addCounter", counter, 1);
140
141     for (func = mn->proc->symbols->funcs; func; func = func->next) {
142         if (!func->tag & TAG_LIB_FUNC) {
143             mn->addInst(func->funcEntry, newCall,
144                 callPreInsn, orderLastAtPoint);
145         }
146     }
147     return;
148 }
149
150 void instAllFunctions(metricDefinitionNode *nm,
151                       int tag,          /* bit mask to use */
152                       AstNode *enterAst,
153                       AstNode *leaveAst)
154 {
155     function *func;
156
157     for (func = nm->proc->symbols->funcs; func; func=func->next) {
158         if (func->tag & tag) {
159             if (enterAst) {
160                 nm->addInst(func->funcEntry,
161                     enterAst, callPreInsn, orderLastAtPoint);
162             }
163             if (leaveAst) {
164                 nm->addInst(func->funcReturn,
165                     leaveAst, callPreInsn, orderFirstAtPoint);
166             }
167         }
168     }
169 }
170
171 dataReqNode *createCPUTime(metricDefinitionNode *mn, AstNode *pred)
172 {
173     function *func;
174     dataReqNode *dataPtr;
175     AstNode *stopNode, *startNode;
176
177
178     dataPtr = mn->addTimer(processTime);
179
180     startNode = new AstNode("DYNINSTstartProcessTimer", 
181         new AstNode(DataValue, dataPtr), NULL);
182     if (pred) startNode = createIf(pred, startNode);
183
184     stopNode = new AstNode("DYNINSTstopProcessTimer", 
185         new AstNode(DataValue, dataPtr), NULL);
186     if (pred) stopNode = createIf(pred, stopNode);
187
188     instAllFunctions(mn, TAG_CPU_STATE, stopNode, startNode);
189
190     func = findFunction(mn->proc->symbols, "main");
191     mn->addInst(func->funcEntry, startNode,callPreInsn,orderLastAtPoint);
192
193     mn->addInst(func->funcReturn, stopNode,callPreInsn,orderLastAtPoint);
194
195     func = findFunction(mn->proc->symbols, "exit");
196     assert(func);
197
198     mn->addInst(func->funcEntry, stopNode, callPreInsn,orderLastAtPoint);
199
200     return(dataPtr);
201 }
202
203 void createExecTime(metricDefinitionNode *mn, AstNode *pred)
204 {
205     function *func;
206     dataReqNode *dataPtr;
207     AstNode *startNode, *stopNode;
208
209     dataPtr = mn->addTimer(wallTime);
210
211     startNode = createPrimitiveCall("DYNINSTstartWallTimer", dataPtr, 0);
212     if (pred) startNode = createIf(pred, startNode);
213
214     stopNode = createPrimitiveCall("DYNINSTstopWallTimer", dataPtr, 0);
215     if (pred) stopNode = createIf(pred, stopNode);
216
217     func = findFunction(mn->proc->symbols, "main");
218     mn->addInst(func->funcEntry, startNode, callPreInsn, orderLastAtPoint);
219
220     mn->addInst(func->funcReturn, stopNode, callPreInsn, orderLastAtPoint);
221
222     func = findFunction(mn->proc->symbols, "exit");
223     assert(func);
224
225     mn->addInst(func->funcEntry, stopNode, callPreInsn, orderLastAtPoint);
226 }
227
228 void createSyncOps(metricDefinitionNode *mn, AstNode *trigger)
229 {
230     AstNode *newSyncOp;
231     dataReqNode *counter;
232     
233     counter = mn->addIntCounter(0, True);
234
235     newSyncOp = createPrimitiveCall("addCounter", counter, 1);
236     if (trigger) newSyncOp = createIf(trigger, newSyncOp);
237
238     instAllFunctions(mn, TAG_CPU_STATE, newSyncOp, NULL);
239 }
240
241 void createActiveProcesses(metricDefinitionNode *mn, AstNode *trigger)
242 {
243     mn->addIntCounter(1, True);
244
245     return;
246 }
247
248 void createMsgs(metricDefinitionNode *mn, AstNode *trigger)
249 {
250     AstNode *newMsgOp;
251     dataReqNode *counter;
252     
253     counter = mn->addIntCounter(0, True);
254
255     newMsgOp = createPrimitiveCall("addCounter", counter, 1);
256     if (trigger) newMsgOp = createIf(trigger, newMsgOp);
257
258     instAllFunctions(mn, TAG_MSG_FUNC, newMsgOp, NULL);
259
260 }
261
262 extern libraryList msgFilterFunctions;
263 extern libraryList msgByteFunctions;
264 extern libraryList msgByteSentFunctions;
265 extern libraryList msgByteRecvFunctions;
266
267 //
268 // ***** Warning this metric is CM-5 specific. *****
269 //
270 void createMsgBytesMetric(metricDefinitionNode *mn,
271                           libraryList *funcs,
272                           AstNode *trigger)
273 {
274     function *func;
275     AstNode *msgBytesAst;
276     dataReqNode *dataPtr;
277
278     dataPtr = mn->addIntCounter(0, True);
279
280     // addCounter(counter, param4 * param5)
281     msgBytesAst = new AstNode("addCounter", 
282             new AstNode(DataValue, dataPtr),
283             new AstNode(timesOp, new AstNode(Param, (void *) 4), 
284                                  new AstNode(Param, (void *) 5)));
285     if (trigger) msgBytesAst = createIf(trigger, msgBytesAst);
286
287     for (func = mn->proc->symbols->funcs; func; func = func->next) {
288         if (funcs->find(func->prettyName)) {
289             mn->addInst(func->funcEntry, msgBytesAst,
290                 callPreInsn, orderLastAtPoint);
291         }
292     }
293 }
294
295 void createMsgBytesTotal(metricDefinitionNode *mn, AstNode *tr)
296 {
297     createMsgBytesMetric(mn, &msgByteFunctions, tr);
298 }
299
300 void createMsgBytesSent(metricDefinitionNode *mn, AstNode *tr)
301 {
302     createMsgBytesMetric(mn, &msgByteSentFunctions, tr);
303 }
304
305 void createMsgBytesRecv(metricDefinitionNode *mn, AstNode *tr)
306 {
307     createMsgBytesMetric(mn, &msgByteSentFunctions, tr);
308 }
309
310 AstNode *defaultMSGTagPredicate(metricDefinitionNode *mn, 
311                                 char *tag, AstNode *trigger)
312 {
313     int iTag;
314     function *func;
315     dataReqNode *data;
316     AstNode *tagTest;
317     AstNode *filterNode, *clearNode;
318
319     iTag = atoi(tag);
320
321     data = mn->addIntCounter(0, False);
322
323     // (== param2, iTag)
324     tagTest = new AstNode(eqOp, new AstNode(Param, (void *) 2),
325                                 new AstNode(Constant, (void *) iTag));
326
327     filterNode = createIf(tagTest, createPrimitiveCall("addCounter", data, 1));
328     if (trigger) filterNode = createIf(trigger, filterNode);
329
330     clearNode = createPrimitiveCall("setCounter", data, 0);
331     if (trigger) clearNode = createIf(trigger, clearNode);
332
333     for (func = mn->proc->symbols->funcs; func; func = func->next) {
334         if (msgFilterFunctions.find(func->prettyName)) {
335             mn->addInst(func->funcEntry, filterNode,
336                 callPreInsn, orderFirstAtPoint);
337             mn->addInst(func->funcReturn, clearNode,
338                 callPreInsn, orderLastAtPoint);
339         }
340     }
341     return(new AstNode(DataValue, data));
342 }
343
344 //
345 // place holder for pause time metric.
346 //
347 void createPauseTime(metricDefinitionNode *mn, AstNode *trigger)
348 {
349     pauseTimeNode = mn;
350 }
351
352 void createSyncWait(metricDefinitionNode *mn, AstNode *trigger)
353 {
354     dataReqNode *dataPtr;
355     AstNode *stopNode, *startNode;
356
357     dataPtr = mn->addTimer(processTime);
358
359     startNode = new AstNode("DYNINSTstartProcessTimer", 
360         new AstNode(DataValue, dataPtr), NULL);
361     if (trigger) startNode = createIf(trigger, startNode);
362
363     stopNode = new AstNode("DYNINSTstopProcessTimer", 
364         new AstNode(DataValue, dataPtr), NULL);
365     if (trigger) stopNode = createIf(trigger, stopNode);
366
367     instAllFunctions(mn, TAG_MSG_FUNC, startNode, stopNode);
368 }
369
370
371 void perProcedureWallTime(metricDefinitionNode *mn, 
372                           char *funcName, 
373                           AstNode *pred)
374 {
375     int i;
376     function *func;
377     dataReqNode *dataPtr;
378     AstNode *startNode, *stopNode;
379
380     dataPtr = mn->addTimer(wallTime);
381
382     /* function does not exhist in this process */
383     func = findFunction(mn->proc->symbols, funcName);
384     if (!func) return;
385
386     startNode = createPrimitiveCall("DYNINSTstartWallTimer", dataPtr, 0);
387     if (pred) startNode = createIf(pred, startNode);
388
389     stopNode = createPrimitiveCall("DYNINSTstopWallTimer", dataPtr, 0);
390     if (pred) stopNode = createIf(pred, stopNode);
391
392     for (; func; func=func->sibling) {
393         for (i = 0; i < func->callCount; i++) {
394             if (callsUserFuncP(func->calls[i])) {
395                 mn->addInst(func->calls[i], stopNode,
396                     callPreInsn, orderLastAtPoint);
397
398                 mn->addInst(func->calls[i], startNode,
399                     callPostInsn, orderFirstAtPoint);
400             }
401         }
402         mn->addInst(func->funcEntry, startNode, callPreInsn, orderLastAtPoint);
403         mn->addInst(func->funcReturn, stopNode, callPreInsn, orderFirstAtPoint);
404     }
405 }
406
407 AstNode *perProcedureCPUTime(metricDefinitionNode *mn, 
408                              char *funcName, 
409                              AstNode *trigger)
410 {
411
412     int i;
413     function *func;
414 #ifdef notdef
415     AstNode *newTrigger;
416 #endif
417     dataReqNode *dataPtr;
418     AstNode *startNode, *stopNode;
419
420     func = findFunction(mn->proc->symbols, funcName);
421
422     /* function does not exhist in this process */
423     if (!func) return(NULL);
424
425 #ifdef notdef
426     // Why did I put this here ???? -- jkh
427     newTrigger = defaultProcedurePredicate(mn, funcName, trigger);
428     dataPtr = createCPUTime(mn, newTrigger);
429 #endif
430     dataPtr = mn->addTimer(processTime);
431
432     startNode = new AstNode("DYNINSTstartProcessTimer", 
433         new AstNode(DataValue, dataPtr), NULL);
434     if (trigger) startNode = createIf(trigger, startNode);
435
436     stopNode = new AstNode("DYNINSTstopProcessTimer", 
437         new AstNode(DataValue, dataPtr), NULL);
438     if (trigger) stopNode = createIf(trigger, stopNode);
439
440     for (; func; func=func->sibling) {
441         for (i = 0; i < func->callCount; i++) {
442             if (callsUserFuncP(func->calls[i])) {
443                 mn->addInst(func->calls[i], stopNode,
444                     callPreInsn, orderFirstAtPoint);
445                 
446                 mn->addInst(func->calls[i], startNode,
447                     callPostInsn, orderFirstAtPoint);
448             }
449         }
450         mn->addInst(func->funcEntry, startNode, callPreInsn, orderLastAtPoint);
451
452         mn->addInst(func->funcReturn, stopNode, callPreInsn, orderFirstAtPoint);
453     }
454
455     return(NULL);
456 }
457
458 AstNode *perProcedureCalls(metricDefinitionNode *mn, 
459                              char *funcName, 
460                              AstNode *trigger)
461 {
462     function *func;
463     AstNode *newCall;
464     dataReqNode *counter;
465
466     func = findFunction(mn->proc->symbols, funcName);
467
468     /* function does not exhist in this process */
469     if (!func) return(new AstNode(Constant, 0));
470
471     counter = mn->addIntCounter(0, True);
472     newCall = createPrimitiveCall("addCounter", counter, 1);
473     if (trigger) newCall = createIf(trigger, newCall);
474
475     for (; func; func=func->sibling) {
476         mn->addInst(func->funcEntry, newCall, callPreInsn, orderLastAtPoint);
477     }
478
479     return(new AstNode(DataValue, counter));
480 }
481
482 resourcePredicate cpuTimePredicates[] = {
483   { "/SyncObject/MsgTag",       
484     invalidPredicate,           
485     (createPredicateFunc) NULL },
486   { "/SyncObject",      
487     invalidPredicate,           
488     (createPredicateFunc) NULL },
489   { "/Machine", 
490     nullPredicate,              
491     (createPredicateFunc) NULL },
492   { "/Process", 
493     nullPredicate,              
494     (createPredicateFunc) NULL },
495   { "/Procedure",       
496     replaceBase,                
497     (createPredicateFunc) perProcedureCPUTime },
498   { NULL, nullPredicate, (createPredicateFunc) NULL },
499 };
500
501 resourcePredicate wallTimePredicates[] = {
502   { "/SyncObject/MsgTag",       
503     simplePredicate,            
504     (createPredicateFunc) defaultMSGTagPredicate },
505   { "/SyncObject",      
506     invalidPredicate,           
507     (createPredicateFunc) NULL },
508   { "/Procedure",       
509     replaceBase,                
510     (createPredicateFunc) perProcedureWallTime },
511   { "/Machine", 
512     nullPredicate,              
513     (createPredicateFunc) NULL },
514   { "/Process", 
515     nullPredicate,              
516     (createPredicateFunc) NULL },
517   { NULL, nullPredicate, (createPredicateFunc) NULL },
518 };
519
520 resourcePredicate procCallsPredicates[] = {
521   { "/SyncObject",      
522     invalidPredicate,           
523     (createPredicateFunc) NULL },
524   { "/Machine", 
525     nullPredicate,              
526     (createPredicateFunc) NULL },
527   { "/Process", 
528     nullPredicate,              
529     (createPredicateFunc) NULL },
530   { "/Procedure",       
531     replaceBase,                
532     (createPredicateFunc) perProcedureCalls },
533   { NULL, nullPredicate, (createPredicateFunc) NULL },
534 };
535
536 resourcePredicate msgPredicates[] = {
537   { "/SyncObject/MsgTag",       
538     simplePredicate,            
539     (createPredicateFunc) defaultMSGTagPredicate },
540   { "/SyncObject",      
541     invalidPredicate,           
542     (createPredicateFunc) NULL },
543   { "/Machine", 
544     nullPredicate,              
545     (createPredicateFunc) NULL },
546   { "/Process", 
547     nullPredicate,              
548     (createPredicateFunc) NULL },
549  { "/Procedure",
550    simplePredicate,     
551    (createPredicateFunc) defaultProcedurePredicate },
552  { NULL, nullPredicate, (createPredicateFunc) NULL },
553 };
554
555 resourcePredicate defaultPredicates[] = {
556   { "/SyncObject/MsgTag",       
557     simplePredicate,            
558     (createPredicateFunc) defaultMSGTagPredicate },
559   { "/SyncObject",      
560     invalidPredicate,           
561     (createPredicateFunc) NULL },
562   { "/Machine", 
563     nullPredicate,              
564     (createPredicateFunc) NULL },
565   { "/Process", 
566     nullPredicate,              
567     (createPredicateFunc) NULL },
568  { "/Procedure",
569    simplePredicate,     
570    (createPredicateFunc) defaultProcedurePredicate },
571  { NULL, nullPredicate, (createPredicateFunc) NULL },
572 };
573
574 resourcePredicate globalOnlyPredicates[] = {
575   { "/SyncObject/MsgTag",       
576     simplePredicate,            
577     (createPredicateFunc) NULL },
578   { "/SyncObject",      
579     invalidPredicate,           
580     (createPredicateFunc) NULL },
581   { "/Machine", 
582     nullPredicate,              
583     (createPredicateFunc) NULL },
584   { "/Process", 
585     nullPredicate,              
586     (createPredicateFunc) NULL },
587  { "/Procedure",
588    simplePredicate,     
589    (createPredicateFunc) NULL },
590  { NULL, nullPredicate, (createPredicateFunc) NULL },
591 };
592
593 struct _metricRec DYNINSTallMetrics[] = {
594     { { "active_processes", SampledFunction, "Processes" },
595       { (createMetricFunc) createActiveProcesses, defaultPredicates },
596     },
597     { { "cpu", EventCounter, "# CPUs" },
598       { (createMetricFunc) createCPUTime, cpuTimePredicates },
599     },
600     { { "exec_time", EventCounter, "%Time" },
601       { (createMetricFunc) createExecTime, wallTimePredicates },
602     },
603     { { "procedure_calls", EventCounter, "Calls/sec" },
604       { (createMetricFunc) createProcCalls, procCallsPredicates },
605     },
606     { { "msgs", EventCounter, "Ops/sec" },
607       { (createMetricFunc) createMsgs, defaultPredicates },
608     },
609     { { "msg_bytes", EventCounter, "Bytes/Sec" },
610       { (createMetricFunc) createMsgBytesTotal, defaultPredicates },
611     },
612     { { "msg_bytes_sent", EventCounter, "Bytes/Sec" },
613       { (createMetricFunc) createMsgBytesSent, defaultPredicates },
614     },
615     { { "msg_bytes_recv", EventCounter, "Bytes/Sec" },
616       { (createMetricFunc) createMsgBytesRecv, defaultPredicates },
617     },
618     { { "sync_ops", EventCounter, "Ops/sec" },
619       { (createMetricFunc) createSyncOps, defaultPredicates },
620     },
621     { { "sync_wait", EventCounter, "# Waiting" },
622       { (createMetricFunc) createSyncWait, defaultPredicates },
623     },
624     { { "pause_time", SampledFunction, "# Paused" },
625       { (createMetricFunc) createPauseTime, globalOnlyPredicates },
626     },
627 };
628
629 int metricCount = sizeof(DYNINSTallMetrics)/sizeof(DYNINSTallMetrics[0]);