|
Packit |
577717 |
/* $Id: virtual_stub.c,v 1.26.2.9 2009/01/23 17:21:20 mikpe Exp $
|
|
Packit |
577717 |
* Kernel stub used to support virtual perfctrs when the
|
|
Packit |
577717 |
* perfctr driver is built as a module.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (C) 2000-2009 Mikael Pettersson
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <linux/version.h>
|
|
Packit |
577717 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
|
Packit |
577717 |
#include <linux/config.h>
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#include <linux/module.h>
|
|
Packit |
577717 |
#include <linux/kernel.h>
|
|
Packit |
577717 |
#include <linux/sched.h>
|
|
Packit |
577717 |
#include <linux/perfctr.h>
|
|
Packit |
577717 |
#include "compat.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void bug_void_perfctr(struct vperfctr *perfctr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
current->thread.perfctr = NULL;
|
|
Packit |
577717 |
BUG();
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PERFCTR_CPUS_FORBIDDEN_MASK
|
|
Packit |
577717 |
static void bug_set_cpus_allowed(struct task_struct *owner, struct vperfctr *perfctr, cpumask_t new_mask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
owner->thread.perfctr = NULL;
|
|
Packit |
577717 |
BUG();
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct vperfctr_stub vperfctr_stub = {
|
|
Packit |
577717 |
.exit = bug_void_perfctr,
|
|
Packit |
577717 |
.flush = bug_void_perfctr,
|
|
Packit |
577717 |
.suspend = bug_void_perfctr,
|
|
Packit |
577717 |
.resume = bug_void_perfctr,
|
|
Packit |
577717 |
.sample = bug_void_perfctr,
|
|
Packit |
577717 |
#ifdef CONFIG_PERFCTR_CPUS_FORBIDDEN_MASK
|
|
Packit |
577717 |
.set_cpus_allowed = bug_set_cpus_allowed,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* exit_thread() calls __vperfctr_exit() via vperfctr_stub.exit().
|
|
Packit |
577717 |
* If the process' reference was the last reference to this
|
|
Packit |
577717 |
* vperfctr object, and this was the last live vperfctr object,
|
|
Packit |
577717 |
* then the perfctr module's use count will drop to zero.
|
|
Packit |
577717 |
* This is Ok, except for the fact that code is still running
|
|
Packit |
577717 |
* in the module (pending returns back to exit_thread()). This
|
|
Packit |
577717 |
* could race with rmmod in a preemptive UP kernel, leading to
|
|
Packit |
577717 |
* code running in freed memory. The race also exists in SMP
|
|
Packit |
577717 |
* kernels, but the time window is extremely small.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Since exit() isn't performance-critical, we wrap the call to
|
|
Packit |
577717 |
* vperfctr_stub.exit() with code to increment the module's use
|
|
Packit |
577717 |
* count before the call, and decrement it again afterwards. Thus,
|
|
Packit |
577717 |
* the final drop to zero occurs here and not in the module itself.
|
|
Packit |
577717 |
* (All other code paths that drop the use count do so via a file
|
|
Packit |
577717 |
* object, and VFS also refcounts the module.)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
void _vperfctr_exit(struct vperfctr *perfctr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
__module_get(vperfctr_stub.owner);
|
|
Packit |
577717 |
vperfctr_stub.exit(perfctr);
|
|
Packit |
577717 |
module_put(vperfctr_stub.owner);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* __vperfctr_flush() is a conditional __vperfctr_exit(),
|
|
Packit |
577717 |
* so it needs the same protection.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
void _vperfctr_flush(struct vperfctr *perfctr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
__module_get(vperfctr_stub.owner);
|
|
Packit |
577717 |
vperfctr_stub.flush(perfctr);
|
|
Packit |
577717 |
module_put(vperfctr_stub.owner);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
EXPORT_SYMBOL(vperfctr_stub);
|
|
Packit |
577717 |
EXPORT_SYMBOL___put_task_struct;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if !defined(CONFIG_UTRACE)
|
|
Packit |
577717 |
#include <linux/mm.h>
|
|
Packit |
577717 |
#include <linux/ptrace.h>
|
|
Packit |
577717 |
EXPORT_SYMBOL(ptrace_check_attach);
|
|
Packit |
577717 |
#endif
|