From e0721cc6221bb347f4106011bec5992b6784cede Mon Sep 17 00:00:00 2001 From: corinna Date: Sun, 15 May 2011 18:49:38 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 38 +++++++++ winsup/cygwin/cygwin.din | 4 + winsup/cygwin/include/cygwin/version.h | 4 +- winsup/cygwin/include/pthread.h | 2 + winsup/cygwin/init.cc | 14 ++-- winsup/cygwin/miscfuncs.cc | 142 ++++++++++++++++++++++++++++++++- winsup/cygwin/miscfuncs.h | 9 ++- winsup/cygwin/ntdll.h | 12 +-- winsup/cygwin/posix.sgml | 7 +- winsup/cygwin/sysconf.cc | 4 +- winsup/cygwin/thread.cc | 61 ++++++++++++-- winsup/cygwin/thread.h | 1 + 12 files changed, 274 insertions(+), 24 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0733a86a7d..415be6df32 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,41 @@ +2011-05-15 Corinna Vinschen + + * 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 * fhandler_process.cc (struct heap_info::heap): Convert base to diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 2eafd2c8ca..12c3f3d576 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -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 diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index cf03080df2..ea66d40978 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -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 diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index c76cd670b5..e963eba549 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -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); diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc index fab71ba27f..5404ed15a0 100644 --- a/winsup/cygwin/init.cc +++ b/winsup/cygwin/init.cc @@ -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; diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 7063472401..0e2945125a 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 #include #include +#include #include #include #include #include #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); +} diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h index 1dcb924db9..6be70e3433 100644 --- a/winsup/cygwin/miscfuncs.h +++ b/winsup/cygwin/miscfuncs.h @@ -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*/ diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index cb4e6d9626..9c5597ec19 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -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); diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml index 235ee2f946..a576b353f1 100644 --- a/winsup/cygwin/posix.sgml +++ b/winsup/cygwin/posix.sgml @@ -532,6 +532,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). 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). 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). 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). posix_trace[...] posix_typed_[...] powl - pthread_attr_getguardsize - pthread_attr_setguardsize - pthread_attr_setstack pthread_barrier[...] pthread_condattr_getclock pthread_condattr_setclock diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc index de84dbc3ed..73c44fe362 100644 --- a/winsup/cygwin/sysconf.cc +++ b/winsup/cygwin/sysconf.cc @@ -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 */ diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 60a6d3a775..b53fc7f701 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -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; } @@ -2240,6 +2242,20 @@ pthread_attr_setscope (pthread_attr_t *attr, int contentionscope) } 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) { if (!pthread_attr::is_good_object (attr)) @@ -2251,6 +2267,17 @@ pthread_attr_getstack (const pthread_attr_t *attr, void **addr, size_t *size) } 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) { if (!pthread_attr::is_good_object (attr)) @@ -2282,6 +2309,27 @@ pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size) } 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) { if (!pthread_attr::is_good_object (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, diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index b1969ed810..d8e4319a48 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -252,6 +252,7 @@ public: struct sched_param schedparam; void *stackaddr; size_t stacksize; + size_t guardsize; pthread_attr (); ~pthread_attr (); -- 2.11.0