I am trying to build a tool that allows me to monitor stack usage on per thread basis. I go about it by creating a monitoring thread that overlooks the stack usage of other threads in the same application. In order to extract stack information for a particular thread, I locate Win32 Thread Information Block (more info @ http://en.wikipedia.org/wiki/Win32_Thread_Information_Block) for each thread by simply accessing FS register during execution. From tread information block, I obtain "top of stack" and "current bottom of stack". However it seems to me that "current bottom of stack" keeps changing as stack usage of thread increases. In addition by peaking into memory I noticed that thread is not given all of the inquired stack size. Instead it seems like stack is allocated in chunks as requirements increases. I tried to figure out how thread stack is allocated by reading http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_stack_size.asp. However, that confused me even more. Can anyone put any sight into how thread stack is allocated and what "Top of stack" and "Current bottom of stack" indicate in Thread Information Block? Thanks in advance.
"neomodus" wrote in message news:99D39C11-8646-4FC2-824F-E76FDBD67678@microsoft.com... >I am trying to build a tool that allows me to monitor stack usage on per > thread basis. I go about it by creating a monitoring thread that overlooks > the stack usage of other threads in the same application. In order to > extract > stack information for a particular thread, I locate Win32 Thread > Information > Block (more info @ > http://en.wikipedia.org/wiki/Win32_Thread_Information_Block) for each > thread > by simply accessing FS register during execution. From tread information > block, I obtain "top of stack" and "current bottom of stack". However it > seems to me that "current bottom of stack" keeps changing as stack usage > of > thread increases. In addition by peaking into memory I noticed that thread > is > not given all of the inquired stack size. Instead it seems like stack is > allocated in chunks as requirements increases. I tried to figure out how > thread stack is allocated by reading > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_stack_size.asp. > However, that confused me even more. Can anyone put any sight into how > thread > stack is allocated and what "Top of stack" and "Current bottom of stack" > indicate in Thread Information Block? Win32 is a virtual memory operting system. Typically 1MB of _virtual_ address space is set aside for the stack. Much less is actually _committed_. Committed pages of virtual memory are the ones for which space has been associated in the paging file. At the boundary between the last committed page and the first page which is not committed is the "guard page". When some number of bytes is pushed onto the stack at the guard page, the hardware and the o/s collaborate to generate a page fault. Windows handles the fault, and if there is virtual address space remaining for the stack, some number of pages (I forget) are now committed. The faulting instruction is restarted and the stack appears to grow. A quick google for some of the terms I mentioned above led me here: http://www.codeproject.com/cpp/StackShrink.asp You may want to read the article for more information. Regards, Will
See code excerpt below. GetCurrentStackPointer returns current stack pointer, GetStackPointerBase returns stack memory block beginning which is "stack top". Roman --- __declspec(naked) __forceinline ULONG_PTR GetCurrentStackPointer() throw() { __asm mov eax, esp __asm ret } inline ULONG_PTR GetStackPointerBase(ULONG_PTR nStackPointer = GetCurrentStackPointer()) throw() { MEMORY_BASIC_INFORMATION MemoryBasicInformation; ATLVERIFY(VirtualQueryEx(GetCurrentProcess(), (VOID*) nStackPointer, &MemoryBasicInformation, sizeof MemoryBasicInformation) == sizeof MemoryBasicInformation); return (ULONG_PTR) MemoryBasicInformation.AllocationBase; } inline SIZE_T GetFreeStackSize(ULONG_PTR nStackPointer = GetCurrentStackPointer()) throw() { return nStackPointer - GetStackPointerBase(nStackPointer); }