Beispiel #1
0
asmlinkage long sys_vperfctr_init() 
{
	struct task_struct  *tsk;
	struct vperfctr *perfctr;

	int err;

	tsk = current; 
	perfctr = NULL;

	if (!tsk) {
		printk(KERN_INFO __FILE__ "vperfctr init: tsk is empty\n");
		return -1;
	}

	perfctr = tsk->arch.thread.perfctr;
	if (perfctr)
		return -EEXIST;

	perfctr = get_empty_vperfctr();
	if (IS_ERR(perfctr)) {
		printk(KERN_INFO __FILE__ "vperfctr init: cannot get empty vperfctr\n");
		err = PTR_ERR(perfctr);
		return err;
	}

	perfctr->owner = tsk;
	tsk->arch.thread.perfctr = perfctr;

	return 0; 
}
/* do_fork() -> copy_process() -> copy_thread() -> __vperfctr_copy().
 * Inherit the parent's perfctr settings to the child.
 * PREEMPT note: do_fork() etc do not run with preemption disabled.
*/
void __vperfctr_copy(struct task_struct *child_tsk, struct pt_regs *regs)
{
	struct vperfctr *parent_perfctr;
	struct vperfctr *child_perfctr;

	/* Do not inherit perfctr settings to kernel-generated
	   threads, like those created by kmod. */
	child_perfctr = NULL;
	if (!user_mode(regs)) {
		goto out;
	}

	/* Allocation may sleep. Do it before the critical region. */
	child_perfctr = get_empty_vperfctr();
	if (IS_ERR(child_perfctr)) {
		child_perfctr = NULL;
		goto out;
	}

	/* Although we're executing in the parent, if it is scheduled
	   then a remote monitor may attach and change the perfctr
	   pointer or the object it points to. This may already have
	   occurred when we get here, so the old copy of the pointer
	   in the child cannot be trusted. */
	preempt_disable();
	parent_perfctr = current->thread.perfctr;
	if (parent_perfctr) {
		child_perfctr->cpu_state.control = parent_perfctr->cpu_state.control;
		child_perfctr->si_signo = parent_perfctr->si_signo;
		child_perfctr->inheritance_id = parent_perfctr->inheritance_id;
	}
	preempt_enable();
	if (!parent_perfctr) {
		put_vperfctr(child_perfctr);
		child_perfctr = NULL;
		goto out;
	}
	(void)perfctr_cpu_update_control(&child_perfctr->cpu_state, 0);
	child_perfctr->owner = child_tsk;
 out:
	child_tsk->thread.perfctr = child_perfctr;
}
/* tid is the actual task/thread id (née pid, stored as ->pid),
   pid/tgid is that 2.6 thread group id crap (stored as ->tgid) */
asmlinkage long sys_vperfctr_open(int tid, int creat)
{
	struct file *filp;
	struct task_struct *tsk;
	struct vperfctr *perfctr;
	int err;
	int fd;

	if (!vperfctr_fs_init_done())
		return -ENODEV;
	filp = vperfctr_get_filp();
	if (!filp)
		return -ENOMEM;
	err = fd = get_unused_fd();
	if (err < 0)
		goto err_filp;
	perfctr = NULL;
	if (creat) {
		perfctr = get_empty_vperfctr(); /* may sleep */
		if (IS_ERR(perfctr)) {
			err = PTR_ERR(perfctr);
			goto err_fd;
		}
	}
	tsk = current;

	if (tid != 0 && tid != tsk->pid) { /* remote? */
		// tasklist_lock is to access the linked list of task_struct structures exclusively
		read_lock(&tasklist_lock);
		//tsk = find_task_by_pid(tid);
		tsk = find_task_by_pid_ns(tid, current->nsproxy->pid_ns);
		if (tsk)
			get_task_struct(tsk);
		read_unlock(&tasklist_lock);
		err = -ESRCH;
		if (!tsk)
			goto err_perfctr;
		err = ptrace_check_attach(tsk, 0);
		if (err < 0)
			goto err_tsk;
	}
	if (creat) {
		/* check+install must be atomic to prevent remote-control races */
		task_lock(tsk);
		if (!tsk->thread.perfctr) {
			perfctr->owner = tsk;
			tsk->thread.perfctr = perfctr;
			err = 0;
		} else
			err = -EEXIST;
		task_unlock(tsk);
		if (err)
			goto err_tsk;
	} else {
		perfctr = tsk->thread.perfctr;
		/* XXX: Old API needed to allow NULL perfctr here.
		   Do we want to keep or change that rule? */
	}
	filp->private_data = perfctr;
	if (perfctr)
		atomic_inc(&perfctr->count);
	if (tsk != current)
		put_task_struct(tsk);
	#if 0
	if (perfctr) {
    	printk ("sys_vperfctr_open(): fd = %d, perfctr is NOT null\n", fd);
	}
	else {
    	printk ("sys_vperfctr_open(): fd = %d, perfctr is null\n", fd);
	}
	#endif
	fd_install(fd, filp);
	return fd;
 err_tsk:
	if (tsk != current)
		put_task_struct(tsk);
 err_perfctr:
	if (perfctr)	/* can only occur if creat != 0 */
		put_vperfctr(perfctr);
 err_fd:
	put_unused_fd(fd);
 err_filp:
	fput(filp);
	return err;
}
Beispiel #4
0
/* tid is the actual task/thread id (née pid, stored as ->pid),
   pid/tgid is that 2.6 thread group id crap (stored as ->tgid) */
int vperfctr_attach(int tid, int creat)
{
	struct file *filp;
	struct task_struct *tsk;
	struct vperfctr *perfctr;
	int err;
	int fd;

	filp = vperfctr_get_filp();
	if (!filp)
		return -ENOMEM;
	err = fd = get_unused_fd();
	if (err < 0)
		goto err_filp;
	perfctr = NULL;
	if (creat) {
		perfctr = get_empty_vperfctr(); /* may sleep */
		if (IS_ERR(perfctr)) {
			err = PTR_ERR(perfctr);
			goto err_fd;
		}
	}
	tsk = current;
	if (tid != 0 && tid != task_pid_vnr(tsk)) { /* remote? */
		vperfctr_lock_find_task_by_vpid();
		tsk = find_task_by_vpid(tid);
		if (tsk)
			get_task_struct(tsk);
		vperfctr_unlock_find_task_by_vpid();
		err = -ESRCH;
		if (!tsk)
			goto err_perfctr;
		err = ptrace_check_attach(tsk, 0);
		if (err < 0)
			goto err_tsk;
	}
	if (creat) {
		/* check+install must be atomic to prevent remote-control races */
		vperfctr_task_lock(tsk);
		if (!tsk->thread.perfctr) {
			perfctr->owner = tsk;
			tsk->thread.perfctr = perfctr;
			err = 0;
		} else
			err = -EEXIST;
		vperfctr_task_unlock(tsk);
		if (err)
			goto err_tsk;
	} else {
		perfctr = tsk->thread.perfctr;
		/* PERFCTR_ABI and PERFCTR_INFO don't need the perfctr.
		   Hence no non-NULL check here. */
	}
	filp->private_data = perfctr;
	if (perfctr)
		atomic_inc(&perfctr->count);
	if (tsk != current)
		put_task_struct(tsk);
	fd_install(fd, filp);
	return fd;
 err_tsk:
	if (tsk != current)
		put_task_struct(tsk);
 err_perfctr:
	if (perfctr)	/* can only occur if creat != 0 */
		put_vperfctr(perfctr);
 err_fd:
	put_unused_fd(fd);
 err_filp:
	fput(filp);
	return err;
}