pt-machine.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. # define PT_EI __extern_always_inline
  26. # endif
  27. /* Get some notion of the current stack. Need not be exactly the top
  28. of the stack, just something somewhere in the current frame. */
  29. # define CURRENT_STACK_FRAME stack_pointer
  30. register char * stack_pointer __asm__ ("%rsp") __attribute_used__;
  31. /* Spinlock implementation; required. */
  32. PT_EI long int
  33. testandset (int *spinlock)
  34. {
  35. long int ret;
  36. __asm__ __volatile__ (
  37. "xchgl %k0, %1"
  38. : "=r"(ret), "=m"(*spinlock)
  39. : "0"(1), "m"(*spinlock)
  40. : "memory");
  41. return ret;
  42. }
  43. /* Compare-and-swap for semaphores. */
  44. # define HAS_COMPARE_AND_SWAP
  45. PT_EI int
  46. __compare_and_swap (long int *p, long int oldval, long int newval)
  47. {
  48. char ret;
  49. long int readval;
  50. __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0"
  51. : "=q" (ret), "=m" (*p), "=a" (readval)
  52. : "r" (newval), "m" (*p), "a" (oldval)
  53. : "memory");
  54. return ret;
  55. }
  56. /* Return the thread descriptor for the current thread.
  57. The contained asm must *not* be marked volatile since otherwise
  58. assignments like
  59. pthread_descr self = thread_self();
  60. do not get optimized away. */
  61. # define THREAD_SELF \
  62. ({ \
  63. register pthread_descr __self; \
  64. __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \
  65. : "i" (offsetof (struct _pthread_descr_struct, \
  66. p_header.data.self))); \
  67. __self; \
  68. })
  69. /* Prototype for the system call. */
  70. extern int arch_prctl (int __code, unsigned long __addr);
  71. /* Initialize the thread-unique value. */
  72. # define INIT_THREAD_SELF(descr, nr) \
  73. { \
  74. if (arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \
  75. abort (); \
  76. }
  77. /* Read member of the thread descriptor directly. */
  78. # define THREAD_GETMEM(descr, member) \
  79. ({ \
  80. __typeof__ (descr->member) __value; \
  81. if (sizeof (__value) == 1) \
  82. __asm__ __volatile__ ("movb %%fs:%P2,%b0" \
  83. : "=q" (__value) \
  84. : "0" (0), \
  85. "i" (offsetof (struct _pthread_descr_struct, \
  86. member))); \
  87. else if (sizeof (__value) == 4) \
  88. __asm__ __volatile__ ("movl %%fs:%P2,%k0" \
  89. : "=r" (__value) \
  90. : "0" (0), \
  91. "i" (offsetof (struct _pthread_descr_struct, \
  92. member))); \
  93. else \
  94. { \
  95. if (sizeof (__value) != 8) \
  96. /* There should not be any value with a size other than 1, 4 or 8. */\
  97. abort (); \
  98. \
  99. __asm__ __volatile__ ("movq %%fs:%P1,%0" \
  100. : "=r" (__value) \
  101. : "i" (offsetof (struct _pthread_descr_struct, \
  102. member))); \
  103. } \
  104. __value; \
  105. })
  106. /* Same as THREAD_GETMEM, but the member offset can be non-constant. */
  107. # define THREAD_GETMEM_NC(descr, member) \
  108. ({ \
  109. __typeof__ (descr->member) __value; \
  110. if (sizeof (__value) == 1) \
  111. __asm__ __volatile__ ("movb %%fs:(%2),%b0" \
  112. : "=q" (__value) \
  113. : "0" (0), \
  114. "r" (offsetof (struct _pthread_descr_struct, \
  115. member))); \
  116. else if (sizeof (__value) == 4) \
  117. __asm__ __volatile__ ("movl %%fs:(%2),%k0" \
  118. : "=r" (__value) \
  119. : "0" (0), \
  120. "r" (offsetof (struct _pthread_descr_struct, \
  121. member))); \
  122. else \
  123. { \
  124. if (sizeof (__value) != 8) \
  125. /* There should not be any value with a size other than 1, 4 or 8. */\
  126. abort (); \
  127. \
  128. __asm__ __volatile__ ("movq %%fs:(%1),%0" \
  129. : "=r" (__value) \
  130. : "r" (offsetof (struct _pthread_descr_struct, \
  131. member))); \
  132. } \
  133. __value; \
  134. })
  135. /* Set member of the thread descriptor directly. */
  136. # define THREAD_SETMEM(descr, member, value) \
  137. ({ \
  138. __typeof__ (descr->member) __value = (value); \
  139. if (sizeof (__value) == 1) \
  140. __asm__ __volatile__ ("movb %0,%%fs:%P1" : \
  141. : "q" (__value), \
  142. "i" (offsetof (struct _pthread_descr_struct, \
  143. member))); \
  144. else if (sizeof (__value) == 4) \
  145. __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \
  146. : "r" (__value), \
  147. "i" (offsetof (struct _pthread_descr_struct, \
  148. member))); \
  149. else \
  150. { \
  151. if (sizeof (__value) != 8) \
  152. /* There should not be any value with a size other than 1, 4 or 8. */\
  153. abort (); \
  154. \
  155. __asm__ __volatile__ ("movq %0,%%fs:%P1" : \
  156. : "r" (__value), \
  157. "i" (offsetof (struct _pthread_descr_struct, \
  158. member))); \
  159. } \
  160. })
  161. /* Same as THREAD_SETMEM, but the member offset can be non-constant. */
  162. # define THREAD_SETMEM_NC(descr, member, value) \
  163. ({ \
  164. __typeof__ (descr->member) __value = (value); \
  165. if (sizeof (__value) == 1) \
  166. __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \
  167. : "q" (__value), \
  168. "r" (offsetof (struct _pthread_descr_struct, \
  169. member))); \
  170. else if (sizeof (__value) == 4) \
  171. __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \
  172. : "r" (__value), \
  173. "r" (offsetof (struct _pthread_descr_struct, \
  174. member))); \
  175. else \
  176. { \
  177. if (sizeof (__value) != 8) \
  178. /* There should not be any value with a size other than 1, 4 or 8. */\
  179. abort (); \
  180. \
  181. __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \
  182. : "r" (__value), \
  183. "r" (offsetof (struct _pthread_descr_struct, \
  184. member))); \
  185. } \
  186. })
  187. #endif /* !__ASSEMBLER__ */
  188. /* We want the OS to assign stack addresses. */
  189. #define FLOATING_STACKS 1
  190. /* Maximum size of the stack if the rlimit is unlimited. */
  191. #define ARCH_STACK_MAX_SIZE 32*1024*1024
  192. /* The ia32e really want some help to prevent overheating. */
  193. #define BUSY_WAIT_NOP __asm__ ("rep; nop")
  194. #endif /* pt-machine.h */