I’m using the official posix port and I am encountering an issue when the task stack size is small.
In my application the task stack size is 2048 bytes. This is not a problem on ARM target. But it may be a potential problem when running with the POSIX port.
In portable/ThirdParty/GCC/Posix/port.c, pxPortInitialiseStack(), the posix port has this code to set the stack location and size with pthreads:
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
I have checked the return value of this call with a small stack size of 2048 bytes and it fails, it returns 22 which is EINVAL.
According to the docs of pthread_attr_setstack it can fail with EINVAL if the stack size is too small:
EINVAL stacksize is less than PTHREAD_STACK_MIN (16384) bytes.
On some systems, this error may also occur if stackaddr or
stackaddr + stacksize is not suitably aligned.
After this failure when I’m in the created task with the debugger I check the stack pointer (‘esp’ register) and it is outside of the stack area that the TCB thinks it is using. So pthreads used its own stack instead of the one in the TCB. I didn’t notice any other failures my application seems to run even with a discrepancy between the stack addresses in the TCB and the real stack. But maybe there will be issues?
If I change my stack size to a little more than 16384 then the call to pthread_attr_setstack() is successful and then inside the task the esp register is in the expected range of the stack addresses in the TCB.
I first looked into this because I was getting stack overflows on target that I didn’t see in posix. I would have liked to debug the stack overflows in posix before I went to target. I suppose that since the minimal stack size is much larger in the posix port I won’t be able to detect this kind of stack overflow there? Maybe there is a way for the posix port to address this?
Luckily I am able to easily set the stack size using #ifdef depending on if it is target build or posix build. So for my posix build I can set the stack size to the higher value of PTHREAD_STACK_MIN. However would be nice if I didn’t have to do that and the posix port could force the stack size of PTHREAD_STACK_MIN if requested stack is too small. But I don’t see an easy way to do this?
Or maybe the posix port should adjust the stack pointers in the TCB after the thread is started to point to the “real stack” in case the earlier call to pthread_attr_setstack() failed?
Perhaps the documentation of the posix port should mention this limitation and advise users to not use small stacks in the posix port and define larger stacks instead?
EDIT: Just realized if I make my stack sizes the minimum of PTHREAD_STACK_MIN for posix then it also requires me to allocate much more space in my FreeRTOS heap (configTOTAL_HEAP_SIZE) due to the stacks getting pvPortMalloc() off the heap. So I’m thinking maybe it would be better to keep the original stack size allocated in the heap and then if the pthread_attr_setstack() failed, adjust the values of the stack pointers stored in the TCB after the thread starts? This way my posix port can still properly check if I allocate too much in the heap. If this is not done then is there any danger if the real stack doesn’t correspond to the one pointed to in the TCB?