return (0);
}
-static int
-lwt_control(int enable, int clear)
-{
- struct libcfs_ioctl_data data;
- int rc;
-
- LIBCFS_IOC_INIT(data);
- data.ioc_flags = (enable ? 1 : 0) | (clear ? 2 : 0);
-
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LWT_CONTROL, &data);
- if (rc == 0)
- return (0);
-
- fprintf(stderr, "IOC_LIBCFS_LWT_CONTROL failed: %s\n",
- strerror(errno));
- return (-1);
-}
-
-static int
-lwt_snapshot(cfs_cycles_t *now, int *ncpu, int *totalsize,
- lwt_event_t *events, int size)
-{
- struct libcfs_ioctl_data data;
- int rc;
-
- LIBCFS_IOC_INIT(data);
- data.ioc_pbuf1 = (char *)events;
- data.ioc_plen1 = size;
-
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LWT_SNAPSHOT, &data);
- if (rc != 0) {
- fprintf(stderr, "IOC_LIBCFS_LWT_SNAPSHOT failed: %s\n",
- strerror(errno));
- return (-1);
- }
-
- /* crappy overloads */
- if (data.ioc_u32[2] != sizeof(lwt_event_t) ||
- data.ioc_u32[3] != offsetof(lwt_event_t, lwte_where)) {
- fprintf(stderr,"kernel/user LWT event mismatch %d(%d),%d(%d)\n",
- (int)data.ioc_u32[2], (int)sizeof(lwt_event_t),
- (int)data.ioc_u32[3],
- (int)offsetof(lwt_event_t, lwte_where));
- return (-1);
- }
-
- if (now != NULL)
- *now = data.ioc_u64[0];
-
- LASSERT (data.ioc_u32[0] != 0);
- if (ncpu != NULL)
- *ncpu = data.ioc_u32[0];
-
- LASSERT (data.ioc_u32[1] != 0);
- if (totalsize != NULL)
- *totalsize = data.ioc_u32[1];
-
- return (0);
-}
-
-static char *
-lwt_get_string(char *kstr)
-{
- char *ustr;
- struct libcfs_ioctl_data data;
- int size;
- int rc;
-
- /* FIXME: this could maintain a symbol table since we expect to be
- * looking up the same strings all the time... */
-
- LIBCFS_IOC_INIT(data);
- data.ioc_pbuf1 = kstr;
- data.ioc_plen1 = 1; /* non-zero just to fool portal_ioctl_is_invalid() */
- data.ioc_pbuf2 = NULL;
- data.ioc_plen2 = 0;
-
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LWT_LOOKUP_STRING, &data);
- if (rc != 0) {
- fprintf(stderr, "IOC_LIBCFS_LWT_LOOKUP_STRING failed: %s\n",
- strerror(errno));
- return (NULL);
- }
-
- size = data.ioc_count;
- ustr = (char *)malloc(size);
- if (ustr == NULL) {
- fprintf(stderr, "Can't allocate string storage of size %d\n",
- size);
- return (NULL);
- }
-
- LIBCFS_IOC_INIT(data);
- data.ioc_pbuf1 = kstr;
- data.ioc_plen1 = 1; /* non-zero just to fool portal_ioctl_is_invalid() */
- data.ioc_pbuf2 = ustr;
- data.ioc_plen2 = size;
-
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LWT_LOOKUP_STRING, &data);
- if (rc != 0) {
- fprintf(stderr, "IOC_LIBCFS_LWT_LOOKUP_STRING failed: %s\n",
- strerror(errno));
- return (NULL);
- }
-
- LASSERT(strlen(ustr) == size - 1);
- return (ustr);
-}
-
-static void
-lwt_put_string(char *ustr)
-{
- free(ustr);
-}
-
-static int
-lwt_print(FILE *f, cfs_cycles_t t0, cfs_cycles_t tlast, double mhz, int cpu,
- lwt_event_t *e)
-{
-#ifndef __WORDSIZE
-# error "__WORDSIZE not defined"
-#elif __WORDSIZE == 32
-# define XFMT "%#010lx"
-#elif __WORDSIZE== 64
-# define XFMT "%#018lx"
-#else
-# error "Unexpected __WORDSIZE"
-#endif
- char *where = lwt_get_string(e->lwte_where);
-
- if (where == NULL)
- return (-1);
-
- fprintf(f, XFMT" "XFMT" "XFMT" "XFMT": "XFMT" %2d %10.6f %10.2f %s\n",
- e->lwte_p1, e->lwte_p2, e->lwte_p3, e->lwte_p4,
- (long)e->lwte_task, cpu, (e->lwte_when - t0) / (mhz * 1000000.0),
- (t0 == e->lwte_when) ? 0.0 : (e->lwte_when - tlast) / mhz,
- where);
-
- lwt_put_string(where);
-
- return (0);
-#undef XFMT
-}
-
double
get_cycles_per_usec ()
{
return (1000.0);
}
-#define LWT_MAX_CPUS (32)
-
-int
-jt_ptl_lwt(int argc, char **argv)
-{
- int ncpus;
- int totalspace;
- int nevents_per_cpu;
- lwt_event_t *events;
- lwt_event_t *cpu_event[LWT_MAX_CPUS + 1];
- lwt_event_t *next_event[LWT_MAX_CPUS];
- lwt_event_t *first_event[LWT_MAX_CPUS];
- int cpu;
- lwt_event_t *e;
- int rc;
- int i;
- double mhz;
- cfs_cycles_t t0;
- cfs_cycles_t tlast;
- cfs_cycles_t tnow;
- struct timeval tvnow;
- int printed_date = 0;
- int nlines = 0;
- FILE *f = stdout;
-
- if (argc < 2 ||
- (strcmp(argv[1], "start") &&
- strcmp(argv[1], "stop"))) {
- fprintf(stderr,
- "usage: %s start\n"
- " %s stop [fname]\n", argv[0], argv[0]);
- return (-1);
- }
-
- if (!strcmp(argv[1], "start")) {
- /* disable */
- if (lwt_control(0, 0) != 0)
- return (-1);
-
- /* clear */
- if (lwt_control(0, 1) != 0)
- return (-1);
-
- /* enable */
- if (lwt_control(1, 0) != 0)
- return (-1);
-
- return (0);
- }
-
- if (lwt_snapshot(NULL, &ncpus, &totalspace, NULL, 0) != 0)
- return (-1);
-
- if (ncpus > LWT_MAX_CPUS) {
- fprintf(stderr, "Too many cpus: %d (%d)\n",
- ncpus, LWT_MAX_CPUS);
- return (-1);
- }
-
- events = (lwt_event_t *)malloc(totalspace);
- if (events == NULL) {
- fprintf(stderr, "Can't allocate %d\n", totalspace);
- return (-1);
- }
-
- if (lwt_control(0, 0) != 0) { /* disable */
- free(events);
- return (-1);
- }
-
- if (lwt_snapshot(&tnow, NULL, NULL, events, totalspace)) {
- free(events);
- return (-1);
- }
-
- /* we want this time to be sampled at snapshot time */
- gettimeofday(&tvnow, NULL);
-
- if (argc > 2) {
- f = fopen (argv[2], "w");
- if (f == NULL) {
- fprintf(stderr, "Can't open %s for writing: %s\n", argv[2], strerror (errno));
- free(events);
- return (-1);
- }
- }
-
- mhz = get_cycles_per_usec();
-
- /* carve events into per-cpu slices */
- nevents_per_cpu = totalspace / (ncpus * sizeof(lwt_event_t));
- for (cpu = 0; cpu <= ncpus; cpu++)
- cpu_event[cpu] = &events[cpu * nevents_per_cpu];
-
- /* find the earliest event on each cpu */
- for (cpu = 0; cpu < ncpus; cpu++) {
- first_event[cpu] = NULL;
-
- for (e = cpu_event[cpu]; e < cpu_event[cpu + 1]; e++) {
-
- if (e->lwte_where == NULL) /* not an event */
- continue;
-
- if (first_event[cpu] == NULL ||
- first_event[cpu]->lwte_when > e->lwte_when)
- first_event[cpu] = e;
- }
-
- next_event[cpu] = first_event[cpu];
- }
-
- t0 = tlast = 0;
- for (cpu = 0; cpu < ncpus; cpu++) {
- e = first_event[cpu];
- if (e == NULL) /* no events this cpu */
- continue;
-
- if (e == cpu_event[cpu])
- e = cpu_event[cpu + 1] - 1;
- else
- e = e - 1;
-
- /* If there's an event immediately before the first one, this
- * cpu wrapped its event buffer */
- if (e->lwte_where == NULL)
- continue;
-
- /* We should only start outputting events from the most recent
- * first event in any wrapped cpu. Events before this time on
- * other cpus won't have any events from this CPU to interleave
- * with. */
- if (t0 < first_event[cpu]->lwte_when)
- t0 = first_event[cpu]->lwte_when;
- }
-
- for (;;) {
- /* find which cpu has the next event */
- cpu = -1;
- for (i = 0; i < ncpus; i++) {
-
- if (next_event[i] == NULL) /* this cpu exhausted */
- continue;
-
- if (cpu < 0 ||
- next_event[i]->lwte_when < next_event[cpu]->lwte_when)
- cpu = i;
- }
-
- if (cpu < 0) /* all cpus exhausted */
- break;
-
- if (t0 == 0) {
- /* no wrapped cpus and this is he first ever event */
- t0 = next_event[cpu]->lwte_when;
- }
-
- if (t0 <= next_event[cpu]->lwte_when) {
- /* on or after the first event */
- if (!printed_date) {
- cfs_cycles_t du = (tnow - t0) / mhz;
- time_t then = tvnow.tv_sec - du/1000000;
-
- if (du % 1000000 > tvnow.tv_usec)
- then--;
-
- fprintf(f, "%s", ctime(&then));
- printed_date = 1;
- }
-
- rc = lwt_print(f, t0, tlast, mhz, cpu, next_event[cpu]);
- if (rc != 0)
- break;
-
- if (++nlines % 10000 == 0 && f != stdout) {
- /* show some activity... */
- printf(".");
- fflush (stdout);
- }
- }
-
- tlast = next_event[cpu]->lwte_when;
-
- next_event[cpu]++;
- if (next_event[cpu] == cpu_event[cpu + 1])
- next_event[cpu] = cpu_event[cpu];
-
- if (next_event[cpu]->lwte_where == NULL ||
- next_event[cpu] == first_event[cpu])
- next_event[cpu] = NULL;
- }
-
- if (f != stdout) {
- printf("\n");
- fclose(f);
- }
-
- free(events);
- return (0);
-}
-
int jt_ptl_memhog(int argc, char **argv)
{
static int gfp = 0; /* sticky! */