diff --git a/thread_pthread.c b/thread_pthread.c index 951885ffa0..cf90321d1d 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -552,9 +552,6 @@ hpux_attr_getstackaddr(const pthread_attr_t *attr, void **addr) # define MAINSTACKADDR_AVAILABLE 0 # endif #endif -#if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack) -# define get_main_stack(addr, size) get_stack(addr, size) -#endif #ifdef STACKADDR_AVAILABLE /* @@ -632,6 +629,55 @@ get_stack(void **addr, size_t *size) return 0; #undef CHECK_ERR } + +#if defined(__linux__) && !defined(__GLIBC__) && defined(HAVE_GETRLIMIT) + +#ifndef PAGE_SIZE +#include <unistd.h> +#define PAGE_SIZE sysconf(_SC_PAGE_SIZE) +#endif + +static int +get_main_stack(void **addr, size_t *size) +{ + size_t start, end, limit, prevend = 0; + struct rlimit r; + FILE *f; + char buf[PATH_MAX+80], s[8]; + int n; + STACK_GROW_DIR_DETECTION; + + f = fopen("/proc/self/maps", "re"); + if (!f) + return -1; + n = 0; + while (fgets(buf, sizeof buf, f)) { + n = sscanf(buf, "%zx-%zx %*s %*s %*s %*s %7s", &start, &end, s); + if (n >= 2) { + if (n == 3 && strcmp(s, "[stack]") == 0) + break; + prevend = end; + } + n = 0; + } + fclose(f); + if (n == 0) + return -1; + + limit = 100 << 20; /* 100MB stack limit */ + if (getrlimit(RLIMIT_STACK, &r)==0 && r.rlim_cur < limit) + limit = r.rlim_cur & -PAGE_SIZE; + if (limit > end) limit = end; + if (prevend < end - limit) prevend = end - limit; + if (start > prevend) start = prevend; + *addr = IS_STACK_DIR_UPPER() ? (void *)start : (void *)end; + *size = end - start; + return 0; +} +#else +# define get_main_stack(addr, size) get_stack(addr, size) +#endif + #endif static struct {