diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/x86_64')
-rw-r--r-- | libpthread/nptl/sysdeps/x86_64/Makefile | 9 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/x86_64/Makefile.arch | 52 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/x86_64/pthreaddef.h | 17 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/x86_64/sysdep.h | 114 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/x86_64/tls.h | 165 |
5 files changed, 307 insertions, 50 deletions
diff --git a/libpthread/nptl/sysdeps/x86_64/Makefile b/libpthread/nptl/sysdeps/x86_64/Makefile index 6e24a26cd..2f0d88f30 100644 --- a/libpthread/nptl/sysdeps/x86_64/Makefile +++ b/libpthread/nptl/sysdeps/x86_64/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003 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 @@ -21,8 +21,7 @@ gen-as-const-headers += tcb-offsets.sym endif ifeq ($(subdir),nptl) -# P4s have problems with 4M aliasing. We disturb the allocation of stacks -# just enough so the subsequent allocations do not use stack address -# (mod 4M) == 0. -CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4 endif diff --git a/libpthread/nptl/sysdeps/x86_64/Makefile.arch b/libpthread/nptl/sysdeps/x86_64/Makefile.arch new file mode 100644 index 000000000..b99a0da0e --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/Makefile.arch @@ -0,0 +1,52 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_spin_lock.c +libpthread_SSRC = pthread_spin_trylock.S + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-x86_64 = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/x86_64 +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/x86_64 +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers-y += $(PTHREAD_ARCH_OUT)/tcb-offsets.h +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + @sed -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +nptl_arch_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/x86_64/pthreaddef.h b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h index 27896a445..b33c18638 100644 --- a/libpthread/nptl/sysdeps/x86_64/pthreaddef.h +++ b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -33,22 +33,11 @@ /* Location of current stack frame. The frame pointer is not usable. */ #define CURRENT_STACK_FRAME \ - ({ char *frame; asm ("movq %%rsp, %0" : "=r" (frame)); frame; }) - - -/* We prefer to have the stack allocated in the low 4GB since this - allows faster context switches. */ -#define ARCH_MAP_FLAGS MAP_32BIT - -/* If it is not possible to allocate memory there retry without that - flag. */ -#define ARCH_RETRY_MMAP(size) \ - mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, \ - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + ({ char *frame; __asm__ ("movq %%rsp, %0" : "=r" (frame)); frame; }) /* XXX Until we have a better place keep the definitions here. */ /* While there is no such syscall. */ #define __exit_thread_inline(val) \ - asm volatile ("syscall" :: "a" (__NR_exit), "D" (val)) + __asm__ volatile ("syscall" :: "a" (__NR_exit), "D" (val)) diff --git a/libpthread/nptl/sysdeps/x86_64/sysdep.h b/libpthread/nptl/sysdeps/x86_64/sysdep.h new file mode 100644 index 000000000..122270f91 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/sysdep.h @@ -0,0 +1,114 @@ +/* Assembler macros for x86-64. + Copyright (C) 2001, 2002, 2003 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. */ + +#include <sysdeps/generic/sysdep.h> + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#ifdef HAVE_ELF + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<<log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name; + +/* In ELF C symbols are asm symbols. */ +#undef NO_UNDERSCORES +#define NO_UNDERSCORES + +#else + +#define ALIGNARG(log2) log2 +#define ASM_TYPE_DIRECTIVE(name,type) /* Nothing is specified. */ +#define ASM_SIZE_DIRECTIVE(name) /* Nothing is specified. */ + +#endif + + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(4); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +/* The mcount code relies on a normal frame pointer being on the stack + to locate our caller, so push one just for its benefit. */ +#define CALL_MCOUNT \ + pushq %rbp; \ + cfi_adjust_cfa_offset(8); \ + movq %rsp, %rbp; \ + cfi_def_cfa_register(%rbp); \ + call JUMPTARGET(mcount); \ + popq %rbp; \ + cfi_def_cfa(rsp,8); +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +#ifdef NO_UNDERSCORES +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount +#endif + +#define PSEUDO(name, syscall_name, args) \ +lose: \ + jmp JUMPTARGET(syscall_error) \ + .globl syscall_error; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + jb lose + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#undef JUMPTARGET +#ifdef PIC +#define JUMPTARGET(name) name##@PLT +#else +#define JUMPTARGET(name) name +#endif + +/* Local label name for asm code. */ +#ifndef L +# ifdef HAVE_ELF +/* ELF-like local names start with `.L'. */ +# define L(name) .L##name +# else +# define L(name) name +# endif +#endif + +#endif /* __ASSEMBLER__ */ diff --git a/libpthread/nptl/sysdeps/x86_64/tls.h b/libpthread/nptl/sysdeps/x86_64/tls.h index 516827b8e..7b40e3d57 100644 --- a/libpthread/nptl/sysdeps/x86_64/tls.h +++ b/libpthread/nptl/sysdeps/x86_64/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. nptl/x86_64 version. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002-2007, 2008, 2009 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 @@ -20,12 +20,15 @@ #ifndef _TLS_H #define _TLS_H 1 -#include <asm/prctl.h> /* For ARCH_SET_FS. */ #ifndef __ASSEMBLER__ +# include <asm/prctl.h> /* For ARCH_SET_FS. */ # include <stdbool.h> # include <stddef.h> # include <stdint.h> # include <stdlib.h> +# include <sysdep.h> +# include <bits/wordsize.h> +# include <xmmintrin.h> /* Type for the dtv. */ @@ -42,13 +45,33 @@ typedef union dtv typedef struct { - void *tcb; /* Pointer to the TCB. Not necessary the + 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; + int gscope_flag; uintptr_t sysinfo; uintptr_t stack_guard; + uintptr_t pointer_guard; + unsigned long int vgetcpu_cache[2]; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# else + int __unused1; +# endif +# if __WORDSIZE == 64 + int rtld_must_xmm_save; +# endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +# if __WORDSIZE == 64 + long int __unused2; + /* Have space for the post-AVX register size. */ + __m128 rtld_savespace_sse[8][4]; + + void *__padding[8]; +# endif } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -57,9 +80,9 @@ typedef struct /* We require TLS support in the tools. */ -#ifndef HAVE_TLS_SUPPORT -# error "TLS support is required." -#endif +#define HAVE_TLS_SUPPORT 1 +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 /* Signal that TLS support is available. */ #define USE_TLS 1 @@ -74,7 +97,7 @@ typedef struct /* Get the thread descriptor definition. */ -# include <nptl/descr.h> +# include <descr.h> #ifndef LOCK_PREFIX # ifdef UP @@ -96,7 +119,12 @@ typedef struct # define TLS_TCB_SIZE sizeof (struct pthread) /* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct pthread) +//# define TLS_TCB_ALIGN __alignof__ (struct pthread) +// Normally the above would be correct But we have to store post-AVX +// vector registers in the TCB and we want the storage to be aligned. +// unfortunately there isn't yet a type for these values and hence no +// 32-byte alignment requirement. Make this explicit, for now. +# define TLS_TCB_ALIGN 32 /* The TCB can have any size and the memory following the address the thread pointer points to is unspecified. Allocate the TCB there. */ @@ -120,9 +148,9 @@ typedef struct /* Macros to load from and store into segment registers. */ # define TLS_GET_FS() \ - ({ int __seg; __asm ("movl %%fs, %0" : "=q" (__seg)); __seg; }) + ({ int __seg; __asm__ ("movl %%fs, %0" : "=q" (__seg)); __seg; }) # define TLS_SET_FS(val) \ - __asm ("movl %0, %%fs" :: "q" (val)) + __asm__ ("movl %0, %%fs" :: "q" (val)) /* Code to initially initialize the thread pointer. This might need @@ -141,7 +169,7 @@ typedef struct _head->self = _thrdescr; \ \ /* It is a simple syscall to set the %fs value for the thread. */ \ - asm volatile ("syscall" \ + __asm__ volatile ("syscall" \ : "=a" (_result) \ : "0" ((unsigned long int) __NR_arch_prctl), \ "D" ((unsigned long int) ARCH_SET_FS), \ @@ -162,11 +190,11 @@ typedef struct The contained asm must *not* be marked volatile since otherwise assignments like - pthread_descr self = thread_self(); + pthread_descr self = thread_self(); do not get optimized away. */ # define THREAD_SELF \ ({ struct pthread *__self; \ - asm ("movq %%fs:%c1,%q0" : "=r" (__self) \ + __asm__ ("movq %%fs:%c1,%q0" : "=r" (__self) \ : "i" (offsetof (struct pthread, header.self))); \ __self;}) @@ -178,11 +206,11 @@ typedef struct # define THREAD_GETMEM(descr, member) \ ({ __typeof (descr->member) __value; \ if (sizeof (__value) == 1) \ - asm volatile ("movb %%fs:%P2,%b0" \ + __asm__ volatile ("movb %%fs:%P2,%b0" \ : "=q" (__value) \ : "0" (0), "i" (offsetof (struct pthread, member))); \ else if (sizeof (__value) == 4) \ - asm volatile ("movl %%fs:%P1,%0" \ + __asm__ volatile ("movl %%fs:%P1,%0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member))); \ else \ @@ -192,7 +220,7 @@ typedef struct 4 or 8. */ \ abort (); \ \ - asm volatile ("movq %%fs:%P1,%q0" \ + __asm__ volatile ("movq %%fs:%P1,%q0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member))); \ } \ @@ -203,12 +231,12 @@ typedef struct # define THREAD_GETMEM_NC(descr, member, idx) \ ({ __typeof (descr->member[0]) __value; \ if (sizeof (__value) == 1) \ - asm volatile ("movb %%fs:%P2(%q3),%b0" \ + __asm__ volatile ("movb %%fs:%P2(%q3),%b0" \ : "=q" (__value) \ : "0" (0), "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ else if (sizeof (__value) == 4) \ - asm volatile ("movl %%fs:%P1(,%q2,4),%0" \ + __asm__ volatile ("movl %%fs:%P1(,%q2,4),%0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ else \ @@ -218,7 +246,7 @@ typedef struct 4 or 8. */ \ abort (); \ \ - asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \ + __asm__ volatile ("movq %%fs:%P1(,%q2,8),%q0" \ : "=r" (__value) \ : "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ @@ -238,11 +266,11 @@ typedef struct /* 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,%%fs:%P1" : \ + __asm__ volatile ("movb %b0,%%fs:%P1" : \ : "iq" (value), \ "i" (offsetof (struct pthread, member))); \ else if (sizeof (descr->member) == 4) \ - asm volatile ("movl %0,%%fs:%P1" : \ + __asm__ volatile ("movl %0,%%fs:%P1" : \ : IMM_MODE (value), \ "i" (offsetof (struct pthread, member))); \ else \ @@ -252,7 +280,7 @@ typedef struct 4 or 8. */ \ abort (); \ \ - asm volatile ("movq %q0,%%fs:%P1" : \ + __asm__ volatile ("movq %q0,%%fs:%P1" : \ : IMM_MODE ((unsigned long int) value), \ "i" (offsetof (struct pthread, member))); \ }}) @@ -261,12 +289,12 @@ typedef struct /* 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,%%fs:%P1(%q2)" : \ + __asm__ volatile ("movb %b0,%%fs:%P1(%q2)" : \ : "iq" (value), \ "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ else if (sizeof (descr->member[0]) == 4) \ - asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ + __asm__ volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ : IMM_MODE (value), \ "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ @@ -277,7 +305,7 @@ typedef struct 4 or 8. */ \ abort (); \ \ - asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ + __asm__ volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ : IMM_MODE ((unsigned long int) value), \ "i" (offsetof (struct pthread, member[0])), \ "r" (idx)); \ @@ -285,11 +313,11 @@ typedef struct /* Atomic compare and exchange on TLS, returning old value. */ -#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ +# 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, %%fs:%P3" \ + __asm__ volatile (LOCK_PREFIX "cmpxchgl %2, %%fs:%P3" \ : "=a" (__ret) \ : "0" (__old), "r" (newval), \ "i" (offsetof (struct pthread, member))); \ @@ -299,10 +327,21 @@ typedef struct __ret; }) +/* Atomic logical and. */ +# define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "andl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + /* Atomic set bit. */ -#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ (void) ({ if (sizeof ((descr)->member) == 4) \ - asm volatile (LOCK_PREFIX "orl %1, %%fs:%P0" \ + __asm__ volatile (LOCK_PREFIX "orl %1, %%fs:%P0" \ :: "i" (offsetof (struct pthread, member)), \ "ir" (1 << (bit))); \ else \ @@ -310,9 +349,9 @@ typedef struct abort (); }) -#define CALL_THREAD_FCT(descr) \ +# define CALL_THREAD_FCT(descr) \ ({ void *__res; \ - asm volatile ("movq %%fs:%P2, %%rdi\n\t" \ + __asm__ volatile ("movq %%fs:%P2, %%rdi\n\t" \ "callq *%%fs:%P1" \ : "=a" (__res) \ : "i" (offsetof (struct pthread, start_routine)), \ @@ -329,6 +368,70 @@ typedef struct ((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, %%fs:%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) () + + +# ifdef SHARED +/* Defined in dl-trampoline.S. */ +extern void _dl_x86_64_save_sse (void); +extern void _dl_x86_64_restore_sse (void); + +# define RTLD_CHECK_FOREIGN_CALL \ + (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) != 0) + +/* NB: Don't use the xchg operation because that would imply a lock + prefix which is expensive and unnecessary. The cache line is also + not contested at all. */ +# define RTLD_ENABLE_FOREIGN_CALL \ + int old_rtld_must_xmm_save = THREAD_GETMEM (THREAD_SELF, \ + header.rtld_must_xmm_save); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 1) + +# define RTLD_PREPARE_FOREIGN_CALL \ + do if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save)) \ + { \ + _dl_x86_64_save_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 0); \ + } \ + while (0) + +# define RTLD_FINALIZE_FOREIGN_CALL \ + do { \ + if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) == 0) \ + _dl_x86_64_restore_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, \ + old_rtld_must_xmm_save); \ + } while (0) +# endif + + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ |