📄 tls.h
字号:
/* Definition for thread-local data handling. nptl/i386 version. Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */#ifndef _TLS_H#define _TLS_H 1#include <dl-sysdep.h>#ifndef __ASSEMBLER__# include <stdbool.h># include <stddef.h># include <stdint.h># include <stdlib.h># include <list.h># include <sysdep.h># include <kernel-features.h>/* Type for the dtv. */typedef union dtv{ size_t counter; struct { void *val; bool is_static; } pointer;} dtv_t;typedef struct{ void *tcb; /* Pointer to the TCB. Not necessarily the thread descriptor used by libpthread. */ dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; int gscope_flag;#ifndef __ASSUME_PRIVATE_FUTEX int private_futex;#endif} tcbhead_t;# define TLS_MULTIPLE_THREADS_IN_TCB 1#else /* __ASSEMBLER__ */# include <tcb-offsets.h>#endif/* We require TLS support in the tools. */#ifndef HAVE_TLS_SUPPORT# error "TLS support is required."#endif/* Alignment requirement for the stack. For IA-32 this is governed by the SSE memory functions. */#define STACK_ALIGN 16#ifndef __ASSEMBLER__/* Get system call information. */# include <sysdep.h>/* The old way: using LDT. *//* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls. */struct user_desc{ unsigned int entry_number; unsigned long int 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; unsigned int empty:25;};/* Initializing bit fields is slow. We speed it up by using a union. */union user_desc_init{ struct user_desc desc; unsigned int vals[4];};/* Get the thread descriptor definition. */# include <nptl/descr.h>/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole struct pthread even when not linked with -lpthread. */# define TLS_INIT_TCB_SIZE sizeof (struct pthread)/* Alignment requirements for the initial TCB. */# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)/* This is the size of the TCB. */# define TLS_TCB_SIZE sizeof (struct pthread)/* Alignment requirements for the TCB. */# define TLS_TCB_ALIGN __alignof__ (struct pthread)/* The TCB can have any size and the memory following the address the thread pointer points to is unspecified. Allocate the TCB there. */# define TLS_TCB_AT_TP 1/* Install the dtv pointer. The pointer passed is to the element with index -1 which contain the length. */# define INSTALL_DTV(descr, dtvp) \ ((tcbhead_t *) (descr))->dtv = (dtvp) + 1/* Install new dtv for current thread. */# define INSTALL_NEW_DTV(dtvp) \ ({ struct pthread *__pd; \ THREAD_SETMEM (__pd, header.dtv, (dtvp)); })/* Return dtv of given thread descriptor. */# define GET_DTV(descr) \ (((tcbhead_t *) (descr))->dtv)#define THREAD_SELF_SYSINFO THREAD_GETMEM (THREAD_SELF, header.sysinfo)#define THREAD_SYSINFO(pd) ((pd)->header.sysinfo)/* Macros to load from and store into segment registers. */# ifndef TLS_GET_GS# define TLS_GET_GS() \ ({ int __seg; __asm ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; })# endif# ifndef TLS_SET_GS# define TLS_SET_GS(val) \ __asm ("movw %w0, %%gs" :: "q" (val))# endif# ifndef __NR_set_thread_area# define __NR_set_thread_area 243# endif# ifndef TLS_FLAG_WRITABLE# define TLS_FLAG_WRITABLE 0x00000001# endif// XXX Enable for the real world.#if 0# ifndef __ASSUME_SET_THREAD_AREA# error "we need set_thread_area"# endif#endif# ifdef __PIC__# define TLS_EBX_ARG "r"# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t"# else# define TLS_EBX_ARG "b"# define TLS_LOAD_EBX# endif#if defined NEED_DL_SYSINFO# define INIT_SYSINFO \ _head->sysinfo = GLRO(dl_sysinfo)#else# define INIT_SYSINFO#endif#ifndef LOCK_PREFIX# ifdef UP# define LOCK_PREFIX /* nothing */# else# define LOCK_PREFIX "lock;"# endif#endif/* Code to initially initialize the thread pointer. This might need special attention since 'errno' is not yet available and if the operation can cause a failure 'errno' must not be touched. */# define TLS_INIT_TP(thrdescr, secondcall) \ ({ void *_thrdescr = (thrdescr); \ tcbhead_t *_head = _thrdescr; \ union user_desc_init _segdescr; \ int _result; \ \ _head->tcb = _thrdescr; \ /* For now the thread descriptor is at the same address. */ \ _head->self = _thrdescr; \ /* New syscall handling support. */ \ INIT_SYSINFO; \ \ /* The 'entry_number' field. Let the kernel pick a value. */ \ if (secondcall) \ _segdescr.vals[0] = TLS_GET_GS () >> 3; \ else \ _segdescr.vals[0] = -1; \ /* The 'base_addr' field. Pointer to the TCB. */ \ _segdescr.vals[1] = (unsigned long int) _thrdescr; \ /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ _segdescr.vals[2] = 0xfffff; \ /* Collapsed value of the bitfield: \ .seg_32bit = 1 \ .contents = 0 \ .read_exec_only = 0 \ .limit_in_pages = 1 \ .seg_not_present = 0 \ .useable = 1 */ \ _segdescr.vals[3] = 0x51; \ \ /* Install the TLS. */ \ asm volatile (TLS_LOAD_EBX \ "int $0x80\n\t" \ TLS_LOAD_EBX \ : "=a" (_result), "=m" (_segdescr.desc.entry_number) \ : "0" (__NR_set_thread_area), \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -