From 2f84de1ff5872260898773859ea2d88cf90c232e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 16 Jul 2014 10:21:18 +0000 Subject: [PATCH] * thread.cc (pthread::create): Handle stackaddr as upper bound address. Add comment. (pthread_attr_setstack): Store upper bound address in stackaddr. Explain why. (pthread_attr_getstack): Handle stackaddr as upper bound address. Add comment. (pthread_attr_setstackaddr): Add comment. (pthread_attr_getstackaddr): Add comment. (pthread_attr_getstacksize): Return default stacksize if stacksize has not been set by the application, just as on Linux. Add comment. (pthread_getattr_np): Store upper bound address in stackaddr. Explain why. * include/pthread.h: Remove outdated comment. (pthread_attr_getstackaddr): Mark as deprecated, as on Linux. (pthread_attr_setstackaddr): Ditto. --- winsup/cygwin/ChangeLog | 18 ++++++++++++++ winsup/cygwin/include/pthread.h | 12 ++++------ winsup/cygwin/thread.cc | 42 ++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index d1bac2ff0..bc71d7a79 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2014-07-16 Corinna Vinschen + + * thread.cc (pthread::create): Handle stackaddr as upper bound address. + Add comment. + (pthread_attr_setstack): Store upper bound address in stackaddr. + Explain why. + (pthread_attr_getstack): Handle stackaddr as upper bound address. + Add comment. + (pthread_attr_setstackaddr): Add comment. + (pthread_attr_getstackaddr): Add comment. + (pthread_attr_getstacksize): Return default stacksize if stacksize has + not been set by the application, just as on Linux. Add comment. + (pthread_getattr_np): Store upper bound address in stackaddr. Explain + why. + * include/pthread.h: Remove outdated comment. + (pthread_attr_getstackaddr): Mark as deprecated, as on Linux. + (pthread_attr_setstackaddr): Ditto. + 2014-07-15 Christopher Faylor * sigproc.cc (sigproc_init): Set aside more buffer space for signal diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index bfedf1f75..9170d96fc 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -1,7 +1,7 @@ /* pthread.h: POSIX pthread interface Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2011, 2012, 2013 Red Hat, Inc. + 2007, 2011, 2012, 2013, 2014 Red Hat, Inc. Written by Marco Fuykschot @@ -75,7 +75,8 @@ int pthread_attr_getschedparam (const pthread_attr_t *, struct sched_param *); int pthread_attr_getschedpolicy (const pthread_attr_t *, int *); int pthread_attr_getscope (const pthread_attr_t *, int *); int pthread_attr_getstack (const pthread_attr_t *, void **, size_t *); -int pthread_attr_getstackaddr (const pthread_attr_t *, void **); +int pthread_attr_getstackaddr (const pthread_attr_t *, void **) + __attribute__ ((deprecated)); int pthread_attr_init (pthread_attr_t *); int pthread_attr_setdetachstate (pthread_attr_t *, int); int pthread_attr_setguardsize (pthread_attr_t *, size_t); @@ -85,12 +86,9 @@ int pthread_attr_setschedpolicy (pthread_attr_t *, int); int pthread_attr_setscope (pthread_attr_t *, int); #ifdef _POSIX_THREAD_ATTR_STACKADDR -/* These functions may be implementable via some low level trickery. For now they are - * Not supported or implemented. The prototypes are here so if someone greps the - * source they will see these comments - */ int pthread_attr_setstack (pthread_attr_t *, void *, size_t); -int pthread_attr_setstackaddr (pthread_attr_t *, void *); +int pthread_attr_setstackaddr (pthread_attr_t *, void *) + __attribute__ ((deprecated)); #endif #ifdef _POSIX_THREAD_ATTR_STACKSIZE diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 8fdbf3610..fc70c3752 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -473,9 +473,13 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, arg = threadarg; mutex.lock (); - win32_obj_id = CygwinCreateThread (thread_init_wrapper, this, attr.stackaddr, - attr.stacksize ?: PTHREAD_DEFAULT_STACKSIZE, - attr.guardsize, 0, &thread_id); + /* stackaddr holds the uppermost stack address. See the comments in + pthread_attr_setstack and pthread_attr_setstackaddr for a description. */ + ULONG stacksize = attr.stacksize ?: PTHREAD_DEFAULT_STACKSIZE; + PVOID stackaddr = attr.stackaddr ? ((caddr_t) attr.stackaddr - stacksize) + : NULL; + win32_obj_id = CygwinCreateThread (thread_init_wrapper, this, stackaddr, + stacksize, attr.guardsize, 0, &thread_id); if (!win32_obj_id) { @@ -2253,7 +2257,13 @@ pthread_attr_setstack (pthread_attr_t *attr, void *addr, size_t size) return EINVAL; if (size < PTHREAD_STACK_MIN) return EINVAL; - (*attr)->stackaddr = addr; + /* The incoming address addr points to the lowest addressable byte of a + buffer of size bytes. Due to the way pthread_attr_setstackaddr is defined + on Linux, the lowest address ot the stack can't be reliably computed when + using pthread_attr_setstackaddr/pthread_attr_setstacksize. Therefore we + store the uppermost address of the stack in stackaddr. See also the + comment in pthread_attr_setstackaddr. */ + (*attr)->stackaddr = (caddr_t) addr + size; (*attr)->stacksize = size; return 0; } @@ -2263,7 +2273,9 @@ pthread_attr_getstack (const pthread_attr_t *attr, void **addr, size_t *size) { if (!pthread_attr::is_good_object (attr)) return EINVAL; - *addr = (*attr)->stackaddr; + /* stackaddr holds the uppermost stack address. See the comment in + pthread_attr_setstack. */ + *addr = (caddr_t) (*attr)->stackaddr - (*attr)->stacksize; *size = (*attr)->stacksize; return 0; } @@ -2275,6 +2287,12 @@ pthread_attr_setstackaddr (pthread_attr_t *attr, void *addr) return EINVAL; if (addr == NULL) return EINVAL; + /* This function is deprecated in SUSv4, but SUSv3 didn't define + if the incoming stack address is the lowest address of the memory + area defined as stack, or if it's the start address of the stack + at which it begins its growth. On Linux it's the latter which + means the uppermost stack address on x86 based systems. See comment + in pthread_attr_setstack as well. */ (*attr)->stackaddr = addr; return 0; } @@ -2284,6 +2302,7 @@ pthread_attr_getstackaddr (const pthread_attr_t *attr, void **addr) { if (!pthread_attr::is_good_object (attr)) return EINVAL; + /* See comment in pthread_attr_setstackaddr. */ *addr = (*attr)->stackaddr; return 0; } @@ -2304,7 +2323,10 @@ pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size) { if (!pthread_attr::is_good_object (attr)) return EINVAL; - *size = (*attr)->stacksize; + /* If the stacksize has not been set by the application, return the + default stacksize. Note that this is different from what + pthread_attr_getstack returns. */ + *size = (*attr)->stacksize ?: PTHREAD_DEFAULT_STACKSIZE; return 0; } @@ -2486,10 +2508,12 @@ pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) if (NT_SUCCESS (status)) { PTEB teb = (PTEB) tbi->TebBaseAddress; - (*attr)->stackaddr = teb->DeallocationStack ?: teb->Tib.StackLimit; - /* stack grows downwards on x86 systems */ + /* stackaddr holds the uppermost stack address. See the comments + in pthread_attr_setstack and pthread_attr_setstackaddr for a + description. */ + (*attr)->stackaddr = teb->Tib.StackBase; (*attr)->stacksize = (uintptr_t) teb->Tib.StackBase - - (uintptr_t) (*attr)->stackaddr; + - (uintptr_t) (teb->DeallocationStack ?: teb->Tib.StackLimit); } else {