Back to index

glibc  2.9
pt-machine.h
Go to the documentation of this file.
00001 /* Machine-dependent pthreads configuration and inline functions.
00002    x86-64 version.
00003    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef _PT_MACHINE_H
00022 #define _PT_MACHINE_H   1
00023 
00024 #ifndef __ASSEMBLER__
00025 # include <stddef.h> /* For offsetof.  */
00026 # include <stdlib.h> /* For abort().  */
00027 # include <asm/prctl.h>
00028 
00029 
00030 # ifndef PT_EI
00031 #  define PT_EI extern inline __attribute__ ((always_inline))
00032 # endif
00033 
00034 extern long int testandset (int *spinlock);
00035 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
00036 
00037 /* Get some notion of the current stack.  Need not be exactly the top
00038    of the stack, just something somewhere in the current frame.  */
00039 # define CURRENT_STACK_FRAME  stack_pointer
00040 register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
00041 
00042 
00043 /* Spinlock implementation; required.  */
00044 PT_EI long int
00045 testandset (int *spinlock)
00046 {
00047   long int ret;
00048 
00049   __asm__ __volatile__ (
00050        "xchgl %k0, %1"
00051        : "=r"(ret), "=m"(*spinlock)
00052        : "0"(1), "m"(*spinlock)
00053        : "memory");
00054 
00055   return ret;
00056 }
00057 
00058 
00059 /* Compare-and-swap for semaphores.  */
00060 # define HAS_COMPARE_AND_SWAP
00061 
00062 PT_EI int
00063 __compare_and_swap (long int *p, long int oldval, long int newval)
00064 {
00065   char ret;
00066   long int readval;
00067 
00068   __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
00069                      : "=q" (ret), "=m" (*p), "=a" (readval)
00070                      : "r" (newval), "m" (*p), "a" (oldval)
00071                      : "memory");
00072   return ret;
00073 }
00074 
00075 /* Return the thread descriptor for the current thread.
00076 
00077    The contained asm must *not* be marked volatile since otherwise
00078    assignments like
00079        pthread_descr self = thread_self();
00080    do not get optimized away.  */
00081 # define THREAD_SELF \
00082 ({                                                                   \
00083   register pthread_descr __self;                                     \
00084   __asm__ ("movq %%fs:%c1,%0" : "=r" (__self)                               \
00085           : "i" (offsetof (struct _pthread_descr_struct,                    \
00086                          p_header.data.self)));                      \
00087   __self;                                                            \
00088 })
00089 
00090 /* Prototype for the system call.  */
00091 extern int __arch_prctl (int __code, unsigned long __addr);
00092 
00093 /* Initialize the thread-unique value.  */
00094 # define INIT_THREAD_SELF(descr, nr) \
00095 {                                                                    \
00096   if (__arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0)                \
00097     abort ();                                                        \
00098 }
00099 
00100 /* Read member of the thread descriptor directly.  */
00101 # define THREAD_GETMEM(descr, member) \
00102 ({                                                                   \
00103   __typeof__ (descr->member) __value;                                       \
00104   if (sizeof (__value) == 1)                                                \
00105     __asm__ __volatile__ ("movb %%fs:%P2,%b0"                               \
00106                        : "=q" (__value)                              \
00107                        : "0" (0),                                    \
00108                          "i" (offsetof (struct _pthread_descr_struct,      \
00109                                       member)));                     \
00110   else if (sizeof (__value) == 4)                                    \
00111     __asm__ __volatile__ ("movl %%fs:%P2,%k0"                               \
00112                        : "=r" (__value)                              \
00113                        : "0" (0),                                    \
00114                          "i" (offsetof (struct _pthread_descr_struct,      \
00115                                       member)));                     \
00116   else                                                               \
00117     {                                                                \
00118       if (sizeof (__value) != 8)                                     \
00119        /* There should not be any value with a size other than 1, 4 or 8.  */\
00120        abort ();                                                     \
00121                                                                      \
00122       __asm__ __volatile__ ("movq %%fs:%P1,%0"                              \
00123                          : "=r" (__value)                            \
00124                          : "i" (offsetof (struct _pthread_descr_struct,    \
00125                                         member)));                          \
00126     }                                                                \
00127   __value;                                                           \
00128 })
00129 
00130 /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
00131 # define THREAD_GETMEM_NC(descr, member) \
00132 ({                                                                   \
00133   __typeof__ (descr->member) __value;                                       \
00134   if (sizeof (__value) == 1)                                                \
00135     __asm__ __volatile__ ("movb %%fs:(%2),%b0"                              \
00136                        : "=q" (__value)                              \
00137                        : "0" (0),                                    \
00138                          "r" (offsetof (struct _pthread_descr_struct,      \
00139                                       member)));                     \
00140   else if (sizeof (__value) == 4)                                    \
00141     __asm__ __volatile__ ("movl %%fs:(%2),%k0"                              \
00142                        : "=r" (__value)                              \
00143                        : "0" (0),                                    \
00144                          "r" (offsetof (struct _pthread_descr_struct,      \
00145                                       member)));                     \
00146   else                                                               \
00147     {                                                                \
00148       if (sizeof (__value) != 8)                                     \
00149        /* There should not be any value with a size other than 1, 4 or 8.  */\
00150        abort ();                                                     \
00151                                                                      \
00152       __asm__ __volatile__ ("movq %%fs:(%1),%0"                             \
00153                          : "=r" (__value)                            \
00154                          : "r" (offsetof (struct _pthread_descr_struct,    \
00155                                         member)));                          \
00156     }                                                                \
00157   __value;                                                           \
00158 })
00159 
00160 /* Set member of the thread descriptor directly.  */
00161 # define THREAD_SETMEM(descr, member, value) \
00162 ({                                                                   \
00163   __typeof__ (descr->member) __value = (value);                             \
00164   if (sizeof (__value) == 1)                                                \
00165     __asm__ __volatile__ ("movb %0,%%fs:%P1" :                              \
00166                        : "q" (__value),                              \
00167                          "i" (offsetof (struct _pthread_descr_struct,      \
00168                                       member)));                     \
00169   else if (sizeof (__value) == 4)                                    \
00170     __asm__ __volatile__ ("movl %k0,%%fs:%P1" :                             \
00171                        : "r" (__value),                              \
00172                          "i" (offsetof (struct _pthread_descr_struct,      \
00173                                       member)));                     \
00174   else                                                               \
00175     {                                                                \
00176       if (sizeof (__value) != 8)                                     \
00177        /* There should not be any value with a size other than 1, 4 or 8.  */\
00178        abort ();                                                     \
00179                                                                      \
00180       __asm__ __volatile__ ("movq %0,%%fs:%P1" :                     \
00181                          : "r" (__value),                            \
00182                            "i" (offsetof (struct _pthread_descr_struct,    \
00183                                         member)));                          \
00184     }                                                                \
00185 })
00186 
00187 /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
00188 # define THREAD_SETMEM_NC(descr, member, value) \
00189 ({                                                                   \
00190   __typeof__ (descr->member) __value = (value);                             \
00191   if (sizeof (__value) == 1)                                                \
00192     __asm__ __volatile__ ("movb %0,%%fs:(%1)" :                             \
00193                        : "q" (__value),                              \
00194                          "r" (offsetof (struct _pthread_descr_struct,      \
00195                                       member)));                     \
00196   else if (sizeof (__value) == 4)                                    \
00197     __asm__ __volatile__ ("movl %k0,%%fs:(%1)" :                     \
00198                        : "r" (__value),                              \
00199                          "r" (offsetof (struct _pthread_descr_struct,      \
00200                                       member)));                     \
00201   else                                                               \
00202     {                                                                \
00203       if (sizeof (__value) != 8)                                     \
00204        /* There should not be any value with a size other than 1, 4 or 8.  */\
00205        abort ();                                                     \
00206                                                                      \
00207       __asm__ __volatile__ ("movq %0,%%fs:(%1)"  :                          \
00208                          : "r" (__value),                            \
00209                            "r" (offsetof (struct _pthread_descr_struct,    \
00210                                         member)));                          \
00211     }                                                                \
00212 })
00213 
00214 #endif /* !__ASSEMBLER__ */
00215 
00216 /* We want the OS to assign stack addresses.  */
00217 #define FLOATING_STACKS     1
00218 
00219 /* Maximum size of the stack if the rlimit is unlimited.  */
00220 #define ARCH_STACK_MAX_SIZE 32*1024*1024
00221 
00222 /* The ia32e really want some help to prevent overheating.  */
00223 #define BUSY_WAIT_NOP       __asm__ ("rep; nop")
00224 
00225 #endif /* pt-machine.h */