* 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.
This commit is contained in:
Corinna Vinschen 2011-05-15 18:49:40 +00:00
parent 2922c6c4aa
commit cdb4231369
12 changed files with 274 additions and 24 deletions

View File

@ -1,3 +1,41 @@
2011-05-15 Corinna Vinschen <corinna@vinschen.de>
* 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.
2011-05-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_process.cc (struct heap_info::heap): Convert base to

View File

@ -1174,6 +1174,7 @@ psignal SIGFE
pthread_atfork SIGFE
pthread_attr_destroy SIGFE
pthread_attr_getdetachstate SIGFE
pthread_attr_getguardsize SIGFE
pthread_attr_getinheritsched SIGFE
pthread_attr_getschedparam SIGFE
pthread_attr_getschedpolicy SIGFE
@ -1183,10 +1184,13 @@ pthread_attr_getstackaddr SIGFE
pthread_attr_getstacksize SIGFE
pthread_attr_init SIGFE
pthread_attr_setdetachstate SIGFE
pthread_attr_setguardsize SIGFE
pthread_attr_setinheritsched SIGFE
pthread_attr_setschedparam SIGFE
pthread_attr_setschedpolicy SIGFE
pthread_attr_setscope SIGFE
pthread_attr_setstack SIGFE
pthread_attr_setstackaddr SIGFE
pthread_attr_setstacksize SIGFE
pthread_cancel SIGFE
_pthread_cleanup_pop SIGFE

View File

@ -410,12 +410,14 @@ details. */
242: Export psiginfo, psignal, sys_siglist.
243: Export sysinfo.
244: Export clock_settime.
245: Export pthread_attr_getguardsize, pthread_attr_setguardsize,
pthread_attr_setstack, pthread_attr_setstackaddr.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 244
#define CYGWIN_VERSION_API_MINOR 245
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible

View File

@ -72,6 +72,7 @@ extern "C"
/* Attributes */
int pthread_attr_destroy (pthread_attr_t *);
int pthread_attr_getdetachstate (const pthread_attr_t *, int *);
int pthread_attr_getguardsize (const pthread_attr_t *, size_t *);
int pthread_attr_getinheritsched (const pthread_attr_t *, int *);
int pthread_attr_getschedparam (const pthread_attr_t *, struct sched_param *);
int pthread_attr_getschedpolicy (const pthread_attr_t *, int *);
@ -80,6 +81,7 @@ int pthread_attr_getstack (const pthread_attr_t *, void **, size_t *);
int pthread_attr_getstackaddr (const pthread_attr_t *, void **);
int pthread_attr_init (pthread_attr_t *);
int pthread_attr_setdetachstate (pthread_attr_t *, int);
int pthread_attr_setguardsize (pthread_attr_t *, size_t);
int pthread_attr_setinheritsched (pthread_attr_t *, int);
int pthread_attr_setschedparam (pthread_attr_t *, const struct sched_param *);
int pthread_attr_setschedpolicy (pthread_attr_t *, int);

View File

@ -1,7 +1,7 @@
/* init.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009 Red Hat, Inc.
2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@ -115,7 +115,7 @@ extern void __stdcall dll_crt0_0 ();
extern "C" BOOL WINAPI
dll_entry (HANDLE h, DWORD reason, void *static_load)
{
BOOL wow64_test_stack_marker;
PNT_TIB tib;
switch (reason)
{
@ -131,9 +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;
if (wincap.is_wow64 ()
&& &wow64_test_stack_marker >= (PBOOL) 0x400000
&& &wow64_test_stack_marker <= (PBOOL) 0x10000000)
&& tib->StackLimit >= (PBOOL) 0x400000
&& tib->StackBase <= (PBOOL) 0x10000000)
respawn_wow64_process ();
dll_crt0_0 ();
@ -149,7 +150,10 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
munge_threadfunc ();
break;
case DLL_THREAD_DETACH:
if (dll_finished_loading && (void *) &_my_tls > (void *) &wow64_test_stack_marker
tib = &NtCurrentTeb ()->Tib;
if (dll_finished_loading
&& (PVOID) &_my_tls >= tib->StackLimit
&& (PVOID) &_my_tls < tib->StackBase
&& _my_tls.isinitialized ())
_my_tls.remove (0);
break;

View File

@ -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);
}

View File

@ -1,7 +1,7 @@
/* miscfuncs.h: main Cygwin header file.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008 Red Hat, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@ -38,4 +38,11 @@ int __stdcall check_invalid_virtual_addr (const void *s, unsigned sz) __attribut
ssize_t check_iovec (const struct iovec *, int, bool) __attribute__ ((regparm(3)));
#define check_iovec_for_read(a, b) check_iovec ((a), (b), false)
#define check_iovec_for_write(a, b) check_iovec ((a), (b), true)
extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
PVOID thread_arg, PVOID stackaddr,
ULONG stacksize, ULONG guardsize,
DWORD creation_flags,
LPDWORD thread_id);
#endif /*_MISCFUNCS_H*/

