|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1993,1992 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26:
1.1.1.2 root 27: #include <kern/printf.h>
28: #include <string.h>
1.1 root 29:
30: #include <mach/mach_types.h> /* vm_address_t */
31: #include <mach/std_types.h> /* pointer_t */
32: #include <mach/pc_sample.h>
1.1.1.2 root 33: #include <machine/trap.h>
34: #include <kern/kalloc.h>
1.1 root 35: #include <kern/host.h>
36: #include <kern/thread.h>
37: #include <kern/pc_sample.h>
1.1.1.2 root 38: #include <kern/mach_clock.h>
1.1 root 39:
40: #if MACH_PCSAMPLE
41:
42: #define MAX_PC_SAMPLES 512
43:
44: typedef sampled_pc_t sampled_pcs[MAX_PC_SAMPLES];
45:
46: void take_pc_sample(
1.1.1.3 root 47: const thread_t t,
48: sample_control_t *cp,
1.1.1.4 ! root 49: sampled_pc_flavor_t flavor,
! 50: boolean_t usermode,
! 51: vm_offset_t kern_pc)
1.1 root 52: {
53: vm_offset_t pc;
54: struct sampled_pc *sample;
55:
1.1.1.4 ! root 56: if (usermode)
! 57: pc = interrupted_pc(t);
! 58: else
! 59: pc = kern_pc;
! 60:
1.1 root 61: cp->seqno++;
62: sample = &((sampled_pc_t *)cp->buffer)[cp->seqno % MAX_PC_SAMPLES];
1.1.1.2 root 63: sample->id = (vm_offset_t)t;
1.1 root 64: sample->pc = pc;
65: sample->sampletype = flavor;
66: }
67:
68: kern_return_t
69: thread_enable_pc_sampling(
70: thread_t thread,
71: int *tickp,
72: sampled_pc_flavor_t flavors)
73: {
74: vm_offset_t buf;
75:
76: if (thread == THREAD_NULL) {
77: return KERN_INVALID_ARGUMENT;
78: }
79: if (thread->pc_sample.buffer == 0) {
80: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
81: if (buf == 0) {
82: printf("thread_enable_pc_sampling: kalloc failed\n");
83: return KERN_INVALID_ARGUMENT;
84: }
85: thread->pc_sample.buffer = buf;
86: thread->pc_sample.seqno = 0;
87: }
88: *tickp = tick;
89: thread->pc_sample.sampletypes = flavors;
90: return KERN_SUCCESS;
91: }
92:
93: kern_return_t
94: task_enable_pc_sampling(
95: task_t task,
96: int *tickp,
97: sampled_pc_flavor_t flavors)
98: {
99: vm_offset_t buf;
100:
101: if (task == TASK_NULL) {
102: return KERN_INVALID_ARGUMENT;
103: }
104: if (task->pc_sample.buffer == 0) {
105: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
106: if (buf == 0) {
107: printf("task_enable_pc_sampling: kalloc failed\n");
108: return KERN_INVALID_ARGUMENT;
109: }
110: task->pc_sample.buffer = buf;
111: task->pc_sample.seqno = 0;
112: }
113: *tickp = tick;
114: task->pc_sample.sampletypes = flavors;
115: return KERN_SUCCESS;
116: }
117:
118: kern_return_t
119: thread_disable_pc_sampling(
120: thread_t thread,
121: int *samplecntp)
122: {
123: vm_offset_t buf;
124:
125: if (thread == THREAD_NULL) {
126: return KERN_INVALID_ARGUMENT;
127: }
128: if ((buf = thread->pc_sample.buffer) != 0)
129: kfree(buf, sizeof (sampled_pcs));
130: thread->pc_sample.buffer = (vm_offset_t) 0;
131: thread->pc_sample.seqno = 0;
132: thread->pc_sample.sampletypes = 0; /* shut off sampling */
133:
134: return KERN_SUCCESS;
135: }
136:
137: kern_return_t
138: task_disable_pc_sampling(
139: task_t task,
140: int *samplecntp)
141: {
142: vm_offset_t buf;
143:
144: if (task == TASK_NULL) {
145: return KERN_INVALID_ARGUMENT;
146: }
147: if ((buf = task->pc_sample.buffer) != 0)
148: kfree(buf, sizeof (sampled_pcs));
149: task->pc_sample.buffer = (vm_offset_t) 0;
150: task->pc_sample.seqno = 0;
151: task->pc_sample.sampletypes = 0; /* shut off sampling */
152:
153: return KERN_SUCCESS;
154: }
155:
156: static kern_return_t
157: get_sampled_pcs(
158: sample_control_t *cp,
159: sampled_pc_seqno_t *seqnop,
160: sampled_pc_array_t sampled_pcs_out,
161: int *sampled_pcs_cntp)
162: {
163: int nsamples;
164: sampled_pc_seqno_t seqidx1, seqidx2;
165:
166: nsamples = cp->seqno - *seqnop;
167: seqidx1 = *seqnop % MAX_PC_SAMPLES; /* index of *seqnop */
168: seqidx2 = cp->seqno % MAX_PC_SAMPLES; /* index of cp->seqno */
169:
170: if (nsamples > MAX_PC_SAMPLES) {
171: nsamples = MAX_PC_SAMPLES;
172: seqidx1 = (seqidx2 + 1) % MAX_PC_SAMPLES;
173: }
174:
175: if (nsamples > 0) {
176: /*
177: * Carefully copy sampled_pcs into sampled_pcs_msgbuf IN ORDER.
178: */
179: if (seqidx1 < seqidx2) {
180: /*
181: * Simple case: no wraparound.
182: * Copy from seqidx1 to seqidx2.
183: */
1.1.1.2 root 184: memcpy(sampled_pcs_out,
185: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
186: nsamples * sizeof(sampled_pc_t));
1.1 root 187: } else {
188: /* seqidx1 > seqidx2 -- Handle wraparound. */
189:
1.1.1.2 root 190: memcpy(sampled_pcs_out,
191: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
192: (MAX_PC_SAMPLES - seqidx1 - 1) * sizeof(sampled_pc_t));
193:
194: memcpy(sampled_pcs_out + (MAX_PC_SAMPLES - seqidx1 - 1),
195: (sampled_pc_array_t)cp->buffer,
196: (seqidx2 + 1) * sizeof(sampled_pc_t));
1.1 root 197: }
1.1.1.3 root 198: } else if (nsamples < 0) {
199: /* Bogus SEQNO supplied. */
200: nsamples = 0;
1.1 root 201: } else {
202: /* could either be zero because of overflow, or because
203: * we are being lied to. In either case, return nothing.
204: * If overflow, only once in a blue moon. If being lied to,
205: * then we have no obligation to return anything useful anyway.
206: */
207: ;
208: }
209:
210: *sampled_pcs_cntp = nsamples;
211: *seqnop = cp->seqno;
212: return KERN_SUCCESS;
213: }
214:
215: kern_return_t
216: thread_get_sampled_pcs(
217: thread_t thread,
218: sampled_pc_seqno_t *seqnop,
219: sampled_pc_array_t sampled_pcs_out,
220: int *sampled_pcs_cntp)
221: {
222: if (thread == THREAD_NULL)
223: return KERN_INVALID_ARGUMENT;
224:
225: if (thread->pc_sample.buffer == 0)
226: return KERN_FAILURE;
227:
228: return get_sampled_pcs(&thread->pc_sample, seqnop, sampled_pcs_out,
229: sampled_pcs_cntp);
230: }
231:
232: kern_return_t
233: task_get_sampled_pcs(
234: task_t task,
235: sampled_pc_seqno_t *seqnop,
236: sampled_pc_array_t sampled_pcs_out,
237: int *sampled_pcs_cntp)
238: {
239: if (task == TASK_NULL)
240: return KERN_INVALID_ARGUMENT;
241:
242: if (task->pc_sample.buffer == 0)
243: return KERN_FAILURE;
244:
245: return get_sampled_pcs(&task->pc_sample, seqnop, sampled_pcs_out,
246: sampled_pcs_cntp);
247: }
248:
249: #else /* MACH_PCSAMPLE */
250:
251: kern_return_t
252: thread_enable_pc_sampling(
1.1.1.3 root 253: const thread_t thread,
254: const int *tickp,
1.1 root 255: sampled_pc_flavor_t flavors)
256: {
257: return KERN_FAILURE; /* not implemented */
258: }
259:
260: kern_return_t
261: task_enable_pc_sampling(
1.1.1.3 root 262: const task_t task,
263: const int *tickp,
1.1 root 264: sampled_pc_flavor_t flavors)
265: {
266: return KERN_FAILURE; /* not implemented */
267: }
268:
269: kern_return_t
270: thread_disable_pc_sampling(
1.1.1.3 root 271: const thread_t thread,
272: const int *samplecntp)
1.1 root 273: {
274: return KERN_FAILURE; /* not implemented */
275: }
276:
277: kern_return_t
278: task_disable_pc_sampling(
1.1.1.3 root 279: const task_t task,
280: const int *samplecntp)
1.1 root 281: {
282: return KERN_FAILURE; /* not implemented */
283: }
284:
285: kern_return_t
286: thread_get_sampled_pcs(
1.1.1.3 root 287: const thread_t thread,
288: const sampled_pc_seqno_t *seqnop,
289: const sampled_pc_array_t sampled_pcs_out,
290: const int *sampled_pcs_cntp)
1.1 root 291: {
292: return KERN_FAILURE; /* not implemented */
293: }
294:
295: kern_return_t
296: task_get_sampled_pcs(
1.1.1.3 root 297: const task_t task,
298: const sampled_pc_seqno_t *seqnop,
299: const sampled_pc_array_t sampled_pcs_out,
300: const int *sampled_pcs_cntp)
1.1 root 301: {
302: return KERN_FAILURE; /* not implemented */
303: }
304:
305: #endif /* MACH_PCSAMPLE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.