System statistical and call profiling
support by Rogier Meurs <rogier@meurs.org>.
This commit is contained in:
@@ -10,14 +10,14 @@ s = system
|
||||
CC = exec cc
|
||||
CPP = $l/cpp
|
||||
LD = $(CC) -.o
|
||||
CFLAGS = -I$i
|
||||
CFLAGS = -I$i $(CPROFILE)
|
||||
LDFLAGS = -i
|
||||
|
||||
HEAD = mpx.o
|
||||
OBJS = start.o protect.o klib.o table.o kprintf.o main.o proc.o \
|
||||
i8259.o exception.o system.o clock.o utility.o debug.o
|
||||
i8259.o exception.o system.o clock.o utility.o debug.o profile.o
|
||||
SYSTEM = system.a
|
||||
LIBS = -ltimers
|
||||
LIBS = -ltimers -lsysutil
|
||||
|
||||
|
||||
# What to make.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "proto.h" /* function prototypes */
|
||||
#include "glo.h" /* global variables */
|
||||
#include "ipc.h" /* IPC constants */
|
||||
#include "profile.h" /* system profiling */
|
||||
#include "debug.h" /* debugging, MUST be last kernel header */
|
||||
|
||||
#endif /* KERNEL_H */
|
||||
|
||||
@@ -181,6 +181,13 @@ PUBLIC void main()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SPROFILE
|
||||
sprofiling = 0; /* we're not profiling until instructed to */
|
||||
#endif /* SPROFILE */
|
||||
#if CPROFILE
|
||||
cprof_procs_no = 0; /* init nr of hash table slots used */
|
||||
#endif /* CPROFILE */
|
||||
|
||||
/* MINIX is now ready. All boot image processes are on the ready queue.
|
||||
* Return to the assembly code to start running the current process.
|
||||
*/
|
||||
|
||||
207
kernel/profile.c
Normal file
207
kernel/profile.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* This file contains several functions and variables used for system
|
||||
* profiling.
|
||||
*
|
||||
* Statistical Profiling:
|
||||
* The interrupt handler and control functions for the CMOS clock.
|
||||
*
|
||||
* Call Profiling:
|
||||
* The table used for profiling data and a function to get its size.
|
||||
*
|
||||
* The function used by kernelspace processes to register the locations
|
||||
* of their control struct and profiling table.
|
||||
*
|
||||
* Changes:
|
||||
* 14 Aug, 2006 Created, (Rogier Meurs)
|
||||
*/
|
||||
|
||||
#include <minix/config.h>
|
||||
|
||||
#if SPROFILE || CPROFILE
|
||||
|
||||
#include <minix/profile.h>
|
||||
#include "kernel.h"
|
||||
#include "profile.h"
|
||||
#include "proc.h"
|
||||
|
||||
#endif
|
||||
|
||||
#if SPROFILE
|
||||
|
||||
#include <string.h>
|
||||
#include <ibm/cmos.h>
|
||||
|
||||
/* Function prototype for the CMOS clock handler. */
|
||||
FORWARD _PROTOTYPE( int cmos_clock_handler, (irq_hook_t *hook) );
|
||||
|
||||
/* A hook for the CMOS clock interrupt handler. */
|
||||
PRIVATE irq_hook_t cmos_clock_hook;
|
||||
|
||||
/*===========================================================================*
|
||||
* init_cmos_clock *
|
||||
*===========================================================================*/
|
||||
PUBLIC void init_cmos_clock(unsigned freq)
|
||||
{
|
||||
int r;
|
||||
/* Register interrupt handler for statistical system profiling.
|
||||
* This uses the CMOS timer.
|
||||
*/
|
||||
cmos_clock_hook.proc_nr_e = CLOCK;
|
||||
put_irq_handler(&cmos_clock_hook, CMOS_CLOCK_IRQ, cmos_clock_handler);
|
||||
enable_irq(&cmos_clock_hook);
|
||||
|
||||
intr_disable();
|
||||
|
||||
/* Set CMOS timer frequency. */
|
||||
outb(RTC_INDEX, RTC_REG_A);
|
||||
outb(RTC_IO, RTC_A_DV_OK | freq);
|
||||
/* Enable CMOS timer interrupts. */
|
||||
outb(RTC_INDEX, RTC_REG_B);
|
||||
r = inb(RTC_IO);
|
||||
outb(RTC_INDEX, RTC_REG_B);
|
||||
outb(RTC_IO, r | RTC_B_PIE);
|
||||
/* Mandatory read of CMOS register to enable timer interrupts. */
|
||||
outb(RTC_INDEX, RTC_REG_C);
|
||||
inb(RTC_IO);
|
||||
|
||||
intr_enable();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cmos_clock_stop *
|
||||
*===========================================================================*/
|
||||
PUBLIC void stop_cmos_clock()
|
||||
{
|
||||
int r;
|
||||
|
||||
intr_disable();
|
||||
|
||||
/* Disable CMOS timer interrupts. */
|
||||
outb(RTC_INDEX, RTC_REG_B);
|
||||
r = inb(RTC_IO);
|
||||
outb(RTC_INDEX, RTC_REG_B);
|
||||
outb(RTC_IO, r & !RTC_B_PIE);
|
||||
|
||||
intr_enable();
|
||||
|
||||
/* Unregister interrupt handler. */
|
||||
disable_irq(&cmos_clock_hook);
|
||||
rm_irq_handler(&cmos_clock_hook);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* cmos_clock_handler *
|
||||
*===========================================================================*/
|
||||
PRIVATE int cmos_clock_handler(hook)
|
||||
irq_hook_t *hook;
|
||||
{
|
||||
/* This executes on every tick of the CMOS timer. */
|
||||
|
||||
/* Are we profiling, and profiling memory not full? */
|
||||
if (!sprofiling || sprof_info.mem_used == -1) return (1);
|
||||
|
||||
/* Check if enough memory available before writing sample. */
|
||||
if (sprof_info.mem_used + sizeof(sprof_info) > sprof_mem_size) {
|
||||
sprof_info.mem_used = -1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* All is OK */
|
||||
|
||||
/* Idle process? */
|
||||
if (priv(proc_ptr)->s_proc_nr == IDLE) {
|
||||
sprof_info.idle_samples++;
|
||||
} else
|
||||
/* Runnable system process? */
|
||||
if (priv(proc_ptr)->s_flags & SYS_PROC && !proc_ptr->p_rts_flags) {
|
||||
/* Note: k_reenter is always 0 here. */
|
||||
|
||||
/* Store sample (process name and program counter). */
|
||||
phys_copy(vir2phys(proc_ptr->p_name),
|
||||
(phys_bytes) (sprof_data_addr + sprof_info.mem_used),
|
||||
(phys_bytes) strlen(proc_ptr->p_name));
|
||||
|
||||
phys_copy(vir2phys(&proc_ptr->p_reg.pc),
|
||||
(phys_bytes) (sprof_data_addr+sprof_info.mem_used +
|
||||
sizeof(proc_ptr->p_name)),
|
||||
(phys_bytes) sizeof(proc_ptr->p_reg.pc));
|
||||
|
||||
sprof_info.mem_used += sizeof(sprof_sample);
|
||||
|
||||
sprof_info.system_samples++;
|
||||
} else {
|
||||
/* User process. */
|
||||
sprof_info.user_samples++;
|
||||
}
|
||||
|
||||
sprof_info.total_samples++;
|
||||
|
||||
/* Mandatory read of CMOS register to re-enable timer interrupts. */
|
||||
outb(RTC_INDEX, RTC_REG_C);
|
||||
inb(RTC_IO);
|
||||
|
||||
return(1); /* reenable interrupts */
|
||||
}
|
||||
|
||||
#endif /* SPROFILE */
|
||||
|
||||
|
||||
#if CPROFILE
|
||||
|
||||
/*
|
||||
* The following variables and functions are used by the procentry/
|
||||
* procentry syslib functions when linked with kernelspace processes.
|
||||
* For userspace processes, the same variables and function are defined
|
||||
* elsewhere. This enables different functionality and variable sizes,
|
||||
* which is needed is a few cases.
|
||||
*/
|
||||
|
||||
/* A small table is declared for the kernelspace processes. */
|
||||
struct cprof_tbl_s cprof_tbl[CPROF_TABLE_SIZE_KERNEL];
|
||||
|
||||
/* Function that returns table size. */
|
||||
PUBLIC int profile_get_tbl_size(void)
|
||||
{
|
||||
return CPROF_TABLE_SIZE_KERNEL;
|
||||
}
|
||||
|
||||
/* Function that returns on which execution of procentry to announce. */
|
||||
PUBLIC int profile_get_announce(void)
|
||||
{
|
||||
return CPROF_ACCOUNCE_KERNEL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The kernel "announces" its control struct and table locations
|
||||
* to itself through this function.
|
||||
*/
|
||||
PUBLIC void profile_register(ctl_ptr, tbl_ptr)
|
||||
void *ctl_ptr;
|
||||
void *tbl_ptr;
|
||||
{
|
||||
int len, proc_nr;
|
||||
vir_bytes vir_dst;
|
||||
struct proc *rp;
|
||||
|
||||
/* Store process name, control struct, table locations. */
|
||||
proc_nr = KERNEL;
|
||||
rp = proc_addr(proc_nr);
|
||||
|
||||
cprof_proc_info[cprof_procs_no].endpt = rp->p_endpoint;
|
||||
cprof_proc_info[cprof_procs_no].name = rp->p_name;
|
||||
|
||||
len = (phys_bytes) sizeof (void *);
|
||||
|
||||
vir_dst = (vir_bytes) ctl_ptr;
|
||||
cprof_proc_info[cprof_procs_no].ctl =
|
||||
numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
vir_dst = (vir_bytes) tbl_ptr;
|
||||
cprof_proc_info[cprof_procs_no].buf =
|
||||
numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
cprof_procs_no++;
|
||||
}
|
||||
|
||||
#endif /* CPROFILE */
|
||||
|
||||
41
kernel/profile.h
Normal file
41
kernel/profile.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef PROFILE_H
|
||||
#define PROFILE_H
|
||||
|
||||
#if SPROFILE || CPROFILE
|
||||
#include <minix/profile.h>
|
||||
#endif
|
||||
|
||||
#if SPROFILE /* statistical profiling */
|
||||
|
||||
_PROTOTYPE( void init_cmos_clock, (unsigned freq) );
|
||||
_PROTOTYPE( void stop_cmos_clock, (void) );
|
||||
|
||||
EXTERN int sprofiling; /* whether profiling is running */
|
||||
EXTERN int sprof_mem_size; /* available user memory for data */
|
||||
EXTERN struct sprof_info_s sprof_info; /* profiling info for user program */
|
||||
EXTERN phys_bytes sprof_data_addr; /* user address to write data */
|
||||
EXTERN phys_bytes sprof_info_addr; /* user address to write info struct */
|
||||
|
||||
#endif /* SPROFILE */
|
||||
|
||||
|
||||
#if CPROFILE /* call profiling */
|
||||
|
||||
EXTERN int cprof_mem_size; /* available user memory for data */
|
||||
EXTERN struct cprof_info_s cprof_info; /* profiling info for user program */
|
||||
EXTERN phys_bytes cprof_data_addr; /* user address to write data */
|
||||
EXTERN phys_bytes cprof_info_addr; /* user address to write info struct */
|
||||
EXTERN int cprof_procs_no; /* number of profiled processes */
|
||||
EXTERN struct cprof_proc_info_s { /* info about profiled process */
|
||||
int endpt; /* endpoint */
|
||||
char *name; /* name */
|
||||
phys_bytes ctl; /* location of control struct */
|
||||
phys_bytes buf; /* location of buffer */
|
||||
int slots_used; /* table slots used */
|
||||
} cprof_proc_info_inst;
|
||||
EXTERN struct cprof_proc_info_s cprof_proc_info[NR_SYS_PROCS];
|
||||
|
||||
#endif /* CPROFILE */
|
||||
|
||||
#endif /* PROFILE_H */
|
||||
|
||||
@@ -190,6 +190,11 @@ PRIVATE void initialize(void)
|
||||
map(SYS_ABORT, do_abort); /* abort MINIX */
|
||||
map(SYS_GETINFO, do_getinfo); /* request system information */
|
||||
map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
|
||||
|
||||
/* Profiling. */
|
||||
map(SYS_SPROF, do_sprofile); /* start/stop statistical profiling */
|
||||
map(SYS_CPROF, do_cprofile); /* get/reset call profiling data */
|
||||
map(SYS_PROFBUF, do_profbuf); /* announce locations to kernel */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
||||
@@ -179,5 +179,20 @@ _PROTOTYPE( int do_iopenable, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_setgrant, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_readbios, (message *m_ptr) );
|
||||
|
||||
_PROTOTYPE( int do_sprofile, (message *m_ptr) );
|
||||
#if ! SPROFILE
|
||||
#define do_sprofile do_unused
|
||||
#endif
|
||||
|
||||
_PROTOTYPE( int do_cprofile, (message *m_ptr) );
|
||||
#if ! CPROFILE
|
||||
#define do_cprofile do_unused
|
||||
#endif
|
||||
|
||||
_PROTOTYPE( int do_profbuf, (message *m_ptr) );
|
||||
#if ! CPROFILE
|
||||
#define do_profbuf do_unused
|
||||
#endif
|
||||
|
||||
#endif /* SYSTEM_H */
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ i = $u/include
|
||||
|
||||
# Programs, flags, etc.
|
||||
CC = exec cc $(CFLAGS) -c
|
||||
CCNOPROF = exec cc $(CFLAGSNOPROF) -c # no call profiling for these
|
||||
CPP = $l/cpp
|
||||
LD = $(CC) -.o
|
||||
CFLAGS = -I$i
|
||||
CFLAGS = -I$i $(CPROFILE)
|
||||
CFLAGSNOPROF = -I$i
|
||||
LDFLAGS = -i
|
||||
|
||||
SYSTEM = ../system.a
|
||||
@@ -50,6 +52,9 @@ OBJECTS = \
|
||||
$(SYSTEM)(do_iopenable.o) \
|
||||
$(SYSTEM)(do_vm.o) \
|
||||
$(SYSTEM)(do_vm_setbuf.o) \
|
||||
$(SYSTEM)(do_sprofile.o) \
|
||||
$(SYSTEM)(do_cprofile.o) \
|
||||
$(SYSTEM)(do_profbuf.o)
|
||||
|
||||
$(SYSTEM): $(OBJECTS)
|
||||
aal cr $@ *.o
|
||||
@@ -163,3 +168,12 @@ do_vm.o: do_vm.c
|
||||
|
||||
$(SYSTEM)(do_vm_setbuf.o): do_vm_setbuf.c
|
||||
$(CC) do_vm_setbuf.c
|
||||
|
||||
$(SYSTEM)(do_sprofile.o): do_sprofile.c
|
||||
$(CC) do_sprofile.c
|
||||
|
||||
$(SYSTEM)(do_cprofile.o): do_cprofile.c
|
||||
$(CC) do_cprofile.c
|
||||
|
||||
$(SYSTEM)(do_profbuf.o): do_profbuf.c
|
||||
$(CC) do_profbuf.c
|
||||
|
||||
160
kernel/system/do_cprofile.c
Normal file
160
kernel/system/do_cprofile.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/* The kernel call that is implemented in this file:
|
||||
* m_type: SYS_CPROFILE
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m7_i1: PROF_ACTION (get/reset profiling data)
|
||||
* m7_i2: PROF_MEM_SIZE (available memory for data)
|
||||
* m7_i4: PROF_ENDPT (endpoint of caller)
|
||||
* m7_p1: PROF_CTL_PTR (location of info struct)
|
||||
* m7_p2: PROF_MEM_PTR (location of memory for data)
|
||||
*
|
||||
* Changes:
|
||||
* 14 Aug, 2006 Created (Rogier Meurs)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if CPROFILE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_cprofile *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_cprofile(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr, i, err = 0, k = 0;
|
||||
vir_bytes vir_dst;
|
||||
phys_bytes phys_src, phys_dst, len;
|
||||
|
||||
switch (m_ptr->PROF_ACTION) {
|
||||
|
||||
case PROF_RESET:
|
||||
|
||||
/* Reset profiling tables. */
|
||||
|
||||
cprof_ctl_inst.reset = 1;
|
||||
|
||||
kprintf("CPROFILE notice: resetting tables:");
|
||||
|
||||
for (i=0; i<cprof_procs_no; i++) {
|
||||
|
||||
kprintf(" %s", cprof_proc_info[i].name);
|
||||
|
||||
/* Test whether proc still alive. */
|
||||
if (!isokendpt(cprof_proc_info[i].endpt, &proc_nr)) {
|
||||
kprintf("endpt not valid %u (%s)\n",
|
||||
cprof_proc_info[i].endpt, cprof_proc_info[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set reset flag. */
|
||||
phys_src = vir2phys((vir_bytes) &cprof_ctl_inst.reset);
|
||||
phys_dst = (phys_bytes) cprof_proc_info[i].ctl;
|
||||
len = (phys_bytes) sizeof(cprof_ctl_inst.reset);
|
||||
phys_copy(phys_src, phys_dst, len);
|
||||
}
|
||||
kprintf("\n");
|
||||
|
||||
return OK;
|
||||
|
||||
case PROF_GET:
|
||||
|
||||
/* Get profiling data.
|
||||
*
|
||||
* Calculate physical addresses of user pointers. Copy to user
|
||||
* program the info struct. Copy to user program the profiling
|
||||
* tables of the profiled processes.
|
||||
*/
|
||||
|
||||
if(!isokendpt(m_ptr->PROF_ENDPT, &proc_nr))
|
||||
return EINVAL;
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
|
||||
len = (phys_bytes) sizeof (int *);
|
||||
cprof_info_addr = numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
|
||||
len = (phys_bytes) sizeof (char *);
|
||||
cprof_data_addr = numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
cprof_mem_size = m_ptr->PROF_MEM_SIZE;
|
||||
|
||||
kprintf("CPROFILE notice: getting tables:");
|
||||
|
||||
/* Copy control structs of profiled processes to calculate total
|
||||
* nr of bytes to be copied to user program and find out if any
|
||||
* errors happened. */
|
||||
cprof_info.mem_used = 0;
|
||||
cprof_info.err = 0;
|
||||
|
||||
for (i=0; i<cprof_procs_no; i++) {
|
||||
|
||||
kprintf(" %s", cprof_proc_info[i].name);
|
||||
|
||||
/* Test whether proc still alive. */
|
||||
if (!isokendpt(cprof_proc_info[i].endpt, &proc_nr)) {
|
||||
kprintf("endpt not valid %u (%s)\n",
|
||||
cprof_proc_info[i].endpt, cprof_proc_info[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Copy control struct from proc to local variable. */
|
||||
phys_src = cprof_proc_info[i].ctl;
|
||||
phys_dst = vir2phys((vir_bytes) &cprof_ctl_inst);
|
||||
len = (phys_bytes) sizeof(cprof_ctl_inst);
|
||||
phys_copy(phys_src, phys_dst, len);
|
||||
|
||||
/* Calculate memory used. */
|
||||
cprof_proc_info[i].slots_used = cprof_ctl_inst.slots_used;
|
||||
cprof_info.mem_used += CPROF_PROCNAME_LEN;
|
||||
cprof_info.mem_used += sizeof(cprof_proc_info_inst.slots_used);
|
||||
cprof_info.mem_used += cprof_proc_info[i].slots_used *
|
||||
sizeof(cprof_tbl_inst);
|
||||
/* Collect errors. */
|
||||
cprof_info.err |= cprof_ctl_inst.err;
|
||||
}
|
||||
kprintf("\n");
|
||||
|
||||
/* Do we have the space available? */
|
||||
if (cprof_mem_size < cprof_info.mem_used) cprof_info.mem_used = -1;
|
||||
|
||||
/* Copy the info struct to the user process. */
|
||||
phys_copy(vir2phys((vir_bytes) &cprof_info), cprof_info_addr,
|
||||
(phys_bytes) sizeof(cprof_info));
|
||||
|
||||
/* If there is no space or errors occurred, don't bother copying. */
|
||||
if (cprof_info.mem_used == -1 || cprof_info.err) return OK;
|
||||
|
||||
/* For each profiled process, copy its name, slots_used and profiling
|
||||
* table to the user process. */
|
||||
phys_dst = cprof_data_addr;
|
||||
for (i=0; i<cprof_procs_no; i++) {
|
||||
phys_src = vir2phys((vir_bytes) cprof_proc_info[i].name);
|
||||
len = (phys_bytes) strlen(cprof_proc_info[i].name);
|
||||
phys_copy(phys_src, phys_dst, len);
|
||||
phys_dst += CPROF_PROCNAME_LEN;
|
||||
|
||||
phys_src = cprof_proc_info[i].ctl +
|
||||
sizeof(cprof_ctl_inst.reset);
|
||||
len = (phys_bytes) sizeof(cprof_ctl_inst.slots_used);
|
||||
phys_copy(phys_src, phys_dst, len);
|
||||
phys_dst += len;
|
||||
|
||||
phys_src = cprof_proc_info[i].buf;
|
||||
len = (phys_bytes)
|
||||
(sizeof(cprof_tbl_inst) * cprof_proc_info[i].slots_used);
|
||||
phys_copy(phys_src, phys_dst, len);
|
||||
phys_dst += len;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CPROFILE */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "../system.h"
|
||||
#include "../ipc.h"
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
#if USE_PRIVCTL
|
||||
|
||||
|
||||
55
kernel/system/do_profbuf.c
Normal file
55
kernel/system/do_profbuf.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* The kernel call that is implemented in this file:
|
||||
* m_type: SYS_PROFBUF
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m7_p1: PROF_CTL_PTR (location of control struct)
|
||||
* m7_p2: PROF_MEM_PTR (location of profiling table)
|
||||
*
|
||||
* Changes:
|
||||
* 14 Aug, 2006 Created (Rogier Meurs)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if CPROFILE
|
||||
|
||||
/*===========================================================================*
|
||||
* do_profbuf *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_profbuf(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* This kernel call is used by profiled system processes when Call
|
||||
* Profiling is enabled. It is called on the first execution of procentry.
|
||||
* By means of this kernel call, the profiled processes inform the kernel
|
||||
* about the location of their profiling table and the control structure
|
||||
* which is used to enable the kernel to have the tables cleared.
|
||||
*/
|
||||
int proc_nr, len;
|
||||
vir_bytes vir_dst;
|
||||
struct proc *rp;
|
||||
|
||||
/* Store process name, control struct, table locations. */
|
||||
isokendpt(m_ptr->m_source, &proc_nr);
|
||||
rp = proc_addr(proc_nr);
|
||||
|
||||
cprof_proc_info[cprof_procs_no].endpt = who_e;
|
||||
cprof_proc_info[cprof_procs_no].name = rp->p_name;
|
||||
|
||||
len = (phys_bytes) sizeof (void *);
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
|
||||
cprof_proc_info[cprof_procs_no].ctl =
|
||||
numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
|
||||
cprof_proc_info[cprof_procs_no].buf =
|
||||
numap_local(proc_nr, vir_dst, len);
|
||||
|
||||
cprof_procs_no++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CPROFILE */
|
||||
|
||||
94
kernel/system/do_sprofile.c
Normal file
94
kernel/system/do_sprofile.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/* The kernel call that is implemented in this file:
|
||||
* m_type: SYS_SPROFILE
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m7_i1: PROF_ACTION (start/stop profiling)
|
||||
* m7_i2: PROF_MEM_SIZE (available memory for data)
|
||||
* m7_i3: PROF_FREQ (requested sample frequency)
|
||||
* m7_i4: PROF_ENDPT (endpoint of caller)
|
||||
* m7_p1: PROF_CTL_PTR (location of info struct)
|
||||
* m7_p2: PROF_MEM_PTR (location of memory for data)
|
||||
*
|
||||
* Changes:
|
||||
* 14 Aug, 2006 Created (Rogier Meurs)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if SPROFILE
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sprofile *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sprofile(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr, i;
|
||||
vir_bytes vir_dst;
|
||||
phys_bytes length;
|
||||
|
||||
switch(m_ptr->PROF_ACTION) {
|
||||
|
||||
case PROF_START:
|
||||
/* Starting profiling.
|
||||
*
|
||||
* Check if profiling is not already running. Calculate physical
|
||||
* addresses of user pointers. Reset counters. Start CMOS timer.
|
||||
* Turn on profiling.
|
||||
*/
|
||||
if (sprofiling) {
|
||||
kprintf("SYSTEM: start s-profiling: already started\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
isokendpt(m_ptr->PROF_ENDPT, &proc_nr);
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
|
||||
length = (phys_bytes) sizeof (int *);
|
||||
sprof_info_addr = numap_local(proc_nr, vir_dst, length);
|
||||
|
||||
vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
|
||||
length = (phys_bytes) sizeof (char *);
|
||||
sprof_data_addr = numap_local(proc_nr, vir_dst, length);
|
||||
|
||||
sprof_info.mem_used = 0;
|
||||
sprof_info.total_samples = 0;
|
||||
sprof_info.idle_samples = 0;
|
||||
sprof_info.system_samples = 0;
|
||||
sprof_info.user_samples = 0;
|
||||
|
||||
sprof_mem_size = m_ptr->PROF_MEM_SIZE;
|
||||
|
||||
init_cmos_clock(m_ptr->PROF_FREQ);
|
||||
|
||||
sprofiling = 1;
|
||||
|
||||
return OK;
|
||||
|
||||
case PROF_STOP:
|
||||
/* Stopping profiling.
|
||||
*
|
||||
* Check if profiling is indeed running. Turn off profiling.
|
||||
* Stop CMOS timer. Copy info struct to user process.
|
||||
*/
|
||||
if (!sprofiling) {
|
||||
kprintf("SYSTEM: stop s-profiling: not started\n");
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
sprofiling = 0;
|
||||
|
||||
stop_cmos_clock();
|
||||
|
||||
phys_copy(vir2phys((vir_bytes) &sprof_info),
|
||||
sprof_info_addr, (phys_bytes) sizeof(sprof_info));
|
||||
|
||||
return OK;
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SPROFILE */
|
||||
|
||||
@@ -82,9 +82,9 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
||||
*/
|
||||
#define FS_C SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
|
||||
SYS_VIRVCOPY, SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
|
||||
SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT
|
||||
SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF
|
||||
#define DRV_C FS_C, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
|
||||
SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT
|
||||
SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF
|
||||
|
||||
PRIVATE int
|
||||
fs_c[] = { FS_C },
|
||||
|
||||
Reference in New Issue
Block a user