View File

@ -622,11 +622,15 @@ typedef struct _PEB
ULONG SessionId;
} PEB, *PPEB;
/* Simplifed definition, just to get the PEB pointer. */
/* Simplified definition, just to get the TIB and the PEB pointer. */
typedef struct _TEB
{
PVOID dummy[12];
PPEB Peb;
NT_TIB Tib;
PVOID EnvironmentPointer;
CLIENT_ID ClientId;
PVOID ActiveRpcHandle;
PVOID ThreadLocalStoragePointer;
PPEB Peb;
/* A lot more follows... */
} TEB, *PTEB;
@ -1111,9 +1115,7 @@ extern "C"
ULONG, ULONG *);
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
NTSTATUS WINAPI NtQuerySystemTime (PLARGE_INTEGER);
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, ULONG, PULONG);
NTSTATUS NTAPI NtQuerySymbolicLinkObject (HANDLE, PUNICODE_STRING, PULONG);

View File

@ -532,6 +532,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
pthread_atfork
pthread_attr_destroy
pthread_attr_getdetachstate
pthread_attr_getguardsize
pthread_attr_getinheritsched
pthread_attr_getschedparam
pthread_attr_getschedpolicy
@ -540,10 +541,12 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
pthread_attr_getstacksize
pthread_attr_init
pthread_attr_setdetachstate
pthread_attr_setguardsize
pthread_attr_setinheritsched
pthread_attr_setschedparam
pthread_attr_setschedpolicy
pthread_attr_setscope
pthread_attr_setstack
pthread_attr_setstacksize
pthread_cancel
pthread_cond_broadcast
@ -1237,6 +1240,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
mktemp (SUSv3)
on_exit (SunOS)
pthread_attr_getstackaddr (SUSv3)
pthread_attr_setstackaddr (SUSv3)
pthread_continue (XPG2)
pthread_getsequence_np (Tru64)
pthread_suspend (XPG2)
@ -1379,9 +1383,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
posix_trace[...]
posix_typed_[...]
powl
pthread_attr_getguardsize
pthread_attr_setguardsize
pthread_attr_setstack
pthread_barrier[...]
pthread_condattr_getclock
pthread_condattr_setclock

View File

@ -140,8 +140,8 @@ static struct
{cons, {c:-1L}}, /* 40, _SC_THREAD_THREADS_MAX */
{cons, {c:TTY_NAME_MAX}}, /* 41, _SC_TTY_NAME_MAX */
{cons, {c:_POSIX_THREADS}}, /* 42, _SC_THREADS */
{cons, {c:-1L}}, /* 43, _SC_THREAD_ATTR_STACKADDR */
{cons, {c:_POSIX_THREAD_ATTR_STACKSIZE}}, /* 44, _SC_THREAD_ATTR_STACKSIZE */
{cons, {c:_POSIX_THREAD_ATTR_STACKADDR}},/* 43, _SC_THREAD_ATTR_STACKADDR */
{cons, {c:_POSIX_THREAD_ATTR_STACKSIZE}},/* 44, _SC_THREAD_ATTR_STACKSIZE */
{cons, {c:_POSIX_THREAD_PRIORITY_SCHEDULING}}, /* 45, _SC_THREAD_PRIORITY_SCHEDULING */
{cons, {c:-1L}}, /* 46, _SC_THREAD_PRIO_INHERIT */
{cons, {c:-1L}}, /* 47, _SC_THREAD_PRIO_PROTECT */

