Exemple #1
0
void *
_profile_alloc_pages (size_t size)
{
	vm_offset_t addr;

	/*
	 * For the MK, we can't support allocating pages at runtime, because we
	 * might be at interrupt level, so abort if we didn't size the table
	 * properly.
	 */

	if (PROFILE_VARS(0)->active) {
		panic("Call to _profile_alloc_pages while profiling is running.");
	}

	if (kmem_alloc(kernel_map, &addr, size)) {
		panic("Could not allocate memory for profiling");
	}

	memset((void *)addr, '\0', size);
	if (PROFILE_VARS(0)->debug) {
		printf("Allocated %d bytes for profiling, address 0x%x\n", (int)size, (int)addr);
	}

	return((caddr_t)addr);
}
Exemple #2
0
void
_profile_free_pages(void *addr, size_t size)
{
	if (PROFILE_VARS(0)->debug) {
		printf("Freed %d bytes for profiling, address 0x%x\n", (int)size, (int)addr);
	}

	kmem_free(kernel_map, (vm_offset_t)addr, size);
	return;
}
long
_profile_kgmon(int write,
	       size_t count,
	       long indx,
	       int max_cpus,
	       void **p_ptr,
	       void (*control_func)(kgmon_control_t))
{
	kgmon_control_t kgmon;
	int cpu;
	int error = 0;
	int i;
	struct profile_vars *pv;
	static struct callback dummy_callback;

	*p_ptr = (void *)0;

	/*
	 * If the number passed is not within bounds, just copy the data directly.
	 */

	if (!LEGAL_KGMON(indx)) {
		*p_ptr = (void *)indx;
		if (!write) {
			if (PROFILE_VARS(0)->debug) {
				printf("_profile_kgmon: copy %5ld bytes, from 0x%lx\n",
				       (long)count,
				       (long)indx);
			}

		} else {
			if (PROFILE_VARS(0)->debug) {
				printf("_profile_kgmon: copy %5ld bytes, to 0x%lx\n",
				       (long)count,
				       (long)indx);
			}
		}			

		return count;
	}

	/*
	 * Decode the record number into the component pieces.
	 */

	DECODE_KGMON(indx, kgmon, cpu);

	if (PROFILE_VARS(0)->debug) {
		printf("_profile_kgmon: start: kgmon control = %2d, cpu = %d, count = %ld\n",
		       kgmon, cpu, (long)count);
	}

	/* Validate the CPU number */
	if (cpu < 0 || cpu >= max_cpus) {
		if (PROFILE_VARS(0)->debug) {
			printf("KGMON, bad cpu %d\n", cpu);
		}

		return -1;

	} else {
		pv = PROFILE_VARS(cpu);

		if (!write) {
			switch (kgmon) {
			default:
				if (PROFILE_VARS(0)->debug) {
					printf("Unknown KGMON read command\n");
				}

				error = -1;
				break;

			case KGMON_GET_STATUS:		/* return whether or not profiling is active */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_STATUS: cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (count != sizeof(pv->active)) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_STATUS: count = %ld, should be %ld\n",
						       (long)count,
						       (long)sizeof(pv->active));
					}

					error = -1;
					break;
				}

				*p_ptr = (void *)&pv->active;
				break;

			case KGMON_GET_DEBUG:		/* return whether or not debugging is active */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_DEBUG: cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (count != sizeof(pv->debug)) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_DEBUG: count = %ld, should be %ld\n",
						       (long)count,
						       (long)sizeof(pv->active));
					}

					error = -1;
					break;
				}

				*p_ptr = (void *)&pv->debug;
				break;

			case KGMON_GET_PROFILE_VARS:	/* return the _profile_vars structure */
				if (count != sizeof(struct profile_vars)) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_PROFILE_VARS: count = %ld, should be %ld\n",
						       (long)count,
						       (long)sizeof(struct profile_vars));
					}

					error = -1;
					break;
				}

				_profile_update_stats(pv);
				*p_ptr = (void *)pv;
				break;

			case KGMON_GET_PROFILE_STATS:	/* return the _profile_stats structure */
				if (count != sizeof(struct profile_stats)) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_GET_PROFILE_STATS: count = %ld, should be = %ld\n",
						       (long)count,
						       (long)sizeof(struct profile_stats));
					}

					error = -1;
					break;
				}

				_profile_update_stats(pv);
				*p_ptr = (void *)&pv->stats;
				break;
			}

		} else {
			switch (kgmon) {
			default:
				if (PROFILE_VARS(0)->debug) {
					printf("Unknown KGMON write command\n");
				}

				error = -1;
				break;

			case KGMON_SET_PROFILE_ON:	/* turn on profiling */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_SET_PROFILE_ON, cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (!PROFILE_VARS(0)->active) {
					for (i = 0; i < max_cpus; i++) {
						PROFILE_VARS(i)->active = 1;
					}

					if (control_func) {
						(*control_func)(kgmon);
					}

					_profile_md_start();
				}

				count = 0;
				break;

			case KGMON_SET_PROFILE_OFF:	/* turn off profiling */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_SET_PROFILE_OFF, cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (PROFILE_VARS(0)->active) {
					for (i = 0; i < max_cpus; i++) {
						PROFILE_VARS(i)->active = 0;
					}

					_profile_md_stop();

					if (control_func) {
						(*control_func)(kgmon);
					}
				}

				count = 0;
				break;

			case KGMON_SET_PROFILE_RESET:	/* reset profiling */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_SET_PROFILE_RESET, cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				for (i = 0; i < max_cpus; i++) {
					_profile_reset(PROFILE_VARS(i));
				}

				if (control_func) {
					(*control_func)(kgmon);
				}

				count = 0;
				break;

			case KGMON_SET_DEBUG_ON:	/* turn on profiling */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_SET_DEBUG_ON, cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (!PROFILE_VARS(0)->debug) {
					for (i = 0; i < max_cpus; i++) {
						PROFILE_VARS(i)->debug = 1;
					}

					if (control_func) {
						(*control_func)(kgmon);
					}
				}

				count = 0;
				break;

			case KGMON_SET_DEBUG_OFF:	/* turn off profiling */
				if (cpu != 0) {
					if (PROFILE_VARS(0)->debug) {
						printf("KGMON_SET_DEBUG_OFF, cpu = %d\n", cpu);
					}

					error = -1;
					break;
				}

				if (PROFILE_VARS(0)->debug) {
					for (i = 0; i < max_cpus; i++) {
						PROFILE_VARS(i)->debug = 0;
					}

					if (control_func) {
						(*control_func)(kgmon);
					}
				}

				count = 0;
				break;
			}
		}
	}

	if (error) {
		if (PROFILE_VARS(0)->debug) {
			printf("_profile_kgmon: done:  kgmon control = %2d, cpu = %d, error = %d\n",
			       kgmon, cpu, error);
		}

		return -1;
	}

	if (PROFILE_VARS(0)->debug) {
		printf("_profile_kgmon: done:  kgmon control = %2d, cpu = %d, count = %ld\n",
		       kgmon, cpu, (long)count);
	}

	return count;
}
Exemple #4
0
void
kmstartup(void)
{
	prof_uptrint_t textsize;
	prof_uptrint_t monsize;
	prof_uptrint_t lowpc;
	prof_uptrint_t highpc;
	int i;
	struct profile_vars *pv;

	/*
	 * round lowpc and highpc to multiples of the density we're using
	 * so the rest of the scaling (here and in gprof) stays in ints.
	 */

	lowpc = ROUNDDOWN((prof_uptrint_t)&pstart[0], HISTFRACTION*sizeof(LHISTCOUNTER));
	highpc = ROUNDUP((prof_uptrint_t)&etext[0], HISTFRACTION*sizeof(LHISTCOUNTER));
	textsize = highpc - lowpc;
	monsize = (textsize / HISTFRACTION) * sizeof(LHISTCOUNTER);

	for (i = 0; i < NCPUS; i++) {
		pv = PROFILE_VARS(i);

#if NCPUS > 1
		if (!pv) {
			_profile_vars_cpus[i] = pv = &_profile_vars_aux[i-i];
		}
#endif

#ifdef DEBUG_PROFILE
		pv->debug = 1;
#endif
		pv->page_size = PAGE_SIZE;
		_profile_md_init(pv, PROFILE_GPROF, PROFILE_ALLOC_MEM_YES);

		/* Profil related variables */
		pv->profil_buf = _profile_alloc (pv, monsize, ACONTEXT_PROFIL);
		pv->profil_info.highpc = highpc;
		pv->profil_info.lowpc = lowpc;
		pv->profil_info.text_len = textsize;
		pv->profil_info.profil_len = monsize;
		pv->profil_info.counter_size = sizeof(LHISTCOUNTER);
		pv->profil_info.scale = 0x10000 / HISTFRACTION;
		pv->stats.profil_buckets = monsize / sizeof(LHISTCOUNTER);

		/* Other gprof variables */
		pv->stats.my_cpu = i;
		pv->stats.max_cpu = NCPUS;
		pv->init = 1;
		pv->active = 1;
		pv->use_dci = 0;
		pv->use_profil = 1;
		pv->check_funcs = 1;		/* for now */

		if (pv->debug) {
			printf("Profiling kernel, s_textsize=%ld, monsize=%ld [0x%lx..0x%lx], cpu = %d\n",
			       (long)textsize,
			       (long)monsize,
			       (long)lowpc,
			       (long)highpc,
			       i);
		}
	}

	_profile_md_start();
}