OSDN Git Service

* cygwin.din (pthread_attr_getguardsize): Export.
authorcorinna <corinna>
Sun, 15 May 2011 18:49:38 +0000 (18:49 +0000)
committercorinna <corinna>
Sun, 15 May 2011 18:49:38 +0000 (18:49 +0000)
(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.

12 files changed:
winsup/cygwin/ChangeLog
winsup/cygwin/cygwin.din
winsup/cygwin/include/cygwin/version.h
winsup/cygwin/include/pthread.h
winsup/cygwin/init.cc
winsup/cygwin/miscfuncs.cc
winsup/cygwin/miscfuncs.h
winsup/cygwin/ntdll.h
winsup/cygwin/posix.sgml
winsup/cygwin/sysconf.cc
winsup/cygwin/thread.cc
winsup/cygwin/thread.h

index 0733a86..415be6d 100644 (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
index 2eafd2c..12c3f3d 100644 (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
index cf03080..ea66d40 100644 (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
index c76cd67..e963eba 100644 (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);
index fab71ba..5404ed1 100644 (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;
index 7063472..0e29451 100644 (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);
+}
index 1dcb924..6be70e3 100644 (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*/
index cb4e6d9..9c5597e 100644 (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);
index 235ee2f..a576b35 100644 (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
index de84dbc..73c44fe 100644 (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 */
index 60a6d3a..b53fc7f 100644 (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;
 }
@@ -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,
index b1969ed..d8e4319 100644 (file)
@@ -252,6 +252,7 @@ public:
   struct sched_param schedparam;
   void *stackaddr;
   size_t stacksize;
+  size_t guardsize;
 
   pthread_attr ();
   ~pthread_attr ();