timexLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:26k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* timexLib.c - execution timer facilities */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03x,16oct01,jn   use symFindSymbol for symbol lookup (SPR #7453)
  8. 03w,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  9. 03v,14feb97,dvs  added error checking in timexShowCalls (SPR #6876).
  10. 03v,14feb97,dvs  timexShowCalls now prints func addr if lookup in sym table 
  11.  fails (SPR #6876).
  12. 03u,05may93,caf  tweaked for ansi.
  13. 03t,13feb93,kdl  changed cplusLib.h to private/cplusLibP.h (SPR #1917).
  14. 03s,20jan93,jdi  documentation cleanup for 5.1.
  15. 03r,01aug92,srh  added C++ demangling idiom to timexShowCalls
  16. 03q,26may92,rrr  the tree shuffle
  17. 03p,01dec91,gae  more ANSI cleanup.
  18. 03o,04oct91,rrr  passed through the ansification filter
  19.                   -changed functions to ansi style
  20.   -changed VOID to void
  21.   -changed copyright notice
  22. 03n,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  23.  doc review by dnw.
  24. 03m,24mar91,jdi  documentation cleanup.
  25. 03l,10aug90,dnw  added include of timexLib.h.
  26. 03k,10aug90,kdl  added forward declarations for functions returning void.
  27. 03j,10jul90,dnw  changed declaration of timexNull from void to int to allow
  28.    void to be void one day
  29. 03i,12mar90,jcf  symbol table type now SYM_TYPE.
  30. 03h,07mar90,jdi  documentation cleanup.
  31. 03g,03apr89,ecs  made optional arguments explicit in timexFunc, timex, timexN,
  32.    +gae     timexPost, timexPre.
  33. 03f,20aug88,gae  documentation.
  34. 03e,07jul88,jcf  lint.
  35. 03d,05jun88,dnw  changed name to timexLib.
  36. 03c,30may88,dnw  changed to v4 names.
  37. 03b,01may88,gae  added null routine timLib().
  38. 03a,27jan88,jcf  made kernel independent.
  39. 02s,18nov87,ecs  documentation.
  40. 02r,04nov87,ecs  documentation.
  41. 02q,08jun87,llk  fixed initialization of tiPreCalls, tiTimeCalls, tiPostCalls.
  42. 02p,23mar87,jlf  documentation.
  43. 02o,12jan87,llk  corrected information in tihelp.
  44. 02n,21dec86,dnw  changed to not get include files from default directories.
  45. 02m,02dec86,llk  changed tiHelp to tihelp.
  46. 02l,04sep86,jlf  documentation.
  47. 02k,27jul86,llk  prints error messages to standard error (uses printErr)
  48. 02j,05jun86,dnw  changed sstLib calls to symLib.
  49. 02i,24mar86,dnw  de-linted.
  50. 02h,19mar86,dnw  fixed calibration to include pushing of args and calling
  51.    routine.
  52.  corrected documentation.
  53.  changed timeN to report how many reps it made.
  54. 02g,11oct85,dnw  de-linted.
  55. 02f,37aug85,rdc  changed MAX_SYM_LEN to MAX_SYS_SYM_LEN.
  56. 02e,21jul85,jlf  documentation.
  57. 02d,01jun85,rdc  updated documentation.
  58. 02c,14aug84,jlf  changed calls to clkGetRate to sysClkGetRate.
  59. 02b,16jul84,ecs  changed to use unix-style format codes.
  60. 02a,24jun84,dnw  rewritten
  61. */
  62. /*
  63. This library contains routines for timing the execution of programs,
  64. individual functions, and groups of functions.  The VxWorks system clock
  65. is used as a time base.  Functions that have a short execution time
  66. relative to this time base can be called repeatedly to establish an
  67. average execution time with an acceptable percentage of error.
  68. Up to four functions can be specified to be timed as a group.
  69. Additionally, sets of up to four functions can be specified as pre- or
  70. post-timing functions, to be executed before and after the timed functions.
  71. The routines timexPre() and timexPost() are used to specify the pre- and
  72. post-timing functions, while timexFunc() specifies the functions to
  73. be timed.
  74. The routine timex() is used to time a single execution of a function or
  75. group of functions.  If called with no arguments, timex() uses the
  76. functions in the lists created by calls to timexPre(), timexPost(), and
  77. timexFunc().  If called with arguments, timex() times the function
  78. specified, instead of the previous list.  The routine timexN() works in
  79. the same manner as timex() except that it iterates the function calls to
  80. be timed.
  81. EXAMPLES
  82. The routine timex() can be used to obtain the execution time of a single
  83. routine:
  84. .CS
  85.     -> timex myFunc, myArg1, myArg2, ...
  86. .CE
  87. The routine timexN() calls a function repeatedly until a 2% or better
  88. tolerance is obtained:
  89. .CS
  90.     -> timexN myFunc, myArg1, myArg2, ...
  91. .CE
  92. The routines timexPre(), timexPost(), and timexFunc() are used to specify
  93. a list of functions to be executed as a group:
  94. .CS
  95.     -> timexPre 0, myPreFunc1, preArg1, preArg2, ...
  96.     -> timexPre 1, myPreFunc2, preArg1, preArg2, ...
  97.     -> timexFunc 0, myFunc1, myArg1, myArg2, ...
  98.     -> timexFunc 1, myFunc2, myArg1, myArg2, ...
  99.     -> timexFunc 2, myFunc3, myArg1, myArg2, ...
  100.     -> timexPost 0, myPostFunc, postArg1, postArg2, ...
  101. .CE
  102. The list is executed by calling timex() or timexN() without arguments:
  103. .CS
  104.     -> timex
  105. .ft 1
  106. or
  107. .ft P
  108.     -> timexN
  109. .CE
  110. In this example, <myPreFunc1> and <myPreFunc2> are called with their
  111. respective arguments.  <myFunc1>, <myFunc2>, and <myFunc3> are then
  112. called in sequence and timed.  If timexN() was used, the sequence is
  113. called repeatedly until a 2% or better error tolerance is achieved.
  114. Finally, <myPostFunc> is called with its arguments.  The timing results
  115. are reported after all post-timing functions are called.
  116. NOTE
  117. The timings measure the execution time of the routine body, without the
  118. usual subroutine entry and exit code (usually LINK, UNLINK, and RTS
  119. instructions).  Also, the time required to set up the arguments and
  120. call the routines is not included in the reported times.  This is
  121. because these timing routines automatically calibrate themselves by
  122. timing the invocation of a null routine, and thereafter subtracting
  123. that constant overhead.
  124. INCLUDE FILES: timexLib.h
  125. SEE ALSO: spyLib
  126. */
  127. #include "vxWorks.h"
  128. #include "symLib.h"
  129. #include "stdio.h"
  130. #include "string.h"
  131. #include "sysSymTbl.h"
  132. #include "sysLib.h"
  133. #include "tickLib.h"
  134. #include "timexLib.h"
  135. #include "private/cplusLibP.h"
  136. #define MAX_CALLS 4 /* max functions in each category */
  137. #define MAX_ARGS 8 /* max args to each function */
  138. #define MAX_PERCENT 2 /* max percent error for auto-timing */
  139. #define MAX_REPS 20000 /* max reps for auto-timing */
  140. #define TIMEX_DEMANGLE_PRINT_LEN 256
  141. typedef struct /* CALL */
  142.     {
  143.     VOIDFUNCPTR func; /* function to call */
  144.     int arg [MAX_ARGS]; /* args to function */
  145.     } CALL;
  146. typedef CALL CALL_ARRAY [MAX_CALLS];
  147. LOCAL char *timexScaleText [] =
  148.     {
  149.     "secs", /* scale = 0 */
  150.     "millisecs", /* scale = 1 */
  151.     "microsecs", /* scale = 2 */
  152.     };
  153. static void timexNull (void); /* forward declaration */
  154. LOCAL CALL_ARRAY timexPreCalls = /* calls to be made just before timing*/
  155.     {
  156.     { timexNull },
  157.     { timexNull },
  158.     { timexNull },
  159.     { timexNull },
  160.     };
  161. LOCAL CALL_ARRAY timexTimeCalls = /* calls to be timed */
  162.     {
  163.     { timexNull },
  164.     { timexNull },
  165.     { timexNull },
  166.     { timexNull },
  167.     };
  168. LOCAL CALL_ARRAY timexPostCalls = /* calls to be made just after timing */
  169.     {
  170.     { timexNull },
  171.     { timexNull },
  172.     { timexNull },
  173.     { timexNull },
  174.     };
  175. LOCAL CALL_ARRAY timexNullCalls =
  176.     {
  177.     { timexNull },
  178.     { timexNull },
  179.     { timexNull },
  180.     { timexNull },
  181.     };
  182. LOCAL int overhead; /* usecs of overhead per rep in timing test */
  183. /* forward static functions */
  184. static void timexAddCall (CALL *callArray, int i, FUNCPTR func, int arg1, int
  185. arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
  186. int arg8);
  187. static void timexAutoTime (CALL_ARRAY preCalls, CALL_ARRAY timeCalls,
  188. CALL_ARRAY postCalls, int *pNreps, int *pScale, int *pTime,
  189. int *pError, int *pPercent);
  190. static void timexCal (void);
  191. static void timexClrArrays (void);
  192. static void timexMakeCalls (CALL_ARRAY calls);
  193. static void timexScale (int ticks, int reps, int *pScale, int *pTime, int
  194. *pError, int *pPercent);
  195. static void timexShowCalls (CALL_ARRAY calls);
  196. static void timexTime (int reps, CALL_ARRAY preCalls, CALL_ARRAY timeCalls,
  197. CALL_ARRAY postCalls, int *pScale, int *pTime, int *pError,
  198. int *pPercent);
  199. /*******************************************************************************
  200. *
  201. * timexInit - include the execution timer library
  202. *
  203. * This null routine is provided so that timexLib can be linked into the system.
  204. * If the configuration macro INCLUDE_TIMEX is defined, it is called by the
  205. * root task, usrRoot(), in usrConfig.c.
  206. *
  207. * RETURNS: N/A
  208. */
  209. void timexInit (void)
  210.     {
  211.     }
  212. /*******************************************************************************
  213. *
  214. * timexClear - clear the list of function calls to be timed
  215. *
  216. * This routine clears the current list of functions to be timed.
  217. *
  218. * RETURNS: N/A
  219. */
  220. void timexClear (void)
  221.     {
  222.     timexClrArrays ();
  223.     timexShow ();
  224.     }
  225. /*******************************************************************************
  226. *
  227. * timexFunc - specify functions to be timed
  228. *
  229. * This routine adds or deletes functions in the list of functions
  230. * to be timed as a group by calls to timex() or timexN().  Up to four
  231. * functions can be included in the list.  The argument <i> specifies the
  232. * function's position in the sequence of execution (0, 1, 2, or 3).
  233. * A function is deleted by specifying its sequence number <i> and NULL for the
  234. * function argument <func>.
  235. *
  236. * RETURNS: N/A
  237. *
  238. * SEE ALSO: timex(), timexN()
  239. */
  240. void timexFunc
  241.     (
  242.     int i,        /* function number in list (0..3)               */
  243.     FUNCPTR func, /* function to be added (NULL if to be deleted) */
  244.     int arg1,     /* first of up to 8 args to call function with */ 
  245.     int arg2,
  246.     int arg3,
  247.     int arg4,
  248.     int arg5,
  249.     int arg6,
  250.     int arg7,
  251.     int arg8
  252.     )
  253.     {
  254.     timexAddCall (timexTimeCalls, i, func, arg1, arg2, arg3, arg4, arg5, arg6,
  255.   arg7, arg8);
  256.     timexShow ();
  257.     }
  258. /*******************************************************************************
  259. *
  260. * timexHelp - display synopsis of execution timer facilities
  261. *
  262. * This routine displays the following summary of the available
  263. * execution timer functions:
  264. * .CS
  265. *     timexHelp                      Print this list.
  266. *     timex       [func,[args...]]   Time a single execution.
  267. *     timexN      [func,[args...]]   Time repeated executions.
  268. *     timexClear                     Clear all functions.
  269. *     timexFunc   i,func,[args...]   Add timed function number i (0,1,2,3).
  270. *     timexPre    i,func,[args...]   Add pre-timing function number i.
  271. *     timexPost   i,func,[args...]   Add post-timing function number i.
  272. *     timexShow                      Show all functions to be called.
  273. *
  274. *     Notes:
  275. *       1) timexN() will repeat calls enough times to get
  276. *          timing accuracy to approximately 2%.
  277. *       2) A single function can be specified with timex() and timexN();
  278. *          or, multiple functions can be pre-set with timexFunc().
  279. *       3) Up to 4 functions can be pre-set with timexFunc(),
  280. *          timexPre(), and timexPost(), i.e., i in the range 0 - 3.
  281. *       4) timexPre() and timexPost() allow locking/unlocking, or
  282. *          raising/lowering priority before/after timing.
  283. * .CE
  284. *
  285. * RETURNS: N/A
  286. */
  287. void timexHelp (void)
  288.     {
  289.     static char *helpMsg [] =
  290.     {
  291.     "timexHelp                      Print this list.",
  292.     "timex       [func,[args...]]   Time a single execution.",
  293.     "timexN      [func,[args...]]   Time repeated executions.",
  294.     "timexClear                     Clear all functions.",
  295.     "timexFunc   i,func,[args...]   Add timed function number i (0,1,2,3).",
  296.     "timexPre    i,func,[args...]   Add pre-timing function number i.",
  297.     "timexPost   i,func,[args...]   Add post-timing function number i.",
  298.     "timexShow                      Show all functions to be called.n",
  299.     "Notes:",
  300.     "  1) timexN() will repeat calls enough times to get",
  301.     "     timing accuracy to approximately 2%.",
  302.     "  2) A single function can be specified with timex() and timexN();",
  303.     "     or, multiple functions can be pre-set with timexFunc().",
  304.     "  3) Up to 4 functions can be pre-set with timexFunc(),",
  305.     "     timexPre(), and timexPost(), i.e., i in the range 0 - 3.",
  306.     "  4) timexPre() and timexPost() allow locking/unlocking, or",
  307.     "     raising/lowering priority before/after timing.",
  308.     NULL, /* list terminator */
  309.     };
  310.     FAST char **ppMsg;
  311.     printf ("n");
  312.     for (ppMsg = helpMsg; *ppMsg != NULL; ++ppMsg)
  313. printf ("%sn", *ppMsg);
  314.     }
  315. /*******************************************************************************
  316. *
  317. * timex - time a single execution of a function or functions
  318. *
  319. * This routine times a single execution of a specified function with up to
  320. * eight of the function's arguments.  If no function is specified, it times
  321. * the execution of the current list of functions to be timed,
  322. * which is created using timexFunc(), timexPre(), and timexPost().
  323. * If timex() is executed with a function argument, the entire current list
  324. * is replaced with the single specified function.
  325. *
  326. * When execution is complete, timex() displays the execution time.
  327. * If the execution was so fast relative to the clock rate that the time is
  328. * meaningless (error > 50%), a warning message is printed instead.  In such
  329. * cases, use timexN().
  330. *
  331. * RETURNS: N/A
  332. *
  333. * SEE ALSO: timexFunc(), timexPre(), timexPost(), timexN()
  334. */
  335. void timex
  336.     (
  337.     FUNCPTR func,   /* function to time (optional)                 */
  338.     int arg1,       /* first of up to 8 args to call function with (optional) */
  339.     int arg2,
  340.     int arg3,
  341.     int arg4,
  342.     int arg5,
  343.     int arg6,
  344.     int arg7,
  345.     int arg8
  346.     )
  347.     {
  348.     int scale;
  349.     int time;
  350.     int error;
  351.     int percent;
  352.     /* if function specified, clear any existing functions and add this one */
  353.     if (func != NULL)
  354. {
  355. timexClrArrays ();
  356. timexAddCall (timexTimeCalls, 0, func, arg1, arg2, arg3, arg4, arg5,
  357.       arg6, arg7, arg8);
  358. }
  359.     /* calibrate if necessary */
  360.     if (overhead == 0)
  361. timexCal ();
  362.     /* time calls */
  363.     timexTime (1, timexPreCalls, timexTimeCalls, timexPostCalls,
  364.     &scale, &time, &error, &percent);
  365.     if (percent > 50)
  366. {
  367. printErr (
  368.     "timex: execution time too short to be measured meaningfullyn");
  369. printErr ("       in a single execution.n");
  370. printErr ("       Type "timexN" to time repeated execution.n");
  371. printErr ("       Type "timexHelp" for more information.n");
  372. }
  373.     else
  374. printErr ("timex: time of execution = %d +/- %d (%d%%) %sn",
  375.   time, error, percent, timexScaleText [scale]);
  376.     }
  377. /*******************************************************************************
  378. *
  379. * timexN - time repeated executions of a function or group of functions
  380. *
  381. * This routine times the execution of the current list of functions to be
  382. * timed in the same manner as timex(); however, the list of functions
  383. * is called a variable number of times until sufficient resolution
  384. * is achieved to establish the time with an error less than 2%. (Since each
  385. * iteration of the list may be measured to a resolution of +/- 1 clock
  386. * tick, repetitive timings decrease this error to 1/N ticks, where N is
  387. * the number of repetitions.)
  388. *
  389. * RETURNS: N/A
  390. *
  391. * SEE ALSO: timexFunc(), timex()
  392. */
  393. void timexN
  394.     (
  395.     FUNCPTR func,  /* function to time (optional)                   */
  396.     int arg1,      /* first of up to 8 args to call function with */
  397.     int arg2,
  398.     int arg3,
  399.     int arg4,
  400.     int arg5,
  401.     int arg6,
  402.     int arg7,
  403.     int arg8
  404.     )
  405.     {
  406.     int scale;
  407.     int time;
  408.     int error;
  409.     int nreps;
  410.     int percent;
  411.     /* if function specified, clear any existing functions and add this one */
  412.     if (func != NULL)
  413. {
  414. timexClrArrays ();
  415. timexAddCall (timexTimeCalls, 0, func, arg1, arg2, arg3, arg4, arg5,
  416.       arg6, arg7, arg8);
  417. }
  418.     /* calibrate if necessary then time calls */
  419.     if (overhead == 0)
  420. timexCal ();
  421.     timexAutoTime (timexPreCalls, timexTimeCalls, timexPostCalls,
  422.    &nreps, &scale, &time, &error, &percent);
  423.     printErr ("timex: %d reps, time per rep = %d +/- %d (%d%%) %sn",
  424.       nreps, time, error, percent, timexScaleText [scale]);
  425.     }
  426. /*******************************************************************************
  427. *
  428. * timexPost - specify functions to be called after timing
  429. *
  430. * This routine adds or deletes functions in the list of functions to be
  431. * called immediately following the timed functions.  A maximum of four
  432. * functions may be included.  Up to eight arguments may be passed to each
  433. * function.
  434. *
  435. * RETURNS: N/A
  436. */
  437. void timexPost
  438.     (
  439.     int i,        /* function number in list (0..3)                */
  440.     FUNCPTR func, /* function to be added (NULL if to be deleted)  */
  441.     int arg1,     /* first of up to 8 args to call function with */
  442.     int arg2,
  443.     int arg3,
  444.     int arg4,
  445.     int arg5,
  446.     int arg6,
  447.     int arg7,
  448.     int arg8
  449.     )
  450.     {
  451.     timexAddCall (timexPostCalls, i, func, arg1, arg2, arg3, arg4, arg5, arg6,
  452.   arg7, arg8);
  453.     timexShow ();
  454.     }
  455. /*******************************************************************************
  456. *
  457. * timexPre - specify functions to be called prior to timing
  458. *
  459. * This routine adds or deletes functions in the list of functions to be
  460. * called immediately prior to the timed functions.  A maximum of four
  461. * functions may be included.  Up to eight arguments may be passed to each
  462. * function.
  463. *
  464. * RETURNS: N/A
  465. */
  466. void timexPre
  467.     (
  468.     int i,        /* function number in list (0..3)                */
  469.     FUNCPTR func, /* function to be added (NULL if to be deleted)  */
  470.     int arg1,     /* first of up to 8 args to call function with */
  471.     int arg2,
  472.     int arg3,
  473.     int arg4,
  474.     int arg5,
  475.     int arg6,
  476.     int arg7,
  477.     int arg8
  478.     )
  479.     {
  480.     timexAddCall (timexPreCalls, i, func, arg1, arg2, arg3, arg4, arg5, arg6,
  481.   arg7, arg8);
  482.     timexShow ();
  483.     }
  484. /*******************************************************************************
  485. *
  486. * timexShow - display the list of function calls to be timed
  487. *
  488. * This routine displays the current list of function calls to be timed.
  489. * These lists are created by calls to timexPre(), timexFunc(), and
  490. * timexPost().
  491. *
  492. * RETURNS: N/A
  493. *
  494. * SEE ALSO: timexPre(), timexFunc(), timexPost()
  495. */
  496. void timexShow (void)
  497.     {
  498.     printf ("ntimex:");
  499.     printf ("n    pre-calls:n");
  500.     timexShowCalls (timexPreCalls);
  501.     printf ("n    timed calls:n");
  502.     timexShowCalls (timexTimeCalls);
  503.     printf ("n    post-calls:n");
  504.     timexShowCalls (timexPostCalls);
  505.     }
  506. /*******************************************************************************
  507. *
  508. * timexAddCall - enter a call in a call array
  509. *
  510. * RETURNS: N/A.
  511. */
  512. LOCAL void timexAddCall
  513.     (
  514.     CALL *callArray,    /* array to be altered                     */
  515.     int i,        /* function number in list (0..3)                */
  516.     FUNCPTR func, /* function to be added (NULL if to be deleted)  */
  517.     int arg1,     /* first of up to 8 params to call function with */
  518.     int arg2,
  519.     int arg3,
  520.     int arg4,
  521.     int arg5,
  522.     int arg6,
  523.     int arg7,
  524.     int arg8
  525.     )
  526.     {
  527.     if (func == NULL)
  528. func = (FUNCPTR) timexNull; /* func should be declared FUNCPTR? */
  529.     if (i >= 0 && i < MAX_CALLS)
  530. {
  531. callArray[i].func   = (VOIDFUNCPTR) func; /* func should be declared FUNCPTR? */
  532. callArray[i].arg[0] = arg1;
  533. callArray[i].arg[1] = arg2;
  534. callArray[i].arg[2] = arg3;
  535. callArray[i].arg[3] = arg4;
  536. callArray[i].arg[4] = arg5;
  537. callArray[i].arg[5] = arg6;
  538. callArray[i].arg[6] = arg7;
  539. callArray[i].arg[7] = arg8;
  540. }
  541.     else
  542. printf ("timex: call number must be in range 0..%dn", MAX_CALLS - 1);
  543.     }
  544. /*******************************************************************************
  545. *
  546. * timexAutoTime - time specified function calls with automatic scaling
  547. *
  548. * This routine performs the specified timing, dynamically increasing
  549. * the number of reps until the desired accuracy is achieved.
  550. *
  551. * RETURNS: N/A.
  552. */
  553. LOCAL void timexAutoTime
  554.     (
  555.     CALL_ARRAY preCalls,        /* list of functions to call before timing */
  556.     FAST CALL_ARRAY timeCalls,  /* list of functions to time */
  557.     CALL_ARRAY postCalls,       /* list of functions to call after timing */
  558.     int *pNreps,        /* ptr where to return number of times called */
  559.     int *pScale,        /* ptr where to return scale:
  560.                          *   0 = secs, 1 = millisecs, 2 = microsecs */
  561.     int *pTime,         /* ptr where to return time per rep in above units */
  562.     int *pError,        /* ptr where to return error margin in above units */
  563.     int *pPercent       /* ptr where to return percent error (0..100) */
  564.     )
  565.     {
  566.     FAST int reps;
  567.     /* start with one rep then increase reps until it takes a long
  568.      * enough interval to provide sufficient resolution */
  569.     reps = 1;
  570.     timexTime (reps, preCalls, timeCalls, postCalls,
  571.             pScale, pTime, pError, pPercent);
  572.     while ((*pPercent > MAX_PERCENT) && ((reps < MAX_REPS) || (*pTime > 0)))
  573. {
  574. reps = reps * (*pPercent) / MAX_PERCENT;
  575. timexTime (reps, preCalls, timeCalls, postCalls,
  576.    pScale, pTime, pError, pPercent);
  577. }
  578.     *pNreps = reps;
  579.     }
  580. /*******************************************************************************
  581. *
  582. * timexCal - calibrate timex by timing null functions
  583. *
  584. * This routine establishes the constant per rep overhead in the timing
  585. * function.
  586. *
  587. * RETURNS: N/A.
  588. */
  589. LOCAL void timexCal (void)
  590.     {
  591.     int scale;
  592.     int time;
  593.     int error;
  594.     int percent;
  595.     int nreps;
  596.     overhead = 0;
  597.     timexAutoTime (timexNullCalls, timexNullCalls, timexNullCalls,
  598.    &nreps, &scale, &time, &error, &percent);
  599.     overhead = time;
  600.     }
  601. /*******************************************************************************
  602. *
  603. * timexClrArrays - clear out function arrays
  604. *
  605. * RETURNS: N/A.
  606. */
  607. LOCAL void timexClrArrays (void)
  608.     {
  609.     bcopy ((char *) timexNullCalls, (char *) timexPreCalls,
  610.    sizeof (timexNullCalls));
  611.     bcopy ((char *) timexNullCalls, (char *) timexTimeCalls,
  612.    sizeof (timexNullCalls));
  613.     bcopy ((char *) timexNullCalls, (char *) timexPostCalls,
  614.    sizeof (timexNullCalls));
  615.     }
  616. /*******************************************************************************
  617. *
  618. * timexMakeCalls - make function calls in specified call array
  619. *
  620. * RETURNS: N/A.
  621. */
  622. LOCAL void timexMakeCalls
  623.     (
  624.     CALL_ARRAY calls    /* list of functions to call */
  625.     )
  626.     {
  627.     FAST int ix;
  628.     FAST CALL *pCall = &calls[0];
  629.     for (ix = 0; ix < MAX_CALLS; ix++, pCall++)
  630. {
  631. (* pCall->func) (pCall->arg[0], pCall->arg[1], pCall->arg[2],
  632.  pCall->arg[3], pCall->arg[4], pCall->arg[5],
  633.  pCall->arg[6], pCall->arg[7]);
  634. }
  635.     }
  636. /*******************************************************************************
  637. *
  638. * timexNull - null routine
  639. *
  640. * This routine is used as a place holder for null routines in the
  641. * timing function arrays.  It is used to guarantee a constant calling
  642. * overhead in each iteration.
  643. *
  644. * RETURNS: N/A.
  645. */
  646. LOCAL void timexNull (void)
  647.     {
  648.     }
  649. /*******************************************************************************
  650. *
  651. * timexScale - scale raw timing data
  652. *
  653. * RETURNS: N/A.
  654. */
  655. LOCAL void timexScale
  656.     (
  657.     int ticks,          /* total ticks required for all reps */
  658.     int reps,           /* number of reps performed */
  659.     FAST int *pScale,   /* ptr where to return scale:
  660.                          *   0 = secs, 1 = millisecs, 2 = microsecs */
  661.     FAST int *pTime,    /* ptr where to return time per rep in above units */
  662.     int *pError,        /* ptr where to return error margin in above units */
  663.     int *pPercent       /* ptr where to return percent error (0..100) */
  664.     )
  665.     {
  666.     FAST int scalePerSec;
  667.     /* calculate time per rep in best scale */
  668.     *pScale = 0; /* start with "seconds" scale */
  669.     scalePerSec = 1;
  670.     *pTime = ticks * scalePerSec / sysClkRateGet () / reps;
  671.     while ((*pScale < 2) && (*pTime < 100))
  672. {
  673. (*pScale)++;
  674. scalePerSec = scalePerSec * 1000;
  675. *pTime = ticks * scalePerSec / sysClkRateGet () / reps;
  676. }
  677.     /* adjust for overhead if in microseconds scale */
  678.     if (*pScale == 2)
  679. {
  680. *pTime -= overhead;
  681. if (*pTime < 0)
  682.     *pTime = 0;
  683. }
  684.     /* calculate error */
  685.     *pError = scalePerSec / sysClkRateGet () / reps;
  686.     if (*pTime == 0)
  687. *pPercent = 100;
  688.     else
  689. *pPercent = 100 * *pError / *pTime;
  690.     }
  691. /*******************************************************************************
  692. *
  693. * timexShowCalls - print specified call array
  694. *
  695. * RETURNS: N/A.
  696. */
  697. LOCAL void timexShowCalls
  698.     (
  699.     CALL_ARRAY calls            /* list of functions to be displayed */
  700.     )
  701.     {
  702.     char      *name;            /* pointer to sym table's copy of name string */
  703.     char      demangled [TIMEX_DEMANGLE_PRINT_LEN + 1];
  704.     char      *nameToPrint;
  705.     void      *value;
  706.     SYMBOL_ID symId;            /* symbol identifier */
  707.     int       offset;
  708.     int       i;
  709.     int       j;
  710.     int       arg;
  711.     int       ncalls = 0;
  712.     for (i = 0; i < MAX_CALLS; i++)
  713. {
  714. if (calls[i].func != timexNull)
  715.     {
  716.     ncalls++;
  717.     if ((symFindSymbol (sysSymTbl, NULL, (void *)calls[i].func, 
  718. SYM_MASK_NONE, SYM_MASK_NONE, 
  719. &symId) != OK) ||
  720. (symNameGet (symId, &name) != OK) ||
  721. (symValueGet (symId, &value) != OK))
  722. printf ("        %d: 0x%x (", i, (int)calls[i].func);
  723.     else
  724. {
  725.         offset = (int) calls[i].func - (int) value;
  726.         nameToPrint = cplusDemangle (name, demangled, 
  727.      sizeof (demangled));
  728.         if (offset == 0)
  729.     printf ("        %d: %s (", i, nameToPrint);
  730.         else
  731.     printf ("        %d: %s+%x (", i, nameToPrint, offset);
  732. }
  733.     for (j = 0; j < MAX_ARGS; j++)
  734. {
  735. if (j != 0)
  736.     printf (", ");
  737. arg = calls[i].arg[j];
  738. if ((-9 <= arg) && (arg <= 9))
  739.     printf ("%d", arg);
  740. else
  741.     printf ("0x%x", arg);
  742. }
  743.     printf (")n");
  744.     }
  745. }
  746.     if (ncalls == 0)
  747. printf ("        (none)n");
  748.     }
  749. /*******************************************************************************
  750. *
  751. * timexTime - time a specified number of reps
  752. *
  753. * RETURNS: N/A.
  754. */
  755. LOCAL void timexTime
  756.     (
  757.     FAST int reps,              /* number of reps to perform */
  758.     CALL_ARRAY preCalls,        /* list of functions to call before timing */
  759.     FAST CALL_ARRAY timeCalls,  /* list of functions to be timed */
  760.     CALL_ARRAY postCalls,       /* list of functions to call after timing */
  761.     int *pScale,        /* ptr where to return scale:
  762.                          *   0 = secs, 1 = millisecs, 2 = microsecs */
  763.     int *pTime,         /* ptr where to return time per rep in above units */
  764.     int *pError,        /* ptr where to return error margin in above units */
  765.     int *pPercent       /* ptr where to return percent error (0..100) */
  766.     )
  767.     {
  768.     int start;
  769.     int end;
  770.     FAST int i;
  771.     timexMakeCalls (preCalls);
  772.     start = (int) tickGet ();
  773.     for (i = 0; i < reps; i++)
  774. timexMakeCalls (timeCalls);
  775.     end = (int) tickGet ();
  776.     timexMakeCalls (postCalls);
  777.     timexScale (end - start, reps, pScale, pTime, pError, pPercent);
  778.     }