pt-machine.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* Machine-dependent pthreads configuration and inline functions.
  2. x86-64 version.
  3. Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
  4. This file is part of the GNU C Library.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, write to the Free
  15. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  16. 02111-1307 USA. */
  17. #ifndef _PT_MACHINE_H
  18. #define _PT_MACHINE_H 1
  19. # include <features.h>
  20. #ifndef __ASSEMBLER__
  21. # include <stddef.h> /* For offsetof. */
  22. # include <stdlib.h> /* For abort(). */
  23. # include <asm/prctl.h>
  24. # ifndef PT_EI
  25. # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
  26. # define PT_EI static inline __attribute__((always_inline))
  27. # else
  28. # define PT_EI extern inline __attribute__((always_inline))
  29. # endif
  30. # endif
  31. /* Get some notion of the current stack. Need not be exactly the top
  32. of the stack, just something somewhere in the current frame. */
  33. # define CURRENT_STACK_FRAME stack_pointer
  34. register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
  35. /* Spinlock implementation; required. */
  36. PT_EI long int
  37. testandset (int *spinlock)
  38. {
  39. long int ret;
  40. __asm__ __volatile__ (
  41. "xchgl %k0, %1"
  42. : "=r"(ret), "=m"(*spinlock)
  43. : "0"(1), "m"(*spinlock)
  44. : "memory");
  45. return ret;
  46. }
  47. /* Compare-and-swap for semaphores. */
  48. # define HAS_COMPARE_AND_SWAP
  49. PT_EI int
  50. __compare_and_swap (long int *p, long int oldval, long int newval)
  51. {
  52. char ret;
  53. long int readval;
  54. __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
  55. : "=q" (ret), "=m" (*p), "=a" (readval)
  56. : "r" (newval), "m" (*p), "a" (oldval)
  57. : "memory");
  58. return ret;
  59. }
  60. /* Return the thread descriptor for the current thread.
  61. The contained asm must *not* be marked volatile since otherwise
  62. assignments like
  63. pthread_descr self = thread_self();
  64. do not get optimized away. */
  65. # define THREAD_SELF \
  66. ({ \
  67. register pthread_descr __self; \
  68. __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \
  69. : "i" (offsetof (struct _pthread_descr_struct, \
  70. p_header.data.self))); \
  71. __self; \
  72. })
  73. /* Prototype for the system call. */
  74. extern int arch_prctl (int __code, unsigned long __addr);
  75. /* Initialize the thread-unique value. */
  76. # define INIT_THREAD_SELF(descr, nr) \
  77. { \
  78. if (arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \
  79. abort (); \
  80. }
  81. /* Read member of the thread descriptor directly. */
  82. # define THREAD_GETMEM(descr, member) \
  83. ({ \
  84. __typeof__ (descr->member) __value; \
  85. if (sizeof (__value) == 1) \
  86. __asm__ __volatile__ ("movb %%fs:%P2,%b0" \
  87. : "=q" (__value) \
  88. : "0" (0), \
  89. "i" (offsetof (struct _pthread_descr_struct, \
  90. member))); \
  91. else if (sizeof (__value) == 4) \
  92. __asm__ __volatile__ ("movl %%fs:%P2,%k0" \
  93. : "=r" (__value) \
  94. : "0" (0), \
  95. "i" (offsetof (struct _pthread_descr_struct, \
  96. member))); \
  97. else \
  98. { \
  99. if (sizeof (__value) != 8) \
  100. /* There should not be any value with a size other than 1, 4 or 8. */\
  101. abort (); \
  102. \
  103. __asm__ __volatile__ ("movq %%fs:%P1,%0" \
  104. : "=r" (__value) \
  105. : "i" (offsetof (struct _pthread_descr_struct, \
  106. member))); \
  107. } \
  108. __value; \
  109. })
  110. /* Same as THREAD_GETMEM, but the member offset can be non-constant. */
  111. # define THREAD_GETMEM_NC(descr, member) \
  112. ({ \
  113. __typeof__ (descr->member) __value; \
  114. if (sizeof (__value) == 1) \
  115. __asm__ __volatile__ ("movb %%fs:(%2),%b0" \
  116. : "=q" (__value) \
  117. : "0" (0), \
  118. "r" (offsetof (struct _pthread_descr_struct, \
  119. member))); \
  120. else if (sizeof (__value) == 4) \
  121. __asm__ __volatile__ ("movl %%fs:(%2),%k0" \
  122. : "=r" (__value) \
  123. : "0" (0), \
  124. "r" (offsetof (struct _pthread_descr_struct, \
  125. member))); \
  126. else \
  127. { \
  128. if (sizeof (__value) != 8) \
  129. /* There should not be any value with a size other than 1, 4 or 8. */\
  130. abort (); \
  131. \
  132. __asm__ __volatile__ ("movq %%fs:(%1),%0" \
  133. : "=r" (__value) \
  134. : "r" (offsetof (struct _pthread_descr_struct, \
  135. member))); \
  136. } \
  137. __value; \
  138. })
  139. /* Set member of the thread descriptor directly. */
  140. # define THREAD_SETMEM(descr, member, value) \
  141. ({ \
  142. __typeof__ (descr->member) __value = (value); \
  143. if (sizeof (__value) == 1) \
  144. __asm__ __volatile__ ("movb %0,%%fs:%P1" : \
  145. : "q" (__value), \
  146. "i" (offsetof (struct _pthread_descr_struct, \
  147. member))); \
  148. else if (sizeof (__value) == 4) \
  149. __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \
  150. : "r" (__value), \
  151. "i" (offsetof (struct _pthread_descr_struct, \
  152. member))); \
  153. else \
  154. { \
  155. if (sizeof (__value) != 8) \
  156. /* There should not be any value with a size other than 1, 4 or 8. */\
  157. abort (); \
  158. \
  159. __asm__ __volatile__ ("movq %0,%%fs:%P1" : \
  160. : "r" (__value), \
  161. "i" (offsetof (struct _pthread_descr_struct, \
  162. member))); \
  163. } \
  164. })
  165. /* Same as THREAD_SETMEM, but the member offset can be non-constant. */
  166. # define THREAD_SETMEM_NC(descr, member, value) \
  167. ({ \
  168. __typeof__ (descr->member) __value = (value); \
  169. if (sizeof (__value) == 1) \
  170. __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \
  171. : "q" (__value), \
  172. "r" (offsetof (struct _pthread_descr_struct, \
  173. member))); \
  174. else if (sizeof (__value) == 4) \
  175. __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \
  176. : "r" (__value), \
  177. "r" (offsetof (struct _pthread_descr_struct, \
  178. member))); \
  179. else \
  180. { \
  181. if (sizeof (__value) != 8) \
  182. /* There should not be any value with a size other than 1, 4 or 8. */\
  183. abort (); \
  184. \
  185. __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \
  186. : "r" (__value), \
  187. "r" (offsetof (struct _pthread_descr_struct, \
  188. member))); \
  189. } \
  190. })
  191. #endif /* !__ASSEMBLER__ */
  192. /* We want the OS to assign stack addresses. */
  193. #define FLOATING_STACKS 1
  194. /* Maximum size of the stack if the rlimit is unlimited. */
  195. #define ARCH_STACK_MAX_SIZE 32*1024*1024
  196. /* The ia32e really want some help to prevent overheating. */
  197. #define BUSY_WAIT_NOP __asm__ ("rep; nop")
  198. #endif /* pt-machine.h */