There is a pthread API to determine where the stack lies:
#include <pthread.h>
void PrintStackInfo (void)
{ pthread_attr_t Attributes;
void *StackAddress;
int StackSize;
// Get the pthread attributes
memset (&Attributes, 0, sizeof (Attributes));
pthread_getattr_np (pthread_self(), &Attributes);
// From the attributes, get the stack info
pthread_attr_getstack (&Attributes, &StackAddress, &StackSize);
// Done with the attributes
pthread_attr_destroy (&Attributes);
printf ("Stack top: %p\n", StackAddress);
printf ("Stack size: %u bytes\n", StackSize);
printf ("Stack bottom: %p\n", StackAddress + StackSize);
}
On i386, the stack starts at the bottom and grows towards the top.
So you know you have ($ESP - StackAddress) bytes available.
In my system, I have a wrapper around pthread_create(), so each thread starts in my private function. In that function, I find the stack as described above, then find the unused portion, then initialize that memory with a distinctive pattern (or "Patton", as my Somerville, MA-born father-in-law would say).
Then when I want to know how much of the stack has been used, I start at the top and search towards the bottom for the first value that doesn't match my pattern.