On Jan 30, 2015 8:59 AM, "Michael Kerrisk (man-pages)" <mtk.manpages@xxxxxxxxx> wrote: > > Hi Andy, > > Thanks for this! > > I've merged this into a branch and done some light editing. > A few questions below. > > On 01/29/2015 10:47 PM, Andy Lutomirski wrote: > > 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. > > (Yep, merging seems a good idea.) > > > > While I'm at it, clarify the related arch_prctl.2 man page. > > > > Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxxxxxx> > > --- > > man2/arch_prctl.2 | 22 +++++++----- > > man2/get_thread_area.2 | 58 +------------------------------ > > man2/set_thread_area.2 | 93 ++++++++++++++++++++++++++++++++++++++++++++++---- > > 3 files changed, 102 insertions(+), 71 deletions(-) > > > > diff --git a/man2/arch_prctl.2 b/man2/arch_prctl.2 > > index a3ab2b566915..c89fa3c7b744 100644 > > --- a/man2/arch_prctl.2 > > +++ b/man2/arch_prctl.2 > > @@ -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 > > Something doesn't quite flow here. "As a result" *of what*? Should this rather > be something like: > > Because of the aforementioned optimization, using Sure. > > > +.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 > > What is a "Glibc program"? A program that links against glibc. Maybe that should just say "Programs". The idea I'm trying to get across is that using ARCH_SET_FS for private purposes is a bad idea, since your threading library (glibc/libpthread) is very likely to use ARCH_SET_FS for its own purposes. ARCH_SET_GS, on the other hand, is more likely to be available for private use. This is most relevant for programs written for the purpose of testing arch_prctl -- using ARCH_SET_FS following by calling any glibc function is very likely to segfault. > > > +.I ARCH_SET_FS > > +directly are very likely to crash. > > .SH SEE ALSO > > .BR mmap (2), > > .BR modify_ldt (2), > > diff --git a/man2/get_thread_area.2 b/man2/get_thread_area.2 > > index 08589e413cc4..a03fe54fb08e 100644 > > --- a/man2/get_thread_area.2 > > +++ b/man2/get_thread_area.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 > > diff --git a/man2/set_thread_area.2 b/man2/set_thread_area.2 > > index 321beb396312..6acc5f79d1ad 100644 > > --- a/man2/set_thread_area.2 > > +++ b/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 > > s/LDT/GDT? in the previous line, right? Yes. --Andy > > > +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. > > s/finds/searched for/ ? How about "searches for"? > > > 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 > > Was that commit e30ab185c490e9a9381385529e0fd32f0a399495 ? Yes. > > > +.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) > > Thanks, > > Michael > > > > -- > Michael Kerrisk > Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ > Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html