1 /*
2 +----------------------------------------------------------------------+
3 | Zend OPcache |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Stanislav Malyshev <stas@zend.com> |
18 | Dmitry Stogov <dmitry@php.net> |
19 +----------------------------------------------------------------------+
20 */
21
22 #include <errno.h>
23 #include "ZendAccelerator.h"
24 #include "zend_shared_alloc.h"
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <fcntl.h>
29 #ifndef ZEND_WIN32
30 # include <sys/types.h>
31 # include <signal.h>
32 # include <sys/stat.h>
33 # include <stdio.h>
34 #endif
35
36 #ifdef HAVE_MPROTECT
37 # include "sys/mman.h"
38 #endif
39
40 #define SEM_FILENAME_PREFIX ".ZendSem."
41 #define S_H(s) g_shared_alloc_handler->s
42
43 /* True globals */
44 /* old/new mapping. We can use true global even for ZTS because its usage
45 is wrapped with exclusive lock anyway */
46 static const zend_shared_memory_handlers *g_shared_alloc_handler = NULL;
47 static const char *g_shared_model;
48 /* pointer to globals allocated in SHM and shared across processes */
49 zend_smm_shared_globals *smm_shared_globals;
50
51 #ifndef ZEND_WIN32
52 #ifdef ZTS
53 static MUTEX_T zts_lock;
54 #endif
55 int lock_file;
56 static char lockfile_name[MAXPATHLEN];
57 #endif
58
59 static const zend_shared_memory_handler_entry handler_table[] = {
60 #ifdef USE_MMAP
61 { "mmap", &zend_alloc_mmap_handlers },
62 #endif
63 #ifdef USE_SHM
64 { "shm", &zend_alloc_shm_handlers },
65 #endif
66 #ifdef USE_SHM_OPEN
67 { "posix", &zend_alloc_posix_handlers },
68 #endif
69 #ifdef ZEND_WIN32
70 { "win32", &zend_alloc_win32_handlers },
71 #endif
72 { NULL, NULL}
73 };
74
75 #ifndef ZEND_WIN32
zend_shared_alloc_create_lock(char * lockfile_path)76 void zend_shared_alloc_create_lock(char *lockfile_path)
77 {
78 int val;
79
80 #ifdef ZTS
81 zts_lock = tsrm_mutex_alloc();
82 #endif
83
84 snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX);
85 lock_file = mkstemp(lockfile_name);
86 fchmod(lock_file, 0666);
87
88 if (lock_file == -1) {
89 zend_accel_error(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
90 }
91 val = fcntl(lock_file, F_GETFD, 0);
92 val |= FD_CLOEXEC;
93 fcntl(lock_file, F_SETFD, val);
94
95 unlink(lockfile_name);
96 }
97 #endif
98
no_memory_bailout(size_t allocate_size,char * error)99 static void no_memory_bailout(size_t allocate_size, char *error)
100 {
101 zend_accel_error(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %zu bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno );
102 }
103
copy_shared_segments(void * to,void * from,int count,int size)104 static void copy_shared_segments(void *to, void *from, int count, int size)
105 {
106 zend_shared_segment **shared_segments_v = (zend_shared_segment **)to;
107 void *shared_segments_to_p = ((char *)to + count*(sizeof(void *)));
108 void *shared_segments_from_p = from;
109 int i;
110
111 for (i = 0; i < count; i++) {
112 shared_segments_v[i] = shared_segments_to_p;
113 memcpy(shared_segments_to_p, shared_segments_from_p, size);
114 shared_segments_to_p = ((char *)shared_segments_to_p + size);
115 shared_segments_from_p = ((char *)shared_segments_from_p + size);
116 }
117 }
118
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)119 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)
120 {
121 int res;
122 g_shared_alloc_handler = he->handler;
123 g_shared_model = he->name;
124 ZSMMG(shared_segments) = NULL;
125 ZSMMG(shared_segments_count) = 0;
126
127 res = S_H(create_segments)(requested_size, shared_segments_p, shared_segments_count, error_in);
128
129 if (res) {
130 /* this model works! */
131 return res;
132 }
133 if (*shared_segments_p) {
134 int i;
135 /* cleanup */
136 for (i = 0; i < *shared_segments_count; i++) {
137 if ((*shared_segments_p)[i]->p && (*shared_segments_p)[i]->p != (void *)-1) {
138 S_H(detach_segment)((*shared_segments_p)[i]);
139 }
140 }
141 free(*shared_segments_p);
142 *shared_segments_p = NULL;
143 }
144 g_shared_alloc_handler = NULL;
145 return ALLOC_FAILURE;
146 }
147
zend_shared_alloc_startup(size_t requested_size)148 int zend_shared_alloc_startup(size_t requested_size)
149 {
150 zend_shared_segment **tmp_shared_segments;
151 size_t shared_segments_array_size;
152 zend_smm_shared_globals tmp_shared_globals, *p_tmp_shared_globals;
153 char *error_in = NULL;
154 const zend_shared_memory_handler_entry *he;
155 int res = ALLOC_FAILURE;
156
157
158 /* shared_free must be valid before we call zend_shared_alloc()
159 * - make it temporarily point to a local variable
160 */
161 smm_shared_globals = &tmp_shared_globals;
162 ZSMMG(shared_free) = requested_size; /* goes to tmp_shared_globals.shared_free */
163
164 #ifndef ZEND_WIN32
165 zend_shared_alloc_create_lock(ZCG(accel_directives).lockfile_path);
166 #else
167 zend_shared_alloc_create_lock();
168 #endif
169
170 if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) {
171 char *model = ZCG(accel_directives).memory_model;
172 /* "cgi" is really "shm"... */
173 if (strncmp(ZCG(accel_directives).memory_model, "cgi", sizeof("cgi")) == 0) {
174 model = "shm";
175 }
176
177 for (he = handler_table; he->name; he++) {
178 if (strcmp(model, he->name) == 0) {
179 res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
180 if (res) {
181 /* this model works! */
182 }
183 break;
184 }
185 }
186 }
187
188 if (res == FAILED_REATTACHED) {
189 smm_shared_globals = NULL;
190 return res;
191 }
192 #if ENABLE_FILE_CACHE_FALLBACK
193 if (ALLOC_FALLBACK == res) {
194 return ALLOC_FALLBACK;
195 }
196 #endif
197
198 if (!g_shared_alloc_handler) {
199 /* try memory handlers in order */
200 for (he = handler_table; he->name; he++) {
201 res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
202 if (res) {
203 /* this model works! */
204 break;
205 }
206 }
207 }
208
209 if (!g_shared_alloc_handler) {
210 no_memory_bailout(requested_size, error_in);
211 return ALLOC_FAILURE;
212 }
213
214 if (res == SUCCESSFULLY_REATTACHED) {
215 return res;
216 }
217 #if ENABLE_FILE_CACHE_FALLBACK
218 if (ALLOC_FALLBACK == res) {
219 return ALLOC_FALLBACK;
220 }
221 #endif
222
223 shared_segments_array_size = ZSMMG(shared_segments_count) * S_H(segment_type_size)();
224
225 /* move shared_segments and shared_free to shared memory */
226 ZCG(locked) = 1; /* no need to perform a real lock at this point */
227 p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals));
228 if (!p_tmp_shared_globals) {
229 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
230 return ALLOC_FAILURE;
231 }
232 memset(p_tmp_shared_globals, 0, sizeof(zend_smm_shared_globals));
233
234 tmp_shared_segments = zend_shared_alloc(shared_segments_array_size + ZSMMG(shared_segments_count) * sizeof(void *));
235 if (!tmp_shared_segments) {
236 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
237 return ALLOC_FAILURE;
238 }
239
240 copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)());
241
242 *p_tmp_shared_globals = tmp_shared_globals;
243 smm_shared_globals = p_tmp_shared_globals;
244
245 free(ZSMMG(shared_segments));
246 ZSMMG(shared_segments) = tmp_shared_segments;
247
248 ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count));
249 if (!ZSMMG(shared_memory_state).positions) {
250 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
251 return ALLOC_FAILURE;
252 }
253
254 ZCG(locked) = 0;
255
256 return res;
257 }
258
zend_shared_alloc_shutdown(void)259 void zend_shared_alloc_shutdown(void)
260 {
261 zend_shared_segment **tmp_shared_segments;
262 zend_shared_segment *shared_segments_buf[16];
263 size_t shared_segments_array_size;
264 zend_smm_shared_globals tmp_shared_globals;
265 int i;
266
267 tmp_shared_globals = *smm_shared_globals;
268 smm_shared_globals = &tmp_shared_globals;
269 shared_segments_array_size = ZSMMG(shared_segments_count) * (S_H(segment_type_size)() + sizeof(void *));
270 if (shared_segments_array_size > 16) {
271 tmp_shared_segments = malloc(shared_segments_array_size);
272 } else {
273 tmp_shared_segments = shared_segments_buf;
274 }
275 copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)());
276 ZSMMG(shared_segments) = tmp_shared_segments;
277
278 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
279 S_H(detach_segment)(ZSMMG(shared_segments)[i]);
280 }
281 if (shared_segments_array_size > 16) {
282 free(ZSMMG(shared_segments));
283 }
284 ZSMMG(shared_segments) = NULL;
285 g_shared_alloc_handler = NULL;
286 #ifndef ZEND_WIN32
287 close(lock_file);
288
289 # ifdef ZTS
290 tsrm_mutex_free(zts_lock);
291 # endif
292 #endif
293 }
294
zend_shared_alloc_get_largest_free_block(void)295 static size_t zend_shared_alloc_get_largest_free_block(void)
296 {
297 int i;
298 size_t largest_block_size = 0;
299
300 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
301 size_t block_size = ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos;
302
303 if (block_size>largest_block_size) {
304 largest_block_size = block_size;
305 }
306 }
307 return largest_block_size;
308 }
309
310 #define MIN_FREE_MEMORY 64*1024
311
312 #define SHARED_ALLOC_FAILED() do { \
313 zend_accel_error(ACCEL_LOG_WARNING, "Not enough free shared space to allocate "ZEND_LONG_FMT" bytes ("ZEND_LONG_FMT" bytes free)", (zend_long)size, (zend_long)ZSMMG(shared_free)); \
314 if (zend_shared_alloc_get_largest_free_block() < MIN_FREE_MEMORY) { \
315 ZSMMG(memory_exhausted) = 1; \
316 } \
317 } while (0)
318
zend_shared_alloc(size_t size)319 void *zend_shared_alloc(size_t size)
320 {
321 int i;
322 unsigned int block_size = ZEND_ALIGNED_SIZE(size);
323
324 #if 1
325 if (!ZCG(locked)) {
326 zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
327 }
328 #endif
329 if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
330 SHARED_ALLOC_FAILED();
331 return NULL;
332 }
333 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
334 if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
335 void *retval = (void *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);
336
337 ZSMMG(shared_segments)[i]->pos += block_size;
338 ZSMMG(shared_free) -= block_size;
339 ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */
340 return retval;
341 }
342 }
343 SHARED_ALLOC_FAILED();
344 return NULL;
345 }
346
zend_shared_memdup_size(void * source,size_t size)347 int zend_shared_memdup_size(void *source, size_t size)
348 {
349 void *old_p;
350 zend_ulong key = (zend_ulong)source;
351
352 key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/
353 if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) {
354 /* we already duplicated this pointer */
355 return 0;
356 }
357 zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, source);
358 return ZEND_ALIGNED_SIZE(size);
359 }
360
_zend_shared_memdup(void * source,size_t size,zend_bool arena,zend_bool get_xlat,zend_bool set_xlat,zend_bool free_source)361 static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, zend_bool arena, zend_bool get_xlat, zend_bool set_xlat, zend_bool free_source)
362 {
363 void *old_p, *retval;
364 zend_ulong key;
365
366 if (get_xlat) {
367 key = (zend_ulong)source;
368 key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/
369 if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) {
370 /* we already duplicated this pointer */
371 return old_p;
372 }
373 }
374 if (arena) {
375 retval = ZCG(arena_mem);
376 ZCG(arena_mem) = (void*)(((char*)ZCG(arena_mem)) + ZEND_ALIGNED_SIZE(size));
377 } else {
378 retval = ZCG(mem);
379 ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
380 }
381 memcpy(retval, source, size);
382 if (set_xlat) {
383 if (!get_xlat) {
384 key = (zend_ulong)source;
385 key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/
386 }
387 zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, retval);
388 }
389 if (free_source) {
390 efree(source);
391 }
392 return retval;
393 }
394
zend_shared_memdup_get_put_free(void * source,size_t size)395 void *zend_shared_memdup_get_put_free(void *source, size_t size)
396 {
397 return _zend_shared_memdup(source, size, 0, 1, 1, 1);
398 }
399
zend_shared_memdup_put_free(void * source,size_t size)400 void *zend_shared_memdup_put_free(void *source, size_t size)
401 {
402 return _zend_shared_memdup(source, size, 0, 0, 1, 1);
403 }
404
zend_shared_memdup_free(void * source,size_t size)405 void *zend_shared_memdup_free(void *source, size_t size)
406 {
407 return _zend_shared_memdup(source, size, 0, 0, 0, 1);
408 }
409
zend_shared_memdup_get_put(void * source,size_t size)410 void *zend_shared_memdup_get_put(void *source, size_t size)
411 {
412 return _zend_shared_memdup(source, size, 0, 1, 1, 0);
413 }
414
zend_shared_memdup_put(void * source,size_t size)415 void *zend_shared_memdup_put(void *source, size_t size)
416 {
417 return _zend_shared_memdup(source, size, 0, 0, 1, 0);
418 }
419
zend_shared_memdup(void * source,size_t size)420 void *zend_shared_memdup(void *source, size_t size)
421 {
422 return _zend_shared_memdup(source, size, 0, 0, 0, 0);
423 }
424
zend_shared_memdup_arena_put(void * source,size_t size)425 void *zend_shared_memdup_arena_put(void *source, size_t size)
426 {
427 return _zend_shared_memdup(source, size, 1, 0, 1, 0);
428 }
429
zend_shared_memdup_arena(void * source,size_t size)430 void *zend_shared_memdup_arena(void *source, size_t size)
431 {
432 return _zend_shared_memdup(source, size, 1, 0, 0, 0);
433 }
434
zend_shared_alloc_safe_unlock(void)435 void zend_shared_alloc_safe_unlock(void)
436 {
437 if (ZCG(locked)) {
438 zend_shared_alloc_unlock();
439 }
440 }
441
zend_shared_alloc_lock(void)442 void zend_shared_alloc_lock(void)
443 {
444 #ifndef ZEND_WIN32
445 struct flock mem_write_lock;
446
447 mem_write_lock.l_type = F_WRLCK;
448 mem_write_lock.l_whence = SEEK_SET;
449 mem_write_lock.l_start = 0;
450 mem_write_lock.l_len = 1;
451
452 #ifdef ZTS
453 tsrm_mutex_lock(zts_lock);
454 #endif
455
456 #if 0
457 /* this will happen once per process, and will un-globalize mem_write_lock */
458 if (mem_write_lock.l_pid == -1) {
459 mem_write_lock.l_pid = getpid();
460 }
461 #endif
462
463 while (1) {
464 if (fcntl(lock_file, F_SETLKW, &mem_write_lock) == -1) {
465 if (errno == EINTR) {
466 continue;
467 }
468 zend_accel_error(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
469 }
470 break;
471 }
472 #else
473 zend_shared_alloc_lock_win32();
474 #endif
475
476 ZCG(locked) = 1;
477 }
478
zend_shared_alloc_unlock(void)479 void zend_shared_alloc_unlock(void)
480 {
481 #ifndef ZEND_WIN32
482 struct flock mem_write_unlock;
483
484 mem_write_unlock.l_type = F_UNLCK;
485 mem_write_unlock.l_whence = SEEK_SET;
486 mem_write_unlock.l_start = 0;
487 mem_write_unlock.l_len = 1;
488 #endif
489
490 ZCG(locked) = 0;
491
492 #ifndef ZEND_WIN32
493 if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) {
494 zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
495 }
496 #ifdef ZTS
497 tsrm_mutex_unlock(zts_lock);
498 #endif
499 #else
500 zend_shared_alloc_unlock_win32();
501 #endif
502 }
503
zend_shared_alloc_init_xlat_table(void)504 void zend_shared_alloc_init_xlat_table(void)
505 {
506 /* Prepare translation table */
507 zend_hash_init(&ZCG(xlat_table), 128, NULL, NULL, 0);
508 }
509
zend_shared_alloc_destroy_xlat_table(void)510 void zend_shared_alloc_destroy_xlat_table(void)
511 {
512 /* Destroy translation table */
513 zend_hash_destroy(&ZCG(xlat_table));
514 }
515
zend_shared_alloc_clear_xlat_table(void)516 void zend_shared_alloc_clear_xlat_table(void)
517 {
518 zend_hash_clean(&ZCG(xlat_table));
519 }
520
zend_shared_alloc_checkpoint_xlat_table(void)521 uint32_t zend_shared_alloc_checkpoint_xlat_table(void)
522 {
523 return ZCG(xlat_table).nNumUsed;
524 }
525
zend_shared_alloc_restore_xlat_table(uint32_t checkpoint)526 void zend_shared_alloc_restore_xlat_table(uint32_t checkpoint)
527 {
528 zend_hash_discard(&ZCG(xlat_table), checkpoint);
529 }
530
zend_shared_alloc_register_xlat_entry(const void * old,const void * new)531 void zend_shared_alloc_register_xlat_entry(const void *old, const void *new)
532 {
533 zend_ulong key = (zend_ulong)old;
534
535 key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/
536 zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, (void*)new);
537 }
538
zend_shared_alloc_get_xlat_entry(const void * old)539 void *zend_shared_alloc_get_xlat_entry(const void *old)
540 {
541 void *retval;
542 zend_ulong key = (zend_ulong)old;
543
544 key = (key >> 3) | (key << ((sizeof(key) * 8) - 3)); /* key = _rotr(key, 3);*/
545 if ((retval = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) == NULL) {
546 return NULL;
547 }
548 return retval;
549 }
550
zend_shared_alloc_get_free_memory(void)551 size_t zend_shared_alloc_get_free_memory(void)
552 {
553 return ZSMMG(shared_free);
554 }
555
zend_shared_alloc_save_state(void)556 void zend_shared_alloc_save_state(void)
557 {
558 int i;
559
560 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
561 ZSMMG(shared_memory_state).positions[i] = ZSMMG(shared_segments)[i]->pos;
562 }
563 ZSMMG(shared_memory_state).shared_free = ZSMMG(shared_free);
564 }
565
zend_shared_alloc_restore_state(void)566 void zend_shared_alloc_restore_state(void)
567 {
568 int i;
569
570 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
571 ZSMMG(shared_segments)[i]->pos = ZSMMG(shared_memory_state).positions[i];
572 }
573 ZSMMG(shared_free) = ZSMMG(shared_memory_state).shared_free;
574 ZSMMG(memory_exhausted) = 0;
575 ZSMMG(wasted_shared_memory) = 0;
576 }
577
zend_accel_get_shared_model(void)578 const char *zend_accel_get_shared_model(void)
579 {
580 return g_shared_model;
581 }
582
zend_accel_shared_protect(int mode)583 void zend_accel_shared_protect(int mode)
584 {
585 #ifdef HAVE_MPROTECT
586 int i;
587
588 if (!smm_shared_globals) {
589 return;
590 }
591
592 if (mode) {
593 mode = PROT_READ;
594 } else {
595 mode = PROT_READ|PROT_WRITE;
596 }
597
598 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
599 mprotect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->size, mode);
600 }
601 #elif defined(ZEND_WIN32)
602 int i;
603
604 if (!smm_shared_globals) {
605 return;
606 }
607
608 if (mode) {
609 mode = PAGE_READONLY;
610 } else {
611 mode = PAGE_READWRITE;
612 }
613
614 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
615 DWORD oldProtect;
616 if (!VirtualProtect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->size, mode, &oldProtect)) {
617 zend_accel_error(ACCEL_LOG_ERROR, "Failed to protect memory");
618 }
619 }
620 #endif
621 }
622
zend_accel_in_shm(void * ptr)623 int zend_accel_in_shm(void *ptr)
624 {
625 int i;
626
627 if (!smm_shared_globals) {
628 return 0;
629 }
630
631 for (i = 0; i < ZSMMG(shared_segments_count); i++) {
632 if ((char*)ptr >= (char*)ZSMMG(shared_segments)[i]->p &&
633 (char*)ptr < (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->size) {
634 return 1;
635 }
636 }
637 return 0;
638 }
639