xref: /php-src/ext/opcache/ZendAccelerator.h (revision 1bae61a4)
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 
22 #ifndef ZEND_ACCELERATOR_H
23 #define ZEND_ACCELERATOR_H
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define ACCELERATOR_PRODUCT_NAME	"Zend OPcache"
30 /* 2 - added Profiler support, on 20010712 */
31 /* 3 - added support for Optimizer's encoded-only-files mode */
32 /* 4 - works with the new Optimizer, that supports the file format with licenses */
33 /* 5 - API 4 didn't really work with the license-enabled file format.  v5 does. */
34 /* 6 - Monitor was removed from ZendPlatform.so, to a module of its own */
35 /* 7 - Optimizer was embedded into Accelerator */
36 /* 8 - Standalone Open Source Zend OPcache */
37 #define ACCELERATOR_API_NO 8
38 
39 #if ZEND_WIN32
40 # include "zend_config.w32.h"
41 #else
42 #include "zend_config.h"
43 # include <sys/time.h>
44 # include <sys/resource.h>
45 #endif
46 
47 #if HAVE_UNISTD_H
48 # include "unistd.h"
49 #endif
50 
51 #include "zend_extensions.h"
52 #include "zend_compile.h"
53 
54 #include "Optimizer/zend_optimizer.h"
55 #include "zend_accelerator_hash.h"
56 #include "zend_accelerator_debug.h"
57 
58 #ifndef PHPAPI
59 # ifdef ZEND_WIN32
60 #  define PHPAPI __declspec(dllimport)
61 # else
62 #  define PHPAPI
63 # endif
64 #endif
65 
66 #ifndef ZEND_EXT_API
67 # ifdef ZEND_WIN32
68 #  define ZEND_EXT_API __declspec(dllexport)
69 # elif defined(__GNUC__) && __GNUC__ >= 4
70 #  define ZEND_EXT_API __attribute__ ((visibility("default")))
71 # else
72 #  define ZEND_EXT_API
73 # endif
74 #endif
75 
76 #ifdef ZEND_WIN32
77 # ifndef MAXPATHLEN
78 #  include "win32/ioutil.h"
79 #  define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
80 # endif
81 # include <direct.h>
82 #else
83 # ifndef MAXPATHLEN
84 #  define MAXPATHLEN     4096
85 # endif
86 # include <sys/param.h>
87 #endif
88 
89 /*** file locking ***/
90 #ifndef ZEND_WIN32
91 extern int lock_file;
92 #endif
93 
94 #if defined(ZEND_WIN32)
95 # define ENABLE_FILE_CACHE_FALLBACK 1
96 #else
97 # define ENABLE_FILE_CACHE_FALLBACK 0
98 #endif
99 
100 #if ZEND_WIN32
101 typedef unsigned __int64 accel_time_t;
102 #else
103 typedef time_t accel_time_t;
104 #endif
105 
106 typedef enum _zend_accel_restart_reason {
107 	ACCEL_RESTART_OOM,    /* restart because of out of memory */
108 	ACCEL_RESTART_HASH,   /* restart because of hash overflow */
109 	ACCEL_RESTART_USER    /* restart scheduled by opcache_reset() */
110 } zend_accel_restart_reason;
111 
112 typedef struct _zend_early_binding {
113 	zend_string *lcname;
114 	zend_string *rtd_key;
115 	zend_string *lc_parent_name;
116 	uint32_t cache_slot;
117 } zend_early_binding;
118 
119 typedef struct _zend_persistent_script {
120 	zend_script    script;
121 	zend_long      compiler_halt_offset;   /* position of __HALT_COMPILER or -1 */
122 	int            ping_auto_globals_mask; /* which autoglobals are used by the script */
123 	accel_time_t   timestamp;              /* the script modification time */
124 	bool      corrupted;
125 	bool      is_phar;
126 	bool      empty;
127 	uint32_t       num_warnings;
128 	uint32_t       num_early_bindings;
129 	zend_error_info **warnings;
130 	zend_early_binding *early_bindings;
131 
132 	void          *mem;                    /* shared memory area used by script structures */
133 	size_t         size;                   /* size of used shared memory */
134 
135 	struct zend_persistent_script_dynamic_members {
136 		time_t       last_used;
137 		zend_ulong   hits;
138 		unsigned int memory_consumption;
139 		time_t       revalidate;
140 	} dynamic_members;
141 } zend_persistent_script;
142 
143 typedef struct _zend_accel_directives {
144 	zend_long           memory_consumption;
145 	zend_long           max_accelerated_files;
146 	double         max_wasted_percentage;
147 	char          *user_blacklist_filename;
148 	zend_long           force_restart_timeout;
149 	bool      use_cwd;
150 	bool      ignore_dups;
151 	bool      validate_timestamps;
152 	bool      revalidate_path;
153 	bool      save_comments;
154 	bool      record_warnings;
155 	bool      protect_memory;
156 	bool      file_override_enabled;
157 	bool      enable_cli;
158 	bool      validate_permission;
159 #ifndef ZEND_WIN32
160 	bool      validate_root;
161 #endif
162 	zend_ulong     revalidate_freq;
163 	zend_ulong     file_update_protection;
164 	char          *error_log;
165 #ifdef ZEND_WIN32
166 	char          *mmap_base;
167 #endif
168 	char          *memory_model;
169 	zend_long           log_verbosity_level;
170 
171 	zend_long           optimization_level;
172 	zend_long           opt_debug_level;
173 	zend_long           max_file_size;
174 	zend_long           interned_strings_buffer;
175 	char          *restrict_api;
176 #ifndef ZEND_WIN32
177 	char          *lockfile_path;
178 #endif
179 	char          *file_cache;
180 	bool      file_cache_only;
181 	bool      file_cache_consistency_checks;
182 #if ENABLE_FILE_CACHE_FALLBACK
183 	bool      file_cache_fallback;
184 #endif
185 #ifdef HAVE_HUGE_CODE_PAGES
186 	bool      huge_code_pages;
187 #endif
188 	char *preload;
189 #ifndef ZEND_WIN32
190 	char *preload_user;
191 #endif
192 #ifdef ZEND_WIN32
193 	char *cache_id;
194 #endif
195 } zend_accel_directives;
196 
197 typedef struct _zend_accel_globals {
198 	bool               counted;   /* the process uses shared memory */
199 	bool               enabled;
200 	bool               locked;    /* thread obtained exclusive lock */
201 	bool               accelerator_enabled; /* accelerator enabled for current request */
202 	bool               pcre_reseted;
203 	zend_accel_directives   accel_directives;
204 	zend_string            *cwd;                  /* current working directory or NULL */
205 	zend_string            *include_path;         /* current value of "include_path" directive */
206 	char                    include_path_key[32]; /* key of current "include_path" */
207 	char                    cwd_key[32];          /* key of current working directory */
208 	int                     include_path_key_len;
209 	bool                    include_path_check;
210 	int                     cwd_key_len;
211 	bool                    cwd_check;
212 	int                     auto_globals_mask;
213 	time_t                  request_time;
214 	time_t                  last_restart_time; /* used to synchronize SHM and in-process caches */
215 	HashTable               xlat_table;
216 #ifndef ZEND_WIN32
217 	zend_ulong              root_hash;
218 #endif
219 	/* preallocated shared-memory block to save current script */
220 	void                   *mem;
221 	zend_persistent_script *current_persistent_script;
222 	/* cache to save hash lookup on the same INCLUDE opcode */
223 	const zend_op          *cache_opline;
224 	zend_persistent_script *cache_persistent_script;
225 	/* preallocated buffer for keys */
226 	zend_string             key;
227 	char                    _key[MAXPATHLEN * 8];
228 } zend_accel_globals;
229 
230 typedef struct _zend_string_table {
231 	uint32_t     nTableMask;
232 	uint32_t     nNumOfElements;
233 	zend_string *start;
234 	zend_string *top;
235 	zend_string *end;
236 	zend_string *saved_top;
237 } zend_string_table;
238 
239 typedef uint32_t zend_string_table_pos_t;
240 
241 #define ZEND_STRING_TABLE_POS_MAX UINT32_MAX
242 #define ZEND_STRING_TABLE_POS_ALIGNMENT 8
243 
244 typedef struct _zend_accel_shared_globals {
245 	/* Cache Data Structures */
246 	zend_ulong   hits;
247 	zend_ulong   misses;
248 	zend_ulong   blacklist_misses;
249 	zend_ulong   oom_restarts;     /* number of restarts because of out of memory */
250 	zend_ulong   hash_restarts;    /* number of restarts because of hash overflow */
251 	zend_ulong   manual_restarts;  /* number of restarts scheduled by opcache_reset() */
252 	zend_accel_hash hash;             /* hash table for cached scripts */
253 
254 	size_t map_ptr_last;
255 
256 	/* Directives & Maintenance */
257 	time_t          start_time;
258 	time_t          last_restart_time;
259 	time_t          force_restart_time;
260 	bool       accelerator_enabled;
261 	bool       restart_pending;
262 	zend_accel_restart_reason restart_reason;
263 	bool       cache_status_before_restart;
264 #ifdef ZEND_WIN32
265 	LONGLONG   mem_usage;
266 	LONGLONG   restart_in;
267 #endif
268 	bool       restart_in_progress;
269 	bool       jit_counters_stopped;
270 
271 	/* Preloading */
272 	zend_persistent_script *preload_script;
273 	zend_persistent_script **saved_scripts;
274 
275 	/* uninitialized HashTable Support */
276 	uint32_t uninitialized_bucket[-HT_MIN_MASK];
277 
278 	/* Tracing JIT */
279 	void *jit_traces;
280 	const void **jit_exit_groups;
281 
282 	/* Interned Strings Support (must be the last element) */
283 	zend_string_table interned_strings;
284 } zend_accel_shared_globals;
285 
286 #ifdef ZEND_WIN32
287 extern char accel_uname_id[32];
288 #endif
289 extern bool accel_startup_ok;
290 extern bool file_cache_only;
291 #if ENABLE_FILE_CACHE_FALLBACK
292 extern bool fallback_process;
293 #endif
294 
295 extern zend_accel_shared_globals *accel_shared_globals;
296 #define ZCSG(element)   (accel_shared_globals->element)
297 
298 #ifdef ZTS
299 # define ZCG(v)	ZEND_TSRMG(accel_globals_id, zend_accel_globals *, v)
300 extern int accel_globals_id;
301 # ifdef COMPILE_DL_OPCACHE
302 ZEND_TSRMLS_CACHE_EXTERN()
303 # endif
304 #else
305 # define ZCG(v) (accel_globals.v)
306 extern zend_accel_globals accel_globals;
307 #endif
308 
309 extern const char *zps_api_failure_reason;
310 
311 BEGIN_EXTERN_C()
312 
313 void accel_shutdown(void);
314 zend_result  accel_activate(INIT_FUNC_ARGS);
315 zend_result accel_post_deactivate(void);
316 void zend_accel_schedule_restart(zend_accel_restart_reason reason);
317 void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
318 accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size);
319 zend_result validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
320 zend_result validate_timestamp_and_record_ex(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
321 zend_result zend_accel_invalidate(zend_string *filename, bool force);
322 zend_result accelerator_shm_read_lock(void);
323 void accelerator_shm_read_unlock(void);
324 
325 zend_string *accel_make_persistent_key(zend_string *path);
326 zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
327 
328 #define IS_ACCEL_INTERNED(str) \
329 	((char*)(str) >= (char*)ZCSG(interned_strings).start && (char*)(str) < (char*)ZCSG(interned_strings).top)
330 
331 zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str);
332 
333 uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name);
334 
335 END_EXTERN_C()
336 
337 /* memory write protection */
338 #define SHM_PROTECT() \
339 	do { \
340 		if (ZCG(accel_directives).protect_memory) { \
341 			zend_accel_shared_protect(true); \
342 		} \
343 	} while (0)
344 
345 #define SHM_UNPROTECT() \
346 	do { \
347 		if (ZCG(accel_directives).protect_memory) { \
348 			zend_accel_shared_protect(false); \
349 		} \
350 	} while (0)
351 
352 #endif /* ZEND_ACCELERATOR_H */
353