The gprof program and associated libc and kernel routines provide a mechanism to produce an execution profile of an oskit-based kernel. The gprof program is linked right into the kernel, performing its data reduction and analysis just before the kernel exits and producing output to the console device. See gprof(1) for more information.
The application to be profiled must be called “a.out”.
It is expected that the current behavior of generating ASCII output to the console device will be changed in the future. For example, the interface might be modified to allow specification of an oskit_stream object (Section 4) to which the binary “gmon.out” data would be written. Typically, this object would refer to a persistent file or a network connection with another machine.
See Section 32.4 for line-by-line instructions on using gprof in the OSKit, including some non-obvious linking magic. You may need to link against additional libraries to use gprof on your kernel; If your kernel does not use a bmod filesystem, you’ll need to additionally link against the memfs library.
#include <oskit/c/sys/gmon.h>
#include <oskit/c/sys/profile.h>
This function enables or disables the statistical sampling of the program counter for the kernel. If profiling is enabled, at RTC clock tick (see below), the program counter is recorded in the samples buffer. This function is most frequently called by moncontrol().
Returns 0 if all is OK, or -1 on error. Sets errno to the reason for failure.
If mode is non-zero (true), enables profiling. If mode is zero, disables profiling.
#include <oskit/c/sys/gmon.h>
#include <oskit/c/sys/profile.h>
void monstartup(unsigned long *lowpc, unsigned long *highpc);
monstartup initiates profiling of the kernel; it should only be called once. Note that by default, monstartup is called by base_multiboot_main when profiling is enabled with configure. If you wish to delay profiling until a later time, disable the monstartup call in base_multiboot_main, and place your own call to monstartup later in your code.
This step is necessary so gprof can access the kernel’s symbol table via the bmodfs.
The default sampling rate is 8192 Hz, using the RTC as the source of the sampling interrupts. You can adjust this by modifying one #define in gmon.h:
Redefine #define PROFHZ xxxx to the sampling rate.
The rate you select must be a power of 2 between 128 and 8192.
in base_console.c, change int enable_gprof = 1; to = 0.
The FreeBSD boot manager won’t pass in the -p flag.
You need to hand-code stubs for them which call __mcount. Sorry. The compiler only autogenerates the _mcount stubs for C routines. The call to __mcount is performed for you if you use the oskit ENTRY() macro.
If you don’t use one of the oskit ENTRY macros, then your function’s symbol may not be declared properly. If you want to do it by hand, then declare the symbol:
.globl symbol_name .type symbol_name,@function |
Note that this is taken care of for you by the macros in asm.h if you simply declare a function with ENTRY(x) or NON_GPROF_ENTRY(x).
Gprof takes over the RTC (irq 8). If you have code which uses the oskit interrupt request mechanism to grab irq 8, it won’t work. If your code just steals irq 8 by replacing the interrupt handler for it, you’ll break gprof.
Gprof installs some atexit handlers for the kernel ‘main’. These are installed in base_multiboot_main.c.