Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack space of a child thread

Tags:

c

linux

I am creating a thread A, from main function, which in turn spawns another child thread B. I want to explicitly assign the stack size to threads A and B using pthread_attr_setstacksize().

As per the requirement, the stack size of parent thread A is smaller than the child thread B.

I am confused that if the stack of a child thread is allocated from stack space of parent thread or the stack space of parent and child thread are completely different.

Can anyone please help me?

like image 804
Tarun Avatar asked Mar 07 '26 15:03

Tarun


1 Answers

I want to explicitly assign the stack size to threads A and B using pthread_attr_setstacksize().

So, you do so:

    pthread_attr_t  attrs;
    pthread_t       A, B;
    void           *A_retval, *B_retval;
    int             result;

    result = pthread_attr_init(&attrs);
    if (result) {
        fprintf(stderr, "Cannot initialize thread attributes: %s.\n", strerror(result));
        exit(EXIT_FAILURE);
    }

    result = pthread_attr_setstacksize(&attrs, A_STACK_SIZE);
    if (result) {
        fprintf(stderr, "Cannot set stack size %zu for thread A: %s.\n", (size_t)A_STACK_SIZE, strerror(result));
        exit(EXIT_FAILURE);
    }

    result = pthread_create(&A, &attrs, A_FUNCTION, NULL);
    if (result) {
        fprintf(stderr, "Cannot create thread A: %s.\n", strerror(result));
        exit(EXIT_FAILURE);
    }

    result = pthread_attr_setstacksize(&attrs, B_STACK_SIZE);
    if (result) {
        fprintf(stderr, "Cannot set stack size %zu for thread B: %s.\n", (size_t)A_STACK_SIZE, strerror(result));
        exit(EXIT_FAILURE);
    }

    result = pthread_create(&B, &attrs, B_FUNCTION, NULL);
    if (result) {
        fprintf(stderr, "Cannot create thread A: %s.\n", strerror(result));
        exit(EXIT_FAILURE);
    }

    pthread_attr_destroy(&attrs);

    /* TODO: Perhaps this thread also does something? */

    /* Wait for A and B to exit. */

    result = pthread_join(A, &A_retval);
    if (result)
        fprintf(stderr, "Warning: Thread A: %s.\n", strerror(result));

    result = pthread_join(B, &B_retval);
    if (result)
        fprintf(stderr, "Warning: Thread B: %s.\n", strerror(result));

As per the requirement, the stack size of parent thread A is smaller than the child thread B.

Just make sure the sizes are a multiple of page size (sysconf(_SC_PAGESIZE)), and at least PTHREAD_STACK_MIN.

There are no parent or child threads. They are all "siblings", belonging to the same process. There is a "main thread", which is the sole thread when the process is started, but it is not special in any way. It gets its name from main(), as it is the thread that starts running that function. It does not matter which thread created some other thread, at all.

If there is a parent-child relationship mentioned between threads in some code, then it is used to reflect the logic of the code, not the threads' actual relationship. "Parent" and "child" are just easy shorthand for "the thread that created the newly created thread" and "the newly created thread".

Processes do have real parent-child relationships -- for example, only a parent can reap its child --, but all threads are siblings within a process in Linux: any thread can join/reap any other thread in the same process.

I am confused that if the stack of a child thread is allocated from stack space of parent thread or the stack space of parent and child thread are completely different.

No, each thread has their own separate stack. This new stack is almost always allocated and prepared by the pthread_create() call automatically, using the desired stack size if attributes are specified, or default stack size (which is huge, several megabytes) if no attributes are specified.

(There is a pthread_attr_setstack() call for setting up an explicit stack for the next thread created using that set of attributes. Some really oddball applications may need specific stack arrangements. The stack area is not just some random chunk of memory; it does need to be properly aligned, sufficiently large, and so on. It is possible to allocate it yourself using mmap() for example, but it is definitely not something you should ever need, or want, to do.)


It may be interesting or informative to see the memory regions used by the program itself, or by some specific process.

In Linux, your program can open and read /proc/self/maps pseudofile (it is not a real file on disk, but a file-like entity that the kernel generates on the fly when you open and read it), or you can read any /proc/PID/maps corresponding to process ID PID.

The first two hexadecimal numbers on each line describe the address range, and stacks are marked [stack].

See man 5 proc for further information on the files in the /proc pseudofilesystem.

like image 160
Nominal Animal Avatar answered Mar 09 '26 16:03

Nominal Animal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!