|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Microkernel interface to common profiling.
27: */
28:
29: #include <profiling/profile-mk.h>
30: #include <string.h>
31: #include <kern/cpu_number.h>
32: #include <kern/processor.h>
33: #include <kern/spl.h>
34: #include <kern/misc_protos.h>
35: #include <vm/vm_kern.h>
36: #include <mach/vm_param.h>
37:
38: #include <device/ds_routines.h>
39: #include <device/io_req.h>
40: #include <device/buf.h>
41:
42: extern char etext[], pstart[];
43:
44: #if NCPUS > 1
45: struct profile_vars *_profile_vars_cpus[NCPUS] = { &_profile_vars };
46: struct profile_vars _profile_vars_aux[NCPUS-1];
47: #endif
48:
49: void *
50: _profile_alloc_pages (size_t size)
51: {
52: vm_offset_t addr;
53:
54: /*
55: * For the MK, we can't support allocating pages at runtime, because we
56: * might be at interrupt level, so abort if we didn't size the table
57: * properly.
58: */
59:
60: if (PROFILE_VARS(0)->active) {
61: panic("Call to _profile_alloc_pages while profiling is running.");
62: }
63:
64: if (kmem_alloc(kernel_map, &addr, size)) {
65: panic("Could not allocate memory for profiling");
66: }
67:
68: memset((void *)addr, '\0', size);
69: if (PROFILE_VARS(0)->debug) {
70: printf("Allocated %d bytes for profiling, address 0x%x\n", (int)size, (int)addr);
71: }
72:
73: return((caddr_t)addr);
74: }
75:
76: void
77: _profile_free_pages(void *addr, size_t size)
78: {
79: if (PROFILE_VARS(0)->debug) {
80: printf("Freed %d bytes for profiling, address 0x%x\n", (int)size, (int)addr);
81: }
82:
83: kmem_free(kernel_map, (vm_offset_t)addr, size);
84: return;
85: }
86:
87: void _profile_error(struct profile_vars *pv)
88: {
89: panic("Fatal error in profiling");
90: }
91:
92: void
93: kmstartup(void)
94: {
95: prof_uptrint_t textsize;
96: prof_uptrint_t monsize;
97: prof_uptrint_t lowpc;
98: prof_uptrint_t highpc;
99: int i;
100: struct profile_vars *pv;
101:
102: /*
103: * round lowpc and highpc to multiples of the density we're using
104: * so the rest of the scaling (here and in gprof) stays in ints.
105: */
106:
107: lowpc = ROUNDDOWN((prof_uptrint_t)&pstart[0], HISTFRACTION*sizeof(LHISTCOUNTER));
108: highpc = ROUNDUP((prof_uptrint_t)&etext[0], HISTFRACTION*sizeof(LHISTCOUNTER));
109: textsize = highpc - lowpc;
110: monsize = (textsize / HISTFRACTION) * sizeof(LHISTCOUNTER);
111:
112: for (i = 0; i < NCPUS; i++) {
113: pv = PROFILE_VARS(i);
114:
115: #if NCPUS > 1
116: if (!pv) {
117: _profile_vars_cpus[i] = pv = &_profile_vars_aux[i-i];
118: }
119: #endif
120:
121: #ifdef DEBUG_PROFILE
122: pv->debug = 1;
123: #endif
124: pv->page_size = PAGE_SIZE;
125: _profile_md_init(pv, PROFILE_GPROF, PROFILE_ALLOC_MEM_YES);
126:
127: /* Profil related variables */
128: pv->profil_buf = _profile_alloc (pv, monsize, ACONTEXT_PROFIL);
129: pv->profil_info.highpc = highpc;
130: pv->profil_info.lowpc = lowpc;
131: pv->profil_info.text_len = textsize;
132: pv->profil_info.profil_len = monsize;
133: pv->profil_info.counter_size = sizeof(LHISTCOUNTER);
134: pv->profil_info.scale = 0x10000 / HISTFRACTION;
135: pv->stats.profil_buckets = monsize / sizeof(LHISTCOUNTER);
136:
137: /* Other gprof variables */
138: pv->stats.my_cpu = i;
139: pv->stats.max_cpu = NCPUS;
140: pv->init = 1;
141: pv->active = 1;
142: pv->use_dci = 0;
143: pv->use_profil = 1;
144: pv->check_funcs = 1; /* for now */
145:
146: if (pv->debug) {
147: printf("Profiling kernel, s_textsize=%ld, monsize=%ld [0x%lx..0x%lx], cpu = %d\n",
148: (long)textsize,
149: (long)monsize,
150: (long)lowpc,
151: (long)highpc,
152: i);
153: }
154: }
155:
156: _profile_md_start();
157: }
158:
159: /* driver component */
160:
161: int
162: gprofprobe(caddr_t port, void *ctlr)
163: {
164: return(1);
165: }
166:
167: void
168: gprofattach(void)
169: {
170: kmstartup();
171: return;
172: }
173:
174: /* struct bus_device *gprofinfo[NGPROF]; */
175: struct bus_device *gprofinfo[1];
176:
177: struct bus_driver gprof_driver = {
178: gprofprobe, 0, gprofattach, 0, 0, "gprof", gprofinfo, "gprofc", 0, 0};
179:
180:
181: io_return_t
182: gprofopen(dev_t dev,
183: int flags,
184: io_req_t ior)
185: {
186: ior->io_error = D_SUCCESS;
187: return(0);
188: }
189:
190: void
191: gprofclose(dev_t dev)
192: {
193: return;
194: }
195:
196: void
197: gprofstrategy(io_req_t ior)
198: {
199: void *sys_ptr = (void *)0;
200:
201: long count = _profile_kgmon(!(ior->io_op & IO_READ),
202: ior->io_count,
203: ior->io_recnum,
204: NCPUS,
205: &sys_ptr,
206: (void (*)(kgmon_control_t))0);
207:
208: if (count < 0) {
209: ior->io_error = D_INVALID_RECNUM;
210:
211: } else {
212: if (count > 0 && sys_ptr != (void *)0) {
213: if (ior->io_op & IO_READ) {
214: memcpy((void *)ior->io_data, sys_ptr, count);
215: } else {
216: memcpy(sys_ptr, (void *)ior->io_data, count);
217: }
218: }
219:
220: ior->io_error = D_SUCCESS;
221: ior->io_residual = ior->io_count - count;
222: }
223:
224: iodone(ior);
225: }
226:
227: io_return_t
228: gprofread(dev_t dev,
229: io_req_t ior)
230: {
231: return(block_io(gprofstrategy, minphys, ior));
232: }
233:
234: io_return_t
235: gprofwrite(dev_t dev,
236: io_req_t ior)
237: {
238: return (block_io(gprofstrategy, minphys, ior));
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.