struct sprof_info_s sprof_info;
struct cprof_info_s cprof_info;
+#define HASH_MOD 128
+struct sproc {
+ endpoint_t ep;
+ char name[8];
+ struct sproc * next;
+};
+
+static struct sproc * proc_hash[HASH_MOD];
+
_PROTOTYPE(int handle_args, (int argc, char *argv[]));
_PROTOTYPE(int start, (void));
_PROTOTYPE(int stop, (void));
mem_size *= MB; /* mem_size in bytes */
}
if (action == START) {
- mem_size -= mem_size % sizeof(sprof_sample); /* align to sample size */
+ mem_size -= mem_size % sizeof(struct sprof_sample); /* align to sample size */
if (freq == 0) freq = DEF_FREQ; /* default frequency */
}
return 0;
close(2);
}
+static void add_proc(struct sprof_proc * p)
+{
+ struct sproc * n;
+ int slot = ((unsigned)(p->proc)) % HASH_MOD;
+
+ n = malloc(sizeof(struct sproc));
+ if (!n)
+ abort();
+ n->ep = p->proc;
+ memcpy(n->name, p->name, 8);
+ n->next = proc_hash[slot];
+ proc_hash[slot] = n;
+}
+
+static char * get_proc_name(endpoint_t ep)
+{
+ struct sproc * p;
+
+ for (p = proc_hash[((unsigned)ep) % HASH_MOD]; p; p = p->next) {
+ if (p->ep == ep)
+ return p->name;
+ }
+
+ return NULL;
+}
int write_outfile()
{
int n, towrite, written = 0;
char *buf = mem_ptr;
char header[80];
+ struct sprof_sample *sample;
printf("Writing to %s ...", outfile);
/* Write data. */
towrite = mem_used == -1 ? mem_size : mem_used;
+ sample = (struct sprof_sample *) mem_ptr;
while (towrite > 0) {
-
- n = write(outfile_fd, buf, towrite);
-
- if (n < 0)
- { printf("Error writing to outfile %s.\n", outfile); return 1; }
-
- towrite -= n;
- buf += n;
- written += n;
+ unsigned bytes;
+ char entry[12];
+ char * name;
+
+ name = get_proc_name(sample->proc);
+ if (!name) {
+ add_proc((struct sprof_proc *)sample);
+ bytes = sizeof(struct sprof_proc);
+ towrite -= bytes;
+ sample = (struct sprof_sample *)(((char *) sample) + bytes);
+ continue;
+ }
+
+ memset(entry, 0, 12);
+ memcpy(entry, name, strlen(name));
+ memcpy(entry + 8, &sample->pc, 4);
+
+ if (write(outfile_fd, entry, 12) != 12) {
+ printf("Error writing to outfile %s.\n", outfile);
+ return 1;
+ }
+ towrite -= sizeof(struct sprof_sample);
+ sample++;
+
+ written += 12;
}
printf(" header %d bytes, data %d bytes.\n", strlen(header), written);
commands/service/service
drivers/ahci/ahci
-drivers/acpi/acpi
drivers/amddev/amddev
drivers/at_wini/at_wini
drivers/atl2/atl2
#define _PROFILE_H
#include <ansi.h>
+#include <minix/type.h>
/*
* Types relating to system profiling. Types are supplied for both
} sprof_info_inst;
/* What a profiling sample looks like (used for sizeof()). */
-struct {
- char name[8];
- int pc;
-} sprof_sample;
+struct sprof_sample {
+ endpoint_t proc;
+ void * pc;
+};
+
+struct sprof_proc {
+ endpoint_t proc;
+ char name[8];
+}i;
#endif /* SPROFILE */
* regs are significant (initialized)*/
#define MF_SENDING_FROM_KERNEL 0x2000 /* message of this process is from kernel */
#define MF_CONTEXT_SET 0x4000 /* don't touch context */
+#define MF_SPROF_SEEN 0x8000 /* profiling has seen this process */
/* Magic process table addresses. */
#define BEG_PROC_ADDR (&proc[0])
rm_irq_handler(&profile_clock_hook);
}
+PRIVATE sprof_save_sample(struct proc * p)
+{
+ struct sprof_sample s;
+
+ s.proc = p->p_endpoint;
+ s.pc = (void *) p->p_reg.pc;
+
+ /* Store sample (process name and program counter). */
+ data_copy(KERNEL, (vir_bytes) &s,
+ sprof_ep, sprof_data_addr_vir + sprof_info.mem_used,
+ sizeof(s));
+
+ sprof_info.mem_used += sizeof(s);
+}
+
+PRIVATE sprof_save_proc(struct proc * p)
+{
+ struct sprof_proc s;
+
+ s.proc = p->p_endpoint;
+ memcpy(s.name, p->p_name, P_NAME_LEN);
+
+ /* Store sample (process name and program counter). */
+ data_copy(KERNEL, (vir_bytes) &s,
+ sprof_ep, sprof_data_addr_vir + sprof_info.mem_used,
+ sizeof(s));
+
+ sprof_info.mem_used += sizeof(s);
+}
+
/*===========================================================================*
* profile_clock_handler *
*===========================================================================*/
p = get_cpulocal_var(proc_ptr);
- /* All is OK */
+ if (!(p->p_misc_flags & MF_SPROF_SEEN)) {
+ p->p_misc_flags |= MF_SPROF_SEEN;
+ sprof_save_proc(p);
+ }
- /* Idle process? */
- if (priv(p)->s_proc_nr == IDLE) {
- sprof_info.idle_samples++;
- } else
/* Runnable system process? */
- if (priv(p)->s_flags & SYS_PROC && proc_is_runnable(p)) {
- /* Note: k_reenter is always 0 here. */
-
- /* Store sample (process name and program counter). */
- data_copy(KERNEL, (vir_bytes) p->p_name,
- sprof_ep, sprof_data_addr_vir + sprof_info.mem_used,
- strlen(p->p_name));
-
- data_copy(KERNEL, (vir_bytes) &p->p_reg.pc, sprof_ep,
- (vir_bytes) (sprof_data_addr_vir + sprof_info.mem_used +
- sizeof(p->p_name)),
- (vir_bytes) sizeof(p->p_reg.pc));
-
- sprof_info.mem_used += sizeof(sprof_sample);
-
- sprof_info.system_samples++;
+ if (p->p_endpoint == IDLE)
+ sprof_info.idle_samples++;
+ else if (priv(p)->s_flags & SYS_PROC && proc_is_runnable(p)) {
+ sprof_save_sample(p);
+ sprof_info.system_samples++;
} else {
/* User process. */
sprof_info.user_samples++;
/* user address to write info struct */
PRIVATE vir_bytes sprof_info_addr_vir;
+PRIVATE clean_seen_flag(void)
+{
+ int i;
+
+ for (i = 0; i < NR_TASKS + NR_PROCS; i++)
+ proc[i].p_misc_flags &= ~MF_SPROF_SEEN;
+}
+
/*===========================================================================*
* do_sprofile *
*===========================================================================*/
sprofiling = 1;
+ clean_seen_flag();
+
return OK;
case PROF_STOP:
data_copy(KERNEL, (vir_bytes) &sprof_info,
sprof_ep, sprof_info_addr_vir, sizeof(sprof_info));
+ clean_seen_flag();
+
return OK;
default: