⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perfmon.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	for (i = 0; mask; i++, mask>>=1) {		/* skip non used pmds */		if ((mask & 0x1) == 0) continue;		if (PMD_IS_COUNTING(i)) {			/*			 * we split the 64bit value according to			 * counter width			 */			val = ctx->ctx_pmds[i].val & ovfl_mask;			ctx->ctx_pmds[i].val &= ~ovfl_mask;		} else {			val = ctx->ctx_pmds[i].val;		}		ia64_set_pmd(i, val);		DPRINT(("pmd[%d]=0x%lx hw_pmd=0x%lx\n",			i,			ctx->ctx_pmds[i].val,			val));	}	/*	 * restore the PMCs	 */	mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;	for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {		if ((mask & 0x1) == 0UL) continue;		th->pmcs[i] = ctx->ctx_pmcs[i];		ia64_set_pmc(i, th->pmcs[i]);		DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, th->pmcs[i]));	}	ia64_srlz_d();	/*	 * must restore DBR/IBR because could be modified while masked	 * XXX: need to optimize 	 */	if (ctx->ctx_fl_using_dbreg) {		pfm_restore_ibrs(ctx->ctx_ibrs, pmu_conf->num_ibrs);		pfm_restore_dbrs(ctx->ctx_dbrs, pmu_conf->num_dbrs);	}	/*	 * now restore PSR	 */	if (is_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) {		/* enable dcr pp */		ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) | IA64_DCR_PP);		ia64_srlz_i();	}	pfm_set_psr_l(psr);}static inline voidpfm_save_pmds(unsigned long *pmds, unsigned long mask){	int i;	ia64_srlz_d();	for (i=0; mask; i++, mask>>=1) {		if (mask & 0x1) pmds[i] = ia64_get_pmd(i);	}}/* * reload from thread state (used for ctxw only) */static inline voidpfm_restore_pmds(unsigned long *pmds, unsigned long mask){	int i;	unsigned long val, ovfl_val = pmu_conf->ovfl_val;	for (i=0; mask; i++, mask>>=1) {		if ((mask & 0x1) == 0) continue;		val = PMD_IS_COUNTING(i) ? pmds[i] & ovfl_val : pmds[i];		ia64_set_pmd(i, val);	}	ia64_srlz_d();}/* * propagate PMD from context to thread-state */static inline voidpfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx){	struct thread_struct *thread = &task->thread;	unsigned long ovfl_val = pmu_conf->ovfl_val;	unsigned long mask = ctx->ctx_all_pmds[0];	unsigned long val;	int i;	DPRINT(("mask=0x%lx\n", mask));	for (i=0; mask; i++, mask>>=1) {		val = ctx->ctx_pmds[i].val;		/*		 * We break up the 64 bit value into 2 pieces		 * the lower bits go to the machine state in the		 * thread (will be reloaded on ctxsw in).		 * The upper part stays in the soft-counter.		 */		if (PMD_IS_COUNTING(i)) {			ctx->ctx_pmds[i].val = val & ~ovfl_val;			 val &= ovfl_val;		}		thread->pmds[i] = val;		DPRINT(("pmd[%d]=0x%lx soft_val=0x%lx\n",			i,			thread->pmds[i],			ctx->ctx_pmds[i].val));	}}/* * propagate PMC from context to thread-state */static inline voidpfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx){	struct thread_struct *thread = &task->thread;	unsigned long mask = ctx->ctx_all_pmcs[0];	int i;	DPRINT(("mask=0x%lx\n", mask));	for (i=0; mask; i++, mask>>=1) {		/* masking 0 with ovfl_val yields 0 */		thread->pmcs[i] = ctx->ctx_pmcs[i];		DPRINT(("pmc[%d]=0x%lx\n", i, thread->pmcs[i]));	}}static inline voidpfm_restore_pmcs(unsigned long *pmcs, unsigned long mask){	int i;	for (i=0; mask; i++, mask>>=1) {		if ((mask & 0x1) == 0) continue;		ia64_set_pmc(i, pmcs[i]);	}	ia64_srlz_d();}static inline intpfm_uuid_cmp(pfm_uuid_t a, pfm_uuid_t b){	return memcmp(a, b, sizeof(pfm_uuid_t));}static inline intpfm_buf_fmt_exit(pfm_buffer_fmt_t *fmt, struct task_struct *task, void *buf, struct pt_regs *regs){	int ret = 0;	if (fmt->fmt_exit) ret = (*fmt->fmt_exit)(task, buf, regs);	return ret;}static inline intpfm_buf_fmt_getsize(pfm_buffer_fmt_t *fmt, struct task_struct *task, unsigned int flags, int cpu, void *arg, unsigned long *size){	int ret = 0;	if (fmt->fmt_getsize) ret = (*fmt->fmt_getsize)(task, flags, cpu, arg, size);	return ret;}static inline intpfm_buf_fmt_validate(pfm_buffer_fmt_t *fmt, struct task_struct *task, unsigned int flags,		     int cpu, void *arg){	int ret = 0;	if (fmt->fmt_validate) ret = (*fmt->fmt_validate)(task, flags, cpu, arg);	return ret;}static inline intpfm_buf_fmt_init(pfm_buffer_fmt_t *fmt, struct task_struct *task, void *buf, unsigned int flags,		     int cpu, void *arg){	int ret = 0;	if (fmt->fmt_init) ret = (*fmt->fmt_init)(task, buf, flags, cpu, arg);	return ret;}static inline intpfm_buf_fmt_restart(pfm_buffer_fmt_t *fmt, struct task_struct *task, pfm_ovfl_ctrl_t *ctrl, void *buf, struct pt_regs *regs){	int ret = 0;	if (fmt->fmt_restart) ret = (*fmt->fmt_restart)(task, ctrl, buf, regs);	return ret;}static inline intpfm_buf_fmt_restart_active(pfm_buffer_fmt_t *fmt, struct task_struct *task, pfm_ovfl_ctrl_t *ctrl, void *buf, struct pt_regs *regs){	int ret = 0;	if (fmt->fmt_restart_active) ret = (*fmt->fmt_restart_active)(task, ctrl, buf, regs);	return ret;}static pfm_buffer_fmt_t *__pfm_find_buffer_fmt(pfm_uuid_t uuid){	struct list_head * pos;	pfm_buffer_fmt_t * entry;	list_for_each(pos, &pfm_buffer_fmt_list) {		entry = list_entry(pos, pfm_buffer_fmt_t, fmt_list);		if (pfm_uuid_cmp(uuid, entry->fmt_uuid) == 0)			return entry;	}	return NULL;} /* * find a buffer format based on its uuid */static pfm_buffer_fmt_t *pfm_find_buffer_fmt(pfm_uuid_t uuid){	pfm_buffer_fmt_t * fmt;	spin_lock(&pfm_buffer_fmt_lock);	fmt = __pfm_find_buffer_fmt(uuid);	spin_unlock(&pfm_buffer_fmt_lock);	return fmt;} intpfm_register_buffer_fmt(pfm_buffer_fmt_t *fmt){	int ret = 0;	/* some sanity checks */	if (fmt == NULL || fmt->fmt_name == NULL) return -EINVAL;	/* we need at least a handler */	if (fmt->fmt_handler == NULL) return -EINVAL;	/*	 * XXX: need check validity of fmt_arg_size	 */	spin_lock(&pfm_buffer_fmt_lock);	if (__pfm_find_buffer_fmt(fmt->fmt_uuid)) {		printk(KERN_ERR "perfmon: duplicate sampling format: %s\n", fmt->fmt_name);		ret = -EBUSY;		goto out;	} 	list_add(&fmt->fmt_list, &pfm_buffer_fmt_list);	printk(KERN_INFO "perfmon: added sampling format %s\n", fmt->fmt_name);out:	spin_unlock(&pfm_buffer_fmt_lock); 	return ret;}EXPORT_SYMBOL(pfm_register_buffer_fmt);intpfm_unregister_buffer_fmt(pfm_uuid_t uuid){	pfm_buffer_fmt_t *fmt;	int ret = 0;	spin_lock(&pfm_buffer_fmt_lock);	fmt = __pfm_find_buffer_fmt(uuid);	if (!fmt) {		printk(KERN_ERR "perfmon: cannot unregister format, not found\n");		ret = -EINVAL;		goto out;	}	list_del_init(&fmt->fmt_list);	printk(KERN_INFO "perfmon: removed sampling format: %s\n", fmt->fmt_name);out:	spin_unlock(&pfm_buffer_fmt_lock);	return ret;}EXPORT_SYMBOL(pfm_unregister_buffer_fmt);static intpfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu){	unsigned long flags;	/*	 * validy checks on cpu_mask have been done upstream	 */	LOCK_PFS(flags);	DPRINT(("in sys_sessions=%u task_sessions=%u dbregs=%u syswide=%d cpu=%u\n",		pfm_sessions.pfs_sys_sessions,		pfm_sessions.pfs_task_sessions,		pfm_sessions.pfs_sys_use_dbregs,		is_syswide,		cpu));	if (is_syswide) {		/*		 * cannot mix system wide and per-task sessions		 */		if (pfm_sessions.pfs_task_sessions > 0UL) {			DPRINT(("system wide not possible, %u conflicting task_sessions\n",			  	pfm_sessions.pfs_task_sessions));			goto abort;		}		if (pfm_sessions.pfs_sys_session[cpu]) goto error_conflict;		DPRINT(("reserving system wide session on CPU%u currently on CPU%u\n", cpu, smp_processor_id()));		pfm_sessions.pfs_sys_session[cpu] = task;		pfm_sessions.pfs_sys_sessions++ ;	} else {		if (pfm_sessions.pfs_sys_sessions) goto abort;		pfm_sessions.pfs_task_sessions++;	}	DPRINT(("out sys_sessions=%u task_sessions=%u dbregs=%u syswide=%d cpu=%u\n",		pfm_sessions.pfs_sys_sessions,		pfm_sessions.pfs_task_sessions,		pfm_sessions.pfs_sys_use_dbregs,		is_syswide,		cpu));	UNLOCK_PFS(flags);	return 0;error_conflict:	DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",  		pfm_sessions.pfs_sys_session[cpu]->pid,		smp_processor_id()));abort:	UNLOCK_PFS(flags);	return -EBUSY;}static intpfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu){	unsigned long flags;	/*	 * validy checks on cpu_mask have been done upstream	 */	LOCK_PFS(flags);	DPRINT(("in sys_sessions=%u task_sessions=%u dbregs=%u syswide=%d cpu=%u\n",		pfm_sessions.pfs_sys_sessions,		pfm_sessions.pfs_task_sessions,		pfm_sessions.pfs_sys_use_dbregs,		is_syswide,		cpu));	if (is_syswide) {		pfm_sessions.pfs_sys_session[cpu] = NULL;		/*		 * would not work with perfmon+more than one bit in cpu_mask		 */		if (ctx && ctx->ctx_fl_using_dbreg) {			if (pfm_sessions.pfs_sys_use_dbregs == 0) {				printk(KERN_ERR "perfmon: invalid release for ctx %p sys_use_dbregs=0\n", ctx);			} else {				pfm_sessions.pfs_sys_use_dbregs--;			}		}		pfm_sessions.pfs_sys_sessions--;	} else {		pfm_sessions.pfs_task_sessions--;	}	DPRINT(("out sys_sessions=%u task_sessions=%u dbregs=%u syswide=%d cpu=%u\n",		pfm_sessions.pfs_sys_sessions,		pfm_sessions.pfs_task_sessions,		pfm_sessions.pfs_sys_use_dbregs,		is_syswide,		cpu));	UNLOCK_PFS(flags);	return 0;}/* * removes virtual mapping of the sampling buffer. * IMPORTANT: cannot be called with interrupts disable, e.g. inside * a PROTECT_CTX() section. */static intpfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long size){	int r;	/* sanity checks */	if (task->mm == NULL || size == 0UL || vaddr == NULL) {		printk(KERN_ERR "perfmon: pfm_remove_smpl_mapping [%d] invalid context mm=%p\n", task->pid, task->mm);		return -EINVAL;	}	DPRINT(("smpl_vaddr=%p size=%lu\n", vaddr, size));	/*	 * does the actual unmapping	 */	down_write(&task->mm->mmap_sem);	DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size));	r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0);	up_write(&task->mm->mmap_sem);	if (r !=0) {		printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task->pid, vaddr, size);	}	DPRINT(("do_unmap(%p, %lu)=%d\n", vaddr, size, r));	return 0;}/* * free actual physical storage used by sampling buffer */#if 0static intpfm_free_smpl_buffer(pfm_context_t *ctx){	pfm_buffer_fmt_t *fmt;	if (ctx->ctx_smpl_hdr == NULL) goto invalid_free;	/*	 * we won't use the buffer format anymore	 */	fmt = ctx->ctx_buf_fmt;	DPRINT(("sampling buffer @%p size %lu vaddr=%p\n",		ctx->ctx_smpl_hdr,		ctx->ctx_smpl_size,		ctx->ctx_smpl_vaddr));	pfm_buf_fmt_exit(fmt, current, NULL, NULL);	/*	 * free the buffer	 */	pfm_rvfree(ctx->ctx_smpl_hdr, ctx->ctx_smpl_size);	ctx->ctx_smpl_hdr  = NULL;	ctx->ctx_smpl_size = 0UL;	return 0;invalid_free:	printk(KERN_ERR "perfmon: pfm_free_smpl_buffer [%d] no buffer\n", current->pid);	return -EINVAL;}#endifstatic inline voidpfm_exit_smpl_buffer(pfm_buffer_fmt_t *fmt){	if (fmt == NULL) return;	pfm_buf_fmt_exit(fmt, current, NULL, NULL);}/* * pfmfs should _never_ be mounted by userland - too much of security hassle, * no real gain from having the whole whorehouse mounted. So we don't need * any operations on the root directory. However, we need a non-trivial * d_name - pfm: will go nicely and kill the special-casing in procfs. */static struct vfsmount *pfmfs_mnt;static int __initinit_pfm_fs(void){	int err = register_filesystem(&pfm_fs_type);	if (!err) {		pfmfs_mnt = kern_mount(&pfm_fs_type);		err = PTR_ERR(pfmfs_mnt);		if (IS_ERR(pfmfs_mnt))			unregister_filesystem(&pfm_fs_type);		else			err = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -