This is the mail archive of the libc-hacker@sourceware.org mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] NPTL proposed large page fix for pthread_create.


This patch fixes the problem on systems that support multiple page
sizes, but we don't want to change the PTHREAD_STACK_MIN const that is
still valid for the smaller page size and the ATTR_FLAG_STACKADDR case.
For the case where the runtime allocates the stack we need to make sure
the 2 page minimum is meet.  Where the PTHREAD_STACK_MIN is less than
the 2 page minimum, bump the allocation up to 2 pages.


2005-12-05  Steven Munroe  <sjmunroe@us.ibm.com>

	* allocatestack.c (allocate_stack): Handle large page case.
	* tst-stack2.c: Include unistd.h.
	(do_test): Add tests for PTHREAD_STACK_MIN < pagesize and
	user allocated stack of PTHREAD_STACK_MIN bytes.

diff -urN libc24-cvstip-20051128/nptl/allocatestack.c libc24/nptl/allocatestack.c
--- libc24-cvstip-20051128/nptl/allocatestack.c	2005-10-03 19:40:01.000000000 -0500
+++ libc24/nptl/allocatestack.c	2005-12-05 15:56:03.076424936 -0600
@@ -407,11 +407,27 @@
       /* Make sure the size of the stack is enough for the guard and
 	 eventually the thread descriptor.  */
       guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1;
-      if (__builtin_expect (size < (guardsize + __static_tls_size
-				    + MINIMAL_REST_STACK + pagesize_m1 + 1),
+      if (__builtin_expect (size < ((guardsize + __static_tls_size
+				    + MINIMAL_REST_STACK
+				    + pagesize_m1) & ~pagesize_m1),
 			    0))
-	/* The stack is too small (or the guard too large).  */
-	return EINVAL;
+	{
+	/* The stack is too small (or the guard too large), but this might not
+	   be an error.  If we are on a system that supports multiple page
+	   sizes,  the current page size may be larger then PTHREAD_STACK_MIN,
+	   but we need to allocate a minimum of two pages for guard and stack.
+	   In this case we can allocate the two page minimum.  */
+	  if ((size >= PTHREAD_STACK_MIN)
+	    && (PTHREAD_STACK_MIN< ((pagesize_m1 + 1)  * 2)))
+	    /* The requested size is >= PTHREAD_STACK_MIN,  so the application
+	       expect this to work. But PTHREAD_STACK_MIN is < 2 of the
+	       current pages,  so bump the stack size up to two pages at the
+	       current page size.  */
+	    size = (pagesize_m1 + 1) * 2;
+	  else
+	    /* Not the large page case so return EINVAL.  */
+	    return EINVAL;
+	}
 
       /* Try to get a stack from the cache.  */
       reqsize = size;
diff -urN libc24-cvstip-20051128/nptl/tst-stack2.c libc24/nptl/tst-stack2.c
--- libc24-cvstip-20051128/nptl/tst-stack2.c	2003-09-03 00:06:52.000000000 -0500
+++ libc24/nptl/tst-stack2.c	2005-12-05 15:45:30.599457656 -0600
@@ -23,6 +23,7 @@
 #include <pthread.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <unistd.h>
 
 static int seen;
 
@@ -38,21 +39,94 @@
 {
   pthread_attr_t attr;
   pthread_attr_init (&attr);
+  long pagesize;
 
   int result = 0;
-  int res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+  int res;
+
+  pagesize = sysconf(_SC_PAGESIZE);
+  printf ("sysconf(_SC_PAGESIZE) = %ld\n", pagesize);
+  
+  res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
   if (res)
     {
       printf ("pthread_attr_setstacksize failed %d\n", res);
       result = 1;
     }
 
-  /* Create the thread.  */
+  /* Create the thread with PTHREAD_STACK_MIN stack size.  */
   pthread_t th;
   res = pthread_create (&th, &attr, tf, NULL);
   if (res)
     {
       printf ("pthread_create failed %d\n", res);
+      
+      if ((PTHREAD_STACK_MIN) < (2 * pagesize))
+        {
+	/* This should have worked because the system has multiple pages sizes
+	   and it is currently running with pagesize >= PTHREAD_STACK_MIN.  */
+          puts("PTHREAD_STACK_MIN < (2 * pagesize)");
+	}
+      else
+        result = 1;
+    }
+  else
+    {
+      res = pthread_join (th, NULL);
+      if (res)
+	{
+	  printf ("pthread_join failed %d\n", res);
+	  result = 1;
+	}
+    }
+    
+  /* The PTHREAD_STACK_MIN should always be valid when stackaddr is set.  */
+  
+  void *stack;
+  size_t size = PTHREAD_STACK_MIN;
+
+  
+  if (posix_memalign (&stack, getpagesize (), size) != 0)
+    {
+      puts ("out of memory while allocating the stack memory");
+      return (1);
+    }
+
+  if (pthread_attr_init (&attr) != 0)
+    {
+      puts ("attr_init failed");
+      return (1);
+    }
+
+  if (pthread_attr_setstack (&attr, stack, size) != 0)
+    {
+      puts ("attr_setstack failed");
+      return (1);
+    }
+    
+  res = pthread_create (&th, &attr, tf, NULL);
+  if (res)
+    {
+      printf ("pthread_create failed %d\n", res);
+      result = 1;
+    }
+  else
+    {
+      res = pthread_join (th, NULL);
+      if (res)
+	{
+	  printf ("pthread_join failed %d\n", res);
+	  result = 1;
+	}
+    }
+
+  /* The default pthread_attr_t should always work, even if the page
+     size is larger then expected.  */
+    
+  res = pthread_create (&th, NULL, tf, NULL);
+  if (res)
+    {
+      printf ("pthread_create failed %d\n", res);
       result = 1;
     }
   else
@@ -65,9 +139,9 @@
 	}
     }
 
-  if (seen != 1)
+  if (seen != 3)
     {
-      printf ("seen %d != 1\n", seen);
+      printf ("seen %d != 3\n", seen);
       result = 1;
     }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]