#include <xen/cpu.h>
#include <xen/init.h>
#include <xen/mm.h>
+#include <xen/rcupdate.h>
unsigned long __per_cpu_offset[NR_CPUS];
#define INVALID_PERCPU_AREA (-(long)__per_cpu_start)
{
char *p;
if ( __per_cpu_offset[cpu] != INVALID_PERCPU_AREA )
- return 0;
+ return -EBUSY;
if ( (p = alloc_xenheap_pages(PERCPU_ORDER, 0)) == NULL )
return -ENOMEM;
memset(p, 0, __per_cpu_data_end - __per_cpu_start);
return 0;
}
-static void free_percpu_area(unsigned int cpu)
+struct free_info {
+ unsigned int cpu;
+ struct rcu_head rcu;
+};
+static DEFINE_PER_CPU(struct free_info, free_info);
+
+static void _free_percpu_area(struct rcu_head *head)
{
+ struct free_info *info = container_of(head, struct free_info, rcu);
+ unsigned int cpu = info->cpu;
char *p = __per_cpu_start + __per_cpu_offset[cpu];
free_xenheap_pages(p, PERCPU_ORDER);
__per_cpu_offset[cpu] = INVALID_PERCPU_AREA;
}
+static void free_percpu_area(unsigned int cpu)
+{
+ struct free_info *info = &per_cpu(free_info, cpu);
+ info->cpu = cpu;
+ call_rcu(&info->rcu, _free_percpu_area);
+}
+
static int cpu_percpu_callback(
struct notifier_block *nfb, unsigned long action, void *hcpu)
{