|
|
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 root 49: sampled_pc_flavor_t flavor)
50: {
51: vm_offset_t pc;
52: struct sampled_pc *sample;
53:
54: pc = interrupted_pc(t);
55: cp->seqno++;
56: sample = &((sampled_pc_t *)cp->buffer)[cp->seqno % MAX_PC_SAMPLES];
1.1.1.2 root 57: sample->id = (vm_offset_t)t;
1.1 root 58: sample->pc = pc;
59: sample->sampletype = flavor;
60: }
61:
62: kern_return_t
63: thread_enable_pc_sampling(
64: thread_t thread,
65: int *tickp,
66: sampled_pc_flavor_t flavors)
67: {
68: vm_offset_t buf;
69:
70: if (thread == THREAD_NULL) {
71: return KERN_INVALID_ARGUMENT;
72: }
73: if (thread->pc_sample.buffer == 0) {
74: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
75: if (buf == 0) {
76: printf("thread_enable_pc_sampling: kalloc failed\n");
77: return KERN_INVALID_ARGUMENT;
78: }
79: thread->pc_sample.buffer = buf;
80: thread->pc_sample.seqno = 0;
81: }
82: *tickp = tick;
83: thread->pc_sample.sampletypes = flavors;
84: return KERN_SUCCESS;
85: }
86:
87: kern_return_t
88: task_enable_pc_sampling(
89: task_t task,
90: int *tickp,
91: sampled_pc_flavor_t flavors)
92: {
93: vm_offset_t buf;
94:
95: if (task == TASK_NULL) {
96: return KERN_INVALID_ARGUMENT;
97: }
98: if (task->pc_sample.buffer == 0) {
99: buf = (vm_offset_t) kalloc(sizeof (sampled_pcs));
100: if (buf == 0) {
101: printf("task_enable_pc_sampling: kalloc failed\n");
102: return KERN_INVALID_ARGUMENT;
103: }
104: task->pc_sample.buffer = buf;
105: task->pc_sample.seqno = 0;
106: }
107: *tickp = tick;
108: task->pc_sample.sampletypes = flavors;
109: return KERN_SUCCESS;
110: }
111:
112: kern_return_t
113: thread_disable_pc_sampling(
114: thread_t thread,
115: int *samplecntp)
116: {
117: vm_offset_t buf;
118:
119: if (thread == THREAD_NULL) {
120: return KERN_INVALID_ARGUMENT;
121: }
122: if ((buf = thread->pc_sample.buffer) != 0)
123: kfree(buf, sizeof (sampled_pcs));
124: thread->pc_sample.buffer = (vm_offset_t) 0;
125: thread->pc_sample.seqno = 0;
126: thread->pc_sample.sampletypes = 0; /* shut off sampling */
127:
128: return KERN_SUCCESS;
129: }
130:
131: kern_return_t
132: task_disable_pc_sampling(
133: task_t task,
134: int *samplecntp)
135: {
136: vm_offset_t buf;
137:
138: if (task == TASK_NULL) {
139: return KERN_INVALID_ARGUMENT;
140: }
141: if ((buf = task->pc_sample.buffer) != 0)
142: kfree(buf, sizeof (sampled_pcs));
143: task->pc_sample.buffer = (vm_offset_t) 0;
144: task->pc_sample.seqno = 0;
145: task->pc_sample.sampletypes = 0; /* shut off sampling */
146:
147: return KERN_SUCCESS;
148: }
149:
150: static kern_return_t
151: get_sampled_pcs(
152: sample_control_t *cp,
153: sampled_pc_seqno_t *seqnop,
154: sampled_pc_array_t sampled_pcs_out,
155: int *sampled_pcs_cntp)
156: {
157: int nsamples;
158: sampled_pc_seqno_t seqidx1, seqidx2;
159:
160: nsamples = cp->seqno - *seqnop;
161: seqidx1 = *seqnop % MAX_PC_SAMPLES; /* index of *seqnop */
162: seqidx2 = cp->seqno % MAX_PC_SAMPLES; /* index of cp->seqno */
163:
164: if (nsamples > MAX_PC_SAMPLES) {
165: nsamples = MAX_PC_SAMPLES;
166: seqidx1 = (seqidx2 + 1) % MAX_PC_SAMPLES;
167: }
168:
169: if (nsamples > 0) {
170: /*
171: * Carefully copy sampled_pcs into sampled_pcs_msgbuf IN ORDER.
172: */
173: if (seqidx1 < seqidx2) {
174: /*
175: * Simple case: no wraparound.
176: * Copy from seqidx1 to seqidx2.
177: */
1.1.1.2 root 178: memcpy(sampled_pcs_out,
179: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
180: nsamples * sizeof(sampled_pc_t));
1.1 root 181: } else {
182: /* seqidx1 > seqidx2 -- Handle wraparound. */
183:
1.1.1.2 root 184: memcpy(sampled_pcs_out,
185: (sampled_pc_array_t)cp->buffer + seqidx1 + 1,
186: (MAX_PC_SAMPLES - seqidx1 - 1) * sizeof(sampled_pc_t));
187:
188: memcpy(sampled_pcs_out + (MAX_PC_SAMPLES - seqidx1 - 1),
189: (sampled_pc_array_t)cp->buffer,
190: (seqidx2 + 1) * sizeof(sampled_pc_t));
1.1 root 191: }
1.1.1.3 ! root 192: } else if (nsamples < 0) {
! 193: /* Bogus SEQNO supplied. */
! 194: nsamples = 0;
1.1 root 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(
1.1.1.3 ! root 247: const thread_t thread,
! 248: const int *tickp,
1.1 root 249: sampled_pc_flavor_t flavors)
250: {
251: return KERN_FAILURE; /* not implemented */
252: }
253:
254: kern_return_t
255: task_enable_pc_sampling(
1.1.1.3 ! root 256: const task_t task,
! 257: const int *tickp,
1.1 root 258: sampled_pc_flavor_t flavors)
259: {
260: return KERN_FAILURE; /* not implemented */
261: }
262:
263: kern_return_t
264: thread_disable_pc_sampling(
1.1.1.3 ! root 265: const thread_t thread,
! 266: const int *samplecntp)
1.1 root 267: {
268: return KERN_FAILURE; /* not implemented */
269: }
270:
271: kern_return_t
272: task_disable_pc_sampling(
1.1.1.3 ! root 273: const task_t task,
! 274: const int *samplecntp)
1.1 root 275: {
276: return KERN_FAILURE; /* not implemented */
277: }
278:
279: kern_return_t
280: thread_get_sampled_pcs(
1.1.1.3 ! root 281: const thread_t thread,
! 282: const sampled_pc_seqno_t *seqnop,
! 283: const sampled_pc_array_t sampled_pcs_out,
! 284: const int *sampled_pcs_cntp)
1.1 root 285: {
286: return KERN_FAILURE; /* not implemented */
287: }
288:
289: kern_return_t
290: task_get_sampled_pcs(
1.1.1.3 ! root 291: const task_t task,
! 292: const sampled_pc_seqno_t *seqnop,
! 293: const sampled_pc_array_t sampled_pcs_out,
! 294: const int *sampled_pcs_cntp)
1.1 root 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.