Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-05-15 22:49:40 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-05-15 22:49:40 +0400
commitcdb4231369f4c06795e170f9cb003d8de1581f5b (patch)
treedd008237ecd92aa1101affbc9577809aa49b8dd5 /winsup/cygwin/miscfuncs.cc
parent2922c6c4aaa754fee3fcaecddd618ec9dff84cc5 (diff)
* cygwin.din (pthread_attr_getguardsize): Export.
(pthread_attr_setguardsize): Export. (pthread_attr_setstack): Export. (pthread_attr_setstackaddr): Export. * init.cc (dll_entry): Remove wow64_test_stack_marker. Check for unusual stack address by testing stack addresses from current TEB. Check validity of _my_tls by testing if it's within the stack as given in current TEB. * miscfuncs.cc (struct thread_wrapper_arg): New structure used to push all required information to thread_wrapper function. (thread_wrapper): Wrapper function for actual thread function. If an application stack has been given, change %ebp and %esp so that the thread function runs on that stack. If the thread has been created by CygwinCreateThread, set up the POSIX guard pages if necessary. (CygwinCreateThread): New function. * miscfuncs.h (CygwinCreateThread): Declare. * ntdll.h (struct _TEB): Define all members up to Peb. * posix.sgml (std-susv4): Move pthread_attr_getguardsize, pthread_attr_setguardsize and pthread_attr_setstack here. (std-deprec): Add pthread_attr_setstackaddr. * sysconf.cc (sca): Set _SC_THREAD_ATTR_STACKADDR to _POSIX_THREAD_ATTR_STACKADDR. * thread.cc (pthread::precreate): Copy pthread_attr stackaddr and guardsize members. (pthread::create): Call CygwinCreateThread. (pthread_attr::pthread_attr): Initialize guardsize. (pthread_attr_setstack): New function. (pthread_attr_setstackaddr): New function. (pthread_attr_setguardsize): New function. (pthread_attr_getguardsize): New function. (pthread_getattr_np): Copy attr.guardsize. * thread.h (pthread_attr): Add member guardsize. * include/pthread.h (pthread_attr_getguardsize): Declare. (pthread_attr_setguardsize): Declare. * include/cygwin/version.h: Bump API minor number.
Diffstat (limited to 'winsup/cygwin/miscfuncs.cc')
-rw-r--r--winsup/cygwin/miscfuncs.cc142
1 files changed, 141 insertions, 1 deletions
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 706347240..0e2945125 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -1,7 +1,7 @@
/* miscfuncs.cc: misc funcs that don't belong anywhere else
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2011 Red Hat, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@@ -15,12 +15,17 @@ details. */
#include <assert.h>
#include <alloca.h>
#include <limits.h>
+#include <sys/param.h>
#include <wchar.h>
#include <wingdi.h>
#include <winuser.h>
#include <winnls.h>
#include "cygtls.h"
#include "ntdll.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
long tls_ix = -1;
@@ -376,3 +381,138 @@ slashify (const char *src, char *dst, bool trailing_slash_p)
*dst++ = '/';
*dst++ = 0;
}
+
+/* CygwinCreateThread.
+
+ Replacement function for CreateThread. What we do here is to remove
+ parameters we don't use and instead to add parameters we need to make
+ the function pthreads compatible. */
+
+struct thread_wrapper_arg
+{
+ LPTHREAD_START_ROUTINE func;
+ PVOID arg;
+ PVOID stackaddr;
+ ULONG stacksize;
+ ULONG guardsize;
+};
+
+DWORD WINAPI
+thread_wrapper (VOID *arg)
+{
+ if (!arg)
+ return ERROR_INVALID_PARAMETER;
+
+ 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 and
+ change the stack pointer accordingly.
+
+ NOTE: _my_tls is on the stack created by CreateThread! It's
+ unlikely the tls structure will ever exceed 64K, but if
+ so, we have to raise the size of the stack in the call
+ to CreateThread, too. */
+ wrapper_arg.stackaddr = (PVOID) ((PBYTE) wrapper_arg.stackaddr
+ + wrapper_arg.stacksize
+ - sizeof (PVOID));
+ __asm__ ("\n\
+ movl %[WRAPPER_ARG], %%ebx \n\
+ movl (%%ebx), %%eax \n\
+ movl 4(%%ebx), %%ecx \n\
+ movl 8(%%ebx), %%edx \n\
+ xorl %%ebp, %%ebp \n\
+ movl %%edx, %%esp \n\
+ pushl %%ecx \n\
+ pushl %%eax \n\
+ jmp *%%eax \n" : : [WRAPPER_ARG] "r" (&wrapper_arg));
+
+ }
+ if (wrapper_arg.guardsize)
+ {
+ /* 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");
+ }
+ __asm__ ("\n\
+ movl %[WRAPPER_ARG], %%ebx \n\
+ movl (%%ebx), %%eax \n\
+ movl 4(%%ebx), %%ecx \n\
+ pushl %%ecx \n\
+ pushl %%eax \n\
+ jmp *%%eax \n" : : [WRAPPER_ARG] "r" (&wrapper_arg));
+ /* Never reached. */
+ return ERROR_INVALID_FUNCTION;
+}
+
+/* FIXME: This should be settable via setrlimit (RLIMIT_STACK). */
+#define DEFAULT_STACKSIZE (512 * 1024)
+
+HANDLE WINAPI
+CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
+ PVOID stackaddr, ULONG stacksize, ULONG guardsize,
+ DWORD creation_flags, LPDWORD thread_id)
+{
+ ULONG real_stacksize = 0;
+ ULONG real_guardsize = 0;
+ thread_wrapper_arg *wrapper_arg;
+
+ wrapper_arg = (thread_wrapper_arg *) ccalloc (HEAP_STR, 1,
+ sizeof *wrapper_arg);
+ if (!wrapper_arg)
+ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ wrapper_arg->func = thread_func;
+ wrapper_arg->arg = thread_arg;
+
+ /* Set stacksize. */
+ real_stacksize = stacksize ?: DEFAULT_STACKSIZE;
+ if (real_stacksize < PTHREAD_STACK_MIN)
+ real_stacksize = PTHREAD_STACK_MIN;
+ if (stackaddr)
+ {
+ wrapper_arg->stackaddr = stackaddr;
+ wrapper_arg->stacksize = real_stacksize;
+ real_stacksize = PTHREAD_STACK_MIN;
+ }
+ else
+ {
+ /* If not, we have to create the stack here. */
+ 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)
+ ? 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)
+ 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;
+ }
+ /* 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);
+}