1
0
Files
irix-657m-src/eoe/cmd/profiler/prfsnap.c
2022-09-29 17:59:04 +03:00

140 lines
3.8 KiB
C

/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* #ident "@(#)profil-3b5:prfsnap.c 1.3" */
#ident "$Revision: 1.10 $"
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/sysmp.h>
#include <sys/time.h>
#include <sys/prf.h>
#include "prf.h"
/*
* prfsnap - dump profile data to a log file
*
* Format of file:
* prfmax - # of addresses (4 bytes)
* address table - (prfmax * sizeof(symaddr_t) bytes)
*
* 'n' peg counter reports:
* time - (4 bytes)
* cpuid - (4 bytes)
* peg counters - prfmax * sizeof(int)
* cpuid - (4bytes)
* peg counters - prfmax * sizeof(int)
* ...
*/
static char *buf;
static int prfmax;
static void fatal(const char *, ...);
int
main(int argc, char *const*argv)
{
int prffd, logfd;
time_t tvec;
int nprocs;
size_t bufsize;
ssize_t nread;
unsigned int prfstatus;
if (argc != 2)
fatal("usage: prfsnap logfile");
if ((prffd = open("/dev/prf", O_RDWR)) < 0)
fatal("cannot open /dev/prf: %s", strerror(errno));
if ((logfd = open(argv[1], O_RDWR|O_CREAT, 0666)) < 0)
fatal("cannot creat log file: %s", strerror(errno));
prfstatus = ioctl(prffd, PRF_GETSTATUS);
if ((int)prfstatus < 0)
fatal("cannot get /dev/prf status: %s", strerror(errno));
if ((prfstatus & PRF_PROFTYPE_MASK) == PRF_PROFTYPE_NONE) {
puts("enabling profiling: range = pc, domain = time");
if (ioctl(prffd, PRF_SETPROFTYPE, PRF_RANGE_PC|PRF_DOMAIN_TIME))
fatal("cannot activate profiling: %s", strerror(errno));
} else if ((prfstatus & PRF_RANGE_MASK) != PRF_RANGE_PC)
fatal("currently enabled profiling is not pc profiling:"
" range code = %#x", prfstatus & PRF_RANGE_MASK);
/* find out how many procesors */
if ((nprocs = (int)sysmp(MP_NPROCS)) < 0)
nprocs = 1;
/* find out how many symbols were loaded */
prfmax = ioctl(prffd, PRF_GETNSYMS);
/* need room for prfmax symbols + nprocs ids +
* nprocs * prfmax counters
*/
bufsize = prfmax * sizeof(symaddr_t)
+ (nprocs + (nprocs * prfmax)) * sizeof(int);
if ((buf = (char *)malloc(bufsize)) == NULL)
fatal("cannot allocate space for addresses: %s", strerror(errno));
time(&tvec);
nread = read(prffd, buf, bufsize);
if (nread != bufsize)
if (nread < 0)
fatal("read of address/counters failed: %s", strerror(errno));
else
fatal("read of address/counters returned short"
" -- requested %u, got %d", bufsize, nread);
if (lseek(logfd, 0, SEEK_END) == 0) {
/* new file - write out prfmax, nprocs and addresses */
write(logfd, &prfmax, sizeof prfmax);
write(logfd, &nprocs, sizeof nprocs);
write(logfd, buf, prfmax * sizeof (symaddr_t));
} else {
/* make sure that log makes sense - prfmax must match */
int tmax;
lseek(logfd, 0, SEEK_SET);
nread = read(logfd, &tmax, sizeof tmax);
if (nread != sizeof tmax)
if (nread < 0)
fatal("error reading log file %s: %s", argv[1],
strerror(errno));
else
fatal("read of log file %s returned short: asked for %u"
" bytes but got %d", sizeof tmax, nread);
if (tmax != prfmax)
fatal("log file exists and has %d symbols while current kernel"
" has %d", tmax, prfmax);
lseek(logfd, 0, SEEK_END);
}
write(logfd, &tvec, sizeof tvec);
write(logfd, &buf[prfmax * sizeof(symaddr_t)],
(nprocs + nprocs * prfmax) * sizeof(int));
exit(EXIT_SUCCESS);
/*NOTREACHED*/
}
static void
fatal(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fputs("prfsnap: ", stderr);
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
va_end(ap);
exit(EXIT_FAILURE);
/*NOTREACHED*/
}