示例#1
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();
}
示例#2
0
void
_profile_md_init(struct profile_vars *pv,
		 profile_type_t type,
		 profile_alloc_mem_t alloc_mem)
{
	size_t page_size = pv->page_size;
	size_t arc_size;
	size_t func_size;
	size_t misc_size;
	size_t hash_size;
	size_t extra_arc_size;
	size_t extra_func_size;
	size_t callback_size = page_size;
	void *ptr;
	acontext_type_t ac;
	int i;
	static struct {
		size_t	    c_size;		/* size C thinks structure is */
		size_t	   *asm_size_ptr;	/* pointer to size asm thinks struct is */
		const char *name;		/* structure name */
	} sizes[] = {
		{ sizeof(struct profile_profil), &_profile_profil_size,	"profile_profil" },
		{ sizeof(struct profile_stats),	 &_profile_stats_size,	"profile_stats" },
		{ sizeof(struct profile_md),	 &_profile_md_size,	"profile_md" },
		{ sizeof(struct profile_vars),	 &_profile_size,	"profile_vars" }};

#ifdef DEBUG_PROFILE
	_profile_printf("_profile_md_init: pv = 0x%lx, type = %d, alloc = %d\n",
			(long) pv,
			(int)type,
			(int)alloc_mem);
#endif

	for (i = 0; i < sizeof (sizes) / sizeof(sizes[0]); i++) {
		if (sizes[i].c_size != *sizes[i].asm_size_ptr) {
			_profile_printf("C thinks struct %s is %ld bytes, asm thinks it is %ld bytes\n",
					sizes[i].name,
					(long)sizes[i].c_size,
					(long)*sizes[i].asm_size_ptr);

			panic(sizes[i].name);
		}
	}

	/* Figure out which function will handle compiler generated profiling */
	if (type == PROFILE_GPROF) {
		pv->md.save_mcount_ptr = _gprof_mcount;

	} else if (type == PROFILE_PROF) {
		pv->md.save_mcount_ptr = _prof_mcount;

	} else {
		pv->md.save_mcount_ptr = _dummy_mcount;
	}

	pv->vars_size         = sizeof(struct profile_vars);
	pv->plist_size        = sizeof(struct page_list);
	pv->acontext_size     = sizeof(struct alloc_context);
	pv->callback_size     = sizeof(struct callback);
	pv->major_version     = PROFILE_MAJOR_VERSION;
	pv->minor_version     = PROFILE_MINOR_VERSION;
	pv->type              = type;
	pv->do_profile        = 1;
	pv->use_dci	      = 1;
	pv->use_profil	      = 1;
	pv->output_uarea      = 1;
	pv->output_stats      = (prof_flag_t) _profile_do_stats;
	pv->output_clock      = 1;
	pv->multiple_sections = 1;
	pv->init_format	      = 0;
	pv->bogus_func	      = _bogus_function;

#ifdef DEBUG_PROFILE
	pv->debug	      = 1;
#endif

	if (!pv->error_msg) {
		pv->error_msg = "error in profiling";
	}

	if (!pv->page_size) {
		pv->page_size = 4096;
	}

	pv->stats.stats_size    = sizeof(struct profile_stats);
	pv->stats.major_version = PROFILE_MAJOR_VERSION;
	pv->stats.minor_version = PROFILE_MINOR_VERSION;

	pv->md.md_size	       = sizeof(struct profile_md);
	pv->md.major_version   = PROFILE_MAJOR_VERSION;
	pv->md.minor_version   = PROFILE_MINOR_VERSION;
	pv->md.hash_size       = _profile_hash_size;
	pv->md.num_cache       = MAX_CACHE;
	pv->md.mcount_ptr_ptr  = &_mcount_ptr;
	pv->md.dummy_ptr       = &_gprof_dummy;
	pv->md.alloc_pages     = _profile_alloc_pages;

	/* zero out all allocation context blocks */
	for (ac = ACONTEXT_FIRST; ac < ACONTEXT_MAX; ac++) {
		pv->acontext[ac] = (struct alloc_context *)0;
	}

	/* Don't allocate memory if not desired */
	if (!alloc_mem) {
		return;
	}

	/* Allocate some space for the initial allocations */
	switch (type) {
	default:
		misc_size = page_size;
		ptr = _profile_alloc_pages(misc_size + callback_size);
		ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
		ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);
		break;

	case PROFILE_GPROF:

#if defined(MACH_KERNEL) || defined(_KERNEL)
		/*
		 * For the MK & server allocate some slop space now for the
		 * secondary context blocks in case allocations are done at
		 * interrupt level when another allocation is being done.  This
		 * is done before the main allocation blocks and will be pushed
		 * so that it will only be used when the main allocation block
		 * is locked.
		 */
		extra_arc_size = 4*page_size;
		extra_func_size = 2*page_size;
#else
		extra_arc_size = extra_func_size = 0;
#endif

		/* Set up allocation areas */
		arc_size = ROUNDUP(PROFILE_NUM_ARCS * sizeof(struct hasharc), page_size);
		func_size = ROUNDUP(PROFILE_NUM_FUNCS * sizeof(struct gfuncs), page_size);
		hash_size = _profile_hash_size * sizeof (struct hasharc *);
		misc_size = ROUNDUP(hash_size + page_size, page_size);

		ptr = _profile_alloc_pages(arc_size
					   + func_size
					   + misc_size
					   + callback_size
					   + extra_arc_size
					   + extra_func_size);

#if defined(MACH_KERNEL) || defined(_KERNEL)
		ptr = _profile_md_acontext(pv, ptr, extra_arc_size, ACONTEXT_GPROF);
		ptr = _profile_md_acontext(pv, ptr, extra_func_size, ACONTEXT_GFUNC);
#endif
		ptr = _profile_md_acontext(pv, ptr, arc_size, ACONTEXT_GPROF);
		ptr = _profile_md_acontext(pv, ptr, func_size, ACONTEXT_GFUNC);
		ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
		ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);

		/* Allocate hash table */
		pv->md.hash_ptr = (struct hasharc **) _profile_alloc(pv, hash_size, ACONTEXT_MISC);
		break;

	case PROFILE_PROF:
		/* Set up allocation areas */
		func_size = ROUNDUP(PROFILE_NUM_FUNCS * sizeof(struct prof_ext), page_size);
		misc_size = page_size;

		ptr = _profile_alloc_pages(func_size
					   + misc_size
					   + callback_size);

		ptr = _profile_md_acontext(pv, ptr, func_size, ACONTEXT_PROF);
		ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
		ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);
		break;
	}
}