|
|
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: int pc_sampling_enabled = 0;
47: decl_simple_lock_data(, pc_sampling_lock) /* lock for enabling */
48:
49: void take_pc_sample(
50: register thread_t t,
51: register sample_control_t *cp,
52: sampled_pc_flavor_t flavor)
53: {
54: vm_offset_t pc;
55: struct sampled_pc *sample;
56:
57: pc = interrupted_pc(t);
58: cp->seqno++;
59: sample = &((sampled_pc_t *)cp->buffer)[cp->seqno % MAX_PC_SAMPLES];
1.1.1.2 ! root 60: sample->id = (vm_offset_t)t;
1.1 root 61: sample->pc = pc;
62: sample->sampletype = flavor;
63: }
64:
65: kern_return_t
66: thread_enable_pc_sampling(
67: thread_t thread,
68: int *tickp,
69: sampled_pc_flavor_t flavors)
70: {
71: vm_offset_t buf;
72:
73: if (thread == THREAD_NULL) {
74: return KERN_INVALID_ARGUMENT;
75: }
76: if (thread->pc_sample.buffer == 0) {
77: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
78: if (buf == 0) {
79: printf("thread_enable_pc_sampling: kalloc failed\n");
80: return KERN_INVALID_ARGUMENT;
81: }
82: thread->pc_sample.buffer = buf;
83: thread->pc_sample.seqno = 0;
84: }
85: *tickp = tick;
86: thread->pc_sample.sampletypes = flavors;
87: return KERN_SUCCESS;
88: }
89:
90: kern_return_t
91: task_enable_pc_sampling(
92: task_t task,
93: int *tickp,
94: sampled_pc_flavor_t flavors)
95: {
96: vm_offset_t buf;
97:
98: if (task == TASK_NULL) {
99: return KERN_INVALID_ARGUMENT;
100: }
101: if (task->pc_sample.buffer == 0) {
102: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
103: if (buf == 0) {
104: printf("task_enable_pc_sampling: kalloc failed\n");
105: return KERN_INVALID_ARGUMENT;
106: }
107: task->pc_sample.buffer = buf;
108: task->pc_sample.seqno = 0;
109: }
110: *tickp = tick;
111: task->pc_sample.sampletypes = flavors;
112: return KERN_SUCCESS;
113: }
114:
115: kern_return_t
116: thread_disable_pc_sampling(
117: thread_t thread,
118: int *samplecntp)
119: {
120: vm_offset_t buf;
121:
122: if (thread == THREAD_NULL) {
123: return KERN_INVALID_ARGUMENT;
124: }
125: if ((buf = thread->pc_sample.buffer) != 0)
126: kfree(buf, sizeof (sampled_pcs));
127: thread->pc_sample.buffer = (vm_offset_t) 0;
128: thread->pc_sample.seqno = 0;
129: thread->pc_sample.sampletypes = 0; /* shut off sampling */
130:
131: return KERN_SUCCESS;
132: }
133:
134: kern_return_t
135: task_disable_pc_sampling(
136: task_t task,
137: int *samplecntp)
138: {
139: vm_offset_t buf;
140:
141: if (task == TASK_NULL) {
142: return KERN_INVALID_ARGUMENT;
143: }
144: if ((buf = task->pc_sample.buffer) != 0)
145: kfree(buf, sizeof (sampled_pcs));
146: task->pc_sample.buffer = (vm_offset_t) 0;
147: task->pc_sample.seqno = 0;
148: task->pc_sample.sampletypes = 0; /* shut off sampling */
149:
150: return KERN_SUCCESS;
151: }
152:
153: static kern_return_t
154: get_sampled_pcs(
155: sample_control_t *cp,
156: sampled_pc_seqno_t *seqnop,
157: sampled_pc_array_t sampled_pcs_out,
158: int *sampled_pcs_cntp)
159: {
160: int nsamples;
161: sampled_pc_seqno_t seqidx1, seqidx2;
162:
163: nsamples = cp->seqno - *seqnop;
164: seqidx1 = *seqnop % MAX_PC_SAMPLES; /* index of *seqnop */
165: seqidx2 = cp->seqno % MAX_PC_SAMPLES; /* index of cp->seqno */
166:
167: if (nsamples > MAX_PC_SAMPLES) {
168: nsamples = MAX_PC_SAMPLES;
169: seqidx1 = (seqidx2 + 1) % MAX_PC_SAMPLES;
170: }
171:
172: if (nsamples > 0) {
173: /*
174: * Carefully copy sampled_pcs into sampled_pcs_msgbuf IN ORDER.
175: */
176: if (seqidx1 < seqidx2) {
177: /*
178: * Simple case: no wraparound.
179: * Copy from seqidx1 to seqidx2.
180: */
1.1.1.2 ! root 181: memcpy(sampled_pcs_out,
! 182: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
! 183: nsamples * sizeof(sampled_pc_t));
1.1 root 184: } else {
185: /* seqidx1 > seqidx2 -- Handle wraparound. */
186:
1.1.1.2 ! root 187: memcpy(sampled_pcs_out,
! 188: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
! 189: (MAX_PC_SAMPLES - seqidx1 - 1) * sizeof(sampled_pc_t));
! 190:
! 191: memcpy(sampled_pcs_out + (MAX_PC_SAMPLES - seqidx1 - 1),
! 192: (sampled_pc_array_t)cp->buffer,
! 193: (seqidx2 + 1) * sizeof(sampled_pc_t));
1.1 root 194: }
195: } else {
196: /* could either be zero because of overflow, or because
197: * we are being lied to. In either case, return nothing.
198: * If overflow, only once in a blue moon. If being lied to,
199: * then we have no obligation to return anything useful anyway.
200: */
201: ;
202: }
203:
204: *sampled_pcs_cntp = nsamples;
205: *seqnop = cp->seqno;
206: return KERN_SUCCESS;
207: }
208:
209: kern_return_t
210: thread_get_sampled_pcs(
211: thread_t thread,
212: sampled_pc_seqno_t *seqnop,
213: sampled_pc_array_t sampled_pcs_out,
214: int *sampled_pcs_cntp)
215: {
216: if (thread == THREAD_NULL)
217: return KERN_INVALID_ARGUMENT;
218:
219: if (thread->pc_sample.buffer == 0)
220: return KERN_FAILURE;
221:
222: return get_sampled_pcs(&thread->pc_sample, seqnop, sampled_pcs_out,
223: sampled_pcs_cntp);
224: }
225:
226: kern_return_t
227: task_get_sampled_pcs(
228: task_t task,
229: sampled_pc_seqno_t *seqnop,
230: sampled_pc_array_t sampled_pcs_out,
231: int *sampled_pcs_cntp)
232: {
233: if (task == TASK_NULL)
234: return KERN_INVALID_ARGUMENT;
235:
236: if (task->pc_sample.buffer == 0)
237: return KERN_FAILURE;
238:
239: return get_sampled_pcs(&task->pc_sample, seqnop, sampled_pcs_out,
240: sampled_pcs_cntp);
241: }
242:
243: #else /* MACH_PCSAMPLE */
244:
245: kern_return_t
246: thread_enable_pc_sampling(
247: thread_t thread,
248: int *tickp,
249: sampled_pc_flavor_t flavors)
250: {
251: return KERN_FAILURE; /* not implemented */
252: }
253:
254: kern_return_t
255: task_enable_pc_sampling(
256: task_t task,
257: int *tickp,
258: sampled_pc_flavor_t flavors)
259: {
260: return KERN_FAILURE; /* not implemented */
261: }
262:
263: kern_return_t
264: thread_disable_pc_sampling(
265: thread_t thread,
266: int *samplecntp)
267: {
268: return KERN_FAILURE; /* not implemented */
269: }
270:
271: kern_return_t
272: task_disable_pc_sampling(
273: task_t task,
274: int *samplecntp)
275: {
276: return KERN_FAILURE; /* not implemented */
277: }
278:
279: kern_return_t
280: thread_get_sampled_pcs(
281: thread_t thread,
282: sampled_pc_seqno_t *seqnop,
283: sampled_pc_array_t sampled_pcs_out,
284: int *sampled_pcs_cntp)
285: {
286: return KERN_FAILURE; /* not implemented */
287: }
288:
289: kern_return_t
290: task_get_sampled_pcs(
291: task_t task,
292: sampled_pc_seqno_t *seqnop,
293: sampled_pc_array_t sampled_pcs_out,
294: int *sampled_pcs_cntp)
295: {
296: return KERN_FAILURE; /* not implemented */
297: }
298:
299: #endif /* MACH_PCSAMPLE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.