/*
- * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
- * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
*
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the
- * License may not be used to create, or enable the creation or
- * redistribution of, unlawful or unlicensed copies of an Apple operating
- * system, or to circumvent, violate, or enable the circumvention or
- * violation of, any terms of an Apple operating system software license
- * agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
* limitations under the License.
- *
- * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
/*-
* @(#)subr_prof.c 8.3 (Berkeley) 9/23/93
*/
+#ifdef GPROF
+#include <libkern/kernel_mach_header.h>
+#endif
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <kern/cpu_number.h>
#include <kern/kalloc.h>
-extern boolean_t ml_set_interrupts_enabled(boolean_t enable);
-
#ifdef GPROF
#include <sys/malloc.h>
#include <sys/gmon.h>
-#include <kern/mach_header.h>
-#include <machine/profile.h>
+
+extern int sysctl_doprof(int *, u_int, user_addr_t, size_t *,
+ user_addr_t, size_t newlen);
+extern int sysctl_struct(user_addr_t, size_t *,
+ user_addr_t, size_t, void *, int);
lck_spin_t * mcount_lock;
lck_grp_t * mcount_lock_grp;
/*
* Froms is actually a bunch of unsigned shorts indexing tos
*/
-struct gmonparam _gmonparam = { GMON_PROF_OFF };
+struct gmonparam _gmonparam = { .state = GMON_PROF_OFF };
/*
* This code uses 32 bit mach object segment information from the currently
void
kmstartup(void)
{
- char *cp;
- u_long fromssize, tossize;
- struct segment_command *sgp; /* 32 bit mach object file segment */
+ tostruct_t *cp;
+ kernel_segment_command_t *sgp; /* 32 bit mach object file segment */
struct gmonparam *p = &_gmonparam;
sgp = getsegbyname("__TEXT");
- p->lowpc = (u_long)sgp->vmaddr;
- p->highpc = (u_long)(sgp->vmaddr + sgp->vmsize);
+ p->lowpc = (u_int32_t)sgp->vmaddr;
+ p->highpc = (u_int32_t)(sgp->vmaddr + sgp->vmsize);
/*
* Round lowpc and highpc to multiples of the density we're using
p->lowpc = ROUNDDOWN(p->lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
p->highpc = ROUNDUP(p->highpc, HISTFRACTION * sizeof(HISTCOUNTER));
p->textsize = p->highpc - p->lowpc;
- printf("Profiling kernel, textsize=%d [0x%08x..0x%08x]\n",
+ printf("Profiling kernel, textsize=%lu [0x%016lx..0x%016lx]\n",
p->textsize, p->lowpc, p->highpc);
p->kcountsize = p->textsize / HISTFRACTION;
p->hashfraction = HASHFRACTION;
p->tolimit = MINARCS;
else if (p->tolimit > MAXARCS)
p->tolimit = MAXARCS;
- p->tossize = p->tolimit * sizeof(struct tostruct);
+ p->tossize = p->tolimit * sizeof(tostruct_t);
/* Why not use MALLOC with M_GPROF ? */
- cp = (char *)kalloc(p->kcountsize + p->fromssize + p->tossize);
+ cp = (tostruct_t *)kalloc(p->kcountsize + p->fromssize + p->tossize);
if (cp == 0) {
printf("No memory for profiling.\n");
return;
}
bzero(cp, p->kcountsize + p->tossize + p->fromssize);
- p->tos = (struct tostruct *)cp;
- cp += p->tossize;
+ p->tos = cp;
+ cp = (tostruct_t *)((vm_offset_t)cp + p->tossize);
p->kcount = (u_short *)cp;
- cp += p->kcountsize;
+ cp = (tostruct_t *)((vm_offset_t)cp + p->kcountsize);
p->froms = (u_short *)cp;
mcount_lock_grp = lck_grp_alloc_init("MCOUNT", LCK_GRP_ATTR_NULL);
mcount_lock_attr = lck_attr_alloc_init();
- //lck_attr_setdebug(mcount_lock_attr);
mcount_lock = lck_spin_alloc_init(mcount_lock_grp, mcount_lock_attr);
}
/*
- * Return kernel profiling information.
+ * XXX These should be broken out into per-argument OID values,
+ * XXX since there are no sub-OID parameter values, but unfortunately
+ * XXX there is barely enough time for an initial conversion.
+ *
+ * Note: These items appear to be read/write.
*/
-int
+STATIC int
+sysctl_doprofhandle SYSCTL_HANDLER_ARGS
+{
sysctl_doprof(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
user_addr_t newp, size_t newlen)
{
+ __unused int cmd = oidp->oid_arg2; /* subcommand*/
+ int *name = arg1; /* oid element argument vector */
+ int namelen = arg2; /* number of oid element arguments */
+ user_addr_t oldp = req->oldptr; /* user buffer copy out address */
+ size_t *oldlenp = req->oldlen; /* user buffer copy out size */
+ user_addr_t newp = req->newptr; /* user buffer copy in address */
+ size_t newlen = req->newlen; /* user buffer copy in size */
+
struct gmonparam *gp = &_gmonparam;
- int error;
+ int error = 0;
/* all sysctl names at this level are terminal */
if (namelen != 1)
case GPROF_STATE:
error = sysctl_int(oldp, oldlenp, newp, newlen, &gp->state);
if (error)
- return (error);
+ break;
if (gp->state == GMON_PROF_OFF)
stopprofclock(kernproc);
else
startprofclock(kernproc);
- return (0);
+ break;
case GPROF_COUNT:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- gp->kcount, gp->kcountsize));
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ gp->kcount, gp->kcountsize);
+ break;
case GPROF_FROMS:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- gp->froms, gp->fromssize));
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ gp->froms, gp->fromssize);
+ break;
case GPROF_TOS:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- gp->tos, gp->tossize));
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ gp->tos, gp->tossize);
+ break;
case GPROF_GMONPARAM:
- return (sysctl_rdstruct(oldp, oldlenp, newp, gp, sizeof *gp));
+ error = sysctl_rdstruct(oldp, oldlenp, newp, gp, sizeof *gp);
+ break;
default:
- return (ENOTSUP);
+ error = ENOTSUP;
+ break;
}
- /* NOTREACHED */
+
+ /* adjust index so we return the right required/consumed amount */
+ if (!error)
+ req->oldidx += req->oldlen;
+
+ return(error);
}
+SYSCTL_PROC(_kern, KERN_PROF, prof, STLFLAG_NODE|CTLFLAG_RW | CTLFLAG_LOCKED,
+ 0, /* Pointer argument (arg1) */
+ 0, /* Integer argument (arg2) */
+ sysctl_doprofhandle, /* Handler function */
+ NULL, /* No explicit data */
+ "");
/*
*/
void
mcount(
- register u_long frompc,
- register u_long selfpc
+ uintptr_t frompc,
+ uintptr_t selfpc
)
{
unsigned short *frompcindex;
- register struct tostruct *top, *prevtop;
+ tostruct_t *top, *prevtop;
struct gmonparam *p = &_gmonparam;
- register long toindex;
+ long toindex;
/*
* check that we are profiling
#define PROFILE_LOCK(x)
#define PROFILE_UNLOCK(x)
-int
-profil(struct proc *p, register struct profil_args *uap, __unused register_t *retval)
-{
- struct uprof *upp = &p->p_stats->p_prof;
- int s;
-
- if (uap->pcscale > (1 << 16))
- return (EINVAL);
- if (uap->pcscale == 0) {
- stopprofclock(p);
- return (0);
- }
-
- /* Block profile interrupts while changing state. */
- s = ml_set_interrupts_enabled(FALSE);
-
- if (proc_is64bit(p)) {
- struct user_uprof *user_upp = &p->p_stats->user_p_prof;
- struct user_uprof *upc, *nupc;
-
- PROFILE_LOCK(&user_upp->pr_lock);
- user_upp->pr_base = uap->bufbase;
- user_upp->pr_size = uap->bufsize;
- user_upp->pr_off = uap->pcoffset;
- user_upp->pr_scale = uap->pcscale;
- upp->pr_base = NULL;
- upp->pr_size = 0;
- upp->pr_scale = 0;
-
- /* remove buffers previously allocated with add_profil() */
- for (upc = user_upp->pr_next; upc; upc = nupc) {
- nupc = upc->pr_next;
- kfree(upc, sizeof (*upc));
- }
- user_upp->pr_next = 0;
- PROFILE_UNLOCK(&user_upp->pr_lock);
- }
- else {
- struct uprof *upc, *nupc;
-
- PROFILE_LOCK(&upp->pr_lock);
- upp->pr_base = CAST_DOWN(caddr_t, uap->bufbase);
- upp->pr_size = uap->bufsize;
- upp->pr_off = uap->pcoffset;
- upp->pr_scale = uap->pcscale;
-
- /* remove buffers previously allocated with add_profil() */
- for (upc = upp->pr_next; upc; upc = nupc) {
- nupc = upc->pr_next;
- kfree(upc, sizeof (struct uprof));
- }
- upp->pr_next = 0;
- PROFILE_UNLOCK(&upp->pr_lock);
- }
-
- startprofclock(p);
- ml_set_interrupts_enabled(s);
- return(0);
-}
-
-int
-add_profil(struct proc *p, register struct add_profil_args *uap, __unused register_t *retval)
-{
- struct uprof *upp = &p->p_stats->p_prof, *upc;
- struct user_uprof *user_upp = NULL, *user_upc;
- int s;
- boolean_t is64bit = proc_is64bit(p);
-
- if (is64bit) {
- user_upp = &p->p_stats->user_p_prof;
- if (user_upp->pr_scale == 0)
- return (0);
- }
- else {
- if (upp->pr_scale == 0)
- return (0);
- }
-
- s = ml_set_interrupts_enabled(FALSE);
-
- if (is64bit) {
- user_upc = (struct user_uprof *) kalloc(sizeof (struct user_uprof));
- user_upc->pr_base = uap->bufbase;
- user_upc->pr_size = uap->bufsize;
- user_upc->pr_off = uap->pcoffset;
- user_upc->pr_scale = uap->pcscale;
- PROFILE_LOCK(&user_upp->pr_lock);
- user_upc->pr_next = user_upp->pr_next;
- user_upp->pr_next = user_upc;
- PROFILE_UNLOCK(&user_upp->pr_lock);
- }
- else {
- upc = (struct uprof *) kalloc(sizeof (struct uprof));
- upc->pr_base = CAST_DOWN(caddr_t, uap->bufbase);
- upc->pr_size = uap->bufsize;
- upc->pr_off = uap->pcoffset;
- upc->pr_scale = uap->pcscale;
- PROFILE_LOCK(&upp->pr_lock);
- upc->pr_next = upp->pr_next;
- upp->pr_next = upc;
- PROFILE_UNLOCK(&upp->pr_lock);
- }
-
- ml_set_interrupts_enabled(s);
- return(0);
-}
/*
* Scale is a fixed-point number with the binary point 16 bits
* into the value, and is <= 1.0. pc is at most 32 bits, so the
* intermediate result is at most 48 bits.
*/
+//K64todo - this doesn't fit into 64 bit any more, it needs 64+16
#define PC_TO_INDEX(pc, prof) \
- ((int)(((u_quad_t)((pc) - (prof)->pr_off) * \
+ ((user_addr_t)(((u_quad_t)((pc) - (prof)->pr_off) * \
(u_quad_t)((prof)->pr_scale)) >> 16) & ~1)
/*
* update fails, we simply turn off profiling.
*/
void
-addupc_task(p, pc, ticks)
- register struct proc *p;
- user_addr_t pc;
- u_int ticks;
+addupc_task(struct proc *p, user_addr_t pc, u_int ticks)
{
- register u_int off;
+ user_addr_t off;
u_short count;
/* Testing P_PROFIL may be unnecessary, but is certainly safe. */
short *cell;
for (prof = &p->p_stats->p_prof; prof; prof = prof->pr_next) {
- off = PC_TO_INDEX(CAST_DOWN(uint, pc),prof);
+ off = PC_TO_INDEX(pc,prof);
cell = (short *)(prof->pr_base + off);
if (cell >= (short *)prof->pr_base &&
- cell < (short*)(prof->pr_size + (int) prof->pr_base)) {
+ cell < (short*)(prof->pr_size + prof->pr_base)) {
if (copyin(CAST_USER_ADDR_T(cell), (caddr_t) &count, sizeof(count)) == 0) {
count += ticks;
if(copyout((caddr_t) &count, CAST_USER_ADDR_T(cell), sizeof(count)) == 0)