mirror of https://github.com/mkerrisk/man-pages
arch_prctl.2, set_thread_area.2, get_thread_area.2: Improve TLS documentation
The documentation for set_thread_area was very vague. This improves it, accounts for recent kernel changes, and merges it with get_thread_area.2. get_thread_area.2 now becomes a link. While I'm at it, clarify the related arch_prctl.2 man page. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
parent
38f7c37983
commit
14620a2531
|
@ -114,27 +114,33 @@ The 64-bit base changes when a new 32-bit segment selector is loaded.
|
|||
is disabled in some kernels.
|
||||
|
||||
Context switches for 64-bit segment bases are rather expensive.
|
||||
It may be a faster alternative to set a 32-bit base using a
|
||||
segment selector by setting up an LDT with
|
||||
.BR modify_ldt (2)
|
||||
or using the
|
||||
As an optimization, if a 32-bit TLS base address is used,
|
||||
.BR arch_prctl (2)
|
||||
may use a real TLS entry as if
|
||||
.BR set_thread_area (2)
|
||||
system call in kernel 2.5 or later.
|
||||
.BR arch_prctl ()
|
||||
is needed only when you want to set bases that are larger than 4GB.
|
||||
had been called instead of manipulating the segment base register directly.
|
||||
Memory in the first 2GB of address space can be allocated by using
|
||||
.BR mmap (2)
|
||||
with the
|
||||
.B MAP_32BIT
|
||||
flag.
|
||||
|
||||
As a result, using
|
||||
.BR arch_prctl (2)
|
||||
and
|
||||
.BR set_thread_area (2)
|
||||
in the same thread is dangerous, as they may overwrite each other's
|
||||
TLS entries.
|
||||
|
||||
As of version 2.7, glibc provides no prototype for
|
||||
.BR arch_prctl ().
|
||||
You have to declare it yourself for now.
|
||||
This may be fixed in future glibc versions.
|
||||
|
||||
.I FS
|
||||
may be already used by the threading library.
|
||||
may be already used by the threading library. Glibc programs that use
|
||||
.I ARCH_SET_FS
|
||||
directly are very likely to crash.
|
||||
.SH SEE ALSO
|
||||
.BR mmap (2),
|
||||
.BR modify_ldt (2),
|
||||
|
|
|
@ -1,57 +1 @@
|
|||
.\" Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
.\" Written by Kent Yoder.
|
||||
.\"
|
||||
.\" %%%LICENSE_START(GPL_NOVERSION_ONELINE)
|
||||
.\" This file is distributed according to the GNU General Public License.
|
||||
.\" %%%LICENSE_END
|
||||
.\"
|
||||
.TH GET_THREAD_AREA 2 2012-07-13 "Linux" "Linux Programmer's Manual"
|
||||
.SH NAME
|
||||
get_thread_area \- get a thread-local storage (TLS) area
|
||||
.SH SYNOPSIS
|
||||
.B #include <linux/unistd.h>
|
||||
.br
|
||||
.B #include <asm/ldt.h>
|
||||
.sp
|
||||
.BI "int get_thread_area(struct user_desc *" u_info );
|
||||
|
||||
.IR Note :
|
||||
There is no glibc wrapper for this system call; see NOTES.
|
||||
.SH DESCRIPTION
|
||||
.BR get_thread_area ()
|
||||
returns an entry in the current thread's thread-local storage (TLS) array.
|
||||
The index of the entry corresponds to the value
|
||||
of \fIu_info\->entry_number\fP, passed in by the user.
|
||||
If the value is in bounds,
|
||||
.BR get_thread_area ()
|
||||
copies the corresponding
|
||||
TLS entry into the area pointed to by \fIu_info\fP.
|
||||
.SH RETURN VALUE
|
||||
.BR get_thread_area ()
|
||||
returns 0 on success.
|
||||
Otherwise, it returns \-1 and sets
|
||||
.I errno
|
||||
appropriately.
|
||||
.SH ERRORS
|
||||
.TP
|
||||
.B EFAULT
|
||||
\fIu_info\fP is an invalid pointer.
|
||||
.TP
|
||||
.B EINVAL
|
||||
\fIu_info\->entry_number\fP is out of bounds.
|
||||
.SH VERSIONS
|
||||
A version of
|
||||
.BR get_thread_area ()
|
||||
first appeared in Linux 2.5.32.
|
||||
.SH CONFORMING TO
|
||||
.BR get_thread_area ()
|
||||
is Linux-specific and should not be used in programs
|
||||
that are intended to be portable.
|
||||
.SH NOTES
|
||||
Glibc does not provide a wrapper for this system call,
|
||||
since it is generally intended for use only by threading libraries.
|
||||
In the unlikely event that you want to call it directly, use
|
||||
.BR syscall (2).
|
||||
.SH SEE ALSO
|
||||
.BR modify_ldt (2),
|
||||
.BR set_thread_area (2)
|
||||
.so man2/set_thread_area.2
|
||||
|
|
|
@ -1,25 +1,54 @@
|
|||
.\" Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 2015 Andrew Lutomirski
|
||||
.\" Author: Kent Yoder
|
||||
.\"
|
||||
.\" %%%LICENSE_START(GPL_NOVERSION_ONELINE)
|
||||
.\" This file is distributed according to the GNU General Public License.
|
||||
.\" %%%LICENSE_END
|
||||
.\"
|
||||
.TH SET_THREAD_AREA 2 2012-07-13 "Linux" "Linux Programmer's Manual"
|
||||
.TH SET_THREAD_AREA 2 2015-01-29 "Linux" "Linux Programmer's Manual"
|
||||
.SH NAME
|
||||
set_thread_area \- set a thread local storage (TLS) area
|
||||
set_thread_area \- set a GDT entry for thread-local storage
|
||||
.SH SYNOPSIS
|
||||
.B #include <linux/unistd.h>
|
||||
.br
|
||||
.B #include <asm/ldt.h>
|
||||
.sp
|
||||
.BI "int get_thread_area(struct user_desc *" u_info );
|
||||
.BI "int set_thread_area(struct user_desc *" u_info );
|
||||
.in +4n
|
||||
.nf
|
||||
|
||||
struct user_desc {
|
||||
unsigned int entry_number;
|
||||
unsigned long base_addr;
|
||||
unsigned int limit;
|
||||
unsigned int seg_32bit:1;
|
||||
unsigned int contents:2;
|
||||
unsigned int read_exec_only:1;
|
||||
unsigned int limit_in_pages:1;
|
||||
unsigned int seg_not_present:1;
|
||||
unsigned int useable:1;
|
||||
};
|
||||
.fi
|
||||
.in
|
||||
|
||||
.IR Note :
|
||||
There is no glibc wrapper for this system call; see NOTES.
|
||||
.SH DESCRIPTION
|
||||
Linux dedicates three global descriptor table (GDT) entries for
|
||||
thread-local storage. For more information about the LDT, see the
|
||||
Intel Software Developer's Manual or the AMD Architecture Programming Manual.
|
||||
|
||||
.BR get_thread_area ()
|
||||
reads the GDT entry indicated by
|
||||
.I u_info\->entry_number
|
||||
and fills in the rest of the fields in
|
||||
.I u_info.
|
||||
|
||||
.BR set_thread_area ()
|
||||
sets an entry in the current thread's thread-local storage (TLS) array.
|
||||
sets a TLS entry in the GDT.
|
||||
.PP
|
||||
The TLS array entry set by
|
||||
.BR set_thread_area ()
|
||||
corresponds to the value of
|
||||
|
@ -27,7 +56,7 @@ corresponds to the value of
|
|||
passed in by the user.
|
||||
If this value is in bounds,
|
||||
.BR set_thread_area ()
|
||||
copies the TLS descriptor pointed to by
|
||||
writes the TLS descriptor pointed to by
|
||||
.I u_info
|
||||
into the thread's TLS array.
|
||||
.PP
|
||||
|
@ -35,12 +64,29 @@ When
|
|||
.BR set_thread_area ()
|
||||
is passed an
|
||||
.I entry_number
|
||||
of \-1, it uses a free TLS entry.
|
||||
of \-1, it finds a free TLS entry.
|
||||
If
|
||||
.BR set_thread_area ()
|
||||
finds a free TLS entry, the value of
|
||||
.I u_info\->entry_number
|
||||
is set upon return to show which entry was changed.
|
||||
.PP
|
||||
A
|
||||
.I user_desc
|
||||
is considered "empty" if
|
||||
.I read_exec_only
|
||||
and
|
||||
.I seg_not_present
|
||||
are set to 1 and all of the other fields are 0. If an "empty" descriptor
|
||||
is passed to
|
||||
.BR set_thread_area,
|
||||
the corresponding TLS entry will be cleared. See BUGS for additional
|
||||
details.
|
||||
.PP
|
||||
On Linux 3.19 and newer,
|
||||
.BR set_thread_area ()
|
||||
cannot be used to write non-present segments, 16-bit segments, or code
|
||||
segments, although clearing a segment is still acceptable.
|
||||
.SH RETURN VALUE
|
||||
.BR set_thread_area ()
|
||||
returns 0 on success, and \-1 on failure, with
|
||||
|
@ -56,6 +102,11 @@ set appropriately.
|
|||
.TP
|
||||
.B ESRCH
|
||||
A free TLS entry could not be located.
|
||||
.B ENOSYS
|
||||
.BR get_thread_area (2)
|
||||
or
|
||||
.BR set_thread_area (2)
|
||||
was invoked as a 64-bit syscall.
|
||||
.SH VERSIONS
|
||||
A version of
|
||||
.BR set_thread_area ()
|
||||
|
@ -64,10 +115,40 @@ first appeared in Linux 2.5.29.
|
|||
.BR set_thread_area ()
|
||||
is Linux-specific and should not be used in programs that are intended
|
||||
to be portable.
|
||||
.SH BUGS
|
||||
On 64-bit kernels before Linux 3.19, one of the padding bits in
|
||||
.I user_desc,
|
||||
if set, would prevent the descriptor from being considered empty.
|
||||
As a result, the only reliable way to clear a TLS entry is to use
|
||||
memset to zero the entire
|
||||
.I user_desc
|
||||
structure, including padding bits, and then to set the
|
||||
.I read_exec_only
|
||||
and
|
||||
.I seg_not_present
|
||||
bits. On Linux 3.19, a
|
||||
.I user_desc
|
||||
consisting entirely of zeros except for
|
||||
.I entry_number
|
||||
will also be interpreted as a request to clear a TLS entry, but this
|
||||
behaved differently on older kernels.
|
||||
.PP
|
||||
Prior to Linux 3.19, the DS and ES segment registers must not reference
|
||||
TLS entries.
|
||||
.SH NOTES
|
||||
Glibc does not provide a wrapper for this system call,
|
||||
since it is generally intended only for use by threading libraries.
|
||||
In the unlikely event that you want to call it directly, use
|
||||
.BR syscall (2).
|
||||
.PP
|
||||
.BR arch_prctl (2)
|
||||
can interfere with
|
||||
.BR set_thread_area (2).
|
||||
See
|
||||
.BR arch_prctl (2)
|
||||
for more details. This is not normally a problem, as
|
||||
.BR arch_prctl (2)
|
||||
is normally only used by 64-bit programs.
|
||||
.SH SEE ALSO
|
||||
.BR get_thread_area (2)
|
||||
.BR arch_prctl (2),
|
||||
.BR modify_ldt (2)
|
||||
|
|
Loading…
Reference in New Issue