Export the guard size of the main thread via vm.guard_size. Add a

complementary writable sysctl for the initial guard size of threads
created via pthread_create. Let the existing attribut accessors do the
right thing. Raise the default guard size for threads to 64KB.
This commit is contained in:
joerg 2017-07-02 16:41:32 +00:00
parent 7fa4406c02
commit 5f391f4ae2
9 changed files with 74 additions and 34 deletions

View File

@ -1,13 +1,9 @@
$NetBSD: TODO,v 1.18 2017/02/08 03:44:41 kamil Exp $ $NetBSD: TODO,v 1.19 2017/07/02 16:41:32 joerg Exp $
Interfaces/features to implement: Interfaces/features to implement:
- Realtime extensions: priority inheritance. - Realtime extensions: priority inheritance.
- Allow threads to change their stack size.
- Allow threads to modify the red zone size; cf. pthread_attr_setguardsize(3).
- Keep a pool of dead LWPs so that we do not have take the full hit of - Keep a pool of dead LWPs so that we do not have take the full hit of
_lwp_create() every time pthread_create() is called. _lwp_create() every time pthread_create() is called.

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread.c,v 1.147 2015/05/29 16:05:13 christos Exp $ */ /* $NetBSD: pthread.c,v 1.148 2017/07/02 16:41:32 joerg Exp $ */
/*- /*-
* Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: pthread.c,v 1.147 2015/05/29 16:05:13 christos Exp $"); __RCSID("$NetBSD: pthread.c,v 1.148 2017/07/02 16:41:32 joerg Exp $");
#define __EXPOSE_STACK 1 #define __EXPOSE_STACK 1
@ -40,7 +40,9 @@ __RCSID("$NetBSD: pthread.c,v 1.147 2015/05/29 16:05:13 christos Exp $");
#include <sys/lwp.h> #include <sys/lwp.h>
#include <sys/lwpctl.h> #include <sys/lwpctl.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/sysctl.h>
#include <sys/tls.h> #include <sys/tls.h>
#include <uvm/uvm_param.h>
#include <assert.h> #include <assert.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -115,6 +117,7 @@ int pthread__dbg; /* set by libpthread_dbg if active */
* stack pointer to thread data afterwards. * stack pointer to thread data afterwards.
*/ */
size_t pthread__stacksize; size_t pthread__stacksize;
size_t pthread__guardsize;
size_t pthread__pagesize; size_t pthread__pagesize;
static struct __pthread_st *pthread__main; static struct __pthread_st *pthread__main;
static size_t __pthread_st_size; static size_t __pthread_st_size;
@ -164,6 +167,9 @@ pthread__init(void)
pthread_t first; pthread_t first;
char *p; char *p;
int i; int i;
int mib[2];
unsigned int value;
size_t len;
extern int __isthreaded; extern int __isthreaded;
/* /*
@ -182,6 +188,14 @@ pthread__init(void)
pthread__pagesize = (size_t)sysconf(_SC_PAGESIZE); pthread__pagesize = (size_t)sysconf(_SC_PAGESIZE);
pthread__concurrency = (int)sysconf(_SC_NPROCESSORS_CONF); pthread__concurrency = (int)sysconf(_SC_NPROCESSORS_CONF);
mib[0] = CTL_VM;
mib[1] = VM_THREAD_GUARD_SIZE;
len = sizeof(value);
if (sysctl(mib, __arraycount(mib), &value, &len, NULL, 0) == 0)
pthread__guardsize = value;
else
pthread__guardsize = pthread__pagesize;
/* Initialize locks first; they're needed elsewhere. */ /* Initialize locks first; they're needed elsewhere. */
pthread__lockprim_init(); pthread__lockprim_init();
for (i = 0; i < NHASHLOCK; i++) { for (i = 0; i < NHASHLOCK; i++) {
@ -335,16 +349,19 @@ pthread__getstack(pthread_t newthread, const pthread_attr_t *attr)
if (attr != NULL) { if (attr != NULL) {
pthread_attr_getstack(attr, &stackbase, &stacksize); pthread_attr_getstack(attr, &stackbase, &stacksize);
pthread_attr_getguardsize(attr, &guardsize);
} else { } else {
stackbase = NULL; stackbase = NULL;
stacksize = 0; stacksize = 0;
guardsize = pthread__guardsize;
} }
if (stacksize == 0) if (stacksize == 0)
stacksize = pthread__stacksize; stacksize = pthread__stacksize;
if (newthread->pt_stack_allocated) { if (newthread->pt_stack_allocated) {
if (stackbase == NULL && if (stackbase == NULL &&
newthread->pt_stack.ss_size == stacksize) newthread->pt_stack.ss_size == stacksize &&
newthread->pt_guardsize == guardsize)
return 0; return 0;
stackbase2 = newthread->pt_stack.ss_sp; stackbase2 = newthread->pt_stack.ss_sp;
#ifndef __MACHINE_STACK_GROWS_UP #ifndef __MACHINE_STACK_GROWS_UP
@ -362,14 +379,13 @@ pthread__getstack(pthread_t newthread, const pthread_attr_t *attr)
if (stackbase == NULL) { if (stackbase == NULL) {
stacksize = ((stacksize - 1) | (pthread__pagesize - 1)) + 1; stacksize = ((stacksize - 1) | (pthread__pagesize - 1)) + 1;
guardsize = pthread__pagesize; guardsize = ((guardsize - 1) | (pthread__pagesize - 1)) + 1;
stackbase = mmap(NULL, stacksize + guardsize, stackbase = mmap(NULL, stacksize + guardsize,
PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0); PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0);
if (stackbase == MAP_FAILED) if (stackbase == MAP_FAILED)
return ENOMEM; return ENOMEM;
allocated = true; allocated = true;
} else { } else {
guardsize = 0;
allocated = false; allocated = false;
} }
#ifdef __MACHINE_STACK_GROWS_UP #ifdef __MACHINE_STACK_GROWS_UP
@ -1280,7 +1296,9 @@ pthread__initmainstack(void)
{ {
struct rlimit slimit; struct rlimit slimit;
const AuxInfo *aux; const AuxInfo *aux;
size_t size; size_t size, len;
int mib[2];
unsigned int value;
_DIAGASSERT(_dlauxinfo() != NULL); _DIAGASSERT(_dlauxinfo() != NULL);
@ -1289,6 +1307,13 @@ pthread__initmainstack(void)
"Couldn't get stack resource consumption limits"); "Couldn't get stack resource consumption limits");
size = slimit.rlim_cur; size = slimit.rlim_cur;
pthread__main->pt_stack.ss_size = size; pthread__main->pt_stack.ss_size = size;
pthread__main->pt_guardsize = pthread__pagesize;
mib[0] = CTL_VM;
mib[1] = VM_GUARD_SIZE;
len = sizeof(value);
if (sysctl(mib, __arraycount(mib), &value, &len, NULL, 0) == 0)
pthread__main->pt_guardsize = value;
for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) { for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) {
if (aux->a_type == AT_STACKBASE) { if (aux->a_type == AT_STACKBASE) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $ */ /* $NetBSD: pthread_attr.c,v 1.17 2017/07/02 16:41:32 joerg Exp $ */
/*- /*-
* Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $"); __RCSID("$NetBSD: pthread_attr.c,v 1.17 2017/07/02 16:41:32 joerg Exp $");
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@ -107,7 +107,7 @@ pthread_attr_get_np(pthread_t thread, pthread_attr_t *attr)
p->ptap_namearg = thread->pt_name; p->ptap_namearg = thread->pt_name;
p->ptap_stackaddr = thread->pt_stack.ss_sp; p->ptap_stackaddr = thread->pt_stack.ss_sp;
p->ptap_stacksize = thread->pt_stack.ss_size; p->ptap_stacksize = thread->pt_stack.ss_size;
p->ptap_guardsize = pthread__pagesize; p->ptap_guardsize = thread->pt_guardsize;
return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp); return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp);
} }
@ -150,7 +150,7 @@ pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard)
struct pthread_attr_private *p; struct pthread_attr_private *p;
if ((p = attr->pta_private) == NULL) if ((p = attr->pta_private) == NULL)
*guard = (size_t)sysconf(_SC_PAGESIZE); *guard = pthread__guardsize;
else else
*guard = p->ptap_guardsize; *guard = p->ptap_guardsize;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: pthread_attr_getguardsize.3,v 1.3 2016/04/07 06:21:48 dholland Exp $ .\" $NetBSD: pthread_attr_getguardsize.3,v 1.4 2017/07/02 16:41:32 joerg Exp $
.\" .\"
.\" Copyright (c) 2010 Jukka Ruohonen <jruohonen@iki.fi> .\" Copyright (c) 2010 Jukka Ruohonen <jruohonen@iki.fi>
.\" All rights reserved. .\" All rights reserved.
@ -25,7 +25,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE. .\" POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd July 7, 2010 .Dd July 2, 2017
.Dt PTHREAD_ATTR_GETGUARDSIZE 3 .Dt PTHREAD_ATTR_GETGUARDSIZE 3
.Os .Os
.Sh NAME .Sh NAME
@ -66,12 +66,9 @@ In
.Nx .Nx
the default the default
.Fa guardsize .Fa guardsize
is the system page size. is given by the
(This value is often 4096 bytes but varies on some ports; the .Pa vm.thread_guard_size
precise value can be retrieved by using .Xr sysctl 7 .
.Xr sysconf 3
with
.Dv _SC_PAGESIZE . )
.Pp .Pp
The rationale behind The rationale behind
.Fa guardsize .Fa guardsize

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_int.h,v 1.93 2017/02/08 03:44:41 kamil Exp $ */ /* $NetBSD: pthread_int.h,v 1.94 2017/07/02 16:41:32 joerg Exp $ */
/*- /*-
* Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -171,6 +171,7 @@ struct __pthread_st {
#define PT_ATTR_DEAD 0xDEAD0002 #define PT_ATTR_DEAD 0xDEAD0002
extern size_t pthread__stacksize; extern size_t pthread__stacksize;
extern size_t pthread__guardsize;
extern size_t pthread__pagesize; extern size_t pthread__pagesize;
extern int pthread__nspins; extern int pthread__nspins;
extern int pthread__concurrency; extern int pthread__concurrency;

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_subr.c,v 1.81 2017/06/23 21:28:38 joerg Exp $ */ /* $NetBSD: exec_subr.c,v 1.82 2017/07/02 16:41:33 joerg Exp $ */
/* /*
* Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.81 2017/06/23 21:28:38 joerg Exp $"); __KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.82 2017/07/02 16:41:33 joerg Exp $");
#include "opt_pax.h" #include "opt_pax.h"
@ -67,7 +67,8 @@ VMCMD_EVCNT_DECL(kills);
#define DPRINTF(a) #define DPRINTF(a)
#endif #endif
uint32_t user_stack_guard_size = 1024 * 1024; unsigned int user_stack_guard_size = 1024 * 1024;
unsigned int user_thread_stack_guard_size = 64 * 1024;
/* /*
* new_vmcmd(): * new_vmcmd():

View File

@ -1,4 +1,4 @@
/* $NetBSD: uvm_meter.c,v 1.65 2014/12/01 04:11:14 msaitoh Exp $ */ /* $NetBSD: uvm_meter.c,v 1.66 2017/07/02 16:41:33 joerg Exp $ */
/* /*
* Copyright (c) 1997 Charles D. Cranor and Washington University. * Copyright (c) 1997 Charles D. Cranor and Washington University.
@ -36,7 +36,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uvm_meter.c,v 1.65 2014/12/01 04:11:14 msaitoh Exp $"); __KERNEL_RCSID(0, "$NetBSD: uvm_meter.c,v 1.66 2017/07/02 16:41:33 joerg Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -281,6 +281,18 @@ SYSCTL_SETUP(sysctl_vm_setup, "sysctl vm subtree setup")
SYSCTL_DESCR("Maximum user address"), SYSCTL_DESCR("Maximum user address"),
NULL, VM_MAX_ADDRESS, NULL, 0, NULL, VM_MAX_ADDRESS, NULL, 0,
CTL_VM, VM_MAXADDRESS, CTL_EOL); CTL_VM, VM_MAXADDRESS, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_UNSIGNED,
CTLTYPE_INT, "guard_size",
SYSCTL_DESCR("Guard size of main thread"),
NULL, 0, &user_stack_guard_size, 0,
CTL_VM, VM_GUARD_SIZE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT|CTLFLAG_UNSIGNED|CTLFLAG_READWRITE,
CTLTYPE_INT, "thread_guard_size",
SYSCTL_DESCR("Guard size of other threads"),
NULL, 0, &user_thread_stack_guard_size, 0,
CTL_VM, VM_THREAD_GUARD_SIZE, CTL_EOL);
uvmpdpol_sysctlsetup(); uvmpdpol_sysctlsetup();
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: uvm_param.h,v 1.36 2017/06/23 21:28:39 joerg Exp $ */ /* $NetBSD: uvm_param.h,v 1.37 2017/07/02 16:41:33 joerg Exp $ */
/* /*
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
@ -178,6 +178,8 @@ extern const int *const uvmexp_pageshift;
#define VM_MINADDRESS 14 #define VM_MINADDRESS 14
#define VM_MAXADDRESS 15 #define VM_MAXADDRESS 15
#define VM_PROC 16 /* process information */ #define VM_PROC 16 /* process information */
#define VM_GUARD_SIZE 17 /* guard size for main thread */
#define VM_THREAD_GUARD_SIZE 18 /* default guard size for new threads */
#define VM_MAXID 17 /* number of valid vm ids */ #define VM_MAXID 17 /* number of valid vm ids */
@ -201,6 +203,8 @@ extern const int *const uvmexp_pageshift;
{ "minaddress", CTLTYPE_LONG }, \ { "minaddress", CTLTYPE_LONG }, \
{ "maxaddress", CTLTYPE_LONG }, \ { "maxaddress", CTLTYPE_LONG }, \
{ "proc", CTLTYPE_STRUCT }, \ { "proc", CTLTYPE_STRUCT }, \
{ "guard_size", CTLTYPE_INT }, \
{ "thread_guard_size", CTLTYPE_INT }, \
} }
#ifndef ASSEMBLER #ifndef ASSEMBLER
@ -224,7 +228,8 @@ extern const int *const uvmexp_pageshift;
round_page((vaddr_t)(da) + (vsize_t)maxdmap) round_page((vaddr_t)(da) + (vsize_t)maxdmap)
#endif #endif
extern uint32_t user_stack_guard_size; extern unsigned int user_stack_guard_size;
extern unsigned int user_thread_stack_guard_size;
#ifndef VM_DEFAULT_ADDRESS_TOPDOWN #ifndef VM_DEFAULT_ADDRESS_TOPDOWN
#define VM_DEFAULT_ADDRESS_TOPDOWN(da, sz) \ #define VM_DEFAULT_ADDRESS_TOPDOWN(da, sz) \
trunc_page(VM_MAXUSER_ADDRESS - MAXSSIZ - (sz) - user_stack_guard_size) trunc_page(VM_MAXUSER_ADDRESS - MAXSSIZ - (sz) - user_stack_guard_size)

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_join.c,v 1.8 2012/03/12 20:17:16 joerg Exp $ */ /* $NetBSD: t_join.c,v 1.9 2017/07/02 16:41:33 joerg Exp $ */
/*- /*-
* Copyright (c) 2010 The NetBSD Foundation, Inc. * Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: t_join.c,v 1.8 2012/03/12 20:17:16 joerg Exp $"); __RCSID("$NetBSD: t_join.c,v 1.9 2017/07/02 16:41:33 joerg Exp $");
#include <errno.h> #include <errno.h>
#include <pthread.h> #include <pthread.h>
@ -104,6 +104,7 @@ threadfunc1(void *arg)
error = true; error = true;
ATF_REQUIRE(pthread_attr_setstacksize(&attr, STACKSIZE * (i + 1)) == 0); ATF_REQUIRE(pthread_attr_setstacksize(&attr, STACKSIZE * (i + 1)) == 0);
ATF_REQUIRE(pthread_attr_setguardsize(&attr, STACKSIZE * (i + 2)) == 0);
rv = pthread_create(&thread[i], &attr, threadfunc2, (void *)i); rv = pthread_create(&thread[i], &attr, threadfunc2, (void *)i);
@ -148,13 +149,15 @@ threadfunc2(void *arg)
static uintptr_t i = 0; static uintptr_t i = 0;
uintptr_t j; uintptr_t j;
pthread_attr_t attr; pthread_attr_t attr;
size_t stacksize; size_t stacksize, guardsize;
j = (uintptr_t)arg; j = (uintptr_t)arg;
ATF_REQUIRE(pthread_attr_get_np(pthread_self(), &attr) == 0); ATF_REQUIRE(pthread_attr_get_np(pthread_self(), &attr) == 0);
ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0); ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0);
ATF_REQUIRE(stacksize == STACKSIZE * (j + 1)); ATF_REQUIRE(stacksize == STACKSIZE * (j + 1));
ATF_REQUIRE(pthread_attr_getguardsize(&attr, &guardsize) == 0);
ATF_REQUIRE(guardsize == STACKSIZE * (j + 2));
ATF_REQUIRE(pthread_attr_destroy(&attr) == 0); ATF_REQUIRE(pthread_attr_destroy(&attr) == 0);
if (i++ == j) if (i++ == j)