home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************/
- /* */
- /* Listing 2 */
- /* */
- /* NAME : PROFCTRL */
- /* */
- /* DATE : March 30, 1988 */
- /* */
- /* AUTHOR : (C) Copyright 1988 G. Kent Cobb - All Rights Reserved */
- /* */
- /* DESCRIPTION : */
- /* This program provides control functions for the terminate-and-stay- */
- /* resident system profiler. The syntax for executing PROFCTRL is: */
- /* */
- /* */
- /* | STATUS | */
- /* | ON | */
- /* PROFCTRL | OFF | */
- /* | ZERO | */
- /* | REPORT [output-file-name] | */
- /* */
- /* The ON and OFF options affect the accumulation of interrupt data; */
- /* STATUS reports the current state; ZERO erases all data that has */
- /* been accumulated; and REPORT generates a listing that describes */
- /* the contents of the tables. */
- /* */
- /* SYS_PROF and PROFCTRL are most easily used in a batch file, such as: */
- /* */
- /* */
- /* SYS_PROF */
- /* PROFCTRL zero */
- /* PROFCTRL on */
- /* chkdsk c: */
- /* PROFCTRL off */
- /* PROFCTRL report temp */
- /* d:list temp */
- /* */
- /*****************************************************************************/
- #include "stdio.h"
- #include "dos.h"
-
- #define NUM_INTS 9
- #define END_OF_STRING '\0'
-
- #define CONTROL_INTERRUPT 96
- #define STATUS 0
- #define OFF 1
- #define ON 2
- #define FIND 3
- #define ZERO 4
- #define REPORT 5
-
- #define DOS 0x21
- #define GET_INT_VECTOR 0x35
-
- struct tally
- {
- long time;
- long number;
- };
-
- long total_ticks; /* TOTAL NUMBER OF TIMER TICKS RECORDED. */
-
- char *int_desc[NUM_INTS+1] = {"OTHER",
- "PRINT SCREEN - INTERRUPT 5H",
- "VIDEO BIOS - INTERRUPT 10H",
- "DISK SERVICES - INTERRUPT 13H",
- "COMM PORT - INTERRUPT 14H",
- "KEYBOARD BIOS - INTERRUPT 16H",
- "PRINTER BIOS - INTERRUPT 17H",
- "DOS FUNCTIONS - INTERRUPT 21H",
- "DOS ABSOLUTE DISK READ - INTERRUPT 25H",
- "DOS ABSOLUTE DISK WRITE - INTERRUPT 26H" };
-
- int max_services[NUM_INTS+1] = {0,0,20,24,4,3,3,99,0,0};
-
- char *other_services[] = {""};
- char *print_screen_services[] = {""};
- char *video_services[] = {"00 - Set Mode",
- "01 - Set Cursor Size",
- "02 - Set Cursor Position",
- "03 - Get Cursor Position",
- "04 - Get Light Pen Position",
- "05 - Set Active Page",
- "06 - Scroll Up",
- "07 - Scroll Down",
- "08 - Read Character and Attribute",
- "09 - Write Character and Attribute",
- "0A - Write Character",
- "0B - Set Palette",
- "0C - Write Dot",
- "0D - Read Dot",
- "0E - Write TTY",
- "0F - Get Mode",
- "10 - Service 16",
- "11 - Service 17",
- "12 - Service 18",
- "13 - Write String",
- "Undefined services"};
- char *disk_services[] = {"00 - Reset Diskette System",
- "01 - Get Diskette Status",
- "02 - Read Sectors",
- "03 - Write Sectors",
- "04 - Verify Sectors",
- "05 - Format Track",
- "06 - Service 6",
- "07 - Service 7",
- "08 - Get Drive Parameters",
- "09 - Initialize Parameter Tables",
- "0A - Read Long",
- "0B - Write Long",
- "0C - Seek to Cylinder",
- "0D - Alternate Disk Reset",
- "0E - Service 14",
- "0F - Service 15",
- "10 - Test Ready",
- "11 - Recalibrate Drive",
- "12 - Service 18",
- "13 - Service 19",
- "14 - Controller Diagnostics",
- "15 - Get Disk Type",
- "16 - Change Disk Status",
- "17 - Set Disk Type",
- "Undefined services"};
- char *comm_services[] = {"00 - Initialize Serial Port",
- "01 - Send Character",
- "02 - Receive Character",
- "03 - Get Status",
- "Undefined services"};
- char *keyboard_services[] = {"00 - Read Character",
- "01 - Character Waiting?",
- "02 - Get Shift Status",
- "Undefined services"};
- char *printer_services[] = {"00 - Send Byte",
- "01 - Initialize Printer",
- "02 - Get Printer Status",
- "Undefined services"};
- char *dos_services[] = {"00 - Terminate",
- "01 - Keyboard Input With Echo",
- "02 - Display Output",
- "03 - Serial Input",
- "04 - Serial Output",
- "05 - Printer Output",
- "06 - Keyboard/Display I/O",
- "07 - Keyboard Input No Echo",
- "08 - Keyboard Input No Echo",
- "09 - Display String",
- "0A - Buffered Keyboard Input",
- "0B - Keyboard Status",
- "0C - Clear Keyboard",
- "0D - Reset Disk",
- "0E - Set Default Drive",
- "0F - Open File FCB Mode",
- "10 - Close File FCB Mode",
- "11 - Find First File FCB Mode",
- "12 - Find Next File FCB Mode",
- "13 - Delete File FCB Mode",
- "14 - Read Sequential",
- "15 - Write Sequential",
- "16 - Create File FCB Mode",
- "17 - Rename File FCB Mode",
- "18 - Service 24",
- "19 - Get Default Drive",
- "1A - Set Disk Transfer Area",
- "1B - Get FAT Info, Default Drive",
- "1C - Get FAT Info, Any Drive",
- "1D - Service 29",
- "1E - Service 30",
- "1F - Service 31",
- "20 - Service 32",
- "21 - Read Random",
- "22 - Write Random",
- "23 - Get File Size",
- "24 - Set Random Record Field",
- "25 - Set Interrupt Vector",
- "26 - Create Program Segment",
- "27 - Read Random, Multiple Records",
- "28 - Write Random, Multiple Records",
- "29 - Parse Filename",
- "2A - Get Date",
- "2B - Set Date",
- "2C - Get Time",
- "2D - Set Time",
- "2E - Set Disk Write Verification",
- "2F - Get DTA Address",
- "30 - Get DOS Version Number",
- "31 - Terminate and Stay Resident",
- "32 - Service 50",
- "33 - Get/Set Ctrl Break",
- "34 - Service 52",
- "35 - Get Interrupt Vector",
- "36 - Get Disk Free Space",
- "37 - Service 55",
- "38 - Get Country-Dependent Info",
- "39 - Make Directory",
- "3A - Remove Directory",
- "3B - Change Default Directory",
- "3C - Create File, Handle Mode",
- "3D - Open File, Handle Mode",
- "3E - Close File, Handle Mode",
- "3F - Read from File or Device",
- "40 - Write to File or Device",
- "41 - Delete File, Handle Mode",
- "42 - Move File Pointer",
- "43 - Get/Set File Attributes",
- "44 - I/O Control for Devices",
- "45 - Duplicate File Handle",
- "46 - Force File Handle Duplication",
- "47 - Get Default Directory",
- "48 - Allocate Memory",
- "49 - Free Memory",
- "4A - Modify Allocated Memory",
- "4B - EXEC",
- "4C - Terminate Process",
- "4D - Get Return Code",
- "4E - Find First File, Handle Mode",
- "4F - Find Next File, Handle Mode",
- "50 - Service 80",
- "51 - Service 81",
- "52 - Service 82",
- "53 - Service 83",
- "54 - Get Verify State",
- "55 - Service 85",
- "56 - Rename File, Handle Mode",
- "57 - Get/Set File Date and Time",
- "58 - Service 88",
- "59 - Service 89",
- "5A - Create Temporary File",
- "5B - Create New File",
- "5C - Lock/Unlock File Access",
- "5D - Service 93",
- "5E - Service 94",
- "5F - Service 95",
- "60 - Service 96",
- "61 - Service 97",
- "62 - Get PSP Address",
- "Undefined services"};
- char *disk_read_services[] = {""};
- char *disk_write_services[] = {""};
-
- char **service_descriptions[NUM_INTS+1] = {other_services,
- print_screen_services,
- video_services,
- disk_services,
- comm_services,
- keyboard_services,
- printer_services,
- dos_services,
- disk_read_services,
- disk_write_services };
-
- FILE *output_file;
-
- main ( argc , argv )
- int argc;
- char *argv[];
- {
- union REGS registers;
- struct SREGS segregs;
- int function;
- int save_status;
- FILE *fopen();
- int int_number;
-
- printf("\n\n(C) Copyright 1988 G. Kent Cobb - All Rights Reserved\n");
- if (argc < 2)
- error_exit();
-
- if (stricmp(argv[1],"STATUS") == 0)
- function = 0;
- else if (stricmp(argv[1],"OFF") == 0)
- function = 1;
- else if (stricmp(argv[1],"ON") == 0)
- function = 2;
- else if (stricmp(argv[1],"ZERO") == 0)
- function = 4;
- else if (stricmp(argv[1],"REPORT") == 0)
- function = 5;
- else
- error_exit();
-
- /* CHECK TO MAKE SURE THAT sys_prof HAS BEEN INSTALLED. */
-
- registers.h.ah = GET_INT_VECTOR;
- registers.h.al = CONTROL_INTERRUPT;
- int86x(DOS,®isters,®isters,&segregs);
- if ((registers.x.bx == 0) && (segregs.es == 0))
- {
- printf("\n\nSYS_PROF has not been installed.");
- exit(2);
- }
-
- switch (function)
- {
-
- /* IF TURNING PROFILER OFF OR ON, DROP THROUGH TO REPORT THE STATUS ALSO. */
-
- case OFF:
- case ON:
- registers.h.ah = function;
- int86(CONTROL_INTERRUPT,®isters,®isters);
- case STATUS:
- registers.h.ah = STATUS;
- int86(CONTROL_INTERRUPT,®isters,®isters);
- printf("\n\nProfiler is %s",(registers.x.ax == 0) ? "OFF" : "ON" );
- break;
- case ZERO:
- registers.h.ah = function;
- int86(CONTROL_INTERRUPT,®isters,®isters);
- printf("\n\nProfiler tables re-initialized.");
- break;
- case REPORT:
-
- /* GET THE CURRENT PROFILER STATUS. */
-
- registers.h.ah = STATUS;
- int86(CONTROL_INTERRUPT,®isters,®isters);
- save_status = registers.x.ax;
-
- /* TURN ACCUMULATION OFF FOR NOW. */
-
- registers.h.ah = OFF;
- int86(CONTROL_INTERRUPT,®isters,®isters);
-
- /* GET THE ADDRESS OF THE ACCUMULATION TABLE. */
-
- registers.h.ah = FIND;
- int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
-
- /* OPEN THE FILE WHICH WILL CONTAIN THE OUTPUT. */
-
- if (argc > 2)
- {
- if ((output_file = fopen(argv[2],"w")) == NULL)
- {
- printf("\n\nCannot open output file.");
- exit(2);
- }
- }
- else
- output_file = stdprn;
-
- /* CALCULATE THE TOTAL NUMBER OF TIMER TICKS. */
-
- tally_total_ticks();
-
- /* PRINT OUT THE HEADERS. */
-
- fprintf(output_file,
- " Number of Number of Percent of\n");
- fprintf(output_file,
- " Service Occurrences Timer ticks Total Time\n");
-
- /* PRINT OUT A SUMMARY FOR EACH INTERRUPT. */
-
- for (int_number = 1; int_number <= NUM_INTS; int_number++)
- print_interrupt_summary(int_number,service_descriptions[int_number]);
- print_interrupt_summary(0,service_descriptions[0]);
-
- fprintf(output_file,"\n\n");
- fprintf(output_file,
- "\n Total time: %ld timer ticks",total_ticks);
- fprintf(output_file,
- "\n %ld seconds\n",
- (long)(total_ticks/18.2));
-
- /* IF ACCUMULATION WAS ON WHEN WE STARTED, TURN IT BACK ON. */
-
- if (save_status != 0)
- {
- registers.h.ah = ON;
- int86(CONTROL_INTERRUPT,®isters,®isters);
- }
-
- default:
-
- break;
- } /* END OF SWITCH (FUNCTION) */
-
- exit(0);
- } /* END OF MAIN */
-
- print_interrupt_summary ( int_number , descriptions )
-
- int int_number;
-
- char *descriptions[];
- {
- struct tally far *beginning_address , far *address;
- int non_zero , service;
- long total_time , total_number;
- int idx;
- union REGS registers;
- struct SREGS segregs;
-
- /* GET THE ADDRESS OF THE TABULATED DATA FOR THIS PARTICULAR INTERRUPT. */
-
- registers.h.ah = FIND;
- int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
- FP_SEG(beginning_address) = segregs.es;
- FP_OFF(beginning_address) = registers.x.bx;
- for (idx = 0; idx < int_number; idx++)
- beginning_address += (1+max_services[idx]);
-
- /* CALCULATE THE TOTAL NUMBER OF TIMER TICKS SPENT IN THIS INTERRUPT. */
-
- for (service = 0 , total_number = 0L , address = beginning_address;
- service <= max_services[int_number]; address++ , service++)
- total_number += address->number;
-
- /* DON'T PRINT ANYTHING IF THIS INTERRUPT WAS NOT USED. */
-
- if (total_number == 0)
- return;
-
- /* PRINT OUT THE HEADER DESCRIBING THE INTERRUPT. */
-
- fprintf(output_file,"\n\n%s\n",int_desc[int_number]);
-
- /* NOW PRINT OUT THE INFORMATION FOR EACH SERVICE. */
-
- for (service = 0 , total_time = 0L , address = beginning_address , non_zero = 0;
- service <= max_services[int_number]; address++ , service++)
- {
- if (address->number != 0)
- {
- print_line(descriptions[service],address->number,address->time);
- non_zero++;
- }
- total_time += address->time;
- }
-
- /* AFTER DETAILING EACH SERVICE, PRINT OUT THE SUMMARY FOR ALL SERVICES. */
-
- if (non_zero > 1)
- print_line("TOTAL",total_number,total_time);
-
- return;
- } /* END OF PRINT_INTERRUPT_SUMMARY */
-
- print_line ( title , number , duration )
- char *title;
- long number;
- long duration;
- {
- char string[120];
- static char blanks[40] = " ";
-
- sprintf(string,"\n %s",title);
- strcat(string,blanks);
- string[40] = END_OF_STRING;
- sprintf(&string[40],"%8ld %8ld %5.2f",number,duration,
- (float)(100*duration)/total_ticks);
- fputs(string,output_file);
- return;
- } /* END OF PRINT_LINE */
-
- tally_total_ticks()
- {
- struct tally far *ptr;
- union REGS registers;
- struct SREGS segregs;
- int idx , total_services;
-
- /* CALCULATE THE TOTAL NUMBER OF BINS. */
-
- for (idx = 0 , total_services = 0; idx <= NUM_INTS; idx++)
- total_services += (1+max_services[idx]);
-
- /* GET THE ADDRESS OF THE TABLE. */
-
- registers.h.ah = FIND;
- int86x(CONTROL_INTERRUPT,®isters,®isters,&segregs);
- FP_SEG(ptr) = segregs.es;
- FP_OFF(ptr) = registers.x.bx;
-
- for (idx = 0 , total_ticks = 0; idx < total_services; idx++ , ptr++)
- total_ticks += ptr->time;
-
- return;
- } /* END OF TALLY_TOTAL_TICKS */
-
- error_exit()
-
- {
- printf("\n\nProper syntax is:\n\n ");
- printf("PROFCTRL STATUS | OFF | ON | ZERO | REPORT");
- exit(1);
- } /* END OF ERROR_EXIT */
-
-
-