📄 tls.h
字号:
TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ \ if (_result == 0) \ /* We know the index in the GDT, now load the segment register. \ The use of the GDT is described by the value 3 in the lower \ three bits of the segment descriptor value. \ \ Note that we have to do this even if the numeric value of \ the descriptor does not change. Loading the segment register \ causes the segment information from the GDT to be loaded \ which is necessary since we have changed it. */ \ TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3); \ \ _result == 0 ? NULL \ : "set_thread_area failed when setting up thread-local storage\n"; })/* Return the address of the dtv for the current thread. */# define THREAD_DTV() \ ({ struct pthread *__pd; \ THREAD_GETMEM (__pd, header.dtv); })/* Return the thread descriptor for the current thread. The contained asm must *not* be marked volatile since otherwise assignments like pthread_descr self = thread_self(); do not get optimized away. */# define THREAD_SELF \ ({ struct pthread *__self; \ asm ("movl %%gs:%c1,%0" : "=r" (__self) \ : "i" (offsetof (struct pthread, header.self))); \ __self;})/* Magic for libthread_db to know how to do THREAD_SELF. */# define DB_THREAD_SELF \ REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs *//* Read member of the thread descriptor directly. */# define THREAD_GETMEM(descr, member) \ ({ __typeof (descr->member) __value; \ if (sizeof (__value) == 1) \ asm volatile ("movb %%gs:%P2,%b0" \ : "=q" (__value) \ : "0" (0), "i" (offsetof (struct pthread, member))); \ else if (sizeof (__value) == 4) \ asm volatile ("movl %%gs:%P1,%0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member))); \ else \ { \ if (sizeof (__value) != 8) \ /* There should not be any value with a size other than 1, \ 4 or 8. */ \ abort (); \ \ asm volatile ("movl %%gs:%P1,%%eax\n\t" \ "movl %%gs:%P2,%%edx" \ : "=A" (__value) \ : "i" (offsetof (struct pthread, member)), \ "i" (offsetof (struct pthread, member) + 4)); \ } \ __value; })/* Same as THREAD_GETMEM, but the member offset can be non-constant. */# define THREAD_GETMEM_NC(descr, member, idx) \ ({ __typeof (descr->member[0]) __value; \ if (sizeof (__value) == 1) \ asm volatile ("movb %%gs:%P2(%3),%b0" \ : "=q" (__value) \ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ else if (sizeof (__value) == 4) \ asm volatile ("movl %%gs:%P1(,%2,4),%0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ else \ { \ if (sizeof (__value) != 8) \ /* There should not be any value with a size other than 1, \ 4 or 8. */ \ abort (); \ \ asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ "movl %%gs:4+%P1(,%2,8),%%edx" \ : "=&A" (__value) \ : "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ } \ __value; })/* Same as THREAD_SETMEM, but the member offset can be non-constant. */# define THREAD_SETMEM(descr, member, value) \ ({ if (sizeof (descr->member) == 1) \ asm volatile ("movb %b0,%%gs:%P1" : \ : "iq" (value), \ "i" (offsetof (struct pthread, member))); \ else if (sizeof (descr->member) == 4) \ asm volatile ("movl %0,%%gs:%P1" : \ : "ir" (value), \ "i" (offsetof (struct pthread, member))); \ else \ { \ if (sizeof (descr->member) != 8) \ /* There should not be any value with a size other than 1, \ 4 or 8. */ \ abort (); \ \ asm volatile ("movl %%eax,%%gs:%P1\n\t" \ "movl %%edx,%%gs:%P2" : \ : "A" (value), \ "i" (offsetof (struct pthread, member)), \ "i" (offsetof (struct pthread, member) + 4)); \ }})/* Set member of the thread descriptor directly. */# define THREAD_SETMEM_NC(descr, member, idx, value) \ ({ if (sizeof (descr->member[0]) == 1) \ asm volatile ("movb %b0,%%gs:%P1(%2)" : \ : "iq" (value), \ "i" (offsetof (struct pthread, member)), \ "r" (idx)); \ else if (sizeof (descr->member[0]) == 4) \ asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \ : "ir" (value), \ "i" (offsetof (struct pthread, member)), \ "r" (idx)); \ else \ { \ if (sizeof (descr->member[0]) != 8) \ /* There should not be any value with a size other than 1, \ 4 or 8. */ \ abort (); \ \ asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ "movl %%edx,%%gs:4+%P1(,%2,8)" : \ : "A" (value), \ "i" (offsetof (struct pthread, member)), \ "r" (idx)); \ }})/* Atomic compare and exchange on TLS, returning old value. */#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ ({ __typeof (descr->member) __ret; \ __typeof (oldval) __old = (oldval); \ if (sizeof (descr->member) == 4) \ asm volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3" \ : "=a" (__ret) \ : "0" (__old), "r" (newval), \ "i" (offsetof (struct pthread, member))); \ else \ /* Not necessary for other sizes in the moment. */ \ abort (); \ __ret; })/* Atomic set bit. */#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ (void) ({ if (sizeof ((descr)->member) == 4) \ asm volatile (LOCK_PREFIX "orl %1, %%gs:%P0" \ :: "i" (offsetof (struct pthread, member)), \ "ir" (1 << (bit))); \ else \ /* Not necessary for other sizes in the moment. */ \ abort (); })/* Call the user-provided thread function. */#define CALL_THREAD_FCT(descr) \ ({ void *__res; \ int __ignore1, __ignore2; \ asm volatile ("pushl %%eax\n\t" \ "pushl %%eax\n\t" \ "pushl %%eax\n\t" \ "pushl %%gs:%P4\n\t" \ "call *%%gs:%P3\n\t" \ "addl $16, %%esp" \ : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2) \ : "i" (offsetof (struct pthread, start_routine)), \ "i" (offsetof (struct pthread, arg))); \ __res; })/* Set the stack guard field in TCB head. */#define THREAD_SET_STACK_GUARD(value) \ THREAD_SETMEM (THREAD_SELF, header.stack_guard, value)#define THREAD_COPY_STACK_GUARD(descr) \ ((descr)->header.stack_guard \ = THREAD_GETMEM (THREAD_SELF, header.stack_guard))/* Set the pointer guard field in the TCB head. */#define THREAD_SET_POINTER_GUARD(value) \ THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value)#define THREAD_COPY_POINTER_GUARD(descr) \ ((descr)->header.pointer_guard \ = THREAD_GETMEM (THREAD_SELF, header.pointer_guard))/* Get and set the global scope generation counter in the TCB head. */#define THREAD_GSCOPE_FLAG_UNUSED 0#define THREAD_GSCOPE_FLAG_USED 1#define THREAD_GSCOPE_FLAG_WAIT 2#define THREAD_GSCOPE_RESET_FLAG() \ do \ { int __res; \ asm volatile ("xchgl %0, %%gs:%P1" \ : "=r" (__res) \ : "i" (offsetof (struct pthread, header.gscope_flag)), \ "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ } \ while (0)#define THREAD_GSCOPE_SET_FLAG() \ THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)#define THREAD_GSCOPE_WAIT() \ GL(dl_wait_lookup_done) ()#endif /* __ASSEMBLER__ */#endif /* tls.h */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -