home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / utilslib / Profile / C / ProfileT < prev   
Encoding:
Text File  |  1991-06-02  |  5.7 KB  |  288 lines

  1. /* C.ProfileT: Execution profiler (by time)
  2.  *
  3.  * Version 1.00, 04-06-1990
  4.  *
  5.  * Copyright (C) Ferdinand Oeinck 1990
  6.  *
  7.  * Modified, Paul Moore 02/06/91.
  8.  *   To conform to the conventions of my "Utils" library.
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include "swis.h"
  15. #include "kernel.h"
  16.  
  17. #include "ProfileAsm.h"
  18. #include "Profile.h"
  19.  
  20. static int *funcadr_ptr;
  21. static int *count_ptr;
  22. static int funccount;
  23.  
  24. static char *_profile_filename;
  25. static void _profile_exithandler(void);
  26.  
  27. void profile_init_time (const char *filename)
  28. {
  29.     unsigned int *codestart;
  30.     unsigned int *codeend;
  31.     unsigned int *i;
  32.     int fpestart, fpeend;
  33.     int len;
  34.     int instr;
  35.     int count = 0;
  36.     char *modulename;
  37.     _kernel_swi_regs regs;
  38.  
  39.     if (_kernel_hostos() != _kernel_ARTHUR)
  40.     {
  41.         printf("Error: Not running on ARTHUR host OS\n");
  42.         exit(1);
  43.     }
  44.  
  45.     if (!_kernel_fpavailable())
  46.     {
  47.         printf("Warning: Execution time profiling not possible.\n");
  48.         printf("         No floating point support.\n");
  49.         return;
  50.     }
  51.  
  52.     regs.r[0] = 12;
  53.     regs.r[1] = 0;
  54.     regs.r[2] = 0;
  55.  
  56.     while (_kernel_swi(OS_Module, ®s, ®s) == NULL)
  57.     {
  58.         modulename = (char*)(regs.r[3] + *((int *)(regs.r[3] + 0x10)));
  59.         if (strcmp(modulename,"FPEmulator") == 0)
  60.             break;
  61.     }
  62.  
  63.     fpestart = regs.r[3];
  64.     _kernel_swi(OS_Module, ®s, ®s);
  65.     fpeend = regs.r[3];
  66.  
  67.     if (filename == NULL || *filename == '\0')
  68.         _profile_filename = NULL;
  69.     else
  70.     {
  71.         if ((_profile_filename = malloc(strlen(filename) + 1)) == NULL)
  72.         {
  73.             printf("Warning: Execution time profiling not possible.\n");
  74.             printf("         Malloc failed.\n");
  75.             return;
  76.         }
  77.  
  78.         strcpy(_profile_filename, filename);
  79.     }
  80.  
  81.     codestart = _profile_getstart();
  82.     codeend = _profile_getend();
  83.  
  84.     for (i = codestart; i != codeend; i++)
  85.     {
  86.         instr = *i & 0xffff0000;
  87.         if (instr == (unsigned int) 0xff000000)
  88.         {
  89.             len = *i & 0xffff;
  90.             if (len >= strlen((char *)i - len))
  91.                 count++;
  92.         }
  93.     }
  94.     count += 4;
  95.  
  96.     if ((funcadr_ptr = calloc(count, sizeof(int))) == NULL)
  97.     {
  98.         printf("Warning: Execution time profiling not possible.\n");
  99.         printf("         Malloc failed.\n");
  100.         free(_profile_filename);
  101.         return;
  102.     }
  103.  
  104.     if ((count_ptr = calloc(count, sizeof(int))) == NULL)
  105.     {
  106.         printf("Warning: Execution time profiling not possible.\n");
  107.         printf("         Malloc failed.\n");
  108.         free(funcadr_ptr);
  109.         free(_profile_filename);
  110.         return;
  111.     }
  112.  
  113.     funccount = count;
  114.  
  115.     count = 1;
  116.     for (i = codestart; i != codeend; i++)
  117.     {
  118.         instr = *i & 0xffff0000;
  119.         if (instr == (unsigned int) 0xff000000)
  120.         {
  121.             len = *i & 0xffff;
  122.             if (len >= strlen((char *)i - len))
  123.             {
  124.                 funcadr_ptr[count++] = (int) i - len;
  125.             }
  126.         }
  127.     }
  128.  
  129.     funcadr_ptr[count]     = (int) codeend;
  130.     funcadr_ptr[count + 1] = (int) fpestart;
  131.     funcadr_ptr[count + 2] = (int) fpeend;
  132.  
  133.     if (!_profile_ClaimIntDeviceVector())
  134.     {
  135.         free(count_ptr);
  136.         free(funcadr_ptr);
  137.         free(_profile_filename);
  138.         printf("Warning: Execution time profiling not possible.\n");
  139.         printf("         I think this is not RISC_OS 2.00\n");
  140.         return;
  141.     }
  142.  
  143.     atexit(_profile_exithandler);
  144. }
  145.  
  146. #define HEADER        \
  147. " Num   Address  Function name                         Percentage    Count\n"
  148.  
  149. #define UNDERLINE    \
  150. "=========================================================================\n"
  151.  
  152. #define FORMAT        \
  153. "%4i  %8x  %-40s  %6.2f  %7i\n"
  154.  
  155. #define TOTALS        \
  156. "%57s %6.2f  %7i\n", ""
  157.  
  158. static void _profile_exithandler(void)
  159. {
  160.     int i;
  161.     int sumc = 0;
  162.     float sum = 0;
  163.     float sump = 0;
  164.     FILE *fp;
  165.  
  166.     _profile_ReleaseIntDeviceVector();
  167.  
  168.     for (i = 0; i < funccount; i++)
  169.         sum += count_ptr[i];
  170.  
  171.     /* Subtract double counted fp values */
  172.     sum -= count_ptr[funccount - 2];
  173.  
  174.     if (sum <= 0)
  175.         sum = 1;
  176.  
  177.     if (_profile_filename == NULL)
  178.     {
  179.         fp = stderr;
  180.     }
  181.     else if ((fp = fopen(_profile_filename, "w")) == NULL)
  182.     {
  183.         fprintf(stderr,"Can't write profile data to %s - using stderr\n",_profile_filename);
  184.         fp = stderr;
  185.     }
  186.  
  187.     fprintf(fp, HEADER);
  188.     fprintf(fp, UNDERLINE);
  189.  
  190.     fprintf(fp, FORMAT,
  191.         0,
  192.         funcadr_ptr[1],
  193.         "Before user code (kernel)",
  194.         100.0 * (float) count_ptr[0] / sum,
  195.         count_ptr[0]);
  196.  
  197.     sump += (float) 100.0 * (float) count_ptr[0] / sum;
  198.     sumc += count_ptr[0];
  199.  
  200.     for (i = 1 ; i < funccount - 3; i++)
  201.     {
  202.         fprintf(fp, FORMAT,
  203.             i,
  204.             funcadr_ptr[i],
  205.             (char *) funcadr_ptr[i],
  206.             100.0 * (float) count_ptr[i] / sum,
  207.             count_ptr[i]);
  208.  
  209.         sump += (float) 100.0 * (float) count_ptr[i] / sum;
  210.         sumc += count_ptr[i];
  211.     }
  212.  
  213.     fprintf(fp, FORMAT,
  214.         funccount-3,
  215.         funcadr_ptr[funccount-3],
  216.         "After user code (kernel)",
  217.         100.0 * (float) count_ptr[funccount-3] / sum,
  218.         count_ptr[funccount-3]);
  219.  
  220.     sump += (float) 100.0 * (float) count_ptr[funccount-3] / sum;
  221.     sumc += count_ptr[funccount - 3];
  222.  
  223.     fprintf(fp, UNDERLINE);
  224.     fprintf(fp, TOTALS, sump, sumc);
  225.     fprintf(fp, "\nPercentage of time spent in the FPE\n");
  226.     fprintf(fp, FORMAT,
  227.         funccount-2,
  228.         funcadr_ptr[funccount-2],
  229.         "fpemulator",
  230.         100.0 * (float) count_ptr[funccount-2] / sum,
  231.         count_ptr[funccount-2]);
  232.  
  233.     if (fp != stderr)
  234.         fclose(fp);
  235.  
  236.     free(count_ptr);
  237.     free(funcadr_ptr);
  238.     free(_profile_filename);
  239. }
  240.  
  241. /* Binary search of address table.
  242.  * This function is called every 1/100 second
  243.  */
  244.  
  245. #define Between(x,l,h) ((int)l < (int)x && (int)x <= (int)h)
  246.  
  247. void binsearch (int *adr)
  248. {
  249.     int high = funccount - 1;
  250.     int low = 1;
  251.  
  252.     if ((int) adr < (int) funcadr_ptr[1])
  253.     {
  254.         ++count_ptr[0];
  255.         return;
  256.     }
  257.  
  258.     if (Between(adr,funcadr_ptr[funccount-2],funcadr_ptr[funccount-1]))
  259.     {
  260.         /* We are in the FPE, so use that return address */
  261.             ++count_ptr[funccount-2];
  262.         adr = (int *)_profile_fp_return_address;
  263.     }
  264.  
  265.     if ((int) adr > (int) funcadr_ptr[funccount-3])
  266.     {
  267.         ++count_ptr[funccount-3];
  268.         return;
  269.     }
  270.  
  271.     while ((high - low) > 1)
  272.     {
  273.             int middle = (high + low) / 2;
  274.         if (Between(adr,funcadr_ptr[middle],funcadr_ptr[middle + 1]))
  275.         {
  276.             low = middle;
  277.             break;
  278.         }
  279.  
  280.         if ((int)adr > (int)funcadr_ptr[middle + 1])
  281.             low = middle + 1;
  282.         else
  283.             high = middle;
  284.     }
  285.  
  286.     ++count_ptr[low];
  287. }
  288.