How can I decide how much stack I can use after a call to pthread_attr_setstacksize?

故事扮演 提交于 2019-12-10 11:42:06

问题


I am trying to debug some code regarding stack usage. I have made the following test program (just as an example to figure out how the pthread library works):

#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>

static void *threadFunc1(void *arg)
{
    char arr[5000];
    printf("Hello fromt threadFunc1 address of arr:%p\n", &arr);
    return;
}

static void *threadFunc2(void *arg)
{
    char arr[10000];
    printf("Hello fromt threadFunc2 adress of arr:%p\n", &arr);
    return;
}

int main(int argc, char *argv[])
{
   pthread_t t1,t2;
   pthread_attr_t thread_attr;
   void *res;
   int s;
   size_t tmp_size=0;
   s=pthread_attr_init(&thread_attr);
   assert(s==0);
   s=pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN );
   assert(s==0);
   s=pthread_attr_getstacksize(&thread_attr , &tmp_size );
   assert(s==0);
   printf("forced stack size of pthread is:%zd\n", tmp_size);
   printf("sizeof char is %zd\n", sizeof(char));

   s = pthread_create(&t1, &thread_attr, threadFunc1, NULL);
   assert(s==0);
   sleep(1);
   s = pthread_create(&t2, &thread_attr, threadFunc2, NULL);
   assert(s==0);
   sleep(1);

   printf("Main done()\n");
   exit(0);
}

When I execute it I get the following output (on my x86_64 Ubuntu):

forced stack size of pthread is:16384
sizeof char is 1
Hello fromt threadFunc1 address of arr:0x7fef350d3b50
Segmentation fault (core dumped)

Is there a way to know how much is left of the requested PTHREAD_STACK_MIN when I enter my newly created thread? If I change the size of the char array when I enter the thread function it seems like the limit is somewhen between 7000 to 8000 which is not what I expected (somewhere in the near of 16384).


回答1:


There are not a lot of "good" things that can come from playing around with thread stack sizes. Usually when this sort of thing comes up, it's because someone is trying to do create hundreds (or thousands) of threads and running into per process limits. This is generally not a good way to use threads. Example: creating a new thread for every incoming connection request to a server.

Even if that's not why you are asking, a few things you should know.

In production (real world) code, not a simple example, you can't ever be sure that a specific "reduced" stack size per thread is 100% safe. You can test it extensively at a given stack size and then maybe once you're convinced in your own test environment that it's "large enough", probably increase it slightly (maybe 10-15%) for production use. I don't know of any specific tools that can tell you the peak stack usage per thread at run time. Better off to avoid this completely.

Reducing the stack size per thread will not reduce memory consumption directly, or improve performance. You're not optimizing your code by experimenting with this.

It's much safer to use the default stack size chosen by the local implementation when you can, until you have a real reason to change it.

You were missing some header files for prototypes, had missing return values in the thread funcs, etc. plus some other slight cleanups.

Slightly modified version of your code that runs here:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <limits.h>

static void *threadFunc1(void *arg)
{
    char arr[5000];
    printf("Hello fromt threadFunc1\n");
    return NULL;
}

static void *threadFunc2(void *arg)
{
    char arr[10000];
    printf("Hello fromt threadFunc2\n");
    return NULL;
}

int main(int argc, char *argv[])
{
   pthread_t t1,t2;
   pthread_attr_t thread_attr;
   int s = 0;
   size_t tmp_size=0;

   s = pthread_attr_init(&thread_attr);
   assert(s==0);

   s = pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN + 0x1000);
   assert(s==0);

   s = pthread_attr_getstacksize(&thread_attr , &tmp_size );
   assert(s==0);

   printf("forced stack size of pthread is:%zu\n", tmp_size);

   s = pthread_create(&t1, &thread_attr, threadFunc1, NULL);
   assert(s==0);

   sleep(1);    /* not the "right" way, but ok for a quick test */

   s = pthread_create(&t2, &thread_attr, threadFunc2, NULL);
   assert(s==0);

   sleep(1);

   printf("Main done()\n");
   return 0;
}

Note: I used

$ gcc -O0 -Wall stack_t.c -o stack_t -pthread
./stack_t

If you want to experiment with other sizes for the stack, be aware that some implementations require the stacksize to be a multiple of the system page file size. You can try values larger than PTHREAD_STACK_MIN as well obviously, just be aware of that potential issue.

EDIT: The example above adds a value to the minimum as an example of increasing it slightly. You may need to add even more. If 0x1000 is not enough, try 0x2000, 0x3000, etc. until you find one that works. As you have discovered, reducing the thread stack size is tricky and can be platform dependent as well. Which is why I have warnings above about it being unsafe.



来源:https://stackoverflow.com/questions/15205734/how-can-i-decide-how-much-stack-i-can-use-after-a-call-to-pthread-attr-setstacks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!