Files
php-src/Zend/zend_call_stack.h
Calvin Buckley 415a415381 zend_call_stack.c: AIX backend (#22906)
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).
2026-07-31 16:26:47 -03:00

136 lines
3.8 KiB
C

/*
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
| Copyright © Zend Technologies Ltd., a subsidiary company of |
| Perforce Software, Inc., and Contributors. |
+----------------------------------------------------------------------+
| This source file is subject to the Modified BSD License that is |
| bundled with this package in the file LICENSE, and is available |
| through the World Wide Web at <https://www.php.net/license/>. |
| |
| SPDX-License-Identifier: BSD-3-Clause |
+----------------------------------------------------------------------+
| Authors: Arnaud Le Blanc <arnaud.lb@gmail.com> |
+----------------------------------------------------------------------+
*/
#ifndef ZEND_CALL_STACK_H
#define ZEND_CALL_STACK_H
#include "zend.h"
#include "zend_portability.h"
#ifdef _MSC_VER
# include <intrin.h>
#endif
#ifdef __APPLE__
# include <pthread.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#ifdef ZEND_CHECK_STACK_LIMIT
typedef struct _zend_call_stack {
void *base; /* high address of the stack */
size_t max_size;
} zend_call_stack;
ZEND_API void zend_call_stack_init(void);
ZEND_API bool zend_call_stack_get(zend_call_stack *stack);
/** Returns an approximation of the current stack position */
static zend_always_inline void *zend_call_stack_position(void) {
#ifdef _MSC_VER
return _AddressOfReturnAddress();
#elif defined(PHP_HAVE_BUILTIN_FRAME_ADDRESS)
return __builtin_frame_address(0);
#else
void *a;
void *pos = (void*)&a;
return pos;
#endif
}
static zend_always_inline bool zend_call_stack_overflowed(void *stack_limit) {
return (uintptr_t) zend_call_stack_position() <= (uintptr_t) stack_limit;
}
static inline void* zend_call_stack_limit(void *base, size_t size, size_t reserved_size)
{
if (UNEXPECTED(size > (uintptr_t)base)) {
return (void*)0;
}
base = (int8_t*)base - size;
if (UNEXPECTED(UINTPTR_MAX - (uintptr_t)base < reserved_size)) {
return (void*)UINTPTR_MAX;
}
return (int8_t*)base + reserved_size;
}
static inline size_t zend_call_stack_default_size(void)
{
#ifdef __linux__
return 8 * 1024 * 1024;
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__)
return 4 * 1024 * 1024;
#endif
#if defined(__DragonFly__)
return 2 * 1024 * 1024;
#endif
#ifdef __OpenBSD__
return 512 * 1024;
#endif
#ifdef __APPLE__
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
if (pthread_main_np()) {
return 8 * 1024 * 1024;
}
return 512 * 1024;
#endif
#ifdef __HAIKU__
return 64 * 4096;
#endif
#ifdef __sun
return 8 * 4096;
#endif
#ifdef _AIX
/*
* default pthread stack limit is 96 KB on 32-bit, 192 KB on 64-bit
* https://www.ibm.com/docs/en/aix/7.1.0?topic=programming-threads-library-options
*/
#ifdef HAVE_PTHREAD_GETTHRDS_NP /* if we have pthread linked (not in libc) */
if (pthread_self() != 1) {
#ifdef __64BIT__
return 192 * 1024;
#else
return 96 * 1024;
#endif
}
#endif
/*
* default AIX ulimit -s value is allegedly 32 MB, default values per:
* https://www.ibm.com/docs/en/aix/7.1.0?topic=u-ulimit-command
* N.B.: the the file uses 512b blocks, but the command uses kilobytes
* https://www.ibm.com/support/pages/ibm-aix-security-ulimit-and-ulimit-d-output-differs-value-etcsecuritylimits
*
* note PASE uses an unlimited stack size by default, which is capped
* at the PowerPC segment size (256 MB)
*/
return 32 * 1024 * 1024;
#endif
return 2 * 1024 * 1024;
}
#endif /* ZEND_CHECK_STACK_LIMIT */
#endif /* ZEND_CALL_STACK_H */