pt-machine.h 7.3 KB

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