View File

@ -23,9 +23,6 @@ details. */
R.Collins, April 2001. */
#ifdef HAVE_CONFIG_H
#endif
#include "winsup.h"
#include "miscfuncs.h"
#include "path.h"
@ -38,6 +35,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "ntdll.h"
#include "miscfuncs.h"
extern "C" void __fp_lock_all ();
extern "C" void __fp_unlock_all ();
@ -425,7 +423,9 @@ pthread::precreate (pthread_attr *newattr)
attr.joinable = newattr->joinable;
attr.contentionscope = newattr->contentionscope;
attr.inheritsched = newattr->inheritsched;
attr.stackaddr = newattr->stackaddr;
attr.stacksize = newattr->stacksize;
attr.guardsize = newattr->guardsize;
}
if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
@ -455,8 +455,9 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
arg = threadarg;
mutex.lock ();
win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
thread_init_wrapper, this, 0, &thread_id);
win32_obj_id = CygwinCreateThread (thread_init_wrapper, this,
attr.stackaddr, attr.stacksize,
attr.guardsize, 0, &thread_id);
if (!win32_obj_id)
{
@ -1087,7 +1088,8 @@ 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)
inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL), stacksize (0),
guardsize (0xffffffff)
{
schedparam.sched_priority = 0;
}
@ -2239,6 +2241,20 @@ pthread_attr_setscope (pthread_attr_t *attr, int contentionscope)
return 0;
}
extern "C" int
pthread_attr_setstack (pthread_attr_t *attr, void *addr, size_t size)
{
if (!pthread_attr::is_good_object (attr))
return EINVAL;
if (addr == NULL)
return EINVAL;
if (size < PTHREAD_STACK_MIN)
return EINVAL;
(*attr)->stackaddr = addr;
(*attr)->stacksize = size;
return 0;
}
extern "C" int
pthread_attr_getstack (const pthread_attr_t *attr, void **addr, size_t *size)
{
@ -2250,6 +2266,17 @@ pthread_attr_getstack (const pthread_attr_t *attr, void **addr, size_t *size)
return 0;
}
extern "C" int
pthread_attr_setstackaddr (pthread_attr_t *attr, void *addr)
{
if (!pthread_attr::is_good_object (attr))
return EINVAL;
if (addr == NULL)
return EINVAL;
(*attr)->stackaddr = addr;
return 0;
}
extern "C" int
pthread_attr_getstackaddr (const pthread_attr_t *attr, void **addr)
{
@ -2281,6 +2308,27 @@ pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size)
return 0;
}
extern "C" int
pthread_attr_setguardsize (pthread_attr_t *attr, size_t size)
{
if (!pthread_attr::is_good_object (attr))
return EINVAL;
/* We don't support a guardsize of more than 1 Meg. */
if (size > 1024 * 1024)
return EINVAL;
(*attr)->guardsize = size;
return 0;
}
extern "C" int
pthread_attr_getguardsize (const pthread_attr_t *attr, size_t *size)
{
if (!pthread_attr::is_good_object (attr))
return EINVAL;
*size = (*attr)->guardsize;
return 0;
}
extern "C" int
pthread_attr_destroy (pthread_attr_t *attr)
{
@ -2429,6 +2477,7 @@ pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
(*attr)->contentionscope = thread->attr.contentionscope;
(*attr)->inheritsched = thread->attr.inheritsched;
(*attr)->schedparam = thread->attr.schedparam;
(*attr)->guardsize = thread->attr.guardsize;
tbi = (PTHREAD_BASIC_INFORMATION) malloc (sizeof_tbi);
ret = NtQueryInformationThread (thread->win32_obj_id, ThreadBasicInformation,

View File

@ -252,6 +252,7 @@ public:
struct sched_param schedparam;
void *stackaddr;
size_t stacksize;
size_t guardsize;
pthread_attr ();
~pthread_attr ();