Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Sep 2014 20:06:58 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        John Baldwin <jhb@freebsd.org>
Cc:        "Ivan A. Kosarev" <ivan@ivan-labs.com>, freebsd-current@freebsd.org, doc@freebsd.org
Subject:   Re: libthr and main thread stack size
Message-ID:  <20140920170658.GE2210@kib.kiev.ua>
In-Reply-To: <5242716.s4iaScq0Bu@ralph.baldwin.cx>
References:  <53E36E84.4060806@ivan-labs.com> <FEB60EB5-546D-454D-AE62-B2483246E42C@scsiguy.com> <20140916081324.GQ2737@kib.kiev.ua> <5242716.s4iaScq0Bu@ralph.baldwin.cx>

next in thread | previous in thread | raw e-mail | index | archive | help

--pAwQNkOnpTn9IO2O
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Fri, Sep 19, 2014 at 03:27:25PM -0400, John Baldwin wrote:
> I suspect it was done out of reasons of being overly conservative in
> interpreting RLIMIT_STACK. I think it is quite surprising behavior
> though and would rather we make your option the default and implement
> what the Open Group says above.

Ok, below is the patch.  I felt bad about adding yet another magic and
undocumented tunable to our libthr.  Since there seems to be no
alternative than a tunable to enforce old behaviour, I documented
the quirks I am aware of.

Doc people, please review the man page in the patch.

diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 9bf0e29..72a067a 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -445,7 +445,7 @@ init_private(void)
 	struct rlimit rlim;
 	size_t len;
 	int mib[2];
-	char *env;
+	char *env, *env_bigstack, *env_splitstack;
=20
 	_thr_umutex_init(&_mutex_static_lock);
 	_thr_umutex_init(&_cond_static_lock);
@@ -473,8 +473,9 @@ init_private(void)
 		len =3D sizeof (_usrstack);
 		if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) =3D=3D -1)
 			PANIC("Cannot get kern.usrstack from sysctl");
