diff --git a/commands/profile/profile.c b/commands/profile/profile.c index fe95fb352..a384b5769 100644 --- a/commands/profile/profile.c +++ b/commands/profile/profile.c @@ -48,6 +48,7 @@ int action = 0; int mem_size = 0; int mem_used = 0; int freq = 0; +int intr_type = PROF_RTC; char *outfile = ""; char *mem_ptr; int outfile_fd, npipe_fd; @@ -104,15 +105,27 @@ int main(int argc, char *argv[]) break; } + /* + * Check the frequency when we know the intr type. Only selected values + * are correct for RTC + */ + if (action == START && intr_type == PROF_RTC && + freq < MIN_FREQ || freq > MAX_FREQ) { + printf("Incorrect frequency.\n"); + return 1; + } + printf("Statistical Profiling:\n"); - printf(" profile start [-m memsize] [-o outfile] [-f frequency]\n"); + printf(" profile start [--rtc | --nmi] " + "[-m memsize] [-o outfile] [-f frequency]\n"); printf(" profile stop\n\n"); + printf(" --rtc is default, --nmi allows kernel profiling\n"); printf("Call Profiling:\n"); printf(" profile get [-m memsize] [-o outfile]\n"); printf(" profile reset\n\n"); printf(" - memsize in MB, default: %u\n", DEF_MEMSIZE); printf(" - default output file: profile.{stat|call}.out\n"); - printf( " - sample frequencies (default: %u):\n", DEF_FREQ); + printf( " - sample frequencies for --rtc (default: %u):\n", DEF_FREQ); printf(" 3 8192 Hz 10 64 Hz\n"); printf(" 4 4096 Hz 11 32 Hz\n"); printf(" 5 2048 Hz 12 16 Hz\n"); @@ -160,13 +173,19 @@ int handle_args(int argc, char *argv[]) } else if (strcmp(*argv, "-f") == 0) { if (--argc == 0) return ESYNTAX; - if (sscanf(*++argv, "%u", &freq) != 1 || - freq < MIN_FREQ || freq > MAX_FREQ) return EFREQ; + if (sscanf(*++argv, "%u", &freq) != 1) + return EFREQ; } else if (strcmp(*argv, "-o") == 0) { if (--argc == 0) return ESYNTAX; outfile = *++argv; } else + if (strcmp(*argv, "--rtc") == 0) { + intr_type = PROF_RTC; + } else + if (strcmp(*argv, "--nmi") == 0) { + intr_type = PROF_NMI; + } else if (strcmp(*argv, "start") == 0) { if (action) return EACTION; action = START; @@ -224,7 +243,7 @@ int start() if (alloc_mem()) return 1; - if (sprofile(PROF_START, mem_size, freq, &sprof_info, mem_ptr)) { + if (sprofile(PROF_START, mem_size, freq, intr_type, &sprof_info, mem_ptr)) { perror("sprofile"); printf("Error starting profiling.\n"); return 1; @@ -280,7 +299,7 @@ int stop() int n; char buf[BUFSIZE]; - if (sprofile(PROF_STOP, 0, 0, 0, 0)) { + if (sprofile(PROF_STOP, 0, 0, 0, 0, 0)) { perror("sprofile"); printf("Error stopping profiling.\n"); return 1; diff --git a/include/minix/com.h b/include/minix/com.h index 53e36ce6b..b452f136c 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -590,6 +590,7 @@ #define PROF_MEM_SIZE m7_i2 /* available memory for data */ #define PROF_FREQ m7_i3 /* sample frequency */ #define PROF_ENDPT m7_i4 /* endpoint of caller */ +#define PROF_INTR_TYPE m7_i5 /* interrupt type */ #define PROF_CTL_PTR m7_p1 /* location of info struct */ #define PROF_MEM_PTR m7_p2 /* location of profiling data */ diff --git a/include/minix/ipc.h b/include/minix/ipc.h index 5585e4ab0..c74425644 100644 --- a/include/minix/ipc.h +++ b/include/minix/ipc.h @@ -22,7 +22,7 @@ typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4; typedef struct {short m5s1, m5s2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5; typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2; char *m6p1, *m6p2;} mess_6; -typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7; +typedef struct {int m7i1, m7i2, m7i3, m7i4, m7i5; char *m7p1, *m7p2;} mess_7; typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8; typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5; short m9s1, m9s2, m9s3, m9s4; } mess_9; @@ -94,6 +94,7 @@ typedef struct { #define m7_i2 m_u.m_m7.m7i2 #define m7_i3 m_u.m_m7.m7i3 #define m7_i4 m_u.m_m7.m7i4 +#define m7_i5 m_u.m_m7.m7i5 #define m7_p1 m_u.m_m7.m7p1 #define m7_p2 m_u.m_m7.m7p2 diff --git a/include/minix/profile.h b/include/minix/profile.h index d78d1ec04..f2e373c95 100644 --- a/include/minix/profile.h +++ b/include/minix/profile.h @@ -14,6 +14,9 @@ # define PROF_START 0 /* start statistical profiling */ # define PROF_STOP 1 /* stop statistical profiling */ +#define PROF_RTC 0 /* RTC based profiling */ +#define PROF_NMI 1 /* NMI based profiling, profiles kernel too */ + /* Info struct to be copied to from kernel to user program. */ struct sprof_info_s { int mem_used; @@ -101,7 +104,7 @@ struct cprof_tbl_s { u64_t cycles; /* execution time of path, in cycles */ } cprof_tbl_inst; -_PROTOTYPE( int sprofile, (int action, int size, int freq, +_PROTOTYPE( int sprofile, (int action, int size, int freq, int type, void *ctl_ptr, void *mem_ptr) ); _PROTOTYPE( int cprofile, (int action, int size, void *ctl_ptr, diff --git a/include/minix/syslib.h b/include/minix/syslib.h index b1a3db189..12850f4c7 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -257,7 +257,7 @@ _PROTOTYPE( int pci_get_bar, (int devind, int port, u32_t *base, u32_t *size, int *ioflag) ); /* Profiling. */ -_PROTOTYPE( int sys_sprof, (int action, int size, int freq, +_PROTOTYPE( int sys_sprof, (int action, int size, int freq, int type, endpoint_t endpt, void *ctl_ptr, void *mem_ptr) ); _PROTOTYPE( int sys_cprof, (int action, int size, endpoint_t endpt, void *ctl_ptr, void *mem_ptr) ); diff --git a/lib/libc/other/_sprofile.c b/lib/libc/other/_sprofile.c index 2c1bd632e..8d119a547 100644 --- a/lib/libc/other/_sprofile.c +++ b/lib/libc/other/_sprofile.c @@ -2,13 +2,19 @@ #define sprofile _sprofile -PUBLIC int sprofile(int action, int size, int freq, char *ctl_ptr, int *mem_ptr) +PUBLIC int sprofile(int action, + int size, + int freq, + int type, + char *ctl_ptr, + int *mem_ptr) { message m; m.PROF_ACTION = action; m.PROF_MEM_SIZE = size; m.PROF_FREQ = freq; + m.PROF_INTR_TYPE = type; m.PROF_CTL_PTR = (void *) ctl_ptr; m.PROF_MEM_PTR = (void *) mem_ptr; diff --git a/lib/libsys/sys_sprof.c b/lib/libsys/sys_sprof.c index 6b72a7221..486cb0da0 100644 --- a/lib/libsys/sys_sprof.c +++ b/lib/libsys/sys_sprof.c @@ -5,10 +5,11 @@ /*===========================================================================* * sys_sprof * *===========================================================================*/ -PUBLIC int sys_sprof(action, size, freq, endpt, ctl_ptr, mem_ptr) +PUBLIC int sys_sprof(action, size, freq, type, endpt, ctl_ptr, mem_ptr) int action; /* start/stop profiling */ int size; /* available profiling memory */ int freq; /* sample frequency */ +int type; endpoint_t endpt; /* caller endpoint */ void *ctl_ptr; /* location of info struct */ void *mem_ptr; /* location of profiling memory */ @@ -18,6 +19,7 @@ void *mem_ptr; /* location of profiling memory */ m.PROF_ACTION = action; m.PROF_MEM_SIZE = size; m.PROF_FREQ = freq; + m.PROF_INTR_TYPE = type; m.PROF_ENDPT = endpt; m.PROF_CTL_PTR = ctl_ptr; m.PROF_MEM_PTR = mem_ptr; diff --git a/servers/pm/profile.c b/servers/pm/profile.c index c7a9b07ec..c7e2b06ea 100644 --- a/servers/pm/profile.c +++ b/servers/pm/profile.c @@ -38,10 +38,11 @@ PUBLIC int do_sprofile(void) return r; return sys_sprof(PROF_START, m_in.PROF_MEM_SIZE, m_in.PROF_FREQ, + m_in.PROF_INTR_TYPE, who_e, m_in.PROF_CTL_PTR, m_in.PROF_MEM_PTR); case PROF_STOP: - return sys_sprof(PROF_STOP,0,0,0,0,0); + return sys_sprof(PROF_STOP,0,0,0,0,0,0); default: return EINVAL;