2013-02-13 12:26:47 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2013-03-19 06:32:24 +00:00
|
|
|
| Zend OPcache |
|
2013-02-13 12:26:47 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2019-02-05 07:33:28 +00:00
|
|
|
| Copyright (c) The PHP Group |
|
2013-02-13 12:26:47 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available through the world-wide-web at the following url: |
|
2021-05-06 10:16:35 +00:00
|
|
|
| https://www.php.net/license/3_01.txt |
|
2013-02-13 12:26:47 +00:00
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
2018-11-01 16:30:28 +00:00
|
|
|
| Authors: Andi Gutmans <andi@php.net> |
|
|
|
|
| Zeev Suraski <zeev@php.net> |
|
2013-02-13 12:26:47 +00:00
|
|
|
| Stanislav Malyshev <stas@zend.com> |
|
2018-11-01 16:30:28 +00:00
|
|
|
| Dmitry Stogov <dmitry@php.net> |
|
2013-02-13 12:26:47 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include "ZendAccelerator.h"
|
|
|
|
#include "zend_shared_alloc.h"
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#include <fcntl.h>
|
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <signal.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <stdio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_MPROTECT
|
|
|
|
# include "sys/mman.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define SEM_FILENAME_PREFIX ".ZendSem."
|
|
|
|
#define S_H(s) g_shared_alloc_handler->s
|
|
|
|
|
|
|
|
/* True globals */
|
|
|
|
/* old/new mapping. We can use true global even for ZTS because its usage
|
|
|
|
is wrapped with exclusive lock anyway */
|
|
|
|
static const zend_shared_memory_handlers *g_shared_alloc_handler = NULL;
|
|
|
|
static const char *g_shared_model;
|
|
|
|
/* pointer to globals allocated in SHM and shared across processes */
|
|
|
|
zend_smm_shared_globals *smm_shared_globals;
|
|
|
|
|
|
|
|
#ifndef ZEND_WIN32
|
2013-02-15 11:08:51 +00:00
|
|
|
#ifdef ZTS
|
|
|
|
static MUTEX_T zts_lock;
|
|
|
|
#endif
|
2013-02-13 12:26:47 +00:00
|
|
|
int lock_file;
|
2016-03-04 10:17:45 +00:00
|
|
|
static char lockfile_name[MAXPATHLEN];
|
2013-02-13 12:26:47 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const zend_shared_memory_handler_entry handler_table[] = {
|
2013-02-14 06:01:29 +00:00
|
|
|
#ifdef USE_MMAP
|
2013-02-13 12:26:47 +00:00
|
|
|
{ "mmap", &zend_alloc_mmap_handlers },
|
|
|
|
#endif
|
2013-02-14 06:01:29 +00:00
|
|
|
#ifdef USE_SHM
|
2013-02-13 12:26:47 +00:00
|
|
|
{ "shm", &zend_alloc_shm_handlers },
|
|
|
|
#endif
|
2013-02-14 06:01:29 +00:00
|
|
|
#ifdef USE_SHM_OPEN
|
2013-02-13 12:26:47 +00:00
|
|
|
{ "posix", &zend_alloc_posix_handlers },
|
|
|
|
#endif
|
|
|
|
#ifdef ZEND_WIN32
|
|
|
|
{ "win32", &zend_alloc_win32_handlers },
|
|
|
|
#endif
|
|
|
|
{ NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef ZEND_WIN32
|
2016-03-04 10:17:45 +00:00
|
|
|
void zend_shared_alloc_create_lock(char *lockfile_path)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
2013-02-15 11:08:51 +00:00
|
|
|
#ifdef ZTS
|
2021-06-29 08:04:10 +00:00
|
|
|
zts_lock = tsrm_mutex_alloc();
|
2013-02-15 11:08:51 +00:00
|
|
|
#endif
|
|
|
|
|
2016-03-04 10:17:45 +00:00
|
|
|
snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX);
|
2013-02-13 12:26:47 +00:00
|
|
|
lock_file = mkstemp(lockfile_name);
|
|
|
|
if (lock_file == -1) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
2022-02-05 19:13:32 +00:00
|
|
|
|
|
|
|
fchmod(lock_file, 0666);
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
val = fcntl(lock_file, F_GETFD, 0);
|
|
|
|
val |= FD_CLOEXEC;
|
|
|
|
fcntl(lock_file, F_SETFD, val);
|
|
|
|
|
|
|
|
unlink(lockfile_name);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-10 06:36:35 +00:00
|
|
|
static void no_memory_bailout(size_t allocate_size, char *error)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %zu bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno );
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void copy_shared_segments(void *to, void *from, int count, int size)
|
|
|
|
{
|
|
|
|
zend_shared_segment **shared_segments_v = (zend_shared_segment **)to;
|
|
|
|
void *shared_segments_to_p = ((char *)to + count*(sizeof(void *)));
|
|
|
|
void *shared_segments_from_p = from;
|
|
|
|
int i;
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < count; i++) {
|
2013-02-13 12:26:47 +00:00
|
|
|
shared_segments_v[i] = shared_segments_to_p;
|
|
|
|
memcpy(shared_segments_to_p, shared_segments_from_p, size);
|
|
|
|
shared_segments_to_p = ((char *)shared_segments_to_p + size);
|
|
|
|
shared_segments_from_p = ((char *)shared_segments_from_p + size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-29 21:34:22 +00:00
|
|
|
static int zend_shared_alloc_try(const zend_shared_memory_handler_entry *he, size_t requested_size, zend_shared_segment ***shared_segments_p, int *shared_segments_count, char **error_in)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
g_shared_alloc_handler = he->handler;
|
|
|
|
g_shared_model = he->name;
|
|
|
|
ZSMMG(shared_segments) = NULL;
|
|
|
|
ZSMMG(shared_segments_count) = 0;
|
|
|
|
|
|
|
|
res = S_H(create_segments)(requested_size, shared_segments_p, shared_segments_count, error_in);
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (res) {
|
2013-02-13 12:26:47 +00:00
|
|
|
/* this model works! */
|
|
|
|
return res;
|
|
|
|
}
|
2013-02-22 06:56:05 +00:00
|
|
|
if (*shared_segments_p) {
|
2013-02-13 12:26:47 +00:00
|
|
|
int i;
|
|
|
|
/* cleanup */
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < *shared_segments_count; i++) {
|
2013-04-18 09:32:46 +00:00
|
|
|
if ((*shared_segments_p)[i]->p && (*shared_segments_p)[i]->p != (void *)-1) {
|
2013-02-13 12:26:47 +00:00
|
|
|
S_H(detach_segment)((*shared_segments_p)[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(*shared_segments_p);
|
|
|
|
*shared_segments_p = NULL;
|
|
|
|
}
|
|
|
|
g_shared_alloc_handler = NULL;
|
|
|
|
return ALLOC_FAILURE;
|
|
|
|
}
|
|
|
|
|
2019-04-01 07:27:11 +00:00
|
|
|
int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
|
|
|
zend_shared_segment **tmp_shared_segments;
|
|
|
|
size_t shared_segments_array_size;
|
|
|
|
zend_smm_shared_globals tmp_shared_globals, *p_tmp_shared_globals;
|
|
|
|
char *error_in = NULL;
|
|
|
|
const zend_shared_memory_handler_entry *he;
|
|
|
|
int res = ALLOC_FAILURE;
|
2019-04-01 07:27:11 +00:00
|
|
|
int i;
|
2014-10-15 07:37:55 +00:00
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
/* shared_free must be valid before we call zend_shared_alloc()
|
|
|
|
* - make it temporarily point to a local variable
|
|
|
|
*/
|
|
|
|
smm_shared_globals = &tmp_shared_globals;
|
2019-04-01 07:27:11 +00:00
|
|
|
ZSMMG(shared_free) = requested_size - reserved_size; /* goes to tmp_shared_globals.shared_free */
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2016-03-04 10:17:45 +00:00
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
zend_shared_alloc_create_lock(ZCG(accel_directives).lockfile_path);
|
|
|
|
#else
|
2013-02-13 12:26:47 +00:00
|
|
|
zend_shared_alloc_create_lock();
|
2016-03-04 10:17:45 +00:00
|
|
|
#endif
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) {
|
|
|
|
char *model = ZCG(accel_directives).memory_model;
|
2013-02-13 12:26:47 +00:00
|
|
|
/* "cgi" is really "shm"... */
|
2013-02-22 06:56:05 +00:00
|
|
|
if (strncmp(ZCG(accel_directives).memory_model, "cgi", sizeof("cgi")) == 0) {
|
2013-02-13 12:26:47 +00:00
|
|
|
model = "shm";
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (he = handler_table; he->name; he++) {
|
|
|
|
if (strcmp(model, he->name) == 0) {
|
|
|
|
res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
|
|
|
|
if (res) {
|
2013-02-13 12:26:47 +00:00
|
|
|
/* this model works! */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (res == FAILED_REATTACHED) {
|
2013-02-13 12:26:47 +00:00
|
|
|
smm_shared_globals = NULL;
|
|
|
|
return res;
|
|
|
|
}
|
2015-10-09 21:07:10 +00:00
|
|
|
#if ENABLE_FILE_CACHE_FALLBACK
|
|
|
|
if (ALLOC_FALLBACK == res) {
|
|
|
|
return ALLOC_FALLBACK;
|
|
|
|
}
|
|
|
|
#endif
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (!g_shared_alloc_handler) {
|
2013-02-13 12:26:47 +00:00
|
|
|
/* try memory handlers in order */
|
2013-02-22 06:56:05 +00:00
|
|
|
for (he = handler_table; he->name; he++) {
|
|
|
|
res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
|
|
|
|
if (res) {
|
2013-02-13 12:26:47 +00:00
|
|
|
/* this model works! */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (!g_shared_alloc_handler) {
|
2013-02-13 12:26:47 +00:00
|
|
|
no_memory_bailout(requested_size, error_in);
|
|
|
|
return ALLOC_FAILURE;
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
if (res == SUCCESSFULLY_REATTACHED) {
|
2013-02-13 12:26:47 +00:00
|
|
|
return res;
|
|
|
|
}
|
2015-10-09 21:07:10 +00:00
|
|
|
#if ENABLE_FILE_CACHE_FALLBACK
|
|
|
|
if (ALLOC_FALLBACK == res) {
|
|
|
|
return ALLOC_FALLBACK;
|
|
|
|
}
|
|
|
|
#endif
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2019-04-01 07:27:11 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
|
|
|
ZSMMG(shared_segments)[i]->end = ZSMMG(shared_segments)[i]->size;
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
shared_segments_array_size = ZSMMG(shared_segments_count) * S_H(segment_type_size)();
|
2013-02-13 12:26:47 +00:00
|
|
|
|
|
|
|
/* move shared_segments and shared_free to shared memory */
|
2013-02-15 13:35:58 +00:00
|
|
|
ZCG(locked) = 1; /* no need to perform a real lock at this point */
|
2019-04-01 07:27:11 +00:00
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals));
|
2013-03-28 09:34:59 +00:00
|
|
|
if (!p_tmp_shared_globals) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
|
2017-06-25 21:24:23 +00:00
|
|
|
return ALLOC_FAILURE;
|
2013-03-28 09:34:59 +00:00
|
|
|
}
|
2017-06-21 07:37:54 +00:00
|
|
|
memset(p_tmp_shared_globals, 0, sizeof(zend_smm_shared_globals));
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
tmp_shared_segments = zend_shared_alloc(shared_segments_array_size + ZSMMG(shared_segments_count) * sizeof(void *));
|
2013-03-28 09:34:59 +00:00
|
|
|
if (!tmp_shared_segments) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
|
2017-06-25 21:24:23 +00:00
|
|
|
return ALLOC_FAILURE;
|
2013-03-28 09:34:59 +00:00
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)());
|
|
|
|
|
|
|
|
*p_tmp_shared_globals = tmp_shared_globals;
|
|
|
|
smm_shared_globals = p_tmp_shared_globals;
|
|
|
|
|
|
|
|
free(ZSMMG(shared_segments));
|
|
|
|
ZSMMG(shared_segments) = tmp_shared_segments;
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count));
|
2013-03-28 09:34:59 +00:00
|
|
|
if (!ZSMMG(shared_memory_state).positions) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
|
2017-06-25 21:24:23 +00:00
|
|
|
return ALLOC_FAILURE;
|
2013-03-28 09:34:59 +00:00
|
|
|
}
|
|
|
|
|
2019-04-01 07:27:11 +00:00
|
|
|
if (reserved_size) {
|
|
|
|
i = ZSMMG(shared_segments_count) - 1;
|
|
|
|
if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= reserved_size) {
|
|
|
|
ZSMMG(shared_segments)[i]->end = ZSMMG(shared_segments)[i]->size - reserved_size;
|
|
|
|
ZSMMG(reserved) = (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->end;
|
|
|
|
ZSMMG(reserved_size) = reserved_size;
|
|
|
|
} else {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
|
2019-04-01 07:27:11 +00:00
|
|
|
return ALLOC_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-15 13:35:58 +00:00
|
|
|
ZCG(locked) = 0;
|
2013-02-13 12:26:47 +00:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_shared_alloc_shutdown(void)
|
|
|
|
{
|
|
|
|
zend_shared_segment **tmp_shared_segments;
|
2018-10-25 16:24:39 +00:00
|
|
|
zend_shared_segment *shared_segments_buf[16];
|
2013-02-13 12:26:47 +00:00
|
|
|
size_t shared_segments_array_size;
|
|
|
|
zend_smm_shared_globals tmp_shared_globals;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
tmp_shared_globals = *smm_shared_globals;
|
|
|
|
smm_shared_globals = &tmp_shared_globals;
|
2013-02-22 06:56:05 +00:00
|
|
|
shared_segments_array_size = ZSMMG(shared_segments_count) * (S_H(segment_type_size)() + sizeof(void *));
|
2018-10-25 16:24:39 +00:00
|
|
|
if (shared_segments_array_size > 16) {
|
|
|
|
tmp_shared_segments = malloc(shared_segments_array_size);
|
|
|
|
} else {
|
|
|
|
tmp_shared_segments = shared_segments_buf;
|
|
|
|
}
|
2013-02-13 12:26:47 +00:00
|
|
|
copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)());
|
|
|
|
ZSMMG(shared_segments) = tmp_shared_segments;
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2013-02-13 12:26:47 +00:00
|
|
|
S_H(detach_segment)(ZSMMG(shared_segments)[i]);
|
|
|
|
}
|
2018-10-25 16:24:39 +00:00
|
|
|
if (shared_segments_array_size > 16) {
|
|
|
|
free(ZSMMG(shared_segments));
|
|
|
|
}
|
2013-02-13 12:26:47 +00:00
|
|
|
ZSMMG(shared_segments) = NULL;
|
|
|
|
g_shared_alloc_handler = NULL;
|
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
close(lock_file);
|
2019-06-27 14:01:13 +00:00
|
|
|
|
|
|
|
# ifdef ZTS
|
|
|
|
tsrm_mutex_free(zts_lock);
|
|
|
|
# endif
|
2013-02-13 12:26:47 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-03-15 07:49:33 +00:00
|
|
|
static size_t zend_shared_alloc_get_largest_free_block(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
size_t largest_block_size = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2019-04-01 07:27:11 +00:00
|
|
|
size_t block_size = ZSMMG(shared_segments)[i]->end - ZSMMG(shared_segments)[i]->pos;
|
2013-03-15 07:49:33 +00:00
|
|
|
|
|
|
|
if (block_size>largest_block_size) {
|
|
|
|
largest_block_size = block_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return largest_block_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MIN_FREE_MEMORY 64*1024
|
|
|
|
|
2013-02-19 14:04:40 +00:00
|
|
|
#define SHARED_ALLOC_FAILED() do { \
|
2022-09-03 09:23:10 +00:00
|
|
|
zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate %zu bytes (%zu bytes free)", size, ZSMMG(shared_free)); \
|
2013-03-15 07:49:33 +00:00
|
|
|
if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { \
|
2013-03-18 09:13:35 +00:00
|
|
|
ZSMMG(memory_exhausted) = 1; \
|
2013-03-15 07:49:33 +00:00
|
|
|
} \
|
2013-02-19 14:04:40 +00:00
|
|
|
} while (0)
|
2013-02-13 12:26:47 +00:00
|
|
|
|
|
|
|
void *zend_shared_alloc(size_t size)
|
|
|
|
{
|
2023-01-02 13:05:57 +00:00
|
|
|
ZEND_ASSERT(ZCG(locked));
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
int i;
|
2013-03-27 18:16:18 +00:00
|
|
|
unsigned int block_size = ZEND_ALIGNED_SIZE(size);
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2022-09-03 09:23:10 +00:00
|
|
|
if (UNEXPECTED(block_size < size)) {
|
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Possible integer overflow in shared memory allocation (%zu + %zu)", size, PLATFORM_ALIGNMENT);
|
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
|
|
|
|
SHARED_ALLOC_FAILED();
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2019-04-01 07:27:11 +00:00
|
|
|
if (ZSMMG(shared_segments)[i]->end - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
|
2013-03-27 18:16:18 +00:00
|
|
|
void *retval = (void *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);
|
2013-02-13 12:26:47 +00:00
|
|
|
|
|
|
|
ZSMMG(shared_segments)[i]->pos += block_size;
|
|
|
|
ZSMMG(shared_free) -= block_size;
|
2015-08-31 10:56:42 +00:00
|
|
|
ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */
|
2013-02-13 12:26:47 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SHARED_ALLOC_FAILED();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-06-23 17:09:48 +00:00
|
|
|
static zend_always_inline zend_ulong zend_rotr3(zend_ulong key)
|
|
|
|
{
|
|
|
|
return (key >> 3) | (key << ((sizeof(key) * 8) - 3));
|
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
int zend_shared_memdup_size(void *source, size_t size)
|
|
|
|
{
|
2014-03-28 19:34:49 +00:00
|
|
|
void *old_p;
|
2017-12-11 15:16:54 +00:00
|
|
|
zend_ulong key = (zend_ulong)source;
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2022-06-23 17:09:48 +00:00
|
|
|
key = zend_rotr3(key);
|
2017-12-11 15:16:54 +00:00
|
|
|
if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) {
|
2013-02-13 12:26:47 +00:00
|
|
|
/* we already duplicated this pointer */
|
|
|
|
return 0;
|
|
|
|
}
|
2018-09-26 14:05:49 +00:00
|
|
|
zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, source);
|
2013-02-13 12:26:47 +00:00
|
|
|
return ZEND_ALIGNED_SIZE(size);
|
|
|
|
}
|
|
|
|
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, bool get_xlat, bool set_xlat, bool free_source)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
2014-03-28 19:34:49 +00:00
|
|
|
void *old_p, *retval;
|
2018-09-26 14:05:49 +00:00
|
|
|
zend_ulong key;
|
|
|
|
|
|
|
|
if (get_xlat) {
|
|
|
|
key = (zend_ulong)source;
|
2022-06-23 17:09:48 +00:00
|
|
|
key = zend_rotr3(key);
|
2018-09-26 14:05:49 +00:00
|
|
|
if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) {
|
|
|
|
/* we already duplicated this pointer */
|
|
|
|
return old_p;
|
|
|
|
}
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
retval = ZCG(mem);
|
|
|
|
ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
|
2013-02-13 12:26:47 +00:00
|
|
|
memcpy(retval, source, size);
|
2018-09-26 14:05:49 +00:00
|
|
|
if (set_xlat) {
|
|
|
|
if (!get_xlat) {
|
|
|
|
key = (zend_ulong)source;
|
2022-06-23 17:09:48 +00:00
|
|
|
key = zend_rotr3(key);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, retval);
|
|
|
|
}
|
2013-02-13 12:26:47 +00:00
|
|
|
if (free_source) {
|
2014-03-31 12:09:45 +00:00
|
|
|
efree(source);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2018-09-26 14:05:49 +00:00
|
|
|
void *zend_shared_memdup_get_put_free(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 1, 1, 1);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_memdup_put_free(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 0, 1, 1);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_memdup_free(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 0, 0, 1);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_memdup_get_put(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 1, 1, 0);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_memdup_put(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 0, 1, 0);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_memdup(void *source, size_t size)
|
|
|
|
{
|
Added Inheritance Cache.
This is a new transparent technology that eliminates overhead of PHP class inheritance.
PHP classes are compiled and cached (by opcahce) separately, however their "linking" was done at run-time - on each request. The process of "linking" may involve a number of compatibility checks and borrowing methods/properties/constants form parent and traits. This takes significant time, but the result is the same on each request.
Inheritance Cache performs "linking" for unique set of all the depending classes (parent, interfaces, traits, property types, method types involved into compatibility checks) once and stores result in opcache shared memory. As a part of the this patch, I removed limitations for immutable classes (unresolved constants, typed properties and covariant type checks). So now all classes stored in opcache are "immutable". They may be lazily loaded into process memory, if necessary, but this usually occurs just once (on first linking).
The patch shows 8% improvement on Symphony "Hello World" app.
2021-02-09 19:53:57 +00:00
|
|
|
return _zend_shared_memdup(source, size, 0, 0, 0);
|
2018-09-26 14:05:49 +00:00
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
void zend_shared_alloc_safe_unlock(void)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
2013-02-15 13:35:58 +00:00
|
|
|
if (ZCG(locked)) {
|
2014-12-13 22:06:14 +00:00
|
|
|
zend_shared_alloc_unlock();
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
void zend_shared_alloc_lock(void)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
2022-12-22 11:38:20 +00:00
|
|
|
ZEND_ASSERT(!ZCG(locked));
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
#ifndef ZEND_WIN32
|
2019-02-12 07:15:16 +00:00
|
|
|
struct flock mem_write_lock;
|
|
|
|
|
|
|
|
mem_write_lock.l_type = F_WRLCK;
|
|
|
|
mem_write_lock.l_whence = SEEK_SET;
|
|
|
|
mem_write_lock.l_start = 0;
|
|
|
|
mem_write_lock.l_len = 1;
|
2013-02-15 11:08:51 +00:00
|
|
|
|
|
|
|
#ifdef ZTS
|
|
|
|
tsrm_mutex_lock(zts_lock);
|
|
|
|
#endif
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
#if 0
|
|
|
|
/* this will happen once per process, and will un-globalize mem_write_lock */
|
|
|
|
if (mem_write_lock.l_pid == -1) {
|
|
|
|
mem_write_lock.l_pid = getpid();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (fcntl(lock_file, F_SETLKW, &mem_write_lock) == -1) {
|
|
|
|
if (errno == EINTR) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
zend_shared_alloc_lock_win32();
|
|
|
|
#endif
|
|
|
|
|
2013-02-15 13:35:58 +00:00
|
|
|
ZCG(locked) = 1;
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
void zend_shared_alloc_unlock(void)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
2022-12-22 11:38:20 +00:00
|
|
|
ZEND_ASSERT(ZCG(locked));
|
|
|
|
|
2019-02-12 07:15:16 +00:00
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
struct flock mem_write_unlock;
|
|
|
|
|
|
|
|
mem_write_unlock.l_type = F_UNLCK;
|
|
|
|
mem_write_unlock.l_whence = SEEK_SET;
|
|
|
|
mem_write_unlock.l_start = 0;
|
|
|
|
mem_write_unlock.l_len = 1;
|
|
|
|
#endif
|
|
|
|
|
2013-02-15 13:35:58 +00:00
|
|
|
ZCG(locked) = 0;
|
2013-02-13 12:26:47 +00:00
|
|
|
|
|
|
|
#ifndef ZEND_WIN32
|
|
|
|
if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
2013-02-15 11:08:51 +00:00
|
|
|
#ifdef ZTS
|
|
|
|
tsrm_mutex_unlock(zts_lock);
|
|
|
|
#endif
|
2013-02-13 12:26:47 +00:00
|
|
|
#else
|
|
|
|
zend_shared_alloc_unlock_win32();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-05-06 20:46:49 +00:00
|
|
|
void zend_shared_alloc_init_xlat_table(void)
|
|
|
|
{
|
2017-06-29 06:24:07 +00:00
|
|
|
/* Prepare translation table */
|
|
|
|
zend_hash_init(&ZCG(xlat_table), 128, NULL, NULL, 0);
|
2015-05-06 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void zend_shared_alloc_destroy_xlat_table(void)
|
|
|
|
{
|
|
|
|
/* Destroy translation table */
|
|
|
|
zend_hash_destroy(&ZCG(xlat_table));
|
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
void zend_shared_alloc_clear_xlat_table(void)
|
|
|
|
{
|
2015-05-06 20:46:49 +00:00
|
|
|
zend_hash_clean(&ZCG(xlat_table));
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
|
2018-10-17 12:52:50 +00:00
|
|
|
uint32_t zend_shared_alloc_checkpoint_xlat_table(void)
|
|
|
|
{
|
|
|
|
return ZCG(xlat_table).nNumUsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_shared_alloc_restore_xlat_table(uint32_t checkpoint)
|
|
|
|
{
|
|
|
|
zend_hash_discard(&ZCG(xlat_table), checkpoint);
|
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
void zend_shared_alloc_register_xlat_entry(const void *old, const void *new)
|
|
|
|
{
|
2017-12-11 15:16:54 +00:00
|
|
|
zend_ulong key = (zend_ulong)old;
|
|
|
|
|
2022-06-23 17:09:48 +00:00
|
|
|
key = zend_rotr3(key);
|
2017-12-11 15:16:54 +00:00
|
|
|
zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, (void*)new);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *zend_shared_alloc_get_xlat_entry(const void *old)
|
|
|
|
{
|
2014-03-28 19:34:49 +00:00
|
|
|
void *retval;
|
2017-12-11 15:16:54 +00:00
|
|
|
zend_ulong key = (zend_ulong)old;
|
2013-02-13 12:26:47 +00:00
|
|
|
|
2022-06-23 17:09:48 +00:00
|
|
|
key = zend_rotr3(key);
|
2017-12-11 15:16:54 +00:00
|
|
|
if ((retval = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) == NULL) {
|
2013-02-13 12:26:47 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-03-28 19:34:49 +00:00
|
|
|
return retval;
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t zend_shared_alloc_get_free_memory(void)
|
|
|
|
{
|
|
|
|
return ZSMMG(shared_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_shared_alloc_save_state(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2013-02-13 12:26:47 +00:00
|
|
|
ZSMMG(shared_memory_state).positions[i] = ZSMMG(shared_segments)[i]->pos;
|
|
|
|
}
|
|
|
|
ZSMMG(shared_memory_state).shared_free = ZSMMG(shared_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zend_shared_alloc_restore_state(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2013-02-13 12:26:47 +00:00
|
|
|
ZSMMG(shared_segments)[i]->pos = ZSMMG(shared_memory_state).positions[i];
|
|
|
|
}
|
|
|
|
ZSMMG(shared_free) = ZSMMG(shared_memory_state).shared_free;
|
|
|
|
ZSMMG(memory_exhausted) = 0;
|
|
|
|
ZSMMG(wasted_shared_memory) = 0;
|
|
|
|
}
|
|
|
|
|
2013-02-25 12:06:38 +00:00
|
|
|
const char *zend_accel_get_shared_model(void)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
|
|
|
return g_shared_model;
|
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
void zend_accel_shared_protect(int mode)
|
2013-02-13 12:26:47 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_MPROTECT
|
|
|
|
int i;
|
|
|
|
|
2016-03-01 02:50:56 +00:00
|
|
|
if (!smm_shared_globals) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-13 12:26:47 +00:00
|
|
|
if (mode) {
|
|
|
|
mode = PROT_READ;
|
|
|
|
} else {
|
|
|
|
mode = PROT_READ|PROT_WRITE;
|
|
|
|
}
|
|
|
|
|
2013-02-22 06:56:05 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
2019-04-01 07:27:11 +00:00
|
|
|
mprotect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->end, mode);
|
2013-02-13 12:26:47 +00:00
|
|
|
}
|
2019-03-25 14:23:11 +00:00
|
|
|
#elif defined(ZEND_WIN32)
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!smm_shared_globals) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode) {
|
|
|
|
mode = PAGE_READONLY;
|
|
|
|
} else {
|
|
|
|
mode = PAGE_READWRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
|
|
|
DWORD oldProtect;
|
2019-04-11 13:42:22 +00:00
|
|
|
if (!VirtualProtect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->end, mode, &oldProtect)) {
|
2020-10-19 14:59:00 +00:00
|
|
|
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Failed to protect memory");
|
2019-03-25 14:23:11 +00:00
|
|
|
}
|
|
|
|
}
|
2013-02-13 12:26:47 +00:00
|
|
|
#endif
|
|
|
|
}
|
2016-02-24 20:46:11 +00:00
|
|
|
|
|
|
|
int zend_accel_in_shm(void *ptr)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2016-02-28 03:50:06 +00:00
|
|
|
if (!smm_shared_globals) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-24 20:46:11 +00:00
|
|
|
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
|
|
|
|
if ((char*)ptr >= (char*)ZSMMG(shared_segments)[i]->p &&
|
2019-04-01 07:27:11 +00:00
|
|
|
(char*)ptr < (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->end) {
|
2016-02-24 20:46:11 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|