-		env =3D getenv("LIBPTHREAD_BIGSTACK_MAIN");
-		if (env !=3D NULL) {
+		env_bigstack =3D getenv("LIBPTHREAD_BIGSTACK_MAIN");
+		env_splitstack =3D getenv("LIBPTHREAD_SPLITSTACK_MAIN");
+		if (bigstack !=3D NULL || env_splitstack =3D=3D NULL) {
 			if (getrlimit(RLIMIT_STACK, &rlim) =3D=3D -1)
 				PANIC("Cannot get stack rlimit");
 			_thr_stack_initial =3D rlim.rlim_cur;
diff --git a/share/man/man7/libthr.7 b/share/man/man7/libthr.7
new file mode 100644
index 0000000..16d916f
--- /dev/null
+++ b/share/man/man7/libthr.7
@@ -0,0 +1,254 @@
+.\" Copyright (c) 2014 The FreeBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Konstantin Belousov <kib@FreeBSD.org>
+.\" under sponsorship from the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PUR=
POSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIAB=
LE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN=
TIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ST=
RICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY =
WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 20, 2014
+.Dt libthr
+.Os
+.Sh NAME
+.Nm libthr
+.Nd FreeBSD implementation of the Posix threading library
+.Sh LIBRARY
+.Lb libpthread
+.Sh DESCRIPTION
+The man page documents the quirks and tunables of the
+.Fx
+implementation for the
+.Lb libpthread .
+When linking with the
+.Li -lpthread ,
+the run-time dependency
+.Dv libthr.so.3
+library is recorded in the produced object.
+.Pp
+The library is tigthly integrated with the Run-time Link-editor
+.Xr ld-elf.so.1 1
+and
+.Lb libc ,
+all three components must be built from the same source tree.
+Mixing
+.Dv libc.so
+and
+.Nm
+libraries from different versions of
+.Fx
+is not supported.
+The run-time linker
+.Li ld-elf.so.1
+has some code to ensure backward-compatibility with older
+.Nm .
+.Sh MUTEX ACQUISITION
+The locked mutex (see
+.Xr pthread_mutex_lock 3 )
+is represented by a volatile variable of type
+.Dv lwpid_t ,
+which records the global system identifier of the thread
+owning the lock.
+The
+.Nm
+performs a congested mutex acquisition in three stages, each of which
+is more resource-consuming than the previous.
+.Pp
+First, the
+.Li spin loop
+is performed, where the library attempts to acquire the lock by
+.Xr atomic 9
+operations.
+The loop count is controlled by the
+.Ev LIBPTHREAD_SPINLOOPS
+environment variable.
+.Pp
+If the
+.Li spin loop
+was unable to acquire the mutex, the
+.Li yield loop
+is executed, performing the same
+.Xr atomic 9
+acquisition attempts as
+.Li spin loop ,
+but each attempt is followed by yield of the CPU time of the thread by
+.Xr sched_yield 2
+syscall.
+By default, the
+.Li yield loop
+is not executed.
+This is controlled by
+.Ev LIBPTHREAD_YIELDLOOPS
+environment variable.
+.Pp
+If both
+.Li spin
+and
+.Li yield loops
+failed to acquire the lock, the thread is taken off the CPU and
+put to sleep in kernel with the
+.Xr umtx 2
+syscall.
+Kernel wakes up a thread and hands the ownership of the lock to
+the woken thread.
+.Sh THREADS STACKS
+Each thread is provided with the private stack area used by C runtime.
+The size of the main (initial) thread stack is set by kernel, and is
+controlled by the
+.Dv RLIMIT_STACK
+process resource limit (see
+.Xr getrlimit 2 ) .
+.Pp
+By default, the main thread size is equal to the value of resource
+.Dv RLIMIT_STACK
+for the process.
+If the
+.Dv LIBPTHREAD_SPLITSTACK_MAIN
+environment variable is present (its value does not matter),
+the main thread size if chomped to 4MB on 64bit architectures, and to
+2MB on 32bit architectures, on the threading library initialization.
+The rest of the address space area reserved by the kernel for initial
+process stack, is used for non-initial threads stack in this case.
+The presence of the
+.Dv LIBPTHREAD_BIGSTACK_MAIN
+environment variable overrides the
+.Dv LIBPTHREAD_SPLITSTACK_MAIN ,
+it is kept for backward-compatibility.
+.Pp
+The size of the stacks for threads created by the process at run-time
+with the
+.Xr pthread_create 3
+call, is controlled by thread attributes, see
+.Xr pthread_attr 3 ,
+in particular, the
+.Xr pthread_attr_setstacksize 3 ,
+.Xr pthread_attr_setguardsize 3
+and
+.Xr pthread_attr_setstackaddr 3 .
+If no attributes for the thread stack size are specified, the default
+non-initial thread stack size is 2MB for 64bit architectures, and 1MB
+for 32bit architectures.
+.Sh RUN-TIME SETTINGS
+The following environment variables are recognized by
+.Dv libthr
+and adjust the operation of the library at run-time:
+.Bl -tag -width LIBPTHREAD_SPLITSTACK_MAIN
+.It Ev LIBPTHREAD_BIGSTACK_MAIN
+Disables the chomp of the initial thread stack, enabled by
+.Ev LIBPTHREAD_SPLITSTACK_MAIN .
+.It Ev LIBPTHREAD_SPLITSTACK_MAIN
+Causes the chomp of the initial thread stack, as described in the
+section
+.Li THREAD_STACKS .
+This was the default behaviour of the
+.Nm
+before
+.Fx 11.0 .
+.It Ev LIBPTHREAD_SPINLOOPS
+The integer value of the variable overrides the default count of
+iterations in the
+.Li spin loop
+of the mutex acquisition.
+The default count is 2000, set by the
+.Dv MUTEX_ADAPTIVE_SPINS
+define in the
+.Nm
+sources.
+.It Ev LIBPTHREAD_YIELDLOOPS
+The non-zero integer value of the variable allows the
+.Li yield loop
+in the process of the mutex acquisition.
+The value is the counter of loop operations.
+.It Ev LIBPTHREAD_QUEUE_FIFO
+The integer value of the variable specifies how often the blocked
+threads are put into the head of the sleep queue, instead of it tail.
+The bigger value reduces the frequency of the FIFO discipline.
+The value must be between 0 and 255.
+.El
+.Sh INTERACTION WITH RUN-TIME LINKER.
+The
+.Nm
+library must appear before
+.Dv libc
+in the global order of depended objects.
+.Pp
+.Pp
+Loading the
+.Nm
+library with the
+.Xr dlopen 3
+call in the process after the program binary is activated,
+is not supported, and causes miscellaneous and hard to diagnose misbehavio=
ur.
+This is due to
+.Nm
+interposing several important
+.Dv libc
+symbols to provide thread-safe services.
+In particular,
+.Dv errno
+and locking stubs from
+.Dv libc
+are affected.
+This requirement is currently not enforced.
+.Pp
+If the program loads the modules at run-time, and modules may require
+the threading services, the main program binary must be linked with
+.Dv libpthread ,
+even if it does not require any service from the library.
+.Pp
+The library cannot be unloaded, the
+.Xr dlclose 3
+function does not perform any action when called with a handle for
+.Dv libthr .
+One of the reason is that interposing of
+.Dv libc
+functions cannot be undone.
+.Sh SIGNALS
+The implementation also interposes the user-installed
+.Xr signal 3
+handlers.
+The interposing is done to postpone signal delivery to threads which
+entered the (libthr-internal) critical sections, where the calling
+of the signal handler is unsafe.
+Example of such situation is owning the internal library lock.
+When the signal is delivered while signal handler cannot be safely
+called, call is postponed and performed after the critical section
+is left.
+This should be taken into account when interpreting the
+.Xr ktrace 1
+logs.
+.Sh SEE ALSO
+.Xr atomic 9 ,
+.Xr dlclose 3 ,
+.Xr dlopen 3 ,
+.Xr errno 3 ,
+.Xr getenv 3 ,
+.Xr getrlimit 2 ,
+.Xr ktrace 1 ,
+.Xr ld-elf.so.1 1 ,
+.Xr libc 3 ,
+.Xr pthread_attr 3 ,
+.Xr pthread_attr_setstacksize 3 ,
+.Xr pthread_create 3 ,
+.Xr signal 3 ,
+.Xr umtx 2 .

--pAwQNkOnpTn9IO2O
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBAgAGBQJUHbQxAAoJEJDCuSvBvK1BJowQAIkGc0gokVCcaGUUXT+WPkuE
2u49WokeTewPizBT0040afss1FKeyeDKI5Gn+mogNl0IIh7XCOLNpL0B3qFtWf44
Ie3hkuuSN+p47e1auaN7KBuRAyWVHCVdJsXsEEO/MiJT8tqVt+fZiLfvSmNAWrse
9hgYupxmQRsNRRTz6m22zdRxAWZVhvM56pt/oFaHbM5DGXw2C9nNqg3EKZjnpqtc
A7uXJelz95k5T/mXK0yxr/aoG/rHv4ON57slvp1cRD+6PiSlsOsR3TWYRPmUgFZO
KEjBknEhSsuaXlh02fjMbY/Ht0r9VqTdijmYffnwxmF3cn4flCewn86zO+6mGo9B
162AS5XpxNMJsudCK/sP9+4VyxICB5A/V7LXESBNYVt67Et6jJBNBZXu50xbMTU+
l5wrx2mMc4XlDQZZM+KRnynzxF3B8FoAUBOvQV2Rw58hLqooJ1HR5rf1HJIdZ2yw
nJr7GH6hIsLYOTDGLHiZpMAYJMwgsAlm++ZPqQAf6a8P3Fqs9A0X40BC07JHS+G5
dCSJgtFd9nzuo75V7qyFpCZVPM4+q9jayWILihcrdjFi6ZuDDpMLjuqaxRHVVP/G
dw9FiV/W8u+Gx2cFdwUPcYQTbxgjgb5DFuTnmln9pRqiWTndwqk7hM6foMEG8qT9
f3QBuQLeUJrKqWpNAzfB
=z6GS
-----END PGP SIGNATURE-----

--pAwQNkOnpTn9IO2O--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140920170658.GE2210>