aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorKirill Korotaev <dev@sw.ru>2007-03-19 07:04:20 -0400
committerTony Luck <tony.luck@intel.com>2007-05-08 17:51:42 -0400
commit690def21414fa43fac1b8053fd952c0366c476de (patch)
tree512295acc56990fa85e9e493fc9b01b104c2b91f /arch
parent3be44b9cc33d26930cb3bb014f35f582c6522481 (diff)
[IA64] unwind did not work for processes born with CLONE_STOPPED
Minor problem for mainstream. Big problem for checkpoint/restore, because all the stopped/traced processes are born in this state, hence they cannot be checkpointed again due to failing unwind. The problem was identified as assumption in kernel unwind library that top level frame is different of syscall frame. It is the case unless process was born with CLONE_STOPPED. Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-Off-By: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-Off-By: Kirill Korotaev <dev@sw.ru> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kernel/unwind.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index e3be21c7bd49..fe1426266b9b 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -60,6 +60,7 @@
60# define UNW_DEBUG_ON(n) unw_debug_level >= n 60# define UNW_DEBUG_ON(n) unw_debug_level >= n
61 /* Do not code a printk level, not all debug lines end in newline */ 61 /* Do not code a printk level, not all debug lines end in newline */
62# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) 62# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
63# undef inline
63# define inline 64# define inline
64#else /* !UNW_DEBUG */ 65#else /* !UNW_DEBUG */
65# define UNW_DEBUG_ON(n) 0 66# define UNW_DEBUG_ON(n) 0
@@ -1943,9 +1944,9 @@ EXPORT_SYMBOL(unw_unwind);
1943int 1944int
1944unw_unwind_to_user (struct unw_frame_info *info) 1945unw_unwind_to_user (struct unw_frame_info *info)
1945{ 1946{
1946 unsigned long ip, sp, pr = 0; 1947 unsigned long ip, sp, pr = info->pr;
1947 1948
1948 while (unw_unwind(info) >= 0) { 1949 do {
1949 unw_get_sp(info, &sp); 1950 unw_get_sp(info, &sp);
1950 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp) 1951 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
1951 < IA64_PT_REGS_SIZE) { 1952 < IA64_PT_REGS_SIZE) {
@@ -1963,7 +1964,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
1963 __FUNCTION__, ip); 1964 __FUNCTION__, ip);
1964 return -1; 1965 return -1;
1965 } 1966 }
1966 } 1967 } while (unw_unwind(info) >= 0);
1967 unw_get_ip(info, &ip); 1968 unw_get_ip(info, &ip);
1968 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", 1969 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
1969 __FUNCTION__, ip); 1970 __FUNCTION__, ip);