Module Name:    src
Committed By:   joerg
Date:           Mon Mar 12 20:16:52 UTC 2012

Modified Files:
        src/lib/libpthread: pthread.c pthread_int.h

Log Message:
Keep track of the size of the guard area, in case we want to make it
modifiable later. Only reuse the stack if it was allocated by libpthread
and if the expected thread size matches the current stack size.


To generate a diff of this commit:
cvs rdiff -u -r1.131 -r1.132 src/lib/libpthread/pthread.c
cvs rdiff -u -r1.83 -r1.84 src/lib/libpthread/pthread_int.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libpthread/pthread.c
diff -u src/lib/libpthread/pthread.c:1.131 src/lib/libpthread/pthread.c:1.132
--- src/lib/libpthread/pthread.c:1.131	Mon Mar 12 16:37:15 2012
+++ src/lib/libpthread/pthread.c	Mon Mar 12 20:16:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread.c,v 1.131 2012/03/12 16:37:15 joerg Exp $	*/
+/*	$NetBSD: pthread.c,v 1.132 2012/03/12 20:16:52 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread.c,v 1.131 2012/03/12 16:37:15 joerg Exp $");
+__RCSID("$NetBSD: pthread.c,v 1.132 2012/03/12 20:16:52 joerg Exp $");
 
 #define	__EXPOSE_STACK	1
 
@@ -317,10 +317,11 @@ pthread__scrubthread(pthread_t t, char *
 }
 
 static int
-pthread__newstack(pthread_t newthread, const pthread_attr_t *attr)
+pthread__getstack(pthread_t newthread, const pthread_attr_t *attr)
 {
-	void *stackbase, *redzone;
+	void *stackbase, *stackbase2, *redzone;
 	size_t stacksize, guardsize;
+	bool allocated;
 
 	if (attr != NULL) {
 		pthread_attr_getstack(attr, &stackbase, &stacksize);
@@ -331,28 +332,51 @@ pthread__newstack(pthread_t newthread, c
 	if (stacksize == 0)
 		stacksize = pthread__stacksize;
 
+	if (newthread->pt_stack_allocated) {
+		if (newthread->pt_stack.ss_size == stacksize)
+			return 0;
+		stackbase2 = newthread->pt_stack.ss_sp;
+#ifndef __MACHINE_STACK_GROWS_UP
+		stackbase2 = (char *)stackbase2 - newthread->pt_guardsize;
+#endif
+		munmap(stackbase2,
+		    newthread->pt_stack.ss_size + newthread->pt_guardsize);
+		newthread->pt_stack.ss_sp = NULL;
+		newthread->pt_stack.ss_size = 0;
+		newthread->pt_guardsize = 0;
+		newthread->pt_stack_allocated = false;
+	}
+
+	newthread->pt_stack_allocated = false;
+
 	if (stackbase == NULL) {
-		stacksize = (stacksize | (pthread__pagesize - 1)) + 1;
+		stacksize = ((stacksize - 1) | (pthread__pagesize - 1)) + 1;
 		guardsize = pthread__pagesize;
 		stackbase = mmap(NULL, stacksize + guardsize,
 		    PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
 		if (stackbase == MAP_FAILED)
 			return ENOMEM;
+		allocated = true;
 	} else {
 		guardsize = 0;
+		allocated = false;
 	}
-	newthread->pt_stack.ss_size = stacksize;
 #ifdef __MACHINE_STACK_GROWS_UP
-	redzone = (char *)stackbase + newthread->pt_stack.ss_size;
-	newthread->pt_stack.ss_sp = (char *)stackbase + guardsize;
+	redzone = (char *)stackbase + stacksize;
+	stackbase2 = (char *)stackbase;
 #else
 	redzone = (char *)stackbase;
-	newthread->pt_stack.ss_sp = (char *)stackbase + guardsize;
+	stackbase2 = (char *)stackbase + guardsize;
 #endif
-	if (guardsize && mprotect(redzone, guardsize, PROT_NONE) == -1) {
+	if (allocated && guardsize &&
+	    mprotect(redzone, guardsize, PROT_NONE) == -1) {
 		munmap(stackbase, stacksize + guardsize);
 		return EPERM;
 	}
+	newthread->pt_stack.ss_size = stacksize;
+	newthread->pt_stack.ss_sp = stackbase2;
+	newthread->pt_guardsize = guardsize;
+	newthread->pt_stack_allocated = allocated;
 	return 0;
 }
 
@@ -427,8 +451,9 @@ pthread_create(pthread_t *thread, const 
 			free(name);
 			return ENOMEM;
 		}
+		newthread->pt_stack_allocated = false;
 
-		if (pthread__newstack(newthread, attr)) {
+		if (pthread__getstack(newthread, attr)) {
 			free(newthread);
 			free(name);
 			return ENOMEM;
@@ -450,6 +475,16 @@ pthread_create(pthread_t *thread, const 
 
 		/* Will be reset by the thread upon exit. */
 		pthread__initthread(newthread);
+	} else {
+		if (pthread__getstack(newthread, attr)) {
+			pthread_mutex_lock(&pthread__deadqueue_lock);
+			PTQ_INSERT_TAIL(&pthread__deadqueue, newthread, pt_deadq);
+			pthread_mutex_unlock(&pthread__deadqueue_lock);
+			return ENOMEM;
+		}
+		_INITCONTEXT_U(&newthread->pt_uc);
+		newthread->pt_uc.uc_stack = newthread->pt_stack;
+		newthread->pt_uc.uc_link = NULL;
 	}
 
 	/*

Index: src/lib/libpthread/pthread_int.h
diff -u src/lib/libpthread/pthread_int.h:1.83 src/lib/libpthread/pthread_int.h:1.84
--- src/lib/libpthread/pthread_int.h:1.83	Fri Mar  2 18:06:05 2012
+++ src/lib/libpthread/pthread_int.h	Mon Mar 12 20:16:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_int.h,v 1.83 2012/03/02 18:06:05 joerg Exp $	*/
+/*	$NetBSD: pthread_int.h,v 1.84 2012/03/12 20:16:52 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -52,9 +52,10 @@
 #include <sys/atomic.h>
 #include <sys/tree.h>
 
+#include <limits.h>
 #include <lwp.h>
 #include <signal.h>
-#include <limits.h>
+#include <stdbool.h>
 
 #ifdef __GNUC__
 #define	PTHREAD_HIDE	__attribute__ ((visibility("hidden")))
@@ -104,6 +105,8 @@ struct	__pthread_st {
 	int		pt_cancel;	/* Deferred cancellation */
 	int		pt_errno;	/* Thread-specific errno. */
 	stack_t		pt_stack;	/* Our stack */
+	bool		pt_stack_allocated;
+	size_t		pt_guardsize;
 	void		*pt_exitval;	/* Read by pthread_join() */
 	char		*pt_name;	/* Thread's name, set by the app. */
 	int		pt_willpark;	/* About to park */

Reply via email to