Пример #1
0
static int sys_vperfctr_read_sum(struct vperfctr *perfctr,
				 struct perfctr_struct_buf *argp,
				 const struct task_struct *tsk)
{
	struct perfctr_sum_ctrs sum;

	if (tsk == current) {
		preempt_disable();
		vperfctr_sample(perfctr);
	}
	//sum = perfctr->cpu_state.sum;
	{
		int j;
		sum.tsc = perfctr->cpu_state.tsc_sum;
		for(j = 0; j < ARRAY_SIZE(sum.pmc); ++j)
			sum.pmc[j] = perfctr->cpu_state.pmc[j].sum;
	}
	if (tsk == current)
		preempt_enable();
	return perfctr_copy_to_user(argp, &sum, &perfctr_sum_ctrs_sdesc);
}
Пример #2
0
static int do_vperfctr_read(struct vperfctr *perfctr,
			    unsigned int domain,
			    void __user *dstp,
			    unsigned int dstbytes,
			    struct task_struct *tsk)
{
	union {
		struct perfctr_sum_ctrs sum;
		struct vperfctr_control control;
		struct perfctr_sum_ctrs children;
	} *tmp;
	unsigned int tmpbytes;
	int ret;

	tmpbytes = dstbytes;
	if (tmpbytes > PAGE_SIZE) /* primitive sanity check */
		return -EINVAL;
	if (tmpbytes < sizeof(*tmp))
		tmpbytes = sizeof(*tmp);
	tmp = kmem_alloc(tmpbytes);
	if (!tmp)
		return -ENOMEM;

	/* PREEMPT note: While we're reading our own control, another
	   process may ptrace ATTACH to us and update our control.
	   Disable preemption to ensure we get a consistent copy.
	   Not needed for other cases since the perfctr is either
	   unlinked or its owner is ptrace ATTACH suspended by us. */

	switch (domain) {
	case VPERFCTR_DOMAIN_SUM: {
		int j;

		vperfctr_sample(perfctr);
		tmp->sum.tsc = perfctr->cpu_state.user.tsc_sum;
		for(j = 0; j < ARRAY_SIZE(tmp->sum.pmc); ++j)
			tmp->sum.pmc[j] = perfctr->cpu_state.user.pmc[j].sum;
		ret = sizeof(tmp->sum);
		break;
	}
	case VPERFCTR_DOMAIN_CONTROL:
		tmp->control.si_signo = perfctr->si_signo;
		tmp->control.preserve = perfctr->preserve;
		ret = sizeof(tmp->control);
		break;
	case VPERFCTR_DOMAIN_CHILDREN:
		if (tsk)
			spin_lock(&perfctr->children_lock);
		tmp->children = perfctr->children;
		if (tsk)
			spin_unlock(&perfctr->children_lock);
		ret = sizeof(tmp->children);
		break;
	case PERFCTR_DOMAIN_CPU_CONTROL:
		if (tmpbytes > sizeof(perfctr->cpu_state.control.header))
			tmpbytes = sizeof(perfctr->cpu_state.control.header);
		memcpy(tmp, &perfctr->cpu_state.control.header, tmpbytes);
		ret = tmpbytes;
		break;
	case PERFCTR_DOMAIN_CPU_MAP:
		if (tmpbytes > sizeof(perfctr->cpu_state.control.pmc_map))
			tmpbytes = sizeof(perfctr->cpu_state.control.pmc_map);
		memcpy(tmp, perfctr->cpu_state.control.pmc_map, tmpbytes);
		ret = tmpbytes;
		break;
	default:
		ret = -EFAULT;
		if (copy_from_user(tmp, dstp, dstbytes) == 0)
			ret = perfctr_cpu_control_read(&perfctr->cpu_state.control,
						       domain, tmp, dstbytes);
	}

	if (ret > 0) {
		if (ret > dstbytes)
			ret = dstbytes;
		if (ret > 0 && copy_to_user(dstp, tmp, ret))
			ret = -EFAULT;
	}
	kmem_free(tmp);
	return ret;
}
Пример #3
0
/* Called from update_one_process() [triggered by timer interrupt].
 * PRE: perfctr == current->thread.perfctr.
 * Sample the counters but do not suspend them.
 * Needed to avoid precision loss due to multiple counter
 * wraparounds between resume/suspend for CPU-bound processes.
 * PREEMPT note: called in IRQ context with preemption disabled.
 */
void __vperfctr_sample(struct vperfctr *perfctr)
{
	if (perfctr->sampling_timer == 0)
		vperfctr_sample(perfctr);
}
Пример #4
0
// sys_vperfctr_read() -> this()
static int do_vperfctr_read(struct vperfctr *perfctr,
			    unsigned int cmd,
			    void __user *argp,
			    unsigned int argbytes,
			    struct task_struct *tsk)
{
	union {
		struct perfctr_sum_ctrs sum;
		struct vperfctr_control control;
		struct perfctr_sum_ctrs children;
	} *tmp;
	unsigned int tmpbytes;
	int ret;

	/* The state snapshot can be large, so kmalloc() it instead of storing it on the stack.
	   We must use task-private storage to prevent racing with a monitor process attaching to 
	   us during the preemptible copy_to_user() step. Therefore we cannot store the snapshot
	   in the perfctr object itself. 
    */
	tmp = kmalloc(sizeof(*tmp), GFP_USER);
	if (!tmp)
		return -ENOMEM;

	/* PREEMPT note: While we're reading our own control, another process may ptrace ATTACH 
       to us and update our control. Disable preemption to ensure we get a consistent copy.
	   Not needed for other cases since the perfctr is either unlinked or its owner is ptrace 
       ATTACH suspended by us. 
	*/
	if (tsk == current)
		preempt_disable();

	switch (cmd) {
    	case VPERFCTR_READ_SUM: {
    		int j;
    
    		vperfctr_sample(perfctr);
    		tmp->sum.tsc = perfctr->cpu_state.tsc_sum;
    		for(j = 0; j < ARRAY_SIZE(tmp->sum.pmc); ++j)
    			tmp->sum.pmc[j] = perfctr->cpu_state.pmc[j].sum;
    		tmpbytes = sizeof(tmp->sum);
    	}
    	break;
    	case VPERFCTR_READ_CONTROL:
    		tmp->control.si_signo = perfctr->si_signo;
    		tmp->control.cpu_control = perfctr->cpu_state.control;
    		tmp->control.preserve = 0;
    		tmpbytes = sizeof(tmp->control);
    	break;
    	case VPERFCTR_READ_CHILDREN:
    		if (tsk)
    			spin_lock(&perfctr->children_lock);
    		tmp->children = perfctr->children;
    		if (tsk)
    			spin_unlock(&perfctr->children_lock);
    		tmpbytes = sizeof(tmp->children);
    	break;
    	default:
    		tmpbytes = 0;
	}

	if (tsk == current)
		preempt_enable();

	ret = -EINVAL;
	if (tmpbytes > argbytes)
		tmpbytes = argbytes;
	if (tmpbytes > 0) {
		ret = tmpbytes;
		if (copy_to_user(argp, tmp, tmpbytes))
			ret = -EFAULT;
	}
	kfree(tmp);
	return ret;
}