]> Zhao Yanbai Git Server - minix.git/commitdiff
New profile protocol
authorTomas Hruby <tom@minix3.org>
Thu, 23 Sep 2010 10:49:39 +0000 (10:49 +0000)
committerTomas Hruby <tom@minix3.org>
Thu, 23 Sep 2010 10:49:39 +0000 (10:49 +0000)
- when kernel profiles a process for the first time it saves an entry
  describing the process [endpoint|name]

- every profile sample is only [endpoint|pc]

- profile utility creates a table of endpoint <-> name relations and
  translates endpoints of samples into names and writing out the
  results to comply with the processing tools

- "task" endpoints like KERNEL are negative thus we must cast it to
  unsigned when hashing

commands/profile/profile.c
commands/profile/sprofalyze.pl
include/minix/profile.h
kernel/proc.h
kernel/profile.c
kernel/system/do_sprofile.c

index a91538b5a76738701d4f6a43a21d9b627e6f8fcf..fe95fb352bb4d1b3fb393969983305cdf8cb73cb 100644 (file)
@@ -54,6 +54,15 @@ int outfile_fd, npipe_fd;
 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));
@@ -186,7 +195,7 @@ int handle_args(int argc, char *argv[])
        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;
@@ -398,12 +407,38 @@ int detach()
   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);
 
@@ -424,16 +459,33 @@ int write_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);
index f0dec85ee183d13d65b1b9041e087b1b1a9783ee..a8861a77c103e245aaba87713b2fa988db4aaf55 100755 (executable)
@@ -42,7 +42,6 @@ servers/sched/sched
 commands/service/service
 
 drivers/ahci/ahci
-drivers/acpi/acpi
 drivers/amddev/amddev
 drivers/at_wini/at_wini
 drivers/atl2/atl2
index afeeec29867b34101667b4653a4a20ed2fa91b99..d78d1ec04d4f453e6a140da7a9333bbf441c702d 100644 (file)
@@ -2,6 +2,7 @@
 #define _PROFILE_H
 
 #include <ansi.h>
+#include <minix/type.h>
 
 /*
  * Types relating to system profiling.  Types are supplied for both
@@ -23,10 +24,15 @@ struct sprof_info_s {
 } 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 */
 
index d934674b81277e06386f6ca72b5f861333b35c4e..3055a0821dab375b71353a6892e400d4c188769b 100644 (file)
@@ -241,6 +241,7 @@ struct proc {
                                         * 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])
index 070ed49a2f05e508aae9987ee1e3f5337b4e7a22..c1c3c653a7843d1ef7d3e0e5db1ad02adc6e12ab 100644 (file)
@@ -60,6 +60,36 @@ PUBLIC void stop_profile_clock()
   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                           *
  *===========================================================================*/
@@ -79,29 +109,17 @@ PRIVATE int profile_clock_handler(irq_hook_t *hook)
 
   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++;
index 629ee1dff910c138efe54b0965cf05ece62dc319..92a8b15180b777d1e02e238dfb5516dedd3c1f5a 100644 (file)
 /* 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                                  *
  *===========================================================================*/
@@ -62,6 +70,8 @@ PUBLIC int do_sprofile(struct proc * caller, message * m_ptr)
        
        sprofiling = 1;
 
+       clean_seen_flag();
+
        return OK;
 
   case PROF_STOP:
@@ -82,6 +92,8 @@ PUBLIC int do_sprofile(struct proc * caller, message * m_ptr)
        data_copy(KERNEL, (vir_bytes) &sprof_info,
                sprof_ep, sprof_info_addr_vir, sizeof(sprof_info));
 
+       clean_seen_flag();
+
        return OK;
 
   default: