summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/miscfuncs.cc51
1 files changed, 48 insertions, 3 deletions
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index b4ab7cd7d..cba2140b6 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -508,9 +508,45 @@ pthread_wrapper (PVOID arg)
class thread_allocator
{
UINT_PTR current;
-public:
- thread_allocator () : current (THREAD_STORAGE_HIGH) {}
- PVOID alloc (SIZE_T size)
+ PVOID (thread_allocator::*alloc_func) (SIZE_T);
+ PVOID _alloc (SIZE_T size)
+ {
+ MEM_ADDRESS_REQUIREMENTS thread_req = {
+ (PVOID) THREAD_STORAGE_LOW,
+ (PVOID) (THREAD_STORAGE_HIGH - 1),
+ THREAD_STACK_SLOT
+ };
+ MEM_EXTENDED_PARAMETER thread_ext = {
+ .Type = MemExtendedParameterAddressRequirements,
+ .Pointer = (PVOID) &thread_req
+ };
+ SIZE_T real_size = roundup2 (size, THREAD_STACK_SLOT);
+ PVOID real_stackaddr = NULL;
+
+ if (real_size <= THREAD_STACK_MAX)
+ real_stackaddr = VirtualAlloc2 (GetCurrentProcess(), NULL, real_size,
+ MEM_RESERVE | MEM_TOP_DOWN,
+ PAGE_READWRITE, &thread_ext, 1);
+ /* If the thread area allocation failed, or if the application requests a
+ monster stack, fulfill request from mmap area. */
+ if (!real_stackaddr)
+ {
+ MEM_ADDRESS_REQUIREMENTS mmap_req = {
+ (PVOID) MMAP_STORAGE_LOW,
+ (PVOID) (MMAP_STORAGE_HIGH - 1),
+ THREAD_STACK_SLOT
+ };
+ MEM_EXTENDED_PARAMETER mmap_ext = {
+ .Type = MemExtendedParameterAddressRequirements,
+ .Pointer = (PVOID) &mmap_req
+ };
+ real_stackaddr = VirtualAlloc2 (GetCurrentProcess(), NULL, real_size,
+ MEM_RESERVE | MEM_TOP_DOWN,
+ PAGE_READWRITE, &mmap_ext, 1);
+ }
+ return real_stackaddr;
+ }
+ PVOID _alloc_old (SIZE_T size)
{
SIZE_T real_size = roundup2 (size, THREAD_STACK_SLOT);
BOOL overflow = FALSE;
@@ -558,6 +594,15 @@ public:
set_errno (EAGAIN);
return real_stackaddr;
}
+public:
+ thread_allocator () : current (THREAD_STORAGE_HIGH)
+ {
+ alloc_func = wincap.has_extended_mem_api () ? &_alloc : &_alloc_old;
+ }
+ PVOID alloc (SIZE_T size)
+ {
+ return (this->*alloc_func) (size);
+ }
};
thread_allocator thr_alloc NO_COPY;