pt-machine.h 7.5 KB

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