Increase pthread's default stack size
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 29 Jul 2015 16:05:59 +0000 (12:05 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 3 Aug 2015 17:52:58 +0000 (13:52 -0400)
We had a bug where cs would occasionally fail service lookups.  It
appeared that cs's threads were running on the small stack and probably
clobbering some memory, leading to the failure.

Increasing the stack size is not ideal - ideally, we'd have applications
and schedulers that were smarter.  Otherwise, we'll be back again the
next time we have some weird corruption due to various library calls.

For this commit, I turned up the size to 4 MB.  Since we don't want to
actually allocate that much per thread, we no longer MAP_POPULATE it.
But we do fault in the first (top) page of the stack.  This prevents us
from taking the page fault later on, when we could be measuring things.

Again, smarter schedulers and applications can do something more
intelligent.

Another option is to implement guard pages in pthreads.  I'm a little
reluctant to do that, since it means the number of VMRs in the kernel is
O(nr_pthreads).  Every stack would take two VMRs, one for the stack and
one for the guard.

Perhaps we can make guard pages an option, turned on by default for
'legacy' apps and turned off for high-perf apps, similar to how we deal
with TLS.

user/pthread/pthread.c
user/pthread/pthread.h

index fd3cadf..956428c 100644 (file)
@@ -514,13 +514,17 @@ static void __pthread_free_stack(struct pthread_tcb *pt)
 
 static int __pthread_allocate_stack(struct pthread_tcb *pt)
 {
+       int force_a_page_fault;
        assert(pt->stacksize);
        void* stackbot = mmap(0, pt->stacksize,
                              PROT_READ|PROT_WRITE|PROT_EXEC,
-                             MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
+                             MAP_ANONYMOUS, -1, 0);
        if (stackbot == MAP_FAILED)
                return -1; // errno set by mmap
        pt->stacktop = stackbot + pt->stacksize;
+       /* Want the top of the stack populated, but not the rest of the stack;
+        * that'll grow on demand (up to pt->stacksize) */
+       force_a_page_fault = ACCESS_ONCE(*(int*)(pt->stacktop - sizeof(int)));
        return 0;
 }
 
index d8004d5..dbdc9d8 100644 (file)
@@ -107,9 +107,7 @@ enum
 #define PTHREAD_CREATE_DETACHED        PTHREAD_CREATE_DETACHED
 };
 
-// TODO: how big do we want these?  ideally, we want to be able to guard and map
-// more space if we go too far.
-#define PTHREAD_STACK_PAGES 4
+#define PTHREAD_STACK_PAGES 1024
 #define PTHREAD_STACK_SIZE (PTHREAD_STACK_PAGES*PGSIZE)
 #define PTHREAD_STACK_MIN PTHREAD_STACK_SIZE