Skip to content

Commit 9eded24

Browse files
committed
zend_call_stack.c: AIX backend
Uses pthread_getthrds_np (so requires pthread linked, by default on ZTS, needs to be added for NTS). The stack size part is weird, but works in testing. An alternative approach is using procfs, but I didn't bother with this due to it not working on PASE (and the pthread approach works for the main thread too).
1 parent c5cdea5 commit 9eded24

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

Zend/Zend.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ AC_CHECK_FUNCS(m4_normalize([
148148
pthread_attr_getstack
149149
pthread_get_stackaddr_np
150150
pthread_getattr_np
151+
pthread_getthrds_np
151152
pthread_stackseg_np
152153
strnlen
153154
]))

Zend/zend_call_stack.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
#endif /* ZEND_WIN32 */
3737
#if (defined(HAVE_PTHREAD_GETATTR_NP) && defined(HAVE_PTHREAD_ATTR_GETSTACK)) || \
3838
defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || \
39-
defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun)
39+
defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun) || \
40+
defined(_AIX)
4041
# include <pthread.h>
4142
#endif
4243
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -788,6 +789,64 @@ static bool zend_call_stack_get_solaris(zend_call_stack *stack)
788789
}
789790
#endif /* defined(__sun) */
790791

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), &reg, &regsz)) {
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+
791850
/** Get the stack information for the calling thread */
792851
ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
793852
{
@@ -823,6 +882,10 @@ ZEND_API bool zend_call_stack_get(zend_call_stack *stack)
823882
return true;
824883
}
825884

885+
if (zend_call_stack_get_aix(stack)) {
886+
return true;
887+
}
888+
826889
return false;
827890
}
828891

0 commit comments

Comments
 (0)