diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ca20f97dc..272595d44 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,35 @@ +2011-05-20 Corinna Vinschen + + * child_info.h (CURR_CHILD_INFO_MAGIC): Update. + (class child_info_fork): Remove stacksize, add stackaddr and guardsize + members. + * dcrt0.cc (child_info_fork::alloc_stack_hard_way): Partial rewrite + to regenerate the stack exactly as in the parent. + (child_info_fork::alloc_stack): Set stackaddr to 0, rather than + stacksize. + (dll_crt0_1): Check for stackaddr before changing the stack addresses + in the TEB. + * fork.cc (frok::child): Check for stackaddr here. + (frok::parent): Set ch.stackaddr and ch.guardsize if not called from + the main thread. + * init.cc (dll_entry): Replace pointer to NT_TIB with pointer to TEB. + Fix incorrectly changed address test before removing _my_tls. + Set StackLimit to NULL on Windows 2000. Explain why. + * miscfuncs.cc (struct thread_wrapper_arg): Store stackbase rather + than stacksize, store commitaddr, remove guardsize. Store all pointers + as char * for easier address arithmetic. + (thread_wrapper): Rewrite to remove OS stack before calling thread + function. Add lots of comments to explain what we do. + (CygwinCreateThread): Reserve our own stack in case we got no + application stack. Add comments. + * ntdll.h (struct _TEB): Extend defintion up to DeallocationStack + member. + * thread.cc (pthread_attr::pthread_attr): Use "(size_t) -1" + rather then 0xffffffff. + * wincap.h (wincaps::has_stack_size_param_is_a_reservation): New + element. + * wincap.cc: Implement above element throughout. + 2011-05-19 Yaakov Selkowitz * thread.cc: Mark psiginfo and psignal as available in list of diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h index 44767edc9..2bf89c183 100644 --- a/winsup/cygwin/child_info.h +++ b/winsup/cygwin/child_info.h @@ -37,7 +37,7 @@ enum child_status #define EXEC_MAGIC_SIZE sizeof(child_info) /* Change this value if you get a message indicating that it is out-of-sync. */ -#define CURR_CHILD_INFO_MAGIC 0xe850717aU +#define CURR_CHILD_INFO_MAGIC 0xbdf5842aU /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between @@ -80,10 +80,12 @@ class child_info_fork: public child_info { public: HANDLE forker_finished;// for synchronization with child - DWORD stacksize; // size of parent stack jmp_buf jmp; // where child will jump to + void *stackaddr; // address of parent stack void *stacktop; // location of top of parent stack void *stackbottom; // location of bottom of parent stack + size_t guardsize; // size of POSIX guard region or (size_t) -1 if + // user stack char filler[4]; child_info_fork (); void handle_fork () __attribute__ ((regparm (1)));; diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index a6eb2696d..6248d0e3f 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -392,14 +392,11 @@ child_info NO_COPY *child_proc_info = NULL; void child_info_fork::alloc_stack_hard_way (volatile char *b) { - void *new_stack_pointer; - MEMORY_BASIC_INFORMATION m; - void *newbase; - int newlen; - bool guard; + void *stack_ptr; + DWORD stacksize; /* First check if the requested stack area is part of the user heap - or part of a mmaped region. If so, we have been started from a + or part of a mmapped region. If so, we have been started from a pthread with an application-provided stack, and the stack has just to be used as is. */ if ((stacktop >= cygheap->user_heap.base @@ -407,46 +404,33 @@ child_info_fork::alloc_stack_hard_way (volatile char *b) || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom)) return; - if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m)) - api_fatal ("fork: couldn't get stack info, %E"); - - LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize; - - if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot) - { - newbase = curbot; - newlen = (LPBYTE) stackbottom - (LPBYTE) curbot; - guard = false; - } - else - { - newbase = (LPBYTE) stacktop - (128 * 1024); - newlen = (LPBYTE) stackbottom - (LPBYTE) newbase; - guard = true; - } - - if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS)) + /* First, try to reserve the entire stack. */ + stacksize = (char *) stackbottom - (char *) stackaddr; + if (!VirtualAlloc (stackaddr, stacksize, MEM_RESERVE, PAGE_NOACCESS)) api_fatal ("fork: can't reserve memory for stack %p - %p, %E", - stacktop, stackbottom); - new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192)); - if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT, - PAGE_EXECUTE_READWRITE)) + stackaddr, stackbottom); + stacksize = (char *) stackbottom - (char *) stacktop; + stack_ptr = VirtualAlloc (stacktop, stacksize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!stack_ptr) api_fatal ("fork: can't commit memory for stack %p(%d), %E", - new_stack_pointer, stacksize); - if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m)) - api_fatal ("fork: couldn't get new stack info, %E"); - - if (guard) + stacktop, stacksize); + if (guardsize != (size_t) -1) { - m.BaseAddress = (LPBYTE) m.BaseAddress - 1; - if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT, - CYGWIN_GUARD)) - api_fatal ("fork: couldn't allocate new stack guard page %p, %E", - m.BaseAddress); + /* Allocate PAGE_GUARD page if it still fits. */ + if (stack_ptr > stackaddr) + { + stack_ptr = (void *) ((LPBYTE) stack_ptr + - wincap.page_size ()); + if (!VirtualAlloc (stack_ptr, wincap.page_size (), MEM_COMMIT, + CYGWIN_GUARD)) + api_fatal ("fork: couldn't allocate new stack guard page %p, %E", + stack_ptr); + } + /* Allocate POSIX guard pages. */ + if (guardsize > 0) + VirtualAlloc (stackaddr, guardsize, MEM_COMMIT, PAGE_NOACCESS); } - if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m)) - api_fatal ("fork: couldn't get new stack info, %E"); - stacktop = m.BaseAddress; b[0] = '\0'; } @@ -473,7 +457,7 @@ child_info_fork::alloc_stack () char *st = (char *) stacktop - 4096; while (_tlstop >= st) esp = getstack (esp); - stacksize = 0; + stackaddr = 0; } } @@ -811,7 +795,7 @@ dll_crt0_1 (void *) NOTE: Don't do anything that involves the stack until you've completed this step. */ - if (fork_info->stacksize) + if (fork_info->stackaddr) { _tlsbase = (char *) fork_info->stackbottom; _tlstop = (char *) fork_info->stacktop; diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 8701cdfa3..4a800b551 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -25,6 +25,7 @@ details. */ #include "tls_pbuf.h" #include "dll_init.h" #include "cygmalloc.h" +#include "ntdll.h" #define NPIDS_HELD 4 @@ -178,7 +179,7 @@ frok::child (volatile char * volatile here) /* If we've played with the stack, stacksize != 0. That means that fork() was invoked from other than the main thread. Make sure that the threadinfo information is properly set up. */ - if (fork_info->stacksize) + if (fork_info->stackaddr) { _main_tls = &_my_tls; _main_tls->init_thread (NULL, NULL); @@ -327,10 +328,33 @@ frok::parent (volatile char * volatile stack_here) ch.forker_finished = forker_finished; ch.stackbottom = _tlsbase; - ch.stacktop = (void *) stack_here; - ch.stacksize = (char *) ch.stackbottom - (char *) stack_here; - debug_printf ("stack - bottom %p, top %p, size %d", - ch.stackbottom, ch.stacktop, ch.stacksize); + ch.stacktop = (void *) _tlstop; + ch.stackaddr = 0; + ch.guardsize = 0; + if (&_my_tls != _main_tls) + { + /* We have not been started from the main thread. Fetch the + information required to set up the thread stack identically + in the child. */ + PTEB teb = NtCurrentTeb (); + if (!teb->DeallocationStack) + { + /* Pthread with application-provided stack. Don't set up a + PAGE_GUARD page. guardsize == -1 is used in alloc_stack_hard_way + to recognize this type of stack. */ + ch.stackaddr = _my_tls.tid->attr.stackaddr; + ch.guardsize = (size_t) -1; + } + else + { + ch.stackaddr = teb->DeallocationStack; + /* If it's a pthread, fetch guardsize from thread attributes. */ + if (_my_tls.tid) + ch.guardsize = _my_tls.tid->attr.guardsize; + } + } + debug_printf ("stack - bottom %p, top %p, addr %p, guardsize %p", + ch.stackbottom, ch.stacktop, ch.stackaddr, ch.guardsize); PROCESS_INFORMATION pi; STARTUPINFOW si; diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index 5404ed15a..9f66c3ba2 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -115,7 +115,7 @@ extern void __stdcall dll_crt0_0 (); extern "C" BOOL WINAPI dll_entry (HANDLE h, DWORD reason, void *static_load) { - PNT_TIB tib; + PTEB teb; switch (reason) { @@ -131,10 +131,10 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) the auto load address of DLLs? Check if we're running in WOW64 on a 64 bit machine *and* are spawned by a genuine 64 bit process. If so, respawn. */ - tib = &NtCurrentTeb ()->Tib; + teb = NtCurrentTeb (); if (wincap.is_wow64 () - && tib->StackLimit >= (PBOOL) 0x400000 - && tib->StackBase <= (PBOOL) 0x10000000) + && teb->Tib.StackLimit >= (PBOOL) 0x400000 + && teb->Tib.StackBase <= (PBOOL) 0x10000000) respawn_wow64_process (); dll_crt0_0 (); @@ -150,12 +150,19 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) munge_threadfunc (); break; case DLL_THREAD_DETACH: - tib = &NtCurrentTeb ()->Tib; + teb = NtCurrentTeb (); if (dll_finished_loading - && (PVOID) &_my_tls >= tib->StackLimit - && (PVOID) &_my_tls < tib->StackBase + && (PVOID) &teb >= teb->Tib.StackLimit + && (PVOID) &teb < teb->Tib.StackBase && _my_tls.isinitialized ()) _my_tls.remove (0); + /* Windows 2000 has a bug in NtTerminateThread. Instead of releasing + the stack at teb->DeallocationStack it uses the value of + teb->Tib.StackLimit to evaluate the stack address. So we just claim + there is no stack. */ + if (teb->DeallocationStack == NULL + && !wincap.has_stack_size_param_is_a_reservation ()) + teb->Tib.StackLimit = NULL; break; } diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index e6bb6c31f..e73ac2290 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -26,6 +26,8 @@ details. */ #include "fhandler.h" #include "dtable.h" #include "cygheap.h" +#include "pinfo.h" +#include "exception.h" long tls_ix = -1; @@ -392,72 +394,109 @@ struct thread_wrapper_arg { LPTHREAD_START_ROUTINE func; PVOID arg; - PVOID stackaddr; - ULONG stacksize; - ULONG guardsize; + char *stackaddr; + char *stackbase; + char *commitaddr; }; DWORD WINAPI thread_wrapper (VOID *arg) { + /* Just plain paranoia. */ if (!arg) return ERROR_INVALID_PARAMETER; + /* Fetch thread wrapper info and free from cygheap. */ thread_wrapper_arg wrapper_arg = *(thread_wrapper_arg *) arg; cfree (arg); - if (wrapper_arg.stackaddr) - { - /* If the application provided the stack, we must make sure that - it's actually used by the thread function. So what we do here is - to compute the stackbase of the application-provided stack, move - _my_tls to the stackbase, and change the stack pointer accordingly. */ - _my_tls.remove (0); - wrapper_arg.stackaddr = (PVOID) ((PBYTE) wrapper_arg.stackaddr - + wrapper_arg.stacksize); - _tlsbase = (char *) wrapper_arg.stackaddr; - wrapper_arg.stackaddr = (PVOID) ((PBYTE) wrapper_arg.stackaddr - - CYGTLS_PADSIZE); - _tlstop = (char *) wrapper_arg.stackaddr; - _my_tls.init_thread ((char *) wrapper_arg.stackaddr, - (DWORD (*)(void*, void*)) wrapper_arg.func); - wrapper_arg.stackaddr = (PVOID) (_tlstop - sizeof (PVOID)); - __asm__ ("\n\ - movl %[WRAPPER_ARG], %%ebx # Load &wrapper_arg into ebx \n\ - movl (%%ebx), %%eax # Load thread func into eax \n\ - movl 4(%%ebx), %%ecx # Load thread arg into ecx \n\ - movl 8(%%ebx), %%edx # Load stackbase into edx \n\ - xorl %%ebp, %%ebp # Set ebp to 0 \n\ - movl %%edx, %%esp # Set esp to stackbase \n\ - pushl %%ecx # Push thread arg onto stack \n\ - pushl %%eax # Push thread func onto stack \n\ - jmp *%%eax # Jump to thread func \n" - : : [WRAPPER_ARG] "r" (&wrapper_arg)); + /* Remove _cygtls from this stack since it won't be used anymore. */ + _cygtls *tls; + tls = &_my_tls; + _my_tls.remove (0); - } - if (wrapper_arg.guardsize) + /* Set stack values in TEB */ + PTEB teb = NtCurrentTeb (); + teb->Tib.StackBase = wrapper_arg.stackbase; + teb->Tib.StackLimit = wrapper_arg.commitaddr ?: wrapper_arg.stackaddr; + /* Set DeallocationStack value. If we have an application-provided stack, + we set DeallocationStack to NULL, so NtTerminateThread does not deallocate + any stack. If we created the stack in CygwinCreateThread, we set + DeallocationStack to the stackaddr of our own stack, so it's automatically + deallocated when the thread is terminated. */ + char *dealloc_addr = (char *) teb->DeallocationStack; + teb->DeallocationStack = wrapper_arg.commitaddr ? wrapper_arg.stackaddr + : NULL; + /* Store the OS-provided DeallocationStack address in wrapper_arg.stackaddr. + The below assembler code will release the OS stack after switching to our + new stack. */ + wrapper_arg.stackaddr = dealloc_addr; + + /* Initialize new _cygtls. */ + _my_tls.init_thread (wrapper_arg.stackbase - CYGTLS_PADSIZE, + (DWORD (*)(void*, void*)) wrapper_arg.func); + + /* Copy exception list over to new stack. I'm not quite sure how the + exception list is extended by Windows itself. What's clear is that it + always grows downwards and that it starts right at the stackbase. + Therefore we first count the number of exception records and place + the copy at the stackbase, too, so there's still a lot of room to + extend the list up to where our _cygtls region starts. */ + _exception_list *old_start = (_exception_list *) teb->Tib.ExceptionList; + unsigned count = 0; + teb->Tib.ExceptionList = NULL; + for (_exception_list *e_ptr = old_start; + e_ptr && e_ptr != (_exception_list *) -1; + e_ptr = e_ptr->prev) + ++count; + if (count) { - /* Set up POSIX guard pages. Note that this is not the same as the - PAGE_GUARD protection. Rather, the POSIX guard pages are a - PAGE_NOACCESS protected area which is supposed to guard against - stack overflow and to trigger a SIGSEGV if that happens. */ - PNT_TIB tib = &NtCurrentTeb ()->Tib; - wrapper_arg.stackaddr = (PVOID) ((PBYTE) tib->StackBase - - wrapper_arg.stacksize); - if (!VirtualAlloc (wrapper_arg.stackaddr, wrapper_arg.guardsize, - MEM_COMMIT, PAGE_NOACCESS)) - system_printf ("VirtualAlloc, %E"); + _exception_list *new_start = (_exception_list *) wrapper_arg.stackbase + - count; + teb->Tib.ExceptionList = (struct _EXCEPTION_REGISTRATION_RECORD *) + new_start; + while (true) + { + new_start->handler = old_start->handler; + if (old_start->prev == (_exception_list *) -1) + { + new_start->prev = (_exception_list *) -1; + break; + } + new_start->prev = new_start + 1; + new_start = new_start->prev; + old_start = old_start->prev; + } } + __asm__ ("\n\ - movl %[WRAPPER_ARG], %%ebx # Load &wrapper_arg into ebx \n\ - movl (%%ebx), %%eax # Load thread func into eax \n\ - movl 4(%%ebx), %%ecx # Load thread arg into ecx \n\ - pushl %%ecx # Push thread arg onto stack \n\ - pushl %%eax # Push thread func onto stack \n\ - jmp *%%eax # Jump to thread func \n" - : : [WRAPPER_ARG] "r" (&wrapper_arg)); - /* Never reached. */ - return ERROR_INVALID_FUNCTION; + movl %[WRAPPER_ARG], %%ebx # Load &wrapper_arg into ebx \n\ + movl (%%ebx), %%eax # Load thread func into eax \n\ + movl 4(%%ebx), %%ecx # Load thread arg into ecx \n\ + movl 8(%%ebx), %%edx # Load stackaddr into edx \n\ + movl 12(%%ebx), %%ebx # Load stackbase into ebx \n\ + subl %[CYGTLS], %%ebx # Subtract CYGTLS_PADSIZE \n\ + subl $4, %%ebx # Subtract another 4 bytes \n\ + movl %%ebx, %%esp # Set esp \n\ + xorl %%ebp, %%ebp # Set ebp to 0 \n\ + # Now we moved to the new stack. Save thread func address\n\ + # and thread arg on new stack \n\ + pushl %%ecx # Push thread arg onto stack \n\ + pushl %%eax # Push thread func onto stack \n\ + # Now it's safe to release the OS stack. \n\ + pushl $0x8000 # dwFreeType: MEM_RELEASE \n\ + pushl $0x0 # dwSize: 0 \n\ + pushl %%edx # lpAddress: stackaddr \n\ + call _VirtualFree@12 # Shoot \n\ + # All set. We can pop the thread function address from \n\ + # the stack and call it. The thread arg is still on the \n\ + # stack in the expected spot. \n\ + popl %%eax # Pop thread_func address \n\ + call *%%eax # Call thread func \n" + : : [WRAPPER_ARG] "r" (&wrapper_arg), + [CYGTLS] "i" (CYGTLS_PADSIZE)); + /* Never return from here. */ + ExitThread (0); } /* FIXME: This should be settable via setrlimit (RLIMIT_STACK). */ @@ -468,9 +507,11 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg, PVOID stackaddr, ULONG stacksize, ULONG guardsize, DWORD creation_flags, LPDWORD thread_id) { + PVOID real_stackaddr = NULL; ULONG real_stacksize = 0; ULONG real_guardsize = 0; thread_wrapper_arg *wrapper_arg; + HANDLE thread = NULL; wrapper_arg = (thread_wrapper_arg *) ccalloc (HEAP_STR, 1, sizeof *wrapper_arg); @@ -488,9 +529,8 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg, real_stacksize = PTHREAD_STACK_MIN; if (stackaddr) { - wrapper_arg->stackaddr = stackaddr; - wrapper_arg->stacksize = real_stacksize; - real_stacksize = PTHREAD_STACK_MIN; + wrapper_arg->stackaddr = (char *) stackaddr; + wrapper_arg->stackbase = (char *) stackaddr + real_stacksize; } else { @@ -498,25 +538,68 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg, real_stacksize = roundup2 (real_stacksize, wincap.page_size ()); /* If no guardsize has been specified by the application, use the system pagesize as default. */ - real_guardsize = (guardsize != 0xffffffff) + real_guardsize = (guardsize != (ULONG) -1) ? guardsize : wincap.page_size (); if (real_guardsize) real_guardsize = roundup2 (real_guardsize, wincap.page_size ()); /* If the default stacksize is used and guardsize has not been specified, - don't add a guard page to the size. */ - if (stacksize && guardsize != 0xffffffff) + don't add a guard page to the size. Same if stacksize is only + PTHREAD_STACK_MIN. */ + if (stacksize && guardsize != (ULONG) -1 + && real_stacksize > PTHREAD_STACK_MIN) real_stacksize += real_guardsize; /* Now roundup the result to the next allocation boundary. */ real_stacksize = roundup2 (real_stacksize, wincap.allocation_granularity ()); - - wrapper_arg->stacksize = real_stacksize; - wrapper_arg->guardsize = real_guardsize; + /* Reserve stack. + FIXME? If the TOP_DOWN method tends to collide too much with + other stuff, we should provide our own mechanism to find a + suitable place for the stack. Top down from the start of + the Cygwin DLL comes to mind. */ + real_stackaddr = VirtualAlloc (NULL, real_stacksize, + MEM_RESERVE | MEM_TOP_DOWN, + PAGE_EXECUTE_READWRITE); + if (!real_stackaddr) + return NULL; + /* Set up committed region. In contrast to the OS we commit 64K and + set up just a single guard page at the end. */ + char *commitaddr = (char *) real_stackaddr + + real_stacksize + - wincap.allocation_granularity (); + if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT, + PAGE_EXECUTE_READWRITE | PAGE_GUARD)) + goto err; + commitaddr += wincap.page_size (); + if (!VirtualAlloc (commitaddr, wincap.allocation_granularity () + - wincap.page_size (), MEM_COMMIT, + PAGE_EXECUTE_READWRITE)) + goto err; + if (real_guardsize) + VirtualAlloc (real_stackaddr, real_guardsize, MEM_COMMIT, + PAGE_NOACCESS); + wrapper_arg->stackaddr = (char *) real_stackaddr; + wrapper_arg->stackbase = (char *) real_stackaddr + real_stacksize; + wrapper_arg->commitaddr = commitaddr; } - /* Use the STACK_SIZE_PARAM_IS_A_RESERVATION parameter to make sure the - stack size is exactly the size we want. */ - return CreateThread (&sec_none_nih, real_stacksize, thread_wrapper, - wrapper_arg, - creation_flags | STACK_SIZE_PARAM_IS_A_RESERVATION, - thread_id); + /* Use the STACK_SIZE_PARAM_IS_A_RESERVATION parameter so only the + minimum size for a thread stack is reserved by the OS. This doesn't + work on Windows 2000, but we deallocate the OS stack in thread_wrapper + anyway, so this should be a problem only in a tight memory condition. + Note that we reserve a 256K stack, not 64K, otherwise the thread creation + might crash the process due to a stack overflow. */ + thread = CreateThread (&sec_none_nih, 4 * PTHREAD_STACK_MIN, + thread_wrapper, wrapper_arg, + creation_flags | STACK_SIZE_PARAM_IS_A_RESERVATION, + thread_id); + +err: + if (!thread && real_stackaddr) + { + /* Don't report the wrong error even though VirtualFree is very unlikely + to fail. */ + DWORD err = GetLastError (); + VirtualFree (real_stackaddr, 0, MEM_RELEASE); + SetLastError (err); + } + return thread; } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 77aeeece0..a085a7115 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -622,7 +622,7 @@ typedef struct _PEB ULONG SessionId; } PEB, *PPEB; -/* Simplified definition, just to get the TIB and the PEB pointer. */ +/* Simplified definition, just to get stuff we're interested in. */ typedef struct _TEB { NT_TIB Tib; @@ -631,6 +631,32 @@ typedef struct _TEB PVOID ActiveRpcHandle; PVOID ThreadLocalStoragePointer; PPEB Peb; + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID _reserved1[2]; + ULONG _reserved2[31]; + PVOID WOW32Reserved; + ULONG CurrentLocale; + ULONG FpSoftwareStatusRegister; + PVOID SystemReserved1[54]; + LONG ExceptionCode; + PVOID ActivationContextStackPointer; + UCHAR SpareBytes1[36]; + ULONG TxFsContext; + ULONG GdiTebBatch[312]; + CLIENT_ID RealClientId; + PVOID GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + ULONG Win32ClientInfo[62]; + PVOID glDispatchTable[233]; + ULONG glReserved1[29]; + PVOID glReserved2[6]; + ULONG LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + PVOID DeallocationStack; /* A lot more follows... */ } TEB, *PTEB; diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index e4bfb74e3..f0f535101 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1089,7 +1089,7 @@ pthread::resume () pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC), joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS), inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL), stacksize (0), -guardsize (0xffffffff) +guardsize ((size_t) -1) { schedparam.sched_priority = 0; } diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index b959d1e57..2a848b4b6 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -51,6 +51,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:false, + has_stack_size_param_is_a_reservation:false, }; wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -81,6 +82,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:false, + has_stack_size_param_is_a_reservation:false, }; wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -111,6 +113,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:true, + has_stack_size_param_is_a_reservation:true, }; wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -141,6 +144,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:true, + has_stack_size_param_is_a_reservation:true, }; wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -171,6 +175,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:true, + has_stack_size_param_is_a_reservation:true, }; wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -201,6 +206,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:false, has_restricted_raw_disk_access:false, use_dont_resolve_hack:true, + has_stack_size_param_is_a_reservation:true, }; wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -231,6 +237,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:true, has_restricted_raw_disk_access:true, use_dont_resolve_hack:false, + has_stack_size_param_is_a_reservation:true, }; wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { @@ -261,6 +268,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { has_fast_cwd:true, has_restricted_raw_disk_access:true, use_dont_resolve_hack:false, + has_stack_size_param_is_a_reservation:true, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 629a062cd..7738d1f8b 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -41,6 +41,7 @@ struct wincaps unsigned has_fast_cwd : 1; unsigned has_restricted_raw_disk_access : 1; unsigned use_dont_resolve_hack : 1; + unsigned has_stack_size_param_is_a_reservation : 1; }; class wincapc @@ -90,6 +91,7 @@ public: bool IMPLEMENT (has_fast_cwd) bool IMPLEMENT (has_restricted_raw_disk_access) bool IMPLEMENT (use_dont_resolve_hack) + bool IMPLEMENT (has_stack_size_param_is_a_reservation) #undef IMPLEMENT };