*
* @APPLE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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. 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 OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_HEADER_END@
*/
unsigned int pcsample_flags = 0;
unsigned int pcsample_enable = 0;
+pid_t pc_sample_pid = 0;
+boolean_t pc_trace_frameworks = FALSE;
+
char pcsample_comm[MAXCOMLEN + 1];
/* Set the default framework boundaries */
extern int pc_trace_buf[];
extern int pc_trace_cnt;
+int
+enable_branch_tracing()
+{
+#ifndef i386
+ struct proc *p;
+ if (-1 != pc_sample_pid) {
+ p = pfind(pc_sample_pid);
+ if (p) {
+ p->p_flag |= P_BTRACE;
+ }
+ }
+ else {
+ pc_trace_frameworks = TRUE;
+ }
+
+ return 1;
+
+#else
+ return 0;
+#endif
+}
+
+int
+disable_branch_tracing()
+{
+ struct proc *p;
+ switch (pc_sample_pid) {
+ case -1:
+ pc_trace_frameworks = FALSE;
+ break;
+ case 0:
+ break;
+ default:
+ p = pfind(pc_sample_pid);
+ if (p) {
+ p->p_flag &= ~P_BTRACE;
+ }
+ break;
+}
+ clr_be_bit();
+ return 1;
+}
+
+/*
+ * this only works for the current proc as it
+ * is called from context_switch in the scheduler
+ */
+int
+branch_tracing_enabled()
+{
+ struct proc *p = current_proc();
+ if (TRUE == pc_trace_frameworks) return TRUE;
+ if (p) {
+ return (P_BTRACE == (p->p_flag & P_BTRACE));
+ }
+ return 0;
+}
+
+
void
add_pcbuffer()
{
if (!pcsample_enable)
return;
- if (pcsample_comm[0] != '\0')
- {
- /* If command string does not match, then return */
- curproc = current_proc();
- if (curproc &&
- (strncmp(curproc->p_comm, pcsample_comm, sizeof(pcsample_comm))))
- return;
- }
-
for (i=0; i < pc_trace_cnt; i++)
{
pc = pc_trace_buf[i];
if ((pc_bufptr + pc_trace_cnt) >= pc_buflast)
{
pcsample_enable = 0;
- (void)clr_be_bit();
+ (void)disable_branch_tracing();
wakeup(&pcsample_enable);
}
return;
pcsamples_bootstrap()
{
- if (!clr_be_bit())
+ if (!disable_branch_tracing())
return(ENOTSUP);
pc_bufsize = npcbufs * sizeof(* pc_buffer);
pcsample_beg= 0;
pcsample_end= 0;
bzero((void *)pcsample_comm, sizeof(pcsample_comm));
- (void)clr_be_bit();
+ (void)disable_branch_tracing();
+ pc_sample_pid = 0;
+ pc_trace_frameworks = FALSE;
+
}
pcsamples_control(name, namelen, where, sizep)
int size=*sizep;
unsigned int value = name[1];
pcinfo_t pc_bufinfo;
+pid_t *pidcheck;
pid_t curpid;
struct proc *p, *curproc;
{
/* Do not wait on the buffer */
pcsample_enable = 0;
- (void)clr_be_bit();
+ (void)disable_branch_tracing();
ret = pcsamples_read(where, sizep);
break;
}
}
/* Turn on branch tracing */
- if (!set_be_bit())
+ if (!enable_branch_tracing())
{
- ret = ENOTSUP;;
+ ret = ENOTSUP;
break;
}
ret = tsleep(&pcsample_enable, PRIBIO | PCATCH, "pcsample", 0);
pcsample_enable = 0;
- (void)clr_be_bit();
+ (void)disable_branch_tracing();
if (ret)
{
break;
}
bzero((void *)pcsample_comm, sizeof(pcsample_comm));
- if (copyin(where, pcsample_comm, size))
- {
- ret = EINVAL;
- }
+ if (copyin(where, pcsample_comm, size))
+ {
+ ret = EINVAL;
+ break;
+ }
+
+ /* Check for command name or pid */
+ if (pcsample_comm[0] != '\0')
+ {
+ ret= EOPNOTSUPP;
+ break;
+ }
+ else
+ {
+ if (size != (2 * sizeof(pid_t)))
+ {
+ ret = EINVAL;
+ break;
+ }
+ else
+ {
+ pidcheck = (pid_t *)pcsample_comm;
+ pc_sample_pid = pidcheck[1];
+ }
+ }
break;
default:
ret= EOPNOTSUPP;
}
}
-
-
-