aboutsummaryrefslogtreecommitdiff
path: root/arch/ia64/kernel/process.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 15:40:28 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 15:40:28 -0800
commit6a306e8b4c81a1c1f538e390d92bfe80d04b254c (patch)
tree9650dfaf138d9ab52affa6e93d19e32879892924 /arch/ia64/kernel/process.c
parent3bf8f5a92cd4b04e3f1e162a1b4b99759a882b5d (diff)
parent785285fc8bc7f846ab68a063a8bf5a009d67725d (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6: [IA64] Fix large MCA bootmem allocation [IA64] Simplify cpu_idle_wait [IA64] Synchronize RBS on PTRACE_ATTACH [IA64] Synchronize kernel RSE to user-space and back [IA64] Rename TIF_PERFMON_WORK back to TIF_NOTIFY_RESUME [IA64] Wire up timerfd_{create,settime,gettime} syscalls
Diffstat (limited to 'arch/ia64/kernel/process.c')
-rw-r--r--arch/ia64/kernel/process.c59
1 files changed, 30 insertions, 29 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 7377d323131..49937a383b2 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -52,7 +52,6 @@
#include "sigframe.h"
void (*ia64_mark_idle)(int);
-static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -157,6 +156,17 @@ show_regs (struct pt_regs *regs)
show_stack(NULL, NULL);
}
+void tsk_clear_notify_resume(struct task_struct *tsk)
+{
+#ifdef CONFIG_PERFMON
+ if (tsk->thread.pfm_needs_checking)
+ return;
+#endif
+ if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE))
+ return;
+ clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME);
+}
+
void
do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
{
@@ -175,6 +185,10 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall
/* deal with pending signal delivery */
if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
ia64_do_signal(scr, in_syscall);
+
+ /* copy user rbs to kernel rbs */
+ if (unlikely(test_thread_flag(TIF_RESTORE_RSE)))
+ ia64_sync_krbs();
}
static int pal_halt = 1;
@@ -239,33 +253,23 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
-void cpu_idle_wait(void)
+static void do_nothing(void *unused)
{
- unsigned int cpu, this_cpu = get_cpu();
- cpumask_t map;
- cpumask_t tmp = current->cpus_allowed;
-
- set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
- put_cpu();
-
- cpus_clear(map);
- for_each_online_cpu(cpu) {
- per_cpu(cpu_idle_state, cpu) = 1;
- cpu_set(cpu, map);
- }
-
- __get_cpu_var(cpu_idle_state) = 0;
+}
- wmb();
- do {
- ssleep(1);
- for_each_online_cpu(cpu) {
- if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
- cpu_clear(cpu, map);
- }
- cpus_and(map, map, cpu_online_map);
- } while (!cpus_empty(map));
- set_cpus_allowed(current, tmp);
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+ smp_mb();
+ /* kick all the CPUs so that they exit out of pm_idle */
+ smp_call_function(do_nothing, NULL, 0, 1);
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -293,9 +297,6 @@ cpu_idle (void)
#ifdef CONFIG_SMP
min_xtp();
#endif
- if (__get_cpu_var(cpu_idle_state))
- __get_cpu_var(cpu_idle_state) = 0;
-
rmb();
if (mark_idle)
(*mark_idle)(1);