|
36 | 36 | #endif /* ZEND_WIN32 */ |
37 | 37 | #if (defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK)) || \ |
38 | 38 | defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || \ |
39 | | - defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun) |
| 39 | + defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun) || \ |
| 40 | + defined(_AIX) |
40 | 41 | # include <pthread.h> |
41 | 42 | #endif |
42 | 43 | #if defined(__FreeBSD__) || defined(__DragonFly__) |
@@ -788,6 +789,64 @@ static bool zend_call_stack_get_solaris(zend_call_stack *stack) |
788 | 789 | } |
789 | 790 | #endif /* defined(__sun) */ |
790 | 791 |
|
| 792 | +#if defined(_AIX) |
| 793 | +static bool zend_call_stack_get_aix_pthread(zend_call_stack *stack) |
| 794 | +{ |
| 795 | +#ifdef HAVE_PTHREAD_GETTHRDS_NP |
| 796 | + pthread_t pt = pthread_self(); |
| 797 | + struct __pthrdsinfo thread_info; |
| 798 | + /* This buffer needs to exist sadly */ |
| 799 | + char reg[256]; |
| 800 | + int regsz = sizeof(reg); |
| 801 | + |
| 802 | + if (pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_ALL, &thread_info, |
| 803 | + sizeof(thread_info), ®, ®sz)) { |
| 804 | + return false; |
| 805 | + } |
| 806 | + |
| 807 | + /* |
| 808 | + * The top of the stack (stackend) is not page aligned, there's some |
| 809 | + * internal stuff above it. Thankfully, we don't need page alignment. |
| 810 | + * |
| 811 | + * The size is a little weird. The stacksize field is smaller than |
| 812 | + * subtracting the bottom (stackaddr) from the top; it's about 0x888 |
| 813 | + * to 0x1888 above stackaddr. |
| 814 | + * |
| 815 | + * A somewhat crude diagram is available here: |
| 816 | + * https://www.ibm.com/docs/en/aix/7.2.0?topic=tuning-thread-environment-variables |
| 817 | + * |
| 818 | + * pthread->pt_stk.st_limit is __pi_stackend, |
| 819 | + * above that is internal pthread junk close to the end of page |
| 820 | + * pthread->pt_stk.st_base is __pi_stackaddr, |
| 821 | + * below that is the red zone |
| 822 | + */ |
| 823 | + stack->base = thread_info.__pi_stackend; |
| 824 | + stack->max_size = thread_info.__pi_stackend - thread_info.__pi_stackaddr; |
| 825 | + return true; |
| 826 | +#else |
| 827 | + /* pthread likely not linked in; default NTS build behaviour */ |
| 828 | + return false; |
| 829 | +#endif |
| 830 | +} |
| 831 | + |
| 832 | +static bool zend_call_stack_get_aix(zend_call_stack *stack) |
| 833 | +{ |
| 834 | + /* |
| 835 | + * While we could use /proc on AIX (and the implementation basically |
| 836 | + * like the Solaris one, as the procfs is similar), it doesn't work on |
| 837 | + * PASE. The pthread API works even on the main thread, so we should |
| 838 | + * use it when we have pthread linked (always with ZTS, maybe not with |
| 839 | + * NTS builds). |
| 840 | + */ |
| 841 | + return zend_call_stack_get_aix_pthread(stack); |
| 842 | +} |
| 843 | +#else |
| 844 | +static bool zend_call_stack_get_aix(zend_call_stack *stack) |
| 845 | +{ |
| 846 | + return false; |
| 847 | +} |
| 848 | +#endif /* defined(_AIX) */ |
| 849 | + |
791 | 850 | /** Get the stack information for the calling thread */ |
792 | 851 | ZEND_API bool zend_call_stack_get(zend_call_stack *stack) |
793 | 852 | { |
@@ -823,6 +882,10 @@ ZEND_API bool zend_call_stack_get(zend_call_stack *stack) |
823 | 882 | return true; |
824 | 883 | } |
825 | 884 |
|
| 885 | + if (zend_call_stack_get_aix(stack)) { |
| 886 | + return true; |
| 887 | + } |
| 888 | + |
826 | 889 | return false; |
827 | 890 | } |
828 | 891 |
|
|
0 commit comments