home *** CD-ROM | disk | FTP | other *** search
- /* C.ProfileT: Execution profiler (by time)
- *
- * Version 1.00, 04-06-1990
- *
- * Copyright (C) Ferdinand Oeinck 1990
- *
- * Modified, Paul Moore 02/06/91.
- * To conform to the conventions of my "Utils" library.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "swis.h"
- #include "kernel.h"
-
- #include "ProfileAsm.h"
- #include "Profile.h"
-
- static int *funcadr_ptr;
- static int *count_ptr;
- static int funccount;
-
- static char *_profile_filename;
- static void _profile_exithandler(void);
-
- void profile_init_time (const char *filename)
- {
- unsigned int *codestart;
- unsigned int *codeend;
- unsigned int *i;
- int fpestart, fpeend;
- int len;
- int instr;
- int count = 0;
- char *modulename;
- _kernel_swi_regs regs;
-
- if (_kernel_hostos() != _kernel_ARTHUR)
- {
- printf("Error: Not running on ARTHUR host OS\n");
- exit(1);
- }
-
- if (!_kernel_fpavailable())
- {
- printf("Warning: Execution time profiling not possible.\n");
- printf(" No floating point support.\n");
- return;
- }
-
- regs.r[0] = 12;
- regs.r[1] = 0;
- regs.r[2] = 0;
-
- while (_kernel_swi(OS_Module, ®s, ®s) == NULL)
- {
- modulename = (char*)(regs.r[3] + *((int *)(regs.r[3] + 0x10)));
- if (strcmp(modulename,"FPEmulator") == 0)
- break;
- }
-
- fpestart = regs.r[3];
- _kernel_swi(OS_Module, ®s, ®s);
- fpeend = regs.r[3];
-
- if (filename == NULL || *filename == '\0')
- _profile_filename = NULL;
- else
- {
- if ((_profile_filename = malloc(strlen(filename) + 1)) == NULL)
- {
- printf("Warning: Execution time profiling not possible.\n");
- printf(" Malloc failed.\n");
- return;
- }
-
- strcpy(_profile_filename, filename);
- }
-
- codestart = _profile_getstart();
- codeend = _profile_getend();
-
- for (i = codestart; i != codeend; i++)
- {
- instr = *i & 0xffff0000;
- if (instr == (unsigned int) 0xff000000)
- {
- len = *i & 0xffff;
- if (len >= strlen((char *)i - len))
- count++;
- }
- }
- count += 4;
-
- if ((funcadr_ptr = calloc(count, sizeof(int))) == NULL)
- {
- printf("Warning: Execution time profiling not possible.\n");
- printf(" Malloc failed.\n");
- free(_profile_filename);
- return;
- }
-
- if ((count_ptr = calloc(count, sizeof(int))) == NULL)
- {
- printf("Warning: Execution time profiling not possible.\n");
- printf(" Malloc failed.\n");
- free(funcadr_ptr);
- free(_profile_filename);
- return;
- }
-
- funccount = count;
-
- count = 1;
- for (i = codestart; i != codeend; i++)
- {
- instr = *i & 0xffff0000;
- if (instr == (unsigned int) 0xff000000)
- {
- len = *i & 0xffff;
- if (len >= strlen((char *)i - len))
- {
- funcadr_ptr[count++] = (int) i - len;
- }
- }
- }
-
- funcadr_ptr[count] = (int) codeend;
- funcadr_ptr[count + 1] = (int) fpestart;
- funcadr_ptr[count + 2] = (int) fpeend;
-
- if (!_profile_ClaimIntDeviceVector())
- {
- free(count_ptr);
- free(funcadr_ptr);
- free(_profile_filename);
- printf("Warning: Execution time profiling not possible.\n");
- printf(" I think this is not RISC_OS 2.00\n");
- return;
- }
-
- atexit(_profile_exithandler);
- }
-
- #define HEADER \
- " Num Address Function name Percentage Count\n"
-
- #define UNDERLINE \
- "=========================================================================\n"
-
- #define FORMAT \
- "%4i %8x %-40s %6.2f %7i\n"
-
- #define TOTALS \
- "%57s %6.2f %7i\n", ""
-
- static void _profile_exithandler(void)
- {
- int i;
- int sumc = 0;
- float sum = 0;
- float sump = 0;
- FILE *fp;
-
- _profile_ReleaseIntDeviceVector();
-
- for (i = 0; i < funccount; i++)
- sum += count_ptr[i];
-
- /* Subtract double counted fp values */
- sum -= count_ptr[funccount - 2];
-
- if (sum <= 0)
- sum = 1;
-
- if (_profile_filename == NULL)
- {
- fp = stderr;
- }
- else if ((fp = fopen(_profile_filename, "w")) == NULL)
- {
- fprintf(stderr,"Can't write profile data to %s - using stderr\n",_profile_filename);
- fp = stderr;
- }
-
- fprintf(fp, HEADER);
- fprintf(fp, UNDERLINE);
-
- fprintf(fp, FORMAT,
- 0,
- funcadr_ptr[1],
- "Before user code (kernel)",
- 100.0 * (float) count_ptr[0] / sum,
- count_ptr[0]);
-
- sump += (float) 100.0 * (float) count_ptr[0] / sum;
- sumc += count_ptr[0];
-
- for (i = 1 ; i < funccount - 3; i++)
- {
- fprintf(fp, FORMAT,
- i,
- funcadr_ptr[i],
- (char *) funcadr_ptr[i],
- 100.0 * (float) count_ptr[i] / sum,
- count_ptr[i]);
-
- sump += (float) 100.0 * (float) count_ptr[i] / sum;
- sumc += count_ptr[i];
- }
-
- fprintf(fp, FORMAT,
- funccount-3,
- funcadr_ptr[funccount-3],
- "After user code (kernel)",
- 100.0 * (float) count_ptr[funccount-3] / sum,
- count_ptr[funccount-3]);
-
- sump += (float) 100.0 * (float) count_ptr[funccount-3] / sum;
- sumc += count_ptr[funccount - 3];
-
- fprintf(fp, UNDERLINE);
- fprintf(fp, TOTALS, sump, sumc);
- fprintf(fp, "\nPercentage of time spent in the FPE\n");
- fprintf(fp, FORMAT,
- funccount-2,
- funcadr_ptr[funccount-2],
- "fpemulator",
- 100.0 * (float) count_ptr[funccount-2] / sum,
- count_ptr[funccount-2]);
-
- if (fp != stderr)
- fclose(fp);
-
- free(count_ptr);
- free(funcadr_ptr);
- free(_profile_filename);
- }
-
- /* Binary search of address table.
- * This function is called every 1/100 second
- */
-
- #define Between(x,l,h) ((int)l < (int)x && (int)x <= (int)h)
-
- void binsearch (int *adr)
- {
- int high = funccount - 1;
- int low = 1;
-
- if ((int) adr < (int) funcadr_ptr[1])
- {
- ++count_ptr[0];
- return;
- }
-
- if (Between(adr,funcadr_ptr[funccount-2],funcadr_ptr[funccount-1]))
- {
- /* We are in the FPE, so use that return address */
- ++count_ptr[funccount-2];
- adr = (int *)_profile_fp_return_address;
- }
-
- if ((int) adr > (int) funcadr_ptr[funccount-3])
- {
- ++count_ptr[funccount-3];
- return;
- }
-
- while ((high - low) > 1)
- {
- int middle = (high + low) / 2;
- if (Between(adr,funcadr_ptr[middle],funcadr_ptr[middle + 1]))
- {
- low = middle;
- break;
- }
-
- if ((int)adr > (int)funcadr_ptr[middle + 1])
- low = middle + 1;
- else
- high = middle;
- }
-
- ++count_ptr[low];
- }
-