aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-11-06 19:36:29 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2010-11-06 19:36:29 -0400
commitd7a2ce4905da7d812407b6354f038aac17e97024 (patch)
treee7a2884f69ed02a09b007211814ef8b6d55be201
parentdd1c781903811416db4e03383a4cb0bfc8cfac40 (diff)
downloadpostgresql-d7a2ce4905da7d812407b6354f038aac17e97024.tar.gz
postgresql-d7a2ce4905da7d812407b6354f038aac17e97024.zip
Add support for detecting register-stack overrun on IA64.
Per recent investigation, the register stack can grow faster than the regular stack depending on compiler and choice of options. To avoid crashes we must check both stacks in check_stack_depth(). Since this is poorly-tested code, committing only to HEAD for the moment ... but we might want to consider back-patching later.
-rw-r--r--src/backend/tcop/postgres.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 60f3c7c63d0..ff2e9bd0aaa 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -119,6 +119,12 @@ static long max_stack_depth_bytes = 100 * 1024L;
*/
char *stack_base_ptr = NULL;
+/*
+ * On IA64 we also have to remember the register stack base.
+ */
+#if defined(__ia64__) || defined(__ia64)
+char *register_stack_base_ptr = NULL;
+#endif
/*
* Flag to mark SIGHUP. Whenever the main loop comes around it
@@ -2984,6 +2990,35 @@ ProcessInterrupts(void)
/*
+ * IA64-specific code to fetch the AR.BSP register for stack depth checks.
+ *
+ * We currently support gcc and icc here.
+ */
+#if defined(__ia64__) || defined(__ia64)
+
+#include <asm/ia64regs.h>
+
+static __inline__ char *
+ia64_get_bsp(void)
+{
+ char *ret;
+
+#ifndef __INTEL_COMPILER
+ /* the ;; is a "stop", seems to be required before fetching BSP */
+ __asm__ __volatile__(
+ ";;\n"
+ " mov %0=ar.bsp \n"
+: "=r"(ret));
+#else
+ ret = (char *) __getReg(_IA64_REG_AR_BSP);
+#endif
+ return ret;
+}
+
+#endif /* IA64 */
+
+
+/*
* check_stack_depth: check for excessively deep recursion
*
* This should be called someplace in any recursive routine that might possibly
@@ -3026,6 +3061,29 @@ check_stack_depth(void)
"after ensuring the platform's stack depth limit is adequate.",
max_stack_depth)));
}
+
+ /*
+ * On IA64 there is a separate "register" stack that requires its own
+ * independent check. For this, we have to measure the change in the
+ * "BSP" pointer from PostgresMain to here. Logic is just as above,
+ * except that we know IA64's register stack grows up.
+ *
+ * Note we assume that the same max_stack_depth applies to both stacks.
+ */
+#if defined(__ia64__) || defined(__ia64)
+ stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
+
+ if (stack_depth > max_stack_depth_bytes &&
+ register_stack_base_ptr != NULL)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
+ errmsg("stack depth limit exceeded"),
+ errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
+ "after ensuring the platform's stack depth limit is adequate.",
+ max_stack_depth)));
+ }
+#endif /* IA64 */
}
/* GUC assign hook for max_stack_depth */
@@ -3435,6 +3493,9 @@ PostgresMain(int argc, char *argv[], const char *username)
/* Set up reference point for stack depth checking */
stack_base_ptr = &stack_base;
+#if defined(__ia64__) || defined(__ia64)
+ register_stack_base_ptr = ia64_get_bsp();
+#endif
/* Compute paths, if we didn't inherit them from postmaster */
if (my_exec_path[0] == '\0')