|
|
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.