1/* 2 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 30/* Sample thread data */ 31 32#include <mach/mach_types.h> 33#include <kern/thread.h> /* thread_* */ 34#include <kern/debug.h> /* panic */ 35// #include <sys/proc.h> 36 37#include <chud/chud_xnu.h> 38#include <kperf/kperf.h> 39 40#include <kperf/buffer.h> 41#include <kperf/context.h> 42#include <kperf/threadinfo.h> 43#include <kperf/ast.h> 44 45// kAppleProfileTriggerClientThreadModeIdle = 0x40, // TH_IDLE 46// #define TH_IDLE 0x40 47 48//kAppleProfileTriggerClientThreadModeNotIdle = kAppleProfileTriggerClientThreadModeIdle << 16, // !TH_IDLE 49#define TH_IDLE_N (TH_IDLE << 16) 50 51static uint64_t 52make_runmode(thread_t thread) 53{ 54 /* CEG: This is a translation of 55 * AppleProfileGetRunModeOfThread below... kinda magic :/ 56 */ 57 const int mode = chudxnu_thread_get_scheduler_state(thread); 58 59#if !TARGET_OS_EMBEDDED 60 if( 0 == mode) 61 { 62 return (chudxnu_thread_get_idle(thread) ? TH_IDLE : TH_IDLE_N); 63 } 64 else 65#endif 66 // Today we happen to know there's a one-to-one mapping. 67 return ((mode & 0xffff) | ((~mode & 0xffff) << 16)); 68} 69 70 71/* code to collect current thread info */ 72void 73kperf_threadinfo_sample(struct threadinfo *ti, struct kperf_context *context) 74{ 75 thread_t cur_thread = context->cur_thread; 76 BUF_INFO1( PERF_TI_SAMPLE, (uintptr_t)cur_thread ); 77 78 // fill out the fields 79 ti->pid = context->cur_pid; 80 ti->tid = thread_tid(cur_thread); 81 ti->dq_addr = thread_dispatchqaddr(cur_thread); 82 ti->runmode = make_runmode(cur_thread); 83} 84 85/* log an existing sample into the buffer */ 86void 87kperf_threadinfo_log(struct threadinfo *ti) 88{ 89 /* XXX: K64 only? */ 90 BUF_DATA( PERF_TI_DATA, ti->pid, ti->tid, ti->dq_addr, ti->runmode ); 91} 92 93/* 'extra' thread-info functions that are deferred 'til thread-context 94 * time 95 */ 96void 97kperf_threadinfo_extra_sample(struct tinfo_ex *tex, struct kperf_context *context) 98{ 99 thread_t cur_thread = context->cur_thread; 100 uint32_t t_chud; 101 102 /* can only pend on the current thread */ 103 /* this is valid from PET mode... */ 104 /* 105 if( cur_thread != chudxnu_current_thread() ) 106 panic("pending to non-current thread"); 107 */ 108 109 /* get our current bits */ 110 t_chud = kperf_get_thread_bits(cur_thread); 111 112 /* check if there's anything for us to do */ 113 if( t_chud & T_AST_NAME ) 114 { 115 BUF_INFO1( PERF_TI_XSAMPLE, (uintptr_t)cur_thread ); 116 117 /* get the name out */ 118#ifdef FIXME 119 /* need kperfbsd.c? */ 120 proc_name( context->cur_pid, 121 &tex->p_comm[0], CHUD_MAXPCOMM ); 122#endif 123 124 /* mark that it's done */ 125 t_chud &= ~T_AST_NAME; 126 t_chud |= T_NAME_DONE; 127 128 kperf_set_thread_bits(cur_thread, t_chud); 129 } 130 else 131 /* empty string */ 132 tex->p_comm[0] = '\0'; 133 134} 135 136/* log it if there's anyting useful there */ 137void 138kperf_threadinfo_extra_log(struct tinfo_ex *tex) 139{ 140 /* no data */ 141 if( tex->p_comm[0] == '\0' ) 142 return; 143 144 /* FIXME: log more */ 145 BUF_DATA1( PERF_TI_XDATA, (uintptr_t)*(uintptr_t*)&tex->p_comm[0] ); 146} 147 148/* pend a flag on a thread */ 149int 150kperf_threadinfo_extra_pend(struct kperf_context *context) 151{ 152 return kperf_ast_pend( context->cur_thread, T_NAME_DONE | T_AST_NAME, 153 T_AST_NAME ); 154} 155 156 157#if 0 158 159/* transalted from the APF */ 160 161APTIAKernelEntry_t *threadInfo = (APTIAKernelEntry_t*)(threadInfos + account->offset); 162 163context->timeStamp = mach_absolute_time(); 164context->cpuNum = chudxnu_cpu_number(); 165 166// record the process info from the callback context 167context->pid = chudxnu_current_pid(); 168threadInfo->pid = context->generic->pid; 169 170// thread_tid is a thread_t to ID function in the kernel 171context->threadID = chudxnu_current_thread(); 172threadInfo->tid = thread_tid(context->generic->threadID); 173 174// also a kernel function 175threadInfo->dispatch_queue_addr = thread_dispatchqaddr(context->generic->threadID); 176 177// see below 178threadInfo->runMode = AppleProfileGetRunModeOfThread(context->generic->threadID); 179 180 181/****** WTF is this?! *******/ 182 183/*!enum AppleProfileTriggerClientThreadRunMode 184 * 185 * Specifies the thread mode in which to record samples. 186 */ 187typedef enum { // Target Thread State - can be OR'd 188 // Basic Building Blocks: 189 // for Time Profile, use kAppleProfileTriggerClientThreadModeRunning (optionally with kAppleProfileTriggerClientThreadModeNotIdle). 190 // for Time Profile (All Thread States), use kAppleProfileTriggerClientThreadModeAny (or just don't specify any thread mode filters). 191 // for Time Profile (Blocked Threads), use kIOProfileTriggerClientThreadModeBlocked. 192 // etc... 193 194 kAppleProfileTriggerClientThreadModeNone = 0x0, 195 196 kAppleProfileTriggerClientThreadModeRunning = 0x1, // On a core 197 kAppleProfileTriggerClientThreadModeRunnable = 0x2, // TH_RUN 198 kAppleProfileTriggerClientThreadModeBlocked = 0x4, // TH_WAIT 199 kAppleProfileTriggerClientThreadModeUninterruptible = 0x8, // TH_UNINT 200 kAppleProfileTriggerClientThreadModeSuspended = 0x10, // TH_SUSP 201 kAppleProfileTriggerClientThreadModeTerminating = 0x20, // TH_TERMINATE 202 kAppleProfileTriggerClientThreadModeIdle = 0x40, // TH_IDLE 203 204 kAppleProfileTriggerClientThreadModeNotRunning = kAppleProfileTriggerClientThreadModeRunning << 16, // Not on a core 205 kAppleProfileTriggerClientThreadModeNotRunnable = kAppleProfileTriggerClientThreadModeRunnable << 16, // !TH_RUN 206 kAppleProfileTriggerClientThreadModeNotBlocked = kAppleProfileTriggerClientThreadModeBlocked << 16, // !TH_WAIT 207 kAppleProfileTriggerClientThreadModeNotUninterruptible = kAppleProfileTriggerClientThreadModeUninterruptible << 16, // !TH_UNINT 208 kAppleProfileTriggerClientThreadModeNotSuspended = kAppleProfileTriggerClientThreadModeSuspended << 16, // !TH_SUSP 209 kAppleProfileTriggerClientThreadModeNotTerminating = kAppleProfileTriggerClientThreadModeTerminating << 16, // !TH_TERMINATE 210 kAppleProfileTriggerClientThreadModeNotIdle = kAppleProfileTriggerClientThreadModeIdle << 16, // !TH_IDLE 211 212 kAppleProfileTriggerClientThreadModeAny = ( kAppleProfileTriggerClientThreadModeRunning 213 | kAppleProfileTriggerClientThreadModeNotRunning), 214} AppleProfileTriggerClientThreadRunMode; 215 216extern "C" AppleProfileTriggerClientThreadRunMode AppleProfileGetRunModeOfThread(thread_t thread) { 217 const int mode = chudxnu_thread_get_scheduler_state(thread); 218 219#if !TARGET_OS_EMBEDDED 220 if (0 == mode) { 221 return (chudxnu_thread_get_idle(thread) ? kAppleProfileTriggerClientThreadModeIdle : kAppleProfileTriggerClientThreadModeNotIdle); 222 } else 223#endif 224 return (AppleProfileTriggerClientThreadRunMode)((mode & 0xffff) | ((~mode & 0xffff) << 16)); // Today we happen to know there's a one-to-one mapping. 225} 226 227#endif 228