eathread_pthread_stack_info.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include <eathread/eathread_callstack.h>
  5. #include <stdlib.h>
  6. #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE)
  7. #include <pthread.h>
  8. #endif
  9. namespace EA
  10. {
  11. namespace Thread
  12. {
  13. #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE) || defined(EA_PLATFORM_SONY)
  14. // With some implementations of pthread, the stack base is returned by pthread as NULL if it's the main thread,
  15. // or possibly if it's a thread you created but didn't call pthread_attr_setstack manually to provide your
  16. // own stack. It's impossible for us to tell here whether will be such a NULL return value, so we just do what
  17. // we can and the user nees to beware that a NULL return value means that the system doesn't provide the
  18. // given information for the current thread. This function returns false and sets pBase and pLimit to NULL in
  19. // the case that the thread base and limit weren't returned by the system or were returned as NULL.
  20. #if defined(EA_PLATFORM_APPLE)
  21. bool GetPthreadStackInfo(void** pBase, void** pLimit)
  22. {
  23. pthread_t thread = pthread_self();
  24. void* pBaseTemp = pthread_get_stackaddr_np(thread);
  25. size_t stackSize = pthread_get_stacksize_np(thread);
  26. if(pBase)
  27. *pBase = pBaseTemp;
  28. if(pLimit)
  29. {
  30. if(pBaseTemp)
  31. *pLimit = (void*)((size_t)pBaseTemp - stackSize);
  32. else
  33. *pLimit = NULL;
  34. }
  35. return (pBaseTemp != NULL);
  36. }
  37. #elif defined(EA_PLATFORM_SONY)
  38. bool GetPthreadStackInfo(void** pBase, void** pLimit)
  39. {
  40. bool returnValue = false;
  41. size_t stackSize;
  42. void* pBaseTemp = NULL;
  43. void* pLimitTemp = NULL;
  44. ScePthreadAttr attr;
  45. scePthreadAttrInit(&attr);
  46. int result = scePthreadAttrGet(scePthreadSelf(), &attr);
  47. if(result == 0) // SCE_OK (=0)
  48. {
  49. result = scePthreadAttrGetstack(&attr, &pLimitTemp, &stackSize);
  50. if((result == 0) && (pLimitTemp != NULL)) // If success...
  51. {
  52. pBaseTemp = (void*)((uintptr_t)pLimitTemp + stackSize); // p is returned by pthread_attr_getstack as the lowest address in the stack, and not the stack base.
  53. returnValue = true;
  54. }
  55. else
  56. {
  57. pBaseTemp = NULL;
  58. pLimitTemp = NULL;
  59. }
  60. }
  61. scePthreadAttrDestroy(&attr);
  62. if(pBase)
  63. *pBase = pBaseTemp;
  64. if(pLimit)
  65. *pLimit = pLimitTemp;
  66. return returnValue;
  67. }
  68. #else
  69. bool GetPthreadStackInfo(void** pBase, void** pLimit)
  70. {
  71. bool returnValue = false;
  72. void* pBaseTemp = NULL;
  73. void* pLimitTemp = NULL;
  74. pthread_attr_t attr;
  75. pthread_attr_init(&attr);
  76. #if defined(EA_PLATFORM_LINUX)
  77. int result = pthread_getattr_np(pthread_self(), &attr);
  78. #else
  79. int result = pthread_attr_get_np(pthread_self(), &attr); // __BSD__ or __FreeBSD__
  80. #endif
  81. if(result == 0)
  82. {
  83. // The pthread_attr_getstack() function returns the stack address and stack size
  84. // attributes of the thread attributes object referred to by attr in the buffers
  85. // pointed to by stackaddr and stacksize, respectively. According to the documentation,
  86. // the stack address reported is the lowest memory address and not the stack 'base'.
  87. // http://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_attr_setstack.html
  88. size_t stackSize;
  89. result = pthread_attr_getstack(&attr, &pLimitTemp, &stackSize);
  90. if((result == 0) && (pLimitTemp != NULL)) // If success...
  91. {
  92. pBaseTemp = (void*)((uintptr_t)pLimitTemp + stackSize); // p is returned by pthread_attr_getstack as the lowest address in the stack, and not the stack base.
  93. returnValue = true;
  94. }
  95. else
  96. {
  97. pBaseTemp = NULL;
  98. pLimitTemp = NULL;
  99. }
  100. }
  101. pthread_attr_destroy(&attr);
  102. if(pBase)
  103. *pBase = pBaseTemp;
  104. if(pLimit)
  105. *pLimit = pLimitTemp;
  106. return returnValue;
  107. }
  108. #endif
  109. #endif
  110. } // namespace Callstack
  111. } // namespace EA