bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Small stack size with libpthread?


From: Wolfram Gloger
Subject: Re: Small stack size with libpthread?
Date: Wed, 25 Jun 2003 18:31:17 +0200 (MDT)

Hi,

> In glibc-2.3.2/glibc-linuxthreads-2.3.2, code in pthread.c calls 
> setrlimit(RLIMIT_STACK, ...) with a soft limit of
> 
>    max_stack = STACK_SIZE - __getpagesize();
> 
> (resulting in max_stack a little below 2MB with my Linux constellation.) 
>   This code is executed at the start of a -lpthread linked program, and 
> cuts the stack size for the program's main thread.  I have two questions 
> about this:
> 
> 1  Why is max_stack a hard value, that does not take into account the 
> stacksize limit set by the user?

First, please note that this applies only to the case when
FLOATING_STACKS is not set in LinuxThreads.  On many modern
systems/kernels, FLOATING_STACKS will be set and the following is a
moot point.

> 2  Why is there a call to setrlimit at all?  I don't know the 
> implementation details, but I would assume that setrlimit(RLIMIT_STACK, 
> ...) only controls the size of the main thread's stack.  Why is it 
> changed?  [I would also assume that calling setrlimit(RLIMIT_STACK, ...) 
> can have only limited effect when a program is already executing, e.g., 
> it should not enlarge the stack into already used address space, and it 
> should not shrink the stack smaller than the current value of the stack 
> pointer.  But some tests show that the size of the main thread's stack 
> is indeed cut by that call from pthread.c during initialization.]

AFAICS, the stack size was hardcoded in order to have enough address
space for the thread stacks, which are allocated starting immediately
below the main thread's stack.  It seemed natural to limit the main
stack to the same size as the other threads' (however there was a
factor of 2 which wasn't properly accounted for in the rlimit call).

Anyway, I agree the fixed setrlimit() is _not_ necessary for the main
thread and while LinuxThreads has many design limitations, this is not
one of them.  I append a patch for LinuxThreads which should give you
much more stack space (at most 128MB though) for the main thread, in
case the limit is set appropriately.

Since LinuxThreads is on its way of being phased out, I don't know
whether the patch will be accepted in glibc.

> I am asking this because we have a program component (the OpenOffice.org 
> Basic interpreter) that runs in a multithreaded program, but is 
> guaranteed to only ever run on the main thread, and can consume huge 
> amounts of stack space.  The easiest fix seemed to increase the 
> stacksize limit in the shell script that starts the program, but that 
> turned out to have no effect...

Even better would be to use malloc() for large allocations..

Regards,
Wolfram.

2003-06-25  Wolfram Gloger  <address@hidden>

        * descr.h: Define MAIN_STACK_SIZE_MAX.
        * internals.h [!FLOATING_STACKS]: Declare __pthread_max_stacksize.
        * pthread.c (pthread_initialize) [!FLOATING_STACKS &&
        !_STACK_GROWS_UP]: Use the minimum of the stack rlimit and
        MAIN_STACK_SIZE_MAX when reserving the initial stack.
        (__pthread_init_max_stacksize): Move setrlimit call to...
        * manager.c(__pthread_manager): ...here.

Index: descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.11
diff -u -r1.11 descr.h
--- descr.h     25 Apr 2003 22:28:56 -0000      1.11
+++ descr.h     25 Jun 2003 15:45:42 -0000
@@ -230,6 +230,12 @@
 #define STACK_SIZE  (2 * 1024 * 1024)
 #endif
 
+/* The max size of the main thread's stack.  Only used if
+   !FLOATING_STACKS and !_STACK_GROWS_UP.  */
+#ifndef MAIN_STACK_SIZE_MAX
+#define MAIN_STACK_SIZE_MAX  (64 * STACK_SIZE)
+#endif
+
 /* Get some notion of the current stack.  Need not be exactly the top
    of the stack, just something somewhere in the current frame.  */
 #ifndef CURRENT_STACK_FRAME
Index: internals.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/internals.h,v
retrieving revision 1.89
diff -u -r1.89 internals.h
--- internals.h 17 Jun 2003 22:22:21 -0000      1.89
+++ internals.h 25 Jun 2003 15:45:55 -0000
@@ -143,10 +143,8 @@
 
 extern int __pthread_manager_reader;
 
-#ifdef FLOATING_STACKS
 /* Maximum stack size.  */
 extern size_t __pthread_max_stacksize;
-#endif
 
 /* Pending request for a process-wide exit */
 
Index: manager.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/manager.c,v
retrieving revision 1.93
diff -u -r1.93 manager.c
--- manager.c   25 Apr 2003 22:09:09 -0000      1.93
+++ manager.c   25 Jun 2003 15:46:13 -0000
@@ -115,7 +115,16 @@
   sigset_t manager_mask;
   int n;
   struct pthread_request request;
+#ifndef FLOATING_STACKS
+  struct rlimit limit;
 
+  /* Set stack limit so all the created threads have it */
+  getrlimit(RLIMIT_STACK, &limit);
+  if (limit.rlim_cur > __pthread_max_stacksize) {
+    limit.rlim_cur = __pthread_max_stacksize;
+    setrlimit(RLIMIT_STACK, &limit);
+  }
+#endif
   /* If we have special thread_self processing, initialize it.  */
 #ifdef INIT_THREAD_SELF
   INIT_THREAD_SELF(self, 1);
Index: pthread.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/pthread.c,v
retrieving revision 1.125
diff -u -r1.125 pthread.c
--- pthread.c   26 Apr 2003 17:08:49 -0000      1.125
+++ pthread.c   25 Jun 2003 15:46:26 -0000
@@ -431,10 +431,6 @@
 # else
   max_stack = STACK_SIZE - __getpagesize();
 # endif
-  if (limit.rlim_cur > max_stack) {
-    limit.rlim_cur = max_stack;
-    setrlimit(RLIMIT_STACK, &limit);
-  }
 #endif
   __pthread_max_stacksize = max_stack;
   if (max_stack / 4 < __MAX_ALLOCA_CUTOFF)
@@ -466,6 +462,9 @@
 {
   struct sigaction sa;
   sigset_t mask;
+#if !defined FLOATING_STACKS && !defined _STACK_GROWS_UP
+  struct rlimit limit;
+#endif
 
   /* If already done (e.g. by a constructor called earlier!), bail out */
   if (__pthread_initial_thread_bos != NULL) return;
@@ -485,11 +484,16 @@
   __pthread_initial_thread_bos = (char *)
     ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1));
 # else
-  /* For the initial stack, reserve at least STACK_SIZE bytes of stack
-     below the current stack address, and align that on a
+  /* For the initial stack, reserve at most MAIN_STACK_SIZE_MAX bytes of
+     stack below the current stack address, and align that on a
      STACK_SIZE boundary. */
+  getrlimit(RLIMIT_STACK, &limit);
+  if (limit.rlim_cur > MAIN_STACK_SIZE_MAX) {
+    limit.rlim_cur = MAIN_STACK_SIZE_MAX;
+    setrlimit(RLIMIT_STACK, &limit);
+  }
   __pthread_initial_thread_bos =
-    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
+    (char *)(((long)CURRENT_STACK_FRAME - limit.rlim_cur) & ~(STACK_SIZE - 1));
 # endif
 #endif
 #ifdef USE_TLS




reply via email to

[Prev in Thread] Current Thread [Next in Thread]