What is the best way to prefix the stack for a pthreads thread?

I am writing code for a real-time program running on an embedded Linux system. Since it is very important that we do not hang unpredictably on page errors, I would like a stack prefix so that the guaranteed coverage of the area we are using is called with mlockall() .

For the main thread, this is quite simple; just make some large alloca() and don't forget to write each page. This works because when the program starts, the stack limit is much larger than we need; we end up highlighting exactly how we prefault inside.

However, for pthread stacks, will they be distributed using MAP_GROWSDOWN ? If so, what is the best way to prefix them, given that:

  • We do not know how much of the (known) stack size is consumed when starting libc
  • We do not want to allocate more memory on the stack than necessary

I know that I can use pthread_attr_setstack to transmit on a manually allocated stack, but this complicates the cleanup after the thread, and therefore I would prefer to avoid this if possible.

As such, what is the best way to accomplish this prefix? It would be enough if there was an easy way to find out the bottom border of the stack (just above the guard page); at that moment I could just write on every page from there to the current stack pointer.

Note that tolerance is not a concern; we will be happy to have a solution that works only on x86-32 and Linux.

+6
source share
2 answers

If you use pthread_attr_setstacksize , you can still have automatic allocation with a known size.

glibc nptl leaves the protection pages between the stacks, so you can also install the SEGV handler and just sketch until you work, and then longjmp exit the loop. That would be ugly!

Edit: A really insecure way would be to open /proc/self/maps to find your stacks!

+3
source

Yes. if you called mlockall (MCL_CURRENT | MCL_FUTURE) before pthread_create, when the thread starts, a page error will occur for the thread stack. and after that again there will be no page crash when accessing the stack in the stream. therefore, people always set the appropriate thread size for a newly created thread to avoid too much memory for future future threads. Take a look at: https://rt.wiki.kernel.org/index.php/Threaded_RT-application_with_memory_locking_and_stack_handling_example

if you change the size of the stream stack to 7MB, you will see: Initial account: Pagefaults, Major: 0 (Allowed> = 0), Minor: 190 (Allowed> = 0) mlockall () generated: Pagefaults, Major: 0 (Allowed> = 0), Minor: 393 (Allowed> = 0) malloc () and the generated touch: Pagefaults, Major: 0 (Allowed> = 0), Minor: 25633 (Allowed> = 0) 2nd malloc () and the generated usage: Pagefaults, Major: 0 (Allowed 0), Minor: 0 (Allowed 0)

Look at the output of ps -leyf and see that RSS is now around 100 [MB] Click to exit I am an RT stream with a stack that does not generate page errors during use, stacksize = 7340032 Called by thread creation: Pagefaults, Major: 0 (Allowed> = 0), Minor: 1797 (Allowed> = 0) Called using the thread stack: Pagefaults, Major: 0 (Allowed 0), Minor: 0 (Allowed 0)

1797 page errors occur when creating a stream, this is about 7 MB. -barry

+1
source

Source: https://habr.com/ru/post/886262/


All Articles