rpms/kernel/devel config-generic, 1.238.6.20, 1.238.6.21 kernel.spec, 1.1294.2.27, 1.1294.2.28 xen.pvops.patch, 1.1.2.21, 1.1.2.22 xen.pvops.post.patch, 1.1.2.14, 1.1.2.15 xen.pvops.pre.patch, 1.1.2.11, 1.1.2.12
Michael Young
myoung at fedoraproject.org
Fri May 22 20:02:54 UTC 2009
Author: myoung
Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv30286
Modified Files:
Tag: private-myoung-dom0-branch
config-generic kernel.spec xen.pvops.patch
xen.pvops.post.patch xen.pvops.pre.patch
Log Message:
enable PERF_COUNTERS to get pvops kernel to build
Index: config-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-generic,v
retrieving revision 1.238.6.20
retrieving revision 1.238.6.21
diff -u -p -r1.238.6.20 -r1.238.6.21
--- config-generic 21 May 2009 22:11:56 -0000 1.238.6.20
+++ config-generic 22 May 2009 20:02:04 -0000 1.238.6.21
@@ -3958,7 +3958,7 @@ CONFIG_STRIP_ASM_SYMS=y
#
# added for xen pvops patch
#
-# CONFIG_PERF_COUNTERS is not set
+CONFIG_PERF_COUNTERS=y
CONFIG_XEN_DOM0=y
CONFIG_XEN_DEV_EVTCHN=m
CONFIG_ALLOW_WARNINGS=y
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1294.2.27
retrieving revision 1.1294.2.28
diff -u -p -r1.1294.2.27 -r1.1294.2.28
--- kernel.spec 22 May 2009 18:09:38 -0000 1.1294.2.27
+++ kernel.spec 22 May 2009 20:02:04 -0000 1.1294.2.28
@@ -1829,6 +1829,7 @@ fi
* Fri May 22 2009 Michael Young <m.a.young at durham.ac.uk>
- update pvops patch to latest xen-tip/next version
- pull in patch for !PERF_COUNTERS build failure
+- That still doesn't work so enable PERF_COUNTERS for the moment
* Thu May 21 2009 Michael Young <m.a.young at durham.ac.uk>
- update pvops patch to latest xen-tip/next version
xen.pvops.patch:
Index: xen.pvops.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.patch,v
retrieving revision 1.1.2.21
retrieving revision 1.1.2.22
diff -u -p -r1.1.2.21 -r1.1.2.22
--- xen.pvops.patch 22 May 2009 18:09:38 -0000 1.1.2.21
+++ xen.pvops.patch 22 May 2009 20:02:04 -0000 1.1.2.22
@@ -6283,7 +6283,7 @@ index 0000000..594d270
+}
diff --git a/Documentation/perf_counter/perf.h b/Documentation/perf_counter/perf.h
new file mode 100644
-index 0000000..6fa3656
+index 0000000..81a7374
--- /dev/null
+++ b/Documentation/perf_counter/perf.h
@@ -0,0 +1,62 @@
@@ -6343,8 +6343,8 @@ index 0000000..6fa3656
+ group_fd, flags);
+}
+
-+#define MAX_COUNTERS 64
-+#define MAX_NR_CPUS 256
++#define MAX_COUNTERS 1024
++#define MAX_NR_CPUS 4096
+
+#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
+
@@ -17391,7 +17391,7 @@ index 8c86b72..1b68659 100644
# drivers-y are linked after core-y
drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
-index 6633b6e..8979283 100644
+index 6633b6e..8d16ada 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -26,9 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
@@ -17426,7 +17426,7 @@ index 6633b6e..8979283 100644
+$(obj)/voffset.h: vmlinux FORCE
+ $(call if_changed,voffset)
+
-+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
++sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+
+quiet_cmd_zoffset = ZOFFSET $@
+ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
@@ -18849,7 +18849,7 @@ index 1aae8f3..c501a5b 100644
return 0;
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
-index 5d84d1c..25fc36b 100644
+index 5d84d1c..b31cc54 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -22,7 +22,8 @@
@@ -18908,7 +18908,7 @@ index 5d84d1c..25fc36b 100644
+pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
+
-+#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_extract_offset)
++#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
+#define VO_INIT_SIZE (VO__end - VO__text)
+#if ZO_INIT_SIZE > VO_INIT_SIZE
+#define INIT_SIZE ZO_INIT_SIZE
@@ -25709,10 +25709,18 @@ index 0000000..6206033
@@ -0,0 +1 @@
+#include "../../../boot/regs.c"
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
-index f287092..9376ff4 100644
+index f287092..9e2c551 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
-@@ -34,6 +34,7 @@
+@@ -14,6 +14,7 @@
+ * Mikael Pettersson : PM converted to driver model.
+ */
+
++#include <linux/perf_counter.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/acpi_pmtmr.h>
+@@ -34,6 +35,7 @@
#include <linux/smp.h>
#include <linux/mm.h>
@@ -25720,7 +25728,7 @@ index f287092..9376ff4 100644
#include <asm/pgalloc.h>
#include <asm/atomic.h>
#include <asm/mpspec.h>
-@@ -98,6 +99,29 @@ early_param("lapic", parse_lapic);
+@@ -98,6 +100,29 @@ early_param("lapic", parse_lapic);
/* Local APIC was disabled by the BIOS and enabled by the kernel */
static int enabled_via_apicbase;
@@ -25750,7 +25758,7 @@ index f287092..9376ff4 100644
#endif
#ifdef CONFIG_X86_64
-@@ -111,13 +135,19 @@ static __init int setup_apicpmtimer(char *s)
+@@ -111,13 +136,19 @@ static __init int setup_apicpmtimer(char *s)
__setup("apicpmtimer", setup_apicpmtimer);
#endif
@@ -25771,7 +25779,7 @@ index f287092..9376ff4 100644
disable_x2apic = 1;
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
return 0;
-@@ -209,6 +239,31 @@ static int modern_apic(void)
+@@ -209,6 +240,31 @@ static int modern_apic(void)
return lapic_get_version() >= 0x14;
}
@@ -25803,7 +25811,7 @@ index f287092..9376ff4 100644
void native_apic_wait_icr_idle(void)
{
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
-@@ -348,7 +403,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
+@@ -348,7 +404,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
{
@@ -25812,7 +25820,7 @@ index f287092..9376ff4 100644
unsigned int v = (mask << 16) | (msg_type << 8) | vector;
apic_write(reg, v);
-@@ -761,6 +816,8 @@ static void local_apic_timer_interrupt(void)
+@@ -761,6 +817,8 @@ static void local_apic_timer_interrupt(void)
inc_irq_stat(apic_timer_irqs);
evt->event_handler(evt);
@@ -25821,7 +25829,7 @@ index f287092..9376ff4 100644
}
/*
-@@ -815,7 +872,7 @@ void clear_local_APIC(void)
+@@ -815,7 +873,7 @@ void clear_local_APIC(void)
u32 v;
/* APIC hasn't been mapped yet */
@@ -25830,7 +25838,7 @@ index f287092..9376ff4 100644
return;
maxlvt = lapic_get_maxlvt();
-@@ -1133,6 +1190,7 @@ void __cpuinit setup_local_APIC(void)
+@@ -1133,6 +1191,7 @@ void __cpuinit setup_local_APIC(void)
apic_write(APIC_ESR, 0);
}
#endif
@@ -25838,7 +25846,7 @@ index f287092..9376ff4 100644
preempt_disable();
-@@ -1287,7 +1345,7 @@ void check_x2apic(void)
+@@ -1287,7 +1346,7 @@ void check_x2apic(void)
{
if (x2apic_enabled()) {
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
@@ -25847,7 +25855,7 @@ index f287092..9376ff4 100644
}
}
-@@ -1295,7 +1353,7 @@ void enable_x2apic(void)
+@@ -1295,7 +1354,7 @@ void enable_x2apic(void)
{
int msr, msr2;
@@ -25856,7 +25864,7 @@ index f287092..9376ff4 100644
return;
rdmsr(MSR_IA32_APICBASE, msr, msr2);
-@@ -1304,6 +1362,7 @@ void enable_x2apic(void)
+@@ -1304,6 +1363,7 @@ void enable_x2apic(void)
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
}
}
@@ -25864,7 +25872,7 @@ index f287092..9376ff4 100644
void __init enable_IR_x2apic(void)
{
-@@ -1312,32 +1371,21 @@ void __init enable_IR_x2apic(void)
+@@ -1312,32 +1372,21 @@ void __init enable_IR_x2apic(void)
unsigned long flags;
struct IO_APIC_route_entry **ioapic_entries = NULL;
@@ -25907,7 +25915,7 @@ index f287092..9376ff4 100644
return;
}
-@@ -1357,19 +1405,16 @@ void __init enable_IR_x2apic(void)
+@@ -1357,19 +1406,16 @@ void __init enable_IR_x2apic(void)
mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
@@ -25933,7 +25941,7 @@ index f287092..9376ff4 100644
}
end_restore:
-@@ -1378,37 +1423,34 @@ end_restore:
+@@ -1378,37 +1424,34 @@ end_restore:
* IR enabling failed
*/
restore_IO_APIC_setup(ioapic_entries);
@@ -25982,7 +25990,7 @@ index f287092..9376ff4 100644
#ifdef CONFIG_X86_64
/*
-@@ -1425,7 +1467,6 @@ static int __init detect_init_APIC(void)
+@@ -1425,7 +1468,6 @@ static int __init detect_init_APIC(void)
}
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
@@ -25990,7 +25998,7 @@ index f287092..9376ff4 100644
return 0;
}
#else
-@@ -1539,32 +1580,42 @@ void __init early_init_lapic_mapping(void)
+@@ -1539,32 +1581,42 @@ void __init early_init_lapic_mapping(void)
*/
void __init init_apic_mappings(void)
{
@@ -26047,7 +26055,7 @@ index f287092..9376ff4 100644
}
/*
-@@ -1733,8 +1784,7 @@ void __init connect_bsp_APIC(void)
+@@ -1733,8 +1785,7 @@ void __init connect_bsp_APIC(void)
*/
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
"enabling APIC mode.\n");
@@ -26057,7 +26065,7 @@ index f287092..9376ff4 100644
}
#endif
if (apic->enable_apic_mode)
-@@ -1762,8 +1812,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+@@ -1762,8 +1813,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
*/
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
"entering PIC mode.\n");
@@ -26067,7 +26075,7 @@ index f287092..9376ff4 100644
return;
}
#endif
-@@ -1969,10 +2018,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+@@ -1969,10 +2019,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
local_irq_save(flags);
disable_local_APIC();
@@ -26080,7 +26088,7 @@ index f287092..9376ff4 100644
local_irq_restore(flags);
return 0;
}
-@@ -1982,8 +2031,6 @@ static int lapic_resume(struct sys_device *dev)
+@@ -1982,8 +2032,6 @@ static int lapic_resume(struct sys_device *dev)
unsigned int l, h;
unsigned long flags;
int maxlvt;
@@ -26089,7 +26097,7 @@ index f287092..9376ff4 100644
int ret;
struct IO_APIC_route_entry **ioapic_entries = NULL;
-@@ -1991,7 +2038,7 @@ static int lapic_resume(struct sys_device *dev)
+@@ -1991,7 +2039,7 @@ static int lapic_resume(struct sys_device *dev)
return 0;
local_irq_save(flags);
@@ -26098,7 +26106,7 @@ index f287092..9376ff4 100644
ioapic_entries = alloc_ioapic_entries();
if (!ioapic_entries) {
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-@@ -2007,17 +2054,10 @@ static int lapic_resume(struct sys_device *dev)
+@@ -2007,17 +2055,10 @@ static int lapic_resume(struct sys_device *dev)
mask_IO_APIC_setup(ioapic_entries);
mask_8259A();
@@ -26117,7 +26125,7 @@ index f287092..9376ff4 100644
else {
/*
* Make sure the APICBASE points to the right address
-@@ -2055,20 +2095,15 @@ static int lapic_resume(struct sys_device *dev)
+@@ -2055,20 +2096,15 @@ static int lapic_resume(struct sys_device *dev)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
@@ -26140,7 +26148,7 @@ index f287092..9376ff4 100644
return 0;
}
-@@ -2117,31 +2152,14 @@ static void apic_pm_activate(void) { }
+@@ -2117,31 +2153,14 @@ static void apic_pm_activate(void) { }
#endif /* CONFIG_PM */
#ifdef CONFIG_X86_64
@@ -26174,7 +26182,7 @@ index f287092..9376ff4 100644
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
-@@ -2177,18 +2195,67 @@ __cpuinit int apic_is_clustered_box(void)
+@@ -2177,18 +2196,67 @@ __cpuinit int apic_is_clustered_box(void)
++zeros;
}
@@ -35368,6 +35376,25 @@ index 7563b31..af71d06 100644
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
+ quirk_amd_nb_node);
#endif
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 1340dad..667188e 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -232,6 +232,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
+ },
+ },
++ { /* Handle problems with rebooting on Sony VGN-Z540N */
++ .callback = set_bios_reboot,
++ .ident = "Sony VGN-Z540N",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
++ },
++ },
+ { }
+ };
+
diff --git a/arch/x86/kernel/scx200_32.c b/arch/x86/kernel/scx200_32.c
index 7e004ac..1b6e3d1 100644
--- a/arch/x86/kernel/scx200_32.c
@@ -56284,33 +56311,10 @@ index 0e06c17..8a11f04 100644
#ifdef MODULE
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
-index d87247d..0d91196 100644
+index d87247d..889bf99 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
-@@ -108,6 +108,18 @@ extern struct group_info init_groups;
-
- extern struct cred init_cred;
-
-+#ifdef CONFIG_PERF_COUNTERS
-+# define INIT_PERF_COUNTERS(tsk) \
-+ .perf_counter_ctx.counter_list = \
-+ LIST_HEAD_INIT(tsk.perf_counter_ctx.counter_list), \
-+ .perf_counter_ctx.event_list = \
-+ LIST_HEAD_INIT(tsk.perf_counter_ctx.event_list), \
-+ .perf_counter_ctx.lock = \
-+ __SPIN_LOCK_UNLOCKED(tsk.perf_counter_ctx.lock),
-+#else
-+# define INIT_PERF_COUNTERS(tsk)
-+#endif
-+
- /*
- * INIT_TASK is used to set up the first task table, touch at
- * your own risk!. Base=0, limit=0x1fffff (=2MB)
-@@ -171,9 +183,11 @@ extern struct cred init_cred;
- }, \
- .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
- INIT_IDS \
-+ INIT_PERF_COUNTERS(tsk) \
+@@ -174,6 +174,7 @@ extern struct cred init_cred;
INIT_TRACE_IRQFLAGS \
INIT_LOCKDEP \
INIT_FTRACE_GRAPH \
@@ -56949,10 +56953,10 @@ index 72698d8..75b0645 100644
#endif /* LINUX_PCI_H */
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
new file mode 100644
-index 0000000..9ab322b
+index 0000000..2eedae8
--- /dev/null
+++ b/include/linux/perf_counter.h
-@@ -0,0 +1,651 @@
+@@ -0,0 +1,659 @@
+/*
+ * Performance counters:
+ *
@@ -57404,7 +57408,6 @@ index 0000000..9ab322b
+ struct hw_perf_counter hw;
+
+ struct perf_counter_context *ctx;
-+ struct task_struct *task;
+ struct file *filp;
+
+ struct perf_counter *parent;
@@ -57453,7 +57456,6 @@ index 0000000..9ab322b
+ * Used as a container for task counters and CPU counters as well:
+ */
+struct perf_counter_context {
-+#ifdef CONFIG_PERF_COUNTERS
+ /*
+ * Protect the states of the counters in the list,
+ * nr_active, and the list:
@@ -57470,7 +57472,9 @@ index 0000000..9ab322b
+ struct list_head event_list;
+ int nr_counters;
+ int nr_active;
++ int nr_enabled;
+ int is_active;
++ atomic_t refcount;
+ struct task_struct *task;
+
+ /*
@@ -57478,7 +57482,14 @@ index 0000000..9ab322b
+ */
+ u64 time;
+ u64 timestamp;
-+#endif
++
++ /*
++ * These fields let us detect when two contexts have both
++ * been cloned (inherited) from a common ancestor.
++ */
++ struct perf_counter_context *parent_ctx;
++ u32 parent_gen;
++ u32 generation;
+};
+
+/**
@@ -57509,7 +57520,8 @@ index 0000000..9ab322b
+extern const struct pmu *hw_perf_counter_init(struct perf_counter *counter);
+
+extern void perf_counter_task_sched_in(struct task_struct *task, int cpu);
-+extern void perf_counter_task_sched_out(struct task_struct *task, int cpu);
++extern void perf_counter_task_sched_out(struct task_struct *task,
++ struct task_struct *next, int cpu);
+extern void perf_counter_task_tick(struct task_struct *task, int cpu);
+extern void perf_counter_init_task(struct task_struct *child);
+extern void perf_counter_exit_task(struct task_struct *child);
@@ -57573,7 +57585,7 @@ index 0000000..9ab322b
+perf_counter_task_sched_in(struct task_struct *task, int cpu) { }
+static inline void
+perf_counter_task_sched_out(struct task_struct *task,
-+ struct task_struct *next, int cpu) { }
++ struct task_struct *next, int cpu) { }
+static inline void
+perf_counter_task_tick(struct task_struct *task, int cpu) { }
+static inline void perf_counter_init_task(struct task_struct *child) { }
@@ -57910,17 +57922,10 @@ index e1b7b21..4016b52 100644
RB_FL_OVERWRITE = 1 << 0,
};
diff --git a/include/linux/sched.h b/include/linux/sched.h
-index b4c38bc..fe68809 100644
+index b4c38bc..5396cf5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -71,12 +71,14 @@ struct sched_param {
- #include <linux/path.h>
- #include <linux/compiler.h>
- #include <linux/completion.h>
-+#include <linux/perf_counter.h>
- #include <linux/pid.h>
- #include <linux/percpu.h>
- #include <linux/topology.h>
+@@ -77,6 +77,7 @@ struct sched_param {
#include <linux/proportions.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
@@ -57928,12 +57933,13 @@ index b4c38bc..fe68809 100644
#include <linux/rtmutex.h>
#include <linux/time.h>
-@@ -96,8 +98,8 @@ struct exec_domain;
+@@ -96,8 +97,9 @@ struct exec_domain;
struct futex_pi_state;
struct robust_list_head;
struct bio;
-struct bts_tracer;
struct fs_struct;
++struct perf_counter_context;
+struct bts_context;
/*
@@ -58039,15 +58045,17 @@ index b4c38bc..fe68809 100644
/* PID/PID hash table linkage. */
struct pid_link pids[PIDTYPE_MAX];
-@@ -1380,6 +1401,7 @@ struct task_struct {
+@@ -1380,6 +1401,9 @@ struct task_struct {
struct list_head pi_state_list;
struct futex_pi_state *pi_state_cache;
#endif
-+ struct perf_counter_context perf_counter_ctx;
++#ifdef CONFIG_PERF_COUNTERS
++ struct perf_counter_context *perf_counter_ctxp;
++#endif
#ifdef CONFIG_NUMA
struct mempolicy *mempolicy;
short il_next;
-@@ -1428,7 +1450,9 @@ struct task_struct {
+@@ -1428,7 +1452,9 @@ struct task_struct {
#ifdef CONFIG_TRACING
/* state flags for use by tracers */
unsigned long trace;
@@ -58058,7 +58066,7 @@ index b4c38bc..fe68809 100644
};
/* Future-safe accessor for struct task_struct's cpus_allowed. */
-@@ -2001,8 +2025,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
+@@ -2001,8 +2027,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from);
extern char *get_task_comm(char *to, struct task_struct *tsk);
#ifdef CONFIG_SMP
@@ -58069,7 +58077,7 @@ index b4c38bc..fe68809 100644
static inline unsigned long wait_task_inactive(struct task_struct *p,
long match_state)
{
-@@ -2010,7 +2036,8 @@ static inline unsigned long wait_task_inactive(struct task_struct *p,
+@@ -2010,7 +2038,8 @@ static inline unsigned long wait_task_inactive(struct task_struct *p,
}
#endif
@@ -58079,7 +58087,7 @@ index b4c38bc..fe68809 100644
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
-@@ -2049,8 +2076,8 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)
+@@ -2049,8 +2078,8 @@ int same_thread_group(struct task_struct *p1, struct task_struct *p2)
static inline struct task_struct *next_thread(const struct task_struct *p)
{
@@ -58090,7 +58098,7 @@ index b4c38bc..fe68809 100644
}
static inline int thread_group_empty(struct task_struct *p)
-@@ -2388,6 +2415,13 @@ static inline void inc_syscw(struct task_struct *tsk)
+@@ -2388,6 +2417,13 @@ static inline void inc_syscw(struct task_struct *tsk)
#define TASK_SIZE_OF(tsk) TASK_SIZE
#endif
@@ -62641,19 +62649,20 @@ index 42d5654..f6c204f 100644
/* compat_time_t is a 32 bit "long" and needs to get converted. */
diff --git a/kernel/exit.c b/kernel/exit.c
-index abf9cf3..c1cd352 100644
+index abf9cf3..49cdf69 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
-@@ -48,7 +48,7 @@
+@@ -48,7 +48,8 @@
#include <linux/tracehook.h>
#include <linux/fs_struct.h>
#include <linux/init_task.h>
-#include <trace/sched.h>
++#include <linux/perf_counter.h>
+#include <trace/events/sched.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
-@@ -56,10 +56,6 @@
+@@ -56,10 +57,6 @@
#include <asm/mmu_context.h>
#include "cred-internals.h"
@@ -62664,17 +62673,17 @@ index abf9cf3..c1cd352 100644
static void exit_mm(struct task_struct * tsk);
static void __unhash_process(struct task_struct *p)
-@@ -158,6 +154,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
+@@ -158,6 +155,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
{
struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
+#ifdef CONFIG_PERF_COUNTERS
-+ WARN_ON_ONCE(!list_empty(&tsk->perf_counter_ctx.counter_list));
++ WARN_ON_ONCE(tsk->perf_counter_ctxp);
+#endif
trace_sched_process_free(tsk);
put_task_struct(tsk);
}
-@@ -174,6 +173,7 @@ repeat:
+@@ -174,6 +174,7 @@ repeat:
atomic_dec(&__task_cred(p)->user->processes);
proc_flush_task(p);
@@ -62682,7 +62691,7 @@ index abf9cf3..c1cd352 100644
write_lock_irq(&tasklist_lock);
tracehook_finish_release_task(p);
__exit_signal(p);
-@@ -975,16 +975,19 @@ NORET_TYPE void do_exit(long code)
+@@ -975,16 +976,19 @@ NORET_TYPE void do_exit(long code)
module_put(tsk->binfmt->module);
proc_exit_connector(tsk);
@@ -62707,18 +62716,20 @@ index abf9cf3..c1cd352 100644
exit_pi_state_list(tsk);
if (unlikely(current->pi_state_cache))
diff --git a/kernel/fork.c b/kernel/fork.c
-index b9e2edd..60a473e 100644
+index b9e2edd..95a374e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -61,7 +61,6 @@
+@@ -61,8 +61,8 @@
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/fs_struct.h>
-#include <trace/sched.h>
#include <linux/magic.h>
++#include <linux/perf_counter.h>
#include <asm/pgtable.h>
-@@ -71,6 +70,8 @@
+ #include <asm/pgalloc.h>
+@@ -71,6 +71,8 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -62727,7 +62738,7 @@ index b9e2edd..60a473e 100644
/*
* Protected counters by write_lock_irq(&tasklist_lock)
*/
-@@ -83,8 +84,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
+@@ -83,8 +85,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
@@ -62736,7 +62747,7 @@ index b9e2edd..60a473e 100644
int nr_processes(void)
{
int cpu;
-@@ -178,7 +177,7 @@ void __init fork_init(unsigned long mempages)
+@@ -178,7 +178,7 @@ void __init fork_init(unsigned long mempages)
/* create a slab on which task_structs can be allocated */
task_struct_cachep =
kmem_cache_create("task_struct", sizeof(struct task_struct),
@@ -62745,7 +62756,7 @@ index b9e2edd..60a473e 100644
#endif
/* do the arch specific task caches init */
-@@ -983,6 +982,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -983,6 +983,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto fork_out;
rt_mutex_init_task(p);
@@ -62753,7 +62764,7 @@ index b9e2edd..60a473e 100644
#ifdef CONFIG_PROVE_LOCKING
DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
-@@ -1089,8 +1089,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1089,8 +1090,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
#ifdef CONFIG_DEBUG_MUTEXES
p->blocked_on = NULL; /* not blocked yet */
#endif
@@ -62764,7 +62775,7 @@ index b9e2edd..60a473e 100644
/* Perform scheduler related setup. Assign this task to a CPU. */
sched_fork(p, clone_flags);
-@@ -1461,20 +1461,20 @@ void __init proc_caches_init(void)
+@@ -1461,20 +1462,20 @@ void __init proc_caches_init(void)
{
sighand_cachep = kmem_cache_create("sighand_cache",
sizeof(struct sighand_struct), 0,
@@ -64962,10 +64973,10 @@ index 507cf2b..947b3ad 100644
+EXPORT_SYMBOL(atomic_dec_and_mutex_lock);
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
new file mode 100644
-index 0000000..08584c1
+index 0000000..c100554
--- /dev/null
+++ b/kernel/perf_counter.c
-@@ -0,0 +1,3584 @@
+@@ -0,0 +1,3719 @@
+/*
+ * Performance counter core code
+ *
@@ -65065,6 +65076,20 @@ index 0000000..08584c1
+ hw_perf_enable();
+}
+
++static void get_ctx(struct perf_counter_context *ctx)
++{
++ atomic_inc(&ctx->refcount);
++}
++
++static void put_ctx(struct perf_counter_context *ctx)
++{
++ if (atomic_dec_and_test(&ctx->refcount)) {
++ if (ctx->parent_ctx)
++ put_ctx(ctx->parent_ctx);
++ kfree(ctx);
++ }
++}
++
+static void
+list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
+{
@@ -65084,14 +65109,24 @@ index 0000000..08584c1
+
+ list_add_rcu(&counter->event_entry, &ctx->event_list);
+ ctx->nr_counters++;
++ if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
++ ctx->nr_enabled++;
+}
+
++/*
++ * Remove a counter from the lists for its context.
++ * Must be called with counter->mutex and ctx->mutex held.
++ */
+static void
+list_del_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
+{
+ struct perf_counter *sibling, *tmp;
+
++ if (list_empty(&counter->list_entry))
++ return;
+ ctx->nr_counters--;
++ if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
++ ctx->nr_enabled--;
+
+ list_del_init(&counter->list_entry);
+ list_del_rcu(&counter->event_entry);
@@ -65155,6 +65190,22 @@ index 0000000..08584c1
+}
+
+/*
++ * Mark this context as not being a clone of another.
++ * Called when counters are added to or removed from this context.
++ * We also increment our generation number so that anything that
++ * was cloned from this context before this will not match anything
++ * cloned from this context after this.
++ */
++static void unclone_ctx(struct perf_counter_context *ctx)
++{
++ ++ctx->generation;
++ if (!ctx->parent_ctx)
++ return;
++ put_ctx(ctx->parent_ctx);
++ ctx->parent_ctx = NULL;
++}
++
++/*
+ * Cross CPU call to remove a performance counter
+ *
+ * We disable the counter on the hardware level first. After that we
@@ -65184,8 +65235,6 @@ index 0000000..08584c1
+
+ counter_sched_out(counter, cpuctx, ctx);
+
-+ counter->task = NULL;
-+
+ list_del_counter(counter, ctx);
+
+ if (!ctx->task) {
@@ -65216,6 +65265,7 @@ index 0000000..08584c1
+ struct perf_counter_context *ctx = counter->ctx;
+ struct task_struct *task = ctx->task;
+
++ unclone_ctx(ctx);
+ if (!task) {
+ /*
+ * Per cpu counters are removed via an smp call and
@@ -65247,7 +65297,6 @@ index 0000000..08584c1
+ */
+ if (!list_empty(&counter->list_entry)) {
+ list_del_counter(counter, ctx);
-+ counter->task = NULL;
+ }
+ spin_unlock_irq(&ctx->lock);
+}
@@ -65332,6 +65381,7 @@ index 0000000..08584c1
+ else
+ counter_sched_out(counter, cpuctx, ctx);
+ counter->state = PERF_COUNTER_STATE_OFF;
++ ctx->nr_enabled--;
+ }
+
+ spin_unlock_irqrestore(&ctx->lock, flags);
@@ -65373,6 +65423,7 @@ index 0000000..08584c1
+ if (counter->state == PERF_COUNTER_STATE_INACTIVE) {
+ update_counter_times(counter);
+ counter->state = PERF_COUNTER_STATE_OFF;
++ ctx->nr_enabled--;
+ }
+
+ spin_unlock_irq(&ctx->lock);
@@ -65536,11 +65587,17 @@ index 0000000..08584c1
+ * If this is a task context, we need to check whether it is
+ * the current task context of this cpu. If not it has been
+ * scheduled out before the smp call arrived.
++ * Or possibly this is the right context but it isn't
++ * on this cpu because it had no counters.
+ */
-+ if (ctx->task && cpuctx->task_ctx != ctx)
-+ return;
++ if (ctx->task && cpuctx->task_ctx != ctx) {
++ if (cpuctx->task_ctx || ctx->task != current)
++ return;
++ cpuctx->task_ctx = ctx;
++ }
+
+ spin_lock_irqsave(&ctx->lock, flags);
++ ctx->is_active = 1;
+ update_context_time(ctx);
+
+ /*
@@ -65621,7 +65678,6 @@ index 0000000..08584c1
+ return;
+ }
+
-+ counter->task = task;
+retry:
+ task_oncpu_function_call(task, __perf_install_in_context,
+ counter);
@@ -65661,10 +65717,14 @@ index 0000000..08584c1
+ * If this is a per-task counter, need to check whether this
+ * counter's task is the current task on this cpu.
+ */
-+ if (ctx->task && cpuctx->task_ctx != ctx)
-+ return;
++ if (ctx->task && cpuctx->task_ctx != ctx) {
++ if (cpuctx->task_ctx || ctx->task != current)
++ return;
++ cpuctx->task_ctx = ctx;
++ }
+
+ spin_lock_irqsave(&ctx->lock, flags);
++ ctx->is_active = 1;
+ update_context_time(ctx);
+
+ counter->prev_state = counter->state;
@@ -65672,6 +65732,7 @@ index 0000000..08584c1
+ goto unlock;
+ counter->state = PERF_COUNTER_STATE_INACTIVE;
+ counter->tstamp_enabled = ctx->time - counter->total_time_enabled;
++ ctx->nr_enabled++;
+
+ /*
+ * If the counter is in a group and isn't the group leader,
@@ -65762,6 +65823,7 @@ index 0000000..08584c1
+ counter->state = PERF_COUNTER_STATE_INACTIVE;
+ counter->tstamp_enabled =
+ ctx->time - counter->total_time_enabled;
++ ctx->nr_enabled++;
+ }
+ out:
+ spin_unlock_irq(&ctx->lock);
@@ -65807,6 +65869,25 @@ index 0000000..08584c1
+}
+
+/*
++ * Test whether two contexts are equivalent, i.e. whether they
++ * have both been cloned from the same version of the same context
++ * and they both have the same number of enabled counters.
++ * If the number of enabled counters is the same, then the set
++ * of enabled counters should be the same, because these are both
++ * inherited contexts, therefore we can't access individual counters
++ * in them directly with an fd; we can only enable/disable all
++ * counters via prctl, or enable/disable all counters in a family
++ * via ioctl, which will have the same effect on both contexts.
++ */
++static int context_equiv(struct perf_counter_context *ctx1,
++ struct perf_counter_context *ctx2)
++{
++ return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx
++ && ctx1->parent_gen == ctx2->parent_gen
++ && ctx1->nr_enabled == ctx2->nr_enabled;
++}
++
++/*
+ * Called from scheduler to remove the counters of the current task,
+ * with interrupts disabled.
+ *
@@ -65817,19 +65898,31 @@ index 0000000..08584c1
+ * accessing the counter control register. If a NMI hits, then it will
+ * not restart the counter.
+ */
-+void perf_counter_task_sched_out(struct task_struct *task, int cpu)
++void perf_counter_task_sched_out(struct task_struct *task,
++ struct task_struct *next, int cpu)
+{
+ struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-+ struct perf_counter_context *ctx = &task->perf_counter_ctx;
++ struct perf_counter_context *ctx = task->perf_counter_ctxp;
++ struct perf_counter_context *next_ctx;
+ struct pt_regs *regs;
+
-+ if (likely(!cpuctx->task_ctx))
++ if (likely(!ctx || !cpuctx->task_ctx))
+ return;
+
+ update_context_time(ctx);
+
+ regs = task_pt_regs(task);
+ perf_swcounter_event(PERF_COUNT_CONTEXT_SWITCHES, 1, 1, regs, 0);
++
++ next_ctx = next->perf_counter_ctxp;
++ if (next_ctx && context_equiv(ctx, next_ctx)) {
++ task->perf_counter_ctxp = next_ctx;
++ next->perf_counter_ctxp = ctx;
++ ctx->task = next;
++ next_ctx->task = task;
++ return;
++ }
++
+ __perf_counter_sched_out(ctx, cpuctx);
+
+ cpuctx->task_ctx = NULL;
@@ -65839,6 +65932,8 @@ index 0000000..08584c1
+{
+ struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
+
++ if (!cpuctx->task_ctx)
++ return;
+ __perf_counter_sched_out(ctx, cpuctx);
+ cpuctx->task_ctx = NULL;
+}
@@ -65937,8 +66032,12 @@ index 0000000..08584c1
+void perf_counter_task_sched_in(struct task_struct *task, int cpu)
+{
+ struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
-+ struct perf_counter_context *ctx = &task->perf_counter_ctx;
++ struct perf_counter_context *ctx = task->perf_counter_ctxp;
+
++ if (likely(!ctx))
++ return;
++ if (cpuctx->task_ctx == ctx)
++ return;
+ __perf_counter_sched_in(ctx, cpuctx, cpu);
+ cpuctx->task_ctx = ctx;
+}
@@ -65953,11 +66052,11 @@ index 0000000..08584c1
+int perf_counter_task_disable(void)
+{
+ struct task_struct *curr = current;
-+ struct perf_counter_context *ctx = &curr->perf_counter_ctx;
++ struct perf_counter_context *ctx = curr->perf_counter_ctxp;
+ struct perf_counter *counter;
+ unsigned long flags;
+
-+ if (likely(!ctx->nr_counters))
++ if (!ctx || !ctx->nr_counters)
+ return 0;
+
+ local_irq_save(flags);
@@ -65988,12 +66087,12 @@ index 0000000..08584c1
+int perf_counter_task_enable(void)
+{
+ struct task_struct *curr = current;
-+ struct perf_counter_context *ctx = &curr->perf_counter_ctx;
++ struct perf_counter_context *ctx = curr->perf_counter_ctxp;
+ struct perf_counter *counter;
+ unsigned long flags;
+ int cpu;
+
-+ if (likely(!ctx->nr_counters))
++ if (!ctx || !ctx->nr_counters)
+ return 0;
+
+ local_irq_save(flags);
@@ -66096,19 +66195,23 @@ index 0000000..08584c1
+ return;
+
+ cpuctx = &per_cpu(perf_cpu_context, cpu);
-+ ctx = &curr->perf_counter_ctx;
++ ctx = curr->perf_counter_ctxp;
+
+ perf_adjust_freq(&cpuctx->ctx);
-+ perf_adjust_freq(ctx);
++ if (ctx)
++ perf_adjust_freq(ctx);
+
+ perf_counter_cpu_sched_out(cpuctx);
-+ __perf_counter_task_sched_out(ctx);
++ if (ctx)
++ __perf_counter_task_sched_out(ctx);
+
+ rotate_ctx(&cpuctx->ctx);
-+ rotate_ctx(ctx);
++ if (ctx)
++ rotate_ctx(ctx);
+
+ perf_counter_cpu_sched_in(cpuctx, cpu);
-+ perf_counter_task_sched_in(curr, cpu);
++ if (ctx)
++ perf_counter_task_sched_in(curr, cpu);
+}
+
+/*
@@ -66144,6 +66247,22 @@ index 0000000..08584c1
+ return atomic64_read(&counter->count);
+}
+
++/*
++ * Initialize the perf_counter context in a task_struct:
++ */
++static void
++__perf_counter_init_context(struct perf_counter_context *ctx,
++ struct task_struct *task)
++{
++ memset(ctx, 0, sizeof(*ctx));
++ spin_lock_init(&ctx->lock);
++ mutex_init(&ctx->mutex);
++ INIT_LIST_HEAD(&ctx->counter_list);
++ INIT_LIST_HEAD(&ctx->event_list);
++ atomic_set(&ctx->refcount, 1);
++ ctx->task = task;
++}
++
+static void put_context(struct perf_counter_context *ctx)
+{
+ if (ctx->task)
@@ -66154,6 +66273,7 @@ index 0000000..08584c1
+{
+ struct perf_cpu_context *cpuctx;
+ struct perf_counter_context *ctx;
++ struct perf_counter_context *tctx;
+ struct task_struct *task;
+
+ /*
@@ -66193,15 +66313,36 @@ index 0000000..08584c1
+ if (!task)
+ return ERR_PTR(-ESRCH);
+
-+ ctx = &task->perf_counter_ctx;
-+ ctx->task = task;
-+
+ /* Reuse ptrace permission checks for now. */
+ if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
-+ put_context(ctx);
++ put_task_struct(task);
+ return ERR_PTR(-EACCES);
+ }
+
++ ctx = task->perf_counter_ctxp;
++ if (!ctx) {
++ ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL);
++ if (!ctx) {
++ put_task_struct(task);
++ return ERR_PTR(-ENOMEM);
++ }
++ __perf_counter_init_context(ctx, task);
++ /*
++ * Make sure other cpus see correct values for *ctx
++ * once task->perf_counter_ctxp is visible to them.
++ */
++ smp_wmb();
++ tctx = cmpxchg(&task->perf_counter_ctxp, NULL, ctx);
++ if (tctx) {
++ /*
++ * We raced with some other task; use
++ * the context they set.
++ */
++ kfree(ctx);
++ ctx = tctx;
++ }
++ }
++
+ return ctx;
+}
+
@@ -66210,6 +66351,7 @@ index 0000000..08584c1
+ struct perf_counter *counter;
+
+ counter = container_of(head, struct perf_counter, rcu_head);
++ put_ctx(counter->ctx);
+ kfree(counter);
+}
+
@@ -67215,7 +67357,7 @@ index 0000000..08584c1
+ perf_counter_comm_ctx(&cpuctx->ctx, comm_event);
+ put_cpu_var(perf_cpu_context);
+
-+ perf_counter_comm_ctx(¤t->perf_counter_ctx, comm_event);
++ perf_counter_comm_ctx(current->perf_counter_ctxp, comm_event);
+}
+
+void perf_counter_comm(struct task_struct *task)
@@ -67224,7 +67366,9 @@ index 0000000..08584c1
+
+ if (!atomic_read(&nr_comm_tracking))
+ return;
-+
++ if (!current->perf_counter_ctxp)
++ return;
++
+ comm_event = (struct perf_comm_event){
+ .task = task,
+ .event = {
@@ -67340,7 +67484,7 @@ index 0000000..08584c1
+ perf_counter_mmap_ctx(&cpuctx->ctx, mmap_event);
+ put_cpu_var(perf_cpu_context);
+
-+ perf_counter_mmap_ctx(¤t->perf_counter_ctx, mmap_event);
++ perf_counter_mmap_ctx(current->perf_counter_ctxp, mmap_event);
+
+ kfree(buf);
+}
@@ -67352,6 +67496,8 @@ index 0000000..08584c1
+
+ if (!atomic_read(&nr_mmap_tracking))
+ return;
++ if (!current->perf_counter_ctxp)
++ return;
+
+ mmap_event = (struct perf_mmap_event){
+ .file = file,
@@ -67953,6 +68099,7 @@ index 0000000..08584c1
+ counter->group_leader = group_leader;
+ counter->pmu = NULL;
+ counter->ctx = ctx;
++ get_ctx(ctx);
+
+ counter->state = PERF_COUNTER_STATE_INACTIVE;
+ if (hw_event->disabled)
@@ -68118,21 +68265,6 @@ index 0000000..08584c1
+}
+
+/*
-+ * Initialize the perf_counter context in a task_struct:
-+ */
-+static void
-+__perf_counter_init_context(struct perf_counter_context *ctx,
-+ struct task_struct *task)
-+{
-+ memset(ctx, 0, sizeof(*ctx));
-+ spin_lock_init(&ctx->lock);
-+ mutex_init(&ctx->mutex);
-+ INIT_LIST_HEAD(&ctx->counter_list);
-+ INIT_LIST_HEAD(&ctx->event_list);
-+ ctx->task = task;
-+}
-+
-+/*
+ * inherit a counter from parent task to child task:
+ */
+static struct perf_counter *
@@ -68161,9 +68293,18 @@ index 0000000..08584c1
+ return child_counter;
+
+ /*
++ * Make the child state follow the state of the parent counter,
++ * not its hw_event.disabled bit. We hold the parent's mutex,
++ * so we won't race with perf_counter_{en,dis}able_family.
++ */
++ if (parent_counter->state >= PERF_COUNTER_STATE_INACTIVE)
++ child_counter->state = PERF_COUNTER_STATE_INACTIVE;
++ else
++ child_counter->state = PERF_COUNTER_STATE_OFF;
++
++ /*
+ * Link it up in the child's context:
+ */
-+ child_counter->task = child;
+ add_counter_to_ctx(child_counter, child_ctx);
+
+ child_counter->parent = parent_counter;
@@ -68186,16 +68327,6 @@ index 0000000..08584c1
+ mutex_lock(&parent_counter->mutex);
+ list_add_tail(&child_counter->child_list, &parent_counter->child_list);
+
-+ /*
-+ * Make the child state follow the state of the parent counter,
-+ * not its hw_event.disabled bit. We hold the parent's mutex,
-+ * so we won't race with perf_counter_{en,dis}able_family.
-+ */
-+ if (parent_counter->state >= PERF_COUNTER_STATE_INACTIVE)
-+ child_counter->state = PERF_COUNTER_STATE_INACTIVE;
-+ else
-+ child_counter->state = PERF_COUNTER_STATE_OFF;
-+
+ mutex_unlock(&parent_counter->mutex);
+
+ return child_counter;
@@ -68262,40 +68393,15 @@ index 0000000..08584c1
+ struct perf_counter *parent_counter;
+
+ /*
-+ * If we do not self-reap then we have to wait for the
-+ * child task to unschedule (it will happen for sure),
-+ * so that its counter is at its final count. (This
-+ * condition triggers rarely - child tasks usually get
-+ * off their CPU before the parent has a chance to
-+ * get this far into the reaping action)
-+ */
-+ if (child != current) {
-+ wait_task_inactive(child, 0);
-+ update_counter_times(child_counter);
-+ list_del_counter(child_counter, child_ctx);
-+ } else {
-+ struct perf_cpu_context *cpuctx;
-+ unsigned long flags;
-+
-+ /*
-+ * Disable and unlink this counter.
-+ *
-+ * Be careful about zapping the list - IRQ/NMI context
-+ * could still be processing it:
-+ */
-+ local_irq_save(flags);
-+ perf_disable();
-+
-+ cpuctx = &__get_cpu_var(perf_cpu_context);
-+
-+ group_sched_out(child_counter, cpuctx, child_ctx);
-+ update_counter_times(child_counter);
++ * Protect against concurrent operations on child_counter
++ * due its fd getting closed, etc.
++ */
++ mutex_lock(&child_counter->mutex);
+
-+ list_del_counter(child_counter, child_ctx);
++ update_counter_times(child_counter);
++ list_del_counter(child_counter, child_ctx);
+
-+ perf_enable();
-+ local_irq_restore(flags);
-+ }
++ mutex_unlock(&child_counter->mutex);
+
+ parent_counter = child_counter->parent;
+ /*
@@ -68314,19 +68420,29 @@ index 0000000..08584c1
+ *
+ * Note: we may be running in child context, but the PID is not hashed
+ * anymore so new counters will not be added.
++ * (XXX not sure that is true when we get called from flush_old_exec.
++ * -- paulus)
+ */
+void perf_counter_exit_task(struct task_struct *child)
+{
+ struct perf_counter *child_counter, *tmp;
+ struct perf_counter_context *child_ctx;
++ unsigned long flags;
+
+ WARN_ON_ONCE(child != current);
+
-+ child_ctx = &child->perf_counter_ctx;
++ child_ctx = child->perf_counter_ctxp;
+
-+ if (likely(!child_ctx->nr_counters))
++ if (likely(!child_ctx))
+ return;
+
++ local_irq_save(flags);
++ __perf_counter_task_sched_out(child_ctx);
++ child->perf_counter_ctxp = NULL;
++ local_irq_restore(flags);
++
++ mutex_lock(&child_ctx->mutex);
++
+again:
+ list_for_each_entry_safe(child_counter, tmp, &child_ctx->counter_list,
+ list_entry)
@@ -68339,6 +68455,10 @@ index 0000000..08584c1
+ */
+ if (!list_empty(&child_ctx->counter_list))
+ goto again;
++
++ mutex_unlock(&child_ctx->mutex);
++
++ put_ctx(child_ctx);
+}
+
+/*
@@ -68349,20 +68469,27 @@ index 0000000..08584c1
+ struct perf_counter_context *child_ctx, *parent_ctx;
+ struct perf_counter *counter;
+ struct task_struct *parent = current;
++ int inherited_all = 1;
+
-+ child_ctx = &child->perf_counter_ctx;
-+ parent_ctx = &parent->perf_counter_ctx;
-+
-+ __perf_counter_init_context(child_ctx, child);
++ child->perf_counter_ctxp = NULL;
+
+ /*
+ * This is executed from the parent task context, so inherit
-+ * counters that have been marked for cloning:
++ * counters that have been marked for cloning.
++ * First allocate and initialize a context for the child.
+ */
+
-+ if (likely(!parent_ctx->nr_counters))
++ child_ctx = kmalloc(sizeof(struct perf_counter_context), GFP_KERNEL);
++ if (!child_ctx)
++ return;
++
++ parent_ctx = parent->perf_counter_ctxp;
++ if (likely(!parent_ctx || !parent_ctx->nr_counters))
+ return;
+
++ __perf_counter_init_context(child_ctx, child);
++ child->perf_counter_ctxp = child_ctx;
++
+ /*
+ * Lock the parent list. No need to lock the child - not PID
+ * hashed yet and not running, so nobody can access it.
@@ -68377,12 +68504,31 @@ index 0000000..08584c1
+ if (counter != counter->group_leader)
+ continue;
+
-+ if (!counter->hw_event.inherit)
++ if (!counter->hw_event.inherit) {
++ inherited_all = 0;
+ continue;
++ }
+
+ if (inherit_group(counter, parent,
-+ parent_ctx, child, child_ctx))
++ parent_ctx, child, child_ctx)) {
++ inherited_all = 0;
+ break;
++ }
++ }
++
++ if (inherited_all) {
++ /*
++ * Mark the child context as a clone of the parent
++ * context, or of whatever the parent is a clone of.
++ */
++ if (parent_ctx->parent_ctx) {
++ child_ctx->parent_ctx = parent_ctx->parent_ctx;
++ child_ctx->parent_gen = parent_ctx->parent_gen;
++ } else {
++ child_ctx->parent_ctx = parent_ctx;
++ child_ctx->parent_gen = parent_ctx->generation;
++ }
++ get_ctx(child_ctx->parent_ctx);
+ }
+
+ mutex_unlock(&parent_ctx->mutex);
@@ -69309,7 +69455,7 @@ index e124bf5..97a2f81 100644
#ifdef CONFIG_DEBUG_RT_MUTEXES
# include "rtmutex-debug.h"
diff --git a/kernel/sched.c b/kernel/sched.c
-index 26efa47..c036590 100644
+index 26efa47..f93305b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -39,6 +39,7 @@
@@ -69837,7 +69983,7 @@ index 26efa47..c036590 100644
if (likely(prev != next)) {
sched_info_switch(prev, next);
-+ perf_counter_task_sched_out(prev, cpu);
++ perf_counter_task_sched_out(prev, next, cpu);
rq->nr_switches++;
rq->curr = next;
xen.pvops.post.patch:
Index: xen.pvops.post.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.post.patch,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -u -p -r1.1.2.14 -r1.1.2.15
--- xen.pvops.post.patch 21 May 2009 22:12:01 -0000 1.1.2.14
+++ xen.pvops.post.patch 22 May 2009 20:02:09 -0000 1.1.2.15
@@ -50,16 +50,6 @@ Test some patches to get STACKPROTECTOR
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
#endif
---- a/include/linux/init_task.h 2009-04-23 20:13:50.000000000 +0100
-+++ b/include/linux/init_task.h 2009-04-24 20:47:17.000000000 +0100
-@@ -170,6 +170,7 @@
- [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
- }, \
- .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
-+ INIT_UTRACE(tsk) \
- INIT_IDS \
- INIT_PERF_COUNTERS(tsk) \
- INIT_TRACE_IRQFLAGS \
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 7727aa8..5d6083c 100644
--- a/arch/x86/include/asm/paravirt_types.h
xen.pvops.pre.patch:
Index: xen.pvops.pre.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.pre.patch,v
retrieving revision 1.1.2.11
retrieving revision 1.1.2.12
diff -u -p -r1.1.2.11 -r1.1.2.12
--- xen.pvops.pre.patch 21 May 2009 22:12:01 -0000 1.1.2.11
+++ xen.pvops.pre.patch 22 May 2009 20:02:09 -0000 1.1.2.12
@@ -2,7 +2,6 @@ temporarily revert various Fedora change
Affected patches;
more linux-2.6-execshield.patch - arch/x86/mm/init.c arch/x86/mm/init_32.c include/linux/sched.h mm/mmap.c arch/x86/include/asm/paravirt.h arch/x86/kernel/process_32.c
linux-2.6-defaults-pci_no_msi.patch - drivers/pci/pci.h
-linux-2.6-utrace.patch - include/linux/init_task.h
--- a/arch/x86/mm/init.c 2009-04-24 20:27:42.000000000 +0100
+++ b/arch/x86/mm/init.c 2009-04-23 20:13:34.000000000 +0100
@@ -86,16 +85,6 @@ linux-2.6-utrace.patch - include/linux/i
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
#endif
---- a/include/linux/init_task.h 2009-04-24 20:47:17.000000000 +0100
-+++ b/include/linux/init_task.h 2009-04-23 20:13:50.000000000 +0100
-@@ -170,7 +170,6 @@
- [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
- }, \
- .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \
-- INIT_UTRACE(tsk) \
- INIT_IDS \
- INIT_TRACE_IRQFLAGS \
- INIT_LOCKDEP \
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 7727aa8..5d6083c 100644
--- a/arch/x86/include/asm/paravirt.h
More information about the fedora-extras-commits
mailing list