]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kperf/threadinfo.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / osfmk / kperf / threadinfo.c
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
51 static uint64_t
52 make_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 {
67 // Today we happen to know there's a one-to-one mapping.
68 return ((mode & 0xffff) | ((~mode & 0xffff) << 16));
69 }
70 }
71
72
73 /* code to collect current thread info */
74 void
75 kperf_threadinfo_sample(struct threadinfo *ti, struct kperf_context *context)
76 {
77 thread_t cur_thread = context->cur_thread;
78 BUF_INFO1( PERF_TI_SAMPLE, (uintptr_t)cur_thread );
79
80 // fill out the fields
81 ti->pid = context->cur_pid;
82 ti->tid = thread_tid(cur_thread);
83 ti->dq_addr = thread_dispatchqaddr(cur_thread);
84 ti->runmode = make_runmode(cur_thread);
85 }
86
87 /* log an existing sample into the buffer */
88 void
89 kperf_threadinfo_log(struct threadinfo *ti)
90 {
91 /* XXX: K64 only? */
92 BUF_DATA( PERF_TI_DATA, ti->pid, ti->tid, ti->dq_addr, ti->runmode );
93 }
94
95 /* 'extra' thread-info functions that are deferred 'til thread-context
96 * time
97 */
98 void
99 kperf_threadinfo_extra_sample(struct tinfo_ex *tex, struct kperf_context *context)
100 {
101 thread_t cur_thread = context->cur_thread;
102 uint32_t t_chud;
103
104 /* can only pend on the current thread */
105 /* this is valid from PET mode... */
106 /*
107 if( cur_thread != chudxnu_current_thread() )
108 panic("pending to non-current thread");
109 */
110
111 /* get our current bits */
112 t_chud = kperf_get_thread_bits(cur_thread);
113
114 /* check if there's anything for us to do */
115 if( t_chud & T_AST_NAME )
116 {
117 BUF_INFO1( PERF_TI_XSAMPLE, (uintptr_t)cur_thread );
118
119 /* get the name out */
120 #ifdef FIXME
121 /* need kperfbsd.c? */
122 proc_name( context->cur_pid,
123 &tex->p_comm[0], CHUD_MAXPCOMM );
124 #endif
125
126 /* mark that it's done */
127 t_chud &= ~T_AST_NAME;
128 t_chud |= T_NAME_DONE;
129
130 kperf_set_thread_bits(cur_thread, t_chud);
131 }
132 else
133 /* empty string */
134 tex->p_comm[0] = '\0';
135
136 }
137
138 /* log it if there's anyting useful there */
139 void
140 kperf_threadinfo_extra_log(struct tinfo_ex *tex)
141 {
142 /* no data */
143 if( tex->p_comm[0] == '\0' )
144 return;
145
146 /* FIXME: log more */
147 BUF_DATA1( PERF_TI_XDATA, (uintptr_t)*(uintptr_t*)&tex->p_comm[0] );
148 }
149
150 /* pend a flag on a thread */
151 int
152 kperf_threadinfo_extra_pend(struct kperf_context *context)
153 {
154 return kperf_ast_pend( context->cur_thread, T_NAME_DONE | T_AST_NAME,
155 T_AST_NAME );
156 }
157
158
159 #if 0
160
161 /* transalted from the APF */
162
163 APTIAKernelEntry_t *threadInfo = (APTIAKernelEntry_t*)(threadInfos + account->offset);
164
165 context->timeStamp = mach_absolute_time();
166 context->cpuNum = chudxnu_cpu_number();
167
168 // record the process info from the callback context
169 context->pid = chudxnu_current_pid();
170 threadInfo->pid = context->generic->pid;
171
172 // thread_tid is a thread_t to ID function in the kernel
173 context->threadID = chudxnu_current_thread();
174 threadInfo->tid = thread_tid(context->generic->threadID);
175
176 // also a kernel function
177 threadInfo->dispatch_queue_addr = thread_dispatchqaddr(context->generic->threadID);
178
179 // see below
180 threadInfo->runMode = AppleProfileGetRunModeOfThread(context->generic->threadID);
181
182
183 /****** WTF is this?! *******/
184
185 /*!enum AppleProfileTriggerClientThreadRunMode
186 *
187 * Specifies the thread mode in which to record samples.
188 */
189 typedef enum { // Target Thread State - can be OR'd
190 // Basic Building Blocks:
191 // for Time Profile, use kAppleProfileTriggerClientThreadModeRunning (optionally with kAppleProfileTriggerClientThreadModeNotIdle).
192 // for Time Profile (All Thread States), use kAppleProfileTriggerClientThreadModeAny (or just don't specify any thread mode filters).
193 // for Time Profile (Blocked Threads), use kIOProfileTriggerClientThreadModeBlocked.
194 // etc...
195
196 kAppleProfileTriggerClientThreadModeNone = 0x0,
197
198 kAppleProfileTriggerClientThreadModeRunning = 0x1, // On a core
199 kAppleProfileTriggerClientThreadModeRunnable = 0x2, // TH_RUN
200 kAppleProfileTriggerClientThreadModeBlocked = 0x4, // TH_WAIT
201 kAppleProfileTriggerClientThreadModeUninterruptible = 0x8, // TH_UNINT
202 kAppleProfileTriggerClientThreadModeSuspended = 0x10, // TH_SUSP
203 kAppleProfileTriggerClientThreadModeTerminating = 0x20, // TH_TERMINATE
204 kAppleProfileTriggerClientThreadModeIdle = 0x40, // TH_IDLE
205
206 kAppleProfileTriggerClientThreadModeNotRunning = kAppleProfileTriggerClientThreadModeRunning << 16, // Not on a core
207 kAppleProfileTriggerClientThreadModeNotRunnable = kAppleProfileTriggerClientThreadModeRunnable << 16, // !TH_RUN
208 kAppleProfileTriggerClientThreadModeNotBlocked = kAppleProfileTriggerClientThreadModeBlocked << 16, // !TH_WAIT
209 kAppleProfileTriggerClientThreadModeNotUninterruptible = kAppleProfileTriggerClientThreadModeUninterruptible << 16, // !TH_UNINT
210 kAppleProfileTriggerClientThreadModeNotSuspended = kAppleProfileTriggerClientThreadModeSuspended << 16, // !TH_SUSP
211 kAppleProfileTriggerClientThreadModeNotTerminating = kAppleProfileTriggerClientThreadModeTerminating << 16, // !TH_TERMINATE
212 kAppleProfileTriggerClientThreadModeNotIdle = kAppleProfileTriggerClientThreadModeIdle << 16, // !TH_IDLE
213
214 kAppleProfileTriggerClientThreadModeAny = ( kAppleProfileTriggerClientThreadModeRunning
215 | kAppleProfileTriggerClientThreadModeNotRunning),
216 } AppleProfileTriggerClientThreadRunMode;
217
218 extern "C" AppleProfileTriggerClientThreadRunMode AppleProfileGetRunModeOfThread(thread_t thread) {
219 const int mode = chudxnu_thread_get_scheduler_state(thread);
220
221 #if !TARGET_OS_EMBEDDED
222 if (0 == mode) {
223 return (chudxnu_thread_get_idle(thread) ? kAppleProfileTriggerClientThreadModeIdle : kAppleProfileTriggerClientThreadModeNotIdle);
224 } else
225 #endif
226 return (AppleProfileTriggerClientThreadRunMode)((mode & 0xffff) | ((~mode & 0xffff) << 16)); // Today we happen to know there's a one-to-one mapping.
227 }
228
229 #endif