home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / sysutl / sysprof3.arc / ORIGINAL.ARC / PROFCTRL.C next >
Encoding:
C/C++ Source or Header  |  1988-06-16  |  19.5 KB  |  492 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*                                 Listing 2                                 */
  4. /*                                                                           */
  5. /*  NAME : PROFCTRL                                                          */
  6. /*                                                                           */
  7. /*  DATE : March 30, 1988                                                    */
  8. /*                                                                           */
  9. /*  AUTHOR : (C) Copyright 1988 G. Kent Cobb - All Rights Reserved           */
  10. /*                                                                           */
  11. /*  DESCRIPTION :                                                            */
  12. /*      This program provides control functions for the terminate-and-stay-  */
  13. /*      resident system profiler.  The syntax for executing PROFCTRL is:     */
  14. /*                                                                           */
  15. /*                                                                           */
  16. /*                          |   STATUS                     |                 */
  17. /*                          |     ON                       |                 */
  18. /*                 PROFCTRL |     OFF                      |                 */
  19. /*                          |    ZERO                      |                 */
  20. /*                          |   REPORT [output-file-name]  |                 */
  21. /*                                                                           */
  22. /*      The ON and OFF options affect the accumulation of interrupt data;    */
  23. /*      STATUS reports the current state; ZERO erases all data that has      */
  24. /*      been accumulated; and REPORT generates a listing that describes      */
  25. /*      the contents of the tables.                                          */
  26. /*                                                                           */
  27. /*      SYS_PROF and PROFCTRL are most easily used in a batch file, such as: */
  28. /*                                                                           */
  29. /*                                                                           */
  30. /*                            SYS_PROF                                       */
  31. /*                            PROFCTRL zero                                  */
  32. /*                            PROFCTRL on                                    */
  33. /*                            chkdsk c:                                      */
  34. /*                            PROFCTRL off                                   */
  35. /*                            PROFCTRL report temp                           */
  36. /*                            d:list temp                                    */
  37. /*                                                                           */
  38. /*****************************************************************************/
  39. #include "stdio.h"
  40. #include "dos.h"
  41.  
  42. #define NUM_INTS 9
  43. #define END_OF_STRING '\0'
  44.  
  45. #define CONTROL_INTERRUPT   96
  46. #define STATUS          0
  47. #define OFF             1
  48. #define ON              2
  49. #define FIND            3
  50. #define ZERO            4
  51. #define REPORT          5
  52.  
  53. #define DOS             0x21
  54. #define GET_INT_VECTOR  0x35
  55.  
  56. struct tally
  57.     {
  58.     long time;
  59.     long number;
  60.     };
  61.  
  62. long total_ticks;       /*  TOTAL NUMBER OF TIMER TICKS RECORDED.  */
  63.  
  64. char *int_desc[NUM_INTS+1] = {"OTHER",
  65.                               "PRINT SCREEN - INTERRUPT 5H",
  66.                               "VIDEO BIOS - INTERRUPT 10H",
  67.                               "DISK SERVICES - INTERRUPT 13H",
  68.                               "COMM PORT - INTERRUPT 14H",
  69.                               "KEYBOARD BIOS - INTERRUPT 16H",
  70.                               "PRINTER BIOS - INTERRUPT 17H",
  71.                               "DOS FUNCTIONS - INTERRUPT 21H",
  72.                               "DOS ABSOLUTE DISK READ - INTERRUPT 25H",
  73.                               "DOS ABSOLUTE DISK WRITE - INTERRUPT 26H" };
  74.  
  75. int max_services[NUM_INTS+1] = {0,0,20,24,4,3,3,99,0,0};
  76.  
  77. char *other_services[] = {""};
  78. char *print_screen_services[] = {""};
  79. char *video_services[] = {"00 - Set Mode",
  80.                           "01 - Set Cursor Size",
  81.                           "02 - Set Cursor Position",
  82.                           "03 - Get Cursor Position",
  83.                           "04 - Get Light Pen Position",
  84.                           "05 - Set Active Page",
  85.                           "06 - Scroll Up",
  86.                           "07 - Scroll Down",
  87.                           "08 - Read Character and Attribute",
  88.                           "09 - Write Character and Attribute",
  89.                           "0A - Write Character",
  90.                           "0B - Set Palette",
  91.                           "0C - Write Dot",
  92.                           "0D - Read Dot",
  93.                           "0E - Write TTY",
  94.                           "0F - Get Mode",
  95.                           "10 - Service 16",
  96.                           "11 - Service 17",
  97.                           "12 - Service 18",
  98.                           "13 - Write String",
  99.                           "Undefined services"};
  100. char *disk_services[] = {"00 - Reset Diskette System",
  101.                          "01 - Get Diskette Status",
  102.                          "02 - Read Sectors",
  103.                          "03 - Write Sectors",
  104.                          "04 - Verify Sectors",
  105.                          "05 - Format Track",
  106.                          "06 - Service 6",
  107.                          "07 - Service 7",
  108.                          "08 - Get Drive Parameters",
  109.                          "09 - Initialize Parameter Tables",
  110.                          "0A - Read Long",
  111.                          "0B - Write Long",
  112.                          "0C - Seek to Cylinder",
  113.                          "0D - Alternate Disk Reset",
  114.                          "0E - Service 14",
  115.                          "0F - Service 15",
  116.                          "10 - Test Ready",
  117.                          "11 - Recalibrate Drive",
  118.                          "12 - Service 18",
  119.                          "13 - Service 19",
  120.                          "14 - Controller Diagnostics",
  121.                          "15 - Get Disk Type",
  122.                          "16 - Change Disk Status",
  123.                          "17 - Set Disk Type",
  124.                          "Undefined services"};
  125. char *comm_services[] = {"00 - Initialize Serial Port",
  126.                        "01 - Send Character",
  127.                        "02 - Receive Character",
  128.                        "03 - Get Status",
  129.                        "Undefined services"};
  130. char *keyboard_services[] = {"00 - Read Character",
  131.                              "01 - Character Waiting?",
  132.                              "02 - Get Shift Status",
  133.                              "Undefined services"};
  134. char *printer_services[] = {"00 - Send Byte",
  135.                             "01 - Initialize Printer",
  136.                             "02 - Get Printer Status",
  137.                             "Undefined services"};
  138. char *dos_services[] = {"00 - Terminate",
  139.                         "01 - Keyboard Input With Echo",
  140.                         "02 - Display Output",
  141.                         "03 - Serial Input",
  142.                         "04 - Serial Output",
  143.                         "05 - Printer Output",
  144.                         "06 - Keyboard/Display I/O",
  145.                         "07 - Keyboard Input No Echo",
  146.                         "08 - Keyboard Input No Echo",
  147.                         "09 - Display String",
  148.                         "0A - Buffered Keyboard Input",
  149.                         "0B - Keyboard Status",
  150.                         "0C - Clear Keyboard",
  151.                         "0D - Reset Disk",
  152.                         "0E - Set Default Drive",
  153.                         "0F - Open File FCB Mode",
  154.                         "10 - Close File FCB Mode",
  155.                         "11 - Find First File FCB Mode",
  156.                         "12 - Find Next File FCB Mode",
  157.                         "13 - Delete File FCB Mode",
  158.                         "14 - Read Sequential",
  159.                         "15 - Write Sequential",
  160.                         "16 - Create File FCB Mode",
  161.                         "17 - Rename File FCB Mode",
  162.                         "18 - Service 24",
  163.                         "19 - Get Default Drive",
  164.                         "1A - Set Disk Transfer Area",
  165.                         "1B - Get FAT Info, Default Drive",
  166.                         "1C - Get FAT Info, Any Drive",
  167.                         "1D - Service 29",
  168.                         "1E - Service 30",
  169.                         "1F - Service 31",
  170.                         "20 - Service 32",
  171.                         "21 - Read Random",
  172.                         "22 - Write Random",
  173.                         "23 - Get File Size",
  174.                         "24 - Set Random Record Field",
  175.                         "25 - Set Interrupt Vector",
  176.                         "26 - Create Program Segment",
  177.                         "27 - Read Random, Multiple Records",
  178.                         "28 - Write Random, Multiple Records",
  179.                         "29 - Parse Filename",
  180.                         "2A - Get Date",
  181.                         "2B - Set Date",
  182.                         "2C - Get Time",
  183.                         "2D - Set Time",
  184.                         "2E - Set Disk Write Verification",
  185.                         "2F - Get DTA Address",
  186.                         "30 - Get DOS Version Number",
  187.                         "31 - Terminate and Stay Resident",
  188.                         "32 - Service 50",
  189.                         "33 - Get/Set Ctrl Break",
  190.                         "34 - Service 52",
  191.                         "35 - Get Interrupt Vector",
  192.                         "36 - Get Disk Free Space",
  193.                         "37 - Service 55",
  194.                         "38 - Get Country-Dependent Info",
  195.                         "39 - Make Directory",
  196.                         "3A - Remove Directory",
  197.                         "3B - Change Default Directory",
  198.                         "3C - Create File, Handle Mode",
  199.                         "3D - Open File, Handle Mode",
  200.                         "3E - Close File, Handle Mode",
  201.                         "3F - Read from File or Device",
  202.                         "40 - Write to File or Device",
  203.                         "41 - Delete File, Handle Mode",
  204.                         "42 - Move File Pointer",
  205.                         "43 - Get/Set File Attributes",
  206.                         "44 - I/O Control for Devices",
  207.                         "45 - Duplicate File Handle",
  208.                         "46 - Force File Handle Duplication",
  209.                         "47 - Get Default Directory",
  210.                         "48 - Allocate Memory",
  211.                         "49 - Free Memory",
  212.                         "4A - Modify Allocated Memory",
  213.                         "4B - EXEC",
  214.                         "4C - Terminate Process",
  215.                         "4D - Get Return Code",
  216.                         "4E - Find First File, Handle Mode",
  217.                         "4F - Find Next File, Handle Mode",
  218.                         "50 - Service 80",
  219.                         "51 - Service 81",
  220.                         "52 - Service 82",
  221.                         "53 - Service 83",
  222.                         "54 - Get Verify State",
  223.                         "55 - Service 85",
  224.                         "56 - Rename File, Handle Mode",
  225.                         "57 - Get/Set File Date and Time",
  226.                         "58 - Service 88",
  227.                         "59 - Service 89",
  228.                         "5A - Create Temporary File",
  229.                         "5B - Create New File",
  230.                         "5C - Lock/Unlock File Access",
  231.                         "5D - Service 93",
  232.                         "5E - Service 94",
  233.                         "5F - Service 95",
  234.                         "60 - Service 96",
  235.                         "61 - Service 97",
  236.                         "62 - Get PSP Address",
  237.                         "Undefined services"};
  238. char *disk_read_services[] = {""};
  239. char *disk_write_services[] = {""};
  240.  
  241. char **service_descriptions[NUM_INTS+1] = {other_services,
  242.                                            print_screen_services,
  243.                                            video_services,
  244.                                            disk_services,
  245.                                            comm_services,
  246.                                            keyboard_services,
  247.                                            printer_services,
  248.                                            dos_services,
  249.                                            disk_read_services,
  250.                                            disk_write_services };
  251.  
  252. FILE *output_file;
  253.  
  254. main ( argc , argv )
  255. int argc;
  256. char *argv[];
  257. {
  258. union REGS registers;
  259. struct SREGS segregs;
  260. int function;
  261. int save_status;
  262. FILE *fopen();
  263. int int_number;
  264.  
  265. printf("\n\n(C) Copyright 1988 G. Kent Cobb - All Rights Reserved\n");
  266. if (argc < 2)
  267.     error_exit();
  268.  
  269. if (stricmp(argv[1],"STATUS") == 0)
  270.     function = 0;
  271. else if (stricmp(argv[1],"OFF") == 0)
  272.     function = 1;
  273. else if (stricmp(argv[1],"ON") == 0)
  274.     function = 2;
  275. else if (stricmp(argv[1],"ZERO") == 0)
  276.     function = 4;
  277. else if (stricmp(argv[1],"REPORT") == 0)
  278.     function = 5;
  279. else
  280.     error_exit();
  281.  
  282.           /*  CHECK TO MAKE SURE THAT sys_prof HAS BEEN INSTALLED.  */
  283.  
  284. registers.h.ah = GET_INT_VECTOR;
  285. registers.h.al = CONTROL_INTERRUPT;
  286. int86x(DOS,®isters,®isters,&segregs);
  287. if ((registers.x.bx == 0) && (segregs.es == 0))
  288.     {
  289.     printf("\n\nSYS_PROF has not been installed.");
  290.     exit(2);
  291.     }
  292.  
  293. switch (function)
  294.     {
  295.  
  296. /*  IF TURNING PROFILER OFF OR ON, DROP THROUGH TO REPORT THE STATUS ALSO.  */
  297.  
  298.     case OFF:
  299.     case ON:
  300.         registers.h.ah = function;
  301.         int86(CONTROL_INTERRUPT,®isters,®isters);
  302.     case STATUS:
  303.         registers.h.ah = STATUS;
  304.         int86(CONTROL_INTERRUPT,®isters,®isters);
  305.         printf("\n\nProfiler is %s",(registers.x.ax == 0) ? "OFF" : "ON" );
  306.         break;
  307.     case ZERO:
  308.         registers.h.ah = function;
  309.         int86(CONTROL_INTERRUPT,®isters,®isters);
  310.         printf("\n\nProfiler tables re-initialized.");
  311.         break;
  312.     case REPORT:
  313.  
  314.                     /*  GET THE CURRENT PROFILER STATUS.  */
  315.  
  316.         registers.h.ah = STATUS;
  317.         int86(CONTROL_INTERRUPT,®isters,®isters);
  318.         save_status = registers.x.ax;
  319.  
  320.                      /*  TURN ACCUMULATION OFF FOR NOW.  */
  321.  
  322.         registers.h.ah = OFF;
  323.         int86(CONTROL_INTERRUPT,®isters,®isters);
  324.  
  325.                /*  GET THE ADDRESS OF THE ACCUMULATION TABLE.  */
  326.  
  327.         registers.h.ah = FIND;
  328.         int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
  329.  
  330.               /*  OPEN THE FILE WHICH WILL CONTAIN THE OUTPUT.  */
  331.  
  332.         if (argc > 2)
  333.             {
  334.             if ((output_file = fopen(argv[2],"w")) == NULL)
  335.                 {
  336.                 printf("\n\nCannot open output file.");
  337.                 exit(2);
  338.                 }
  339.             }
  340.         else
  341.             output_file = stdprn;
  342.  
  343.                /*  CALCULATE THE TOTAL NUMBER OF TIMER TICKS.  */
  344.  
  345.         tally_total_ticks();
  346.  
  347.                          /*  PRINT OUT THE HEADERS.  */
  348.  
  349.         fprintf(output_file,
  350.         "                                         Number of      Number of    Percent of\n");
  351.         fprintf(output_file,
  352.         "             Service                    Occurrences    Timer ticks   Total Time\n");
  353.  
  354.                 /*  PRINT OUT A SUMMARY FOR EACH INTERRUPT.  */
  355.  
  356.         for (int_number = 1; int_number <= NUM_INTS; int_number++)
  357.             print_interrupt_summary(int_number,service_descriptions[int_number]);
  358.         print_interrupt_summary(0,service_descriptions[0]);
  359.  
  360.         fprintf(output_file,"\n\n");
  361.         fprintf(output_file,
  362.         "\n                          Total time: %ld timer ticks",total_ticks);
  363.         fprintf(output_file,
  364.                      "\n                                       %ld seconds\n",
  365.                                                      (long)(total_ticks/18.2));
  366.  
  367.         /*  IF ACCUMULATION WAS ON WHEN WE STARTED, TURN IT BACK ON.  */
  368.  
  369.         if (save_status != 0)
  370.             {
  371.             registers.h.ah = ON;
  372.             int86(CONTROL_INTERRUPT,®isters,®isters);
  373.             }
  374.  
  375.     default:
  376.  
  377.         break;
  378.     }  /*  END OF SWITCH (FUNCTION)  */
  379.  
  380. exit(0);
  381. }  /*  END OF MAIN  */
  382.  
  383. print_interrupt_summary ( int_number , descriptions )
  384.  
  385. int int_number;
  386.  
  387. char *descriptions[];
  388. {
  389. struct tally far *beginning_address , far *address;
  390. int non_zero , service;
  391. long total_time , total_number;
  392. int idx;
  393. union REGS registers;
  394. struct SREGS segregs;
  395.  
  396.   /*  GET THE ADDRESS OF THE TABULATED DATA FOR THIS PARTICULAR INTERRUPT.  */
  397.  
  398. registers.h.ah = FIND;
  399. int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
  400. FP_SEG(beginning_address) = segregs.es;
  401. FP_OFF(beginning_address) = registers.x.bx;
  402. for (idx = 0; idx < int_number; idx++)
  403.     beginning_address += (1+max_services[idx]);
  404.  
  405.    /*  CALCULATE THE TOTAL NUMBER OF TIMER TICKS SPENT IN THIS INTERRUPT.  */
  406.  
  407. for (service = 0 , total_number = 0L , address = beginning_address;
  408.                    service <= max_services[int_number]; address++ , service++)
  409.     total_number += address->number;
  410.  
  411.           /*  DON'T PRINT ANYTHING IF THIS INTERRUPT WAS NOT USED.  */
  412.  
  413. if (total_number == 0)
  414.     return;
  415.  
  416.              /*  PRINT OUT THE HEADER DESCRIBING THE INTERRUPT.  */
  417.  
  418. fprintf(output_file,"\n\n%s\n",int_desc[int_number]);
  419.  
  420.             /*  NOW PRINT OUT THE INFORMATION FOR EACH SERVICE.  */
  421.  
  422. for (service = 0 , total_time = 0L , address = beginning_address , non_zero = 0;
  423.                      service <= max_services[int_number]; address++ , service++)
  424.     {
  425.     if (address->number != 0)
  426.         {
  427.         print_line(descriptions[service],address->number,address->time);
  428.         non_zero++;
  429.         }
  430.     total_time += address->time;
  431.     }
  432.  
  433.  /*  AFTER DETAILING EACH SERVICE, PRINT OUT THE SUMMARY FOR ALL SERVICES.  */
  434.  
  435. if (non_zero > 1)
  436.     print_line("TOTAL",total_number,total_time);
  437.  
  438. return;
  439. }  /*  END OF PRINT_INTERRUPT_SUMMARY  */
  440.  
  441. print_line ( title , number , duration )
  442. char *title;
  443. long number;
  444. long duration;
  445. {
  446. char string[120];
  447. static char blanks[40] = "                                       ";
  448.  
  449. sprintf(string,"\n     %s",title);
  450. strcat(string,blanks);
  451. string[40] = END_OF_STRING;
  452. sprintf(&string[40],"%8ld        %8ld        %5.2f",number,duration,
  453.                                              (float)(100*duration)/total_ticks);
  454. fputs(string,output_file);
  455. return;
  456. }  /*  END OF PRINT_LINE  */
  457.  
  458. tally_total_ticks()
  459. {
  460. struct tally far *ptr;
  461. union REGS registers;
  462. struct SREGS segregs;
  463. int idx , total_services;
  464.  
  465.                   /*  CALCULATE THE TOTAL NUMBER OF BINS.  */
  466.  
  467. for (idx = 0 , total_services = 0; idx <= NUM_INTS; idx++)
  468.     total_services += (1+max_services[idx]);
  469.  
  470.                      /*  GET THE ADDRESS OF THE TABLE.  */
  471.  
  472. registers.h.ah = FIND;
  473. int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
  474. FP_SEG(ptr) = segregs.es;
  475. FP_OFF(ptr) = registers.x.bx;
  476.  
  477. for (idx = 0 , total_ticks = 0; idx < total_services; idx++ , ptr++)
  478.     total_ticks += ptr->time;
  479.  
  480. return;
  481. }  /*  END OF TALLY_TOTAL_TICKS  */
  482.  
  483. error_exit()
  484.  
  485. {
  486. printf("\n\nProper syntax is:\n\n               ");
  487. printf("PROFCTRL STATUS | OFF | ON | ZERO | REPORT");
  488. exit(1);
  489. }  /*  END OF ERROR_EXIT  */
  490.  
  491.  
  492.