kgmon.c revision 134505
1246149Ssjg/* 2246149Ssjg * Copyright (c) 1983, 1992, 1993 3246149Ssjg * The Regents of the University of California. All rights reserved. 4246149Ssjg * 5246149Ssjg * Redistribution and use in source and binary forms, with or without 6246149Ssjg * modification, are permitted provided that the following conditions 7246149Ssjg * are met: 8246149Ssjg * 1. Redistributions of source code must retain the above copyright 9246149Ssjg * notice, this list of conditions and the following disclaimer. 10246149Ssjg * 2. Redistributions in binary form must reproduce the above copyright 11246149Ssjg * notice, this list of conditions and the following disclaimer in the 12246149Ssjg * documentation and/or other materials provided with the distribution. 13246149Ssjg * 4. Neither the name of the University nor the names of its contributors 14246149Ssjg * may be used to endorse or promote products derived from this software 15246149Ssjg * without specific prior written permission. 16246149Ssjg * 17246149Ssjg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18246149Ssjg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19246149Ssjg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20246149Ssjg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21246149Ssjg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22246149Ssjg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23246149Ssjg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24246149Ssjg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25246149Ssjg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26246149Ssjg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27246149Ssjg * SUCH DAMAGE. 28246149Ssjg */ 29246149Ssjg 30246149Ssjg#ifndef lint 31246149Ssjgstatic const char copyright[] = 32246149Ssjg"@(#) Copyright (c) 1983, 1992, 1993\n\ 33246149Ssjg The Regents of the University of California. All rights reserved.\n"; 34246149Ssjg#endif /* not lint */ 35246149Ssjg 36246149Ssjg#ifndef lint 37246149Ssjg#if 0 38253883Ssjgstatic char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93"; 39246149Ssjg#endif 40249033Ssjgstatic const char rcsid[] = 41249033Ssjg "$FreeBSD: head/usr.sbin/kgmon/kgmon.c 134505 2004-08-30 03:11:46Z marcel $"; 42246149Ssjg#endif /* not lint */ 43246149Ssjg 44246149Ssjg#include <sys/param.h> 45246149Ssjg#include <sys/file.h> 46246149Ssjg#include <sys/time.h> 47246149Ssjg#include <sys/sysctl.h> 48246149Ssjg#include <sys/gmon.h> 49246149Ssjg#include <ctype.h> 50246149Ssjg#include <err.h> 51246149Ssjg#include <errno.h> 52246149Ssjg#include <kvm.h> 53246149Ssjg#include <limits.h> 54246149Ssjg#include <nlist.h> 55246149Ssjg#include <paths.h> 56246149Ssjg#include <stddef.h> 57246149Ssjg#include <stdio.h> 58246149Ssjg#include <stdlib.h> 59246149Ssjg#include <string.h> 60246149Ssjg#include <unistd.h> 61246149Ssjg 62246149Ssjgstruct nlist nl[] = { 63246149Ssjg#define N_GMONPARAM 0 64246149Ssjg { "__gmonparam" }, 65246149Ssjg#define N_PROFHZ 1 66246149Ssjg { "_profhz" }, 67246149Ssjg { NULL }, 68246149Ssjg}; 69246149Ssjg 70246149Ssjgstruct kvmvars { 71246149Ssjg kvm_t *kd; 72246149Ssjg struct gmonparam gpm; 73246149Ssjg}; 74246149Ssjg 75246149Ssjgint Bflag, bflag, hflag, kflag, rflag, pflag; 76246149Ssjgint debug = 0; 77246149Ssjgint getprof(struct kvmvars *); 78246149Ssjgint getprofhz(struct kvmvars *); 79246149Ssjgvoid kern_readonly(int); 80253883Ssjgint openfiles(char *, char *, struct kvmvars *); 81246149Ssjgvoid setprof(struct kvmvars *kvp, int state); 82246149Ssjgvoid dumpstate(struct kvmvars *kvp); 83246149Ssjgvoid reset(struct kvmvars *kvp); 84246149Ssjgstatic void usage(void); 85246149Ssjg 86246149Ssjgint 87246149Ssjgmain(int argc, char **argv) 88246149Ssjg{ 89246149Ssjg int ch, mode, disp, accessmode; 90246149Ssjg struct kvmvars kvmvars; 91246149Ssjg char *system, *kmemf; 92246149Ssjg 93246149Ssjg seteuid(getuid()); 94246149Ssjg kmemf = NULL; 95246149Ssjg system = NULL; 96246149Ssjg while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != -1) { 97246149Ssjg switch((char)ch) { 98246149Ssjg 99246149Ssjg case 'M': 100246149Ssjg kmemf = optarg; 101246149Ssjg kflag = 1; 102246149Ssjg break; 103246149Ssjg 104246149Ssjg case 'N': 105246149Ssjg system = optarg; 106246149Ssjg break; 107246149Ssjg 108246149Ssjg case 'B': 109246149Ssjg Bflag = 1; 110253883Ssjg break; 111253883Ssjg 112253883Ssjg case 'b': 113253883Ssjg bflag = 1; 114253883Ssjg break; 115253883Ssjg 116246149Ssjg case 'h': 117246149Ssjg hflag = 1; 118246149Ssjg break; 119246149Ssjg 120246149Ssjg case 'p': 121246149Ssjg pflag = 1; 122246149Ssjg break; 123246149Ssjg 124246149Ssjg case 'r': 125246149Ssjg rflag = 1; 126246149Ssjg break; 127246149Ssjg 128246149Ssjg default: 129250837Ssjg usage(); 130250837Ssjg } 131250837Ssjg } 132250837Ssjg argc -= optind; 133250837Ssjg argv += optind; 134250837Ssjg 135246149Ssjg#define BACKWARD_COMPATIBILITY 136246149Ssjg#ifdef BACKWARD_COMPATIBILITY 137246149Ssjg if (*argv) { 138246149Ssjg system = *argv; 139246149Ssjg if (*++argv) { 140246149Ssjg kmemf = *argv; 141246149Ssjg ++kflag; 142246149Ssjg } 143246149Ssjg } 144246149Ssjg#endif 145246149Ssjg if (system == NULL) 146246149Ssjg system = (char *)getbootfile(); 147246149Ssjg accessmode = openfiles(system, kmemf, &kvmvars); 148246149Ssjg mode = getprof(&kvmvars); 149246149Ssjg if (hflag) 150246149Ssjg disp = GMON_PROF_OFF; 151246149Ssjg else if (Bflag) 152246149Ssjg disp = GMON_PROF_HIRES; 153246149Ssjg else if (bflag) 154246149Ssjg disp = GMON_PROF_ON; 155246149Ssjg else 156246149Ssjg disp = mode; 157246149Ssjg if (pflag) 158246149Ssjg dumpstate(&kvmvars); 159246149Ssjg if (rflag) 160246149Ssjg reset(&kvmvars); 161249033Ssjg if (accessmode == O_RDWR) 162246149Ssjg setprof(&kvmvars, disp); 163250837Ssjg (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n", 164250837Ssjg disp == GMON_PROF_OFF ? "off" : 165250837Ssjg disp == GMON_PROF_HIRES ? "running (high resolution)" : 166246149Ssjg disp == GMON_PROF_ON ? "running" : 167246149Ssjg disp == GMON_PROF_BUSY ? "busy" : 168246149Ssjg disp == GMON_PROF_ERROR ? "off (error)" : 169246149Ssjg "in an unknown state"); 170246149Ssjg return (0); 171246149Ssjg} 172246149Ssjg 173246149Ssjgstatic void 174246149Ssjgusage() 175246149Ssjg{ 176246149Ssjg fprintf(stderr, "usage: kgmon [-Bbhrp] [-M core] [-N system]\n"); 177246149Ssjg exit(1); 178246149Ssjg} 179246149Ssjg 180246149Ssjg/* 181246149Ssjg * Check that profiling is enabled and open any ncessary files. 182246149Ssjg */ 183246149Ssjgint 184246149Ssjgopenfiles(system, kmemf, kvp) 185246149Ssjg char *system; 186246149Ssjg char *kmemf; 187246149Ssjg struct kvmvars *kvp; 188246149Ssjg{ 189246149Ssjg size_t size; 190249033Ssjg int mib[3], state, openmode; 191250837Ssjg char errbuf[_POSIX2_LINE_MAX]; 192250837Ssjg 193249033Ssjg if (!kflag) { 194249033Ssjg mib[0] = CTL_KERN; 195249033Ssjg mib[1] = KERN_PROF; 196253883Ssjg mib[2] = GPROF_STATE; 197249033Ssjg size = sizeof state; 198246149Ssjg if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) 199246149Ssjg errx(20, "profiling not defined in kernel"); 200246149Ssjg if (!(Bflag || bflag || hflag || rflag || 201246149Ssjg (pflag && 202246149Ssjg (state == GMON_PROF_HIRES || state == GMON_PROF_ON)))) 203246149Ssjg return (O_RDONLY); 204246149Ssjg (void)seteuid(0); 205246149Ssjg if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0) 206246149Ssjg return (O_RDWR); 207246149Ssjg (void)seteuid(getuid()); 208246149Ssjg kern_readonly(state); 209246149Ssjg return (O_RDONLY); 210246149Ssjg } 211246149Ssjg openmode = (Bflag || bflag || hflag || pflag || rflag) 212246149Ssjg ? O_RDWR : O_RDONLY; 213250837Ssjg kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf); 214249033Ssjg if (kvp->kd == NULL) { 215250837Ssjg if (openmode == O_RDWR) { 216250837Ssjg openmode = O_RDONLY; 217250837Ssjg kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY, 218249033Ssjg errbuf); 219246149Ssjg } 220249033Ssjg if (kvp->kd == NULL) 221249033Ssjg errx(2, "kvm_openfiles: %s", errbuf); 222249033Ssjg kern_readonly(GMON_PROF_ON); 223249033Ssjg } 224249033Ssjg if (kvm_nlist(kvp->kd, nl) < 0) 225249033Ssjg errx(3, "%s: no namelist", system); 226246149Ssjg if (!nl[N_GMONPARAM].n_value) 227246149Ssjg errx(20, "profiling not defined in kernel"); 228246149Ssjg return (openmode); 229246149Ssjg} 230246149Ssjg 231246149Ssjg/* 232246149Ssjg * Suppress options that require a writable kernel. 233246149Ssjg */ 234249033Ssjgvoid 235249033Ssjgkern_readonly(mode) 236249033Ssjg int mode; 237249033Ssjg{ 238246149Ssjg 239246149Ssjg (void)fprintf(stderr, "kgmon: kernel read-only: "); 240246149Ssjg if (pflag && (mode == GMON_PROF_HIRES || mode == GMON_PROF_ON)) 241246149Ssjg (void)fprintf(stderr, "data may be inconsistent\n"); 242246149Ssjg if (rflag) 243246149Ssjg (void)fprintf(stderr, "-r supressed\n"); 244246149Ssjg if (Bflag) 245246149Ssjg (void)fprintf(stderr, "-B supressed\n"); 246246149Ssjg if (bflag) 247246149Ssjg (void)fprintf(stderr, "-b supressed\n"); 248246149Ssjg if (hflag) 249246149Ssjg (void)fprintf(stderr, "-h supressed\n"); 250246149Ssjg rflag = Bflag = bflag = hflag = 0; 251246149Ssjg} 252246149Ssjg 253246149Ssjg/* 254246149Ssjg * Get the state of kernel profiling. 255246149Ssjg */ 256246149Ssjgint 257249033Ssjggetprof(kvp) 258249033Ssjg struct kvmvars *kvp; 259246149Ssjg{ 260253883Ssjg size_t size; 261246149Ssjg int mib[3]; 262246149Ssjg 263246149Ssjg if (kflag) { 264246149Ssjg size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm, 265246149Ssjg sizeof kvp->gpm); 266246149Ssjg } else { 267246149Ssjg mib[0] = CTL_KERN; 268246149Ssjg mib[1] = KERN_PROF; 269246149Ssjg mib[2] = GPROF_GMONPARAM; 270246149Ssjg size = sizeof kvp->gpm; 271246149Ssjg if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0) 272246149Ssjg size = 0; 273246149Ssjg } 274246149Ssjg 275246149Ssjg /* 276246149Ssjg * Accept certain undersized "structs" from old kernels. We need 277246149Ssjg * everything up to hashfraction, and want profrate and 278246149Ssjg * histcounter_type. Assume that the kernel doesn't put garbage 279246149Ssjg * in any padding that is returned instead of profrate and 280246149Ssjg * histcounter_type. This is a bad assumption for dead kernels, 281246149Ssjg * since kvm_read() will normally return garbage for bytes beyond 282246149Ssjg * the end of the actual kernel struct, if any. 283246149Ssjg */ 284246149Ssjg if (size < offsetof(struct gmonparam, hashfraction) + 285246149Ssjg sizeof(kvp->gpm.hashfraction) || size > sizeof(kvp->gpm)) 286246149Ssjg errx(4, "cannot get gmonparam: %s", 287246149Ssjg kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 288246149Ssjg bzero((char *)&kvp->gpm + size, sizeof(kvp->gpm) - size); 289246149Ssjg if (kvp->gpm.profrate == 0) 290246149Ssjg kvp->gpm.profrate = getprofhz(kvp); 291246149Ssjg#ifdef __i386__ 292246149Ssjg if (kvp->gpm.histcounter_type == 0) { 293246149Ssjg /* 294246149Ssjg * This fixup only works for not-so-old i386 kernels. The 295246149Ssjg * magic 16 is the kernel FUNCTION_ALIGNMENT. 64-bit 296246149Ssjg * counters are signed; smaller counters are unsigned. 297246149Ssjg */ 298246149Ssjg kvp->gpm.histcounter_type = 16 / 299246149Ssjg (kvp->gpm.textsize / kvp->gpm.kcountsize) * CHAR_BIT; 300246149Ssjg if (kvp->gpm.histcounter_type == 64) 301246149Ssjg kvp->gpm.histcounter_type = -64; 302246149Ssjg } 303246149Ssjg#endif 304246149Ssjg 305246149Ssjg return (kvp->gpm.state); 306246149Ssjg} 307246149Ssjg 308246149Ssjg/* 309246149Ssjg * Enable or disable kernel profiling according to the state variable. 310246149Ssjg */ 311246149Ssjgvoid 312246149Ssjgsetprof(kvp, state) 313246149Ssjg struct kvmvars *kvp; 314246149Ssjg int state; 315250837Ssjg{ 316250837Ssjg struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value; 317246149Ssjg size_t sz; 318246149Ssjg int mib[3], oldstate; 319246149Ssjg 320246149Ssjg sz = sizeof(state); 321246149Ssjg if (!kflag) { 322246149Ssjg mib[0] = CTL_KERN; 323246149Ssjg mib[1] = KERN_PROF; 324246149Ssjg mib[2] = GPROF_STATE; 325246149Ssjg if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0) 326246149Ssjg goto bad; 327246149Ssjg if (oldstate == state) 328246149Ssjg return; 329246149Ssjg (void)seteuid(0); 330246149Ssjg if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) { 331246149Ssjg (void)seteuid(getuid()); 332246149Ssjg return; 333246149Ssjg } 334246149Ssjg (void)seteuid(getuid()); 335246149Ssjg } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) 336246149Ssjg == sz) 337246149Ssjg return; 338246149Ssjgbad: 339253883Ssjg warnx("warning: cannot turn profiling %s", 340253883Ssjg state == GMON_PROF_OFF ? "off" : "on"); 341253883Ssjg} 342253883Ssjg 343253883Ssjg/* 344253883Ssjg * Build the gmon.out file. 345253883Ssjg */ 346253883Ssjgvoid 347253883Ssjgdumpstate(kvp) 348246149Ssjg struct kvmvars *kvp; 349246149Ssjg{ 350246149Ssjg register FILE *fp; 351246149Ssjg struct rawarc rawarc; 352246149Ssjg struct tostruct *tos; 353246149Ssjg u_long frompc; 354246149Ssjg u_short *froms, *tickbuf; 355246149Ssjg size_t i; 356246149Ssjg int mib[3]; 357246149Ssjg struct gmonhdr h; 358246149Ssjg int fromindex, endfrom, toindex; 359246149Ssjg 360246149Ssjg setprof(kvp, GMON_PROF_OFF); 361246149Ssjg fp = fopen("gmon.out", "w"); 362246149Ssjg if (fp == 0) { 363246149Ssjg warn("gmon.out"); 364246149Ssjg return; 365246149Ssjg } 366246149Ssjg 367246149Ssjg /* 368246149Ssjg * Build the gmon header and write it to a file. 369246149Ssjg */ 370246149Ssjg bzero(&h, sizeof(h)); 371246149Ssjg h.lpc = kvp->gpm.lowpc; 372246149Ssjg h.hpc = kvp->gpm.highpc; 373246149Ssjg h.ncnt = kvp->gpm.kcountsize + sizeof(h); 374246149Ssjg h.version = GMONVERSION; 375246149Ssjg h.profrate = kvp->gpm.profrate; 376246149Ssjg h.histcounter_type = kvp->gpm.histcounter_type; 377246149Ssjg fwrite((char *)&h, sizeof(h), 1, fp); 378246149Ssjg 379246149Ssjg /* 380246149Ssjg * Write out the tick buffer. 381246149Ssjg */ 382246149Ssjg mib[0] = CTL_KERN; 383246149Ssjg mib[1] = KERN_PROF; 384246149Ssjg if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) 385246149Ssjg errx(5, "cannot allocate kcount space"); 386246149Ssjg if (kflag) { 387246149Ssjg i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf, 388253883Ssjg kvp->gpm.kcountsize); 389246149Ssjg } else { 390246149Ssjg mib[2] = GPROF_COUNT; 391246149Ssjg i = kvp->gpm.kcountsize; 392246149Ssjg if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0) 393246149Ssjg i = 0; 394253883Ssjg } 395246149Ssjg if (i != kvp->gpm.kcountsize) 396246149Ssjg errx(6, "read ticks: read %lu, got %ld: %s", 397246149Ssjg kvp->gpm.kcountsize, (long)i, 398246149Ssjg kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 399246149Ssjg if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) 400246149Ssjg err(7, "writing tocks to gmon.out"); 401246149Ssjg free(tickbuf); 402246149Ssjg 403246149Ssjg /* 404246149Ssjg * Write out the arc info. 405246149Ssjg */ 406246149Ssjg if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) 407246149Ssjg errx(8, "cannot allocate froms space"); 408246149Ssjg if (kflag) { 409246149Ssjg i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms, 410246149Ssjg kvp->gpm.fromssize); 411246149Ssjg } else { 412246149Ssjg mib[2] = GPROF_FROMS; 413246149Ssjg i = kvp->gpm.fromssize; 414246149Ssjg if (sysctl(mib, 3, froms, &i, NULL, 0) < 0) 415246149Ssjg i = 0; 416246149Ssjg } 417246149Ssjg if (i != kvp->gpm.fromssize) 418246149Ssjg errx(9, "read froms: read %lu, got %ld: %s", 419246149Ssjg kvp->gpm.fromssize, (long)i, 420246149Ssjg kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 421246149Ssjg if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) 422246149Ssjg errx(10, "cannot allocate tos space"); 423246149Ssjg if (kflag) { 424246149Ssjg i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos, 425246149Ssjg kvp->gpm.tossize); 426246149Ssjg } else { 427246149Ssjg mib[2] = GPROF_TOS; 428246149Ssjg i = kvp->gpm.tossize; 429246149Ssjg if (sysctl(mib, 3, tos, &i, NULL, 0) < 0) 430246149Ssjg i = 0; 431246149Ssjg } 432246149Ssjg if (i != kvp->gpm.tossize) 433246149Ssjg errx(11, "read tos: read %lu, got %ld: %s", 434246149Ssjg kvp->gpm.tossize, (long)i, 435246149Ssjg kflag ? kvm_geterr(kvp->kd) : strerror(errno)); 436246149Ssjg if (debug) 437246149Ssjg warnx("lowpc 0x%lx, textsize 0x%lx", 438246149Ssjg (unsigned long)kvp->gpm.lowpc, kvp->gpm.textsize); 439246149Ssjg endfrom = kvp->gpm.fromssize / sizeof(*froms); 440246149Ssjg for (fromindex = 0; fromindex < endfrom; ++fromindex) { 441246149Ssjg if (froms[fromindex] == 0) 442246149Ssjg continue; 443246149Ssjg frompc = (u_long)kvp->gpm.lowpc + 444246149Ssjg (fromindex * kvp->gpm.hashfraction * sizeof(*froms)); 445246149Ssjg for (toindex = froms[fromindex]; toindex != 0; 446246149Ssjg toindex = tos[toindex].link) { 447246149Ssjg if (debug) 448246149Ssjg warnx("[mcleanup] frompc 0x%lx selfpc 0x%lx " 449246149Ssjg "count %ld", frompc, tos[toindex].selfpc, 450246149Ssjg tos[toindex].count); 451246149Ssjg rawarc.raw_frompc = frompc; 452246149Ssjg rawarc.raw_selfpc = (u_long)tos[toindex].selfpc; 453246149Ssjg rawarc.raw_count = tos[toindex].count; 454246149Ssjg fwrite((char *)&rawarc, sizeof(rawarc), 1, fp); 455246149Ssjg } 456246149Ssjg } 457246149Ssjg fclose(fp); 458246149Ssjg} 459246149Ssjg 460246149Ssjg/* 461246149Ssjg * Get the profiling rate. 462246149Ssjg */ 463246149Ssjgint 464246149Ssjggetprofhz(kvp) 465246149Ssjg struct kvmvars *kvp; 466246149Ssjg{ 467246149Ssjg size_t size; 468246149Ssjg int mib[2], profrate; 469246149Ssjg struct clockinfo clockrate; 470246149Ssjg 471246149Ssjg if (kflag) { 472246149Ssjg profrate = 1; 473246149Ssjg if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate, 474246149Ssjg sizeof profrate) != sizeof profrate) 475246149Ssjg warnx("get clockrate: %s", kvm_geterr(kvp->kd)); 476246149Ssjg return (profrate); 477246149Ssjg } 478246149Ssjg mib[0] = CTL_KERN; 479246149Ssjg mib[1] = KERN_CLOCKRATE; 480246149Ssjg clockrate.profhz = 1; 481246149Ssjg size = sizeof clockrate; 482246149Ssjg if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0) 483246149Ssjg warn("get clockrate"); 484246149Ssjg return (clockrate.profhz); 485246149Ssjg} 486246149Ssjg 487246149Ssjg/* 488246149Ssjg * Reset the kernel profiling date structures. 489246149Ssjg */ 490246149Ssjgvoid 491246149Ssjgreset(kvp) 492246149Ssjg struct kvmvars *kvp; 493246149Ssjg{ 494246149Ssjg char *zbuf; 495246149Ssjg u_long biggest; 496246149Ssjg int mib[3]; 497246149Ssjg 498246149Ssjg setprof(kvp, GMON_PROF_OFF); 499246149Ssjg 500246149Ssjg biggest = kvp->gpm.kcountsize; 501246149Ssjg if (kvp->gpm.fromssize > biggest) 502246149Ssjg biggest = kvp->gpm.fromssize; 503246149Ssjg if (kvp->gpm.tossize > biggest) 504246149Ssjg biggest = kvp->gpm.tossize; 505246149Ssjg if ((zbuf = (char *)malloc(biggest)) == NULL) 506246149Ssjg errx(12, "cannot allocate zbuf space"); 507246149Ssjg bzero(zbuf, biggest); 508246149Ssjg if (kflag) { 509246149Ssjg if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf, 510246149Ssjg kvp->gpm.kcountsize) != kvp->gpm.kcountsize) 511246149Ssjg errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd)); 512246149Ssjg if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf, 513246149Ssjg kvp->gpm.fromssize) != kvp->gpm.fromssize) 514246149Ssjg errx(14, "froms zero: %s", kvm_geterr(kvp->kd)); 515246149Ssjg if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf, 516246149Ssjg kvp->gpm.tossize) != kvp->gpm.tossize) 517246149Ssjg errx(15, "tos zero: %s", kvm_geterr(kvp->kd)); 518246149Ssjg return; 519246149Ssjg } 520246149Ssjg (void)seteuid(0); 521246149Ssjg mib[0] = CTL_KERN; 522246149Ssjg mib[1] = KERN_PROF; 523246149Ssjg mib[2] = GPROF_COUNT; 524246149Ssjg if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) 525246149Ssjg err(13, "tickbuf zero"); 526246149Ssjg mib[2] = GPROF_FROMS; 527246149Ssjg if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) 528246149Ssjg err(14, "froms zero"); 529246149Ssjg mib[2] = GPROF_TOS; 530246149Ssjg if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) 531246149Ssjg err(15, "tos zero"); 532246149Ssjg (void)seteuid(getuid()); 533246149Ssjg free(zbuf); 534246149Ssjg} 535246149Ssjg