zend_shared_alloc.c 17 KB

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