Skip to content

Commit 2417094

Browse files
committed
Allow building opcache statically
Opcache is both a Zend extension and a PHP module. When Opcache is built statically, the engine will attempt to initialize it as a PHP module, but will not initialize the Zend extension. Here I make Opcache a two-way hybrid extension [1] so that initializing it as a PHP module also initializes the Zend extension. [1] https://www.phpinternalsbook.com/php7/extensions_design/zend_extensions.html#hybrid-extensions
1 parent e2b47d8 commit 2417094

File tree

6 files changed

+72
-11
lines changed

6 files changed

+72
-11
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "zend_extensions.h"
2626
#include "zend_compile.h"
2727
#include "ZendAccelerator.h"
28+
#include "zend_modules.h"
2829
#include "zend_persist.h"
2930
#include "zend_shared_alloc.h"
3031
#include "zend_accelerator_module.h"
@@ -100,7 +101,13 @@ typedef int gid_t;
100101

101102
#include "zend_simd.h"
102103

104+
#ifdef COMPILE_DL_OPCACHE
103105
ZEND_EXTENSION();
106+
ZEND_EXT_API zend_extension zend_extension_entry;
107+
#define opcache_extension_entry zend_extension_entry
108+
#else
109+
zend_extension opcache_extension_entry;
110+
#endif
104111

105112
#ifndef ZTS
106113
zend_accel_globals accel_globals;
@@ -118,6 +125,7 @@ zend_accel_shared_globals *accel_shared_globals = NULL;
118125
#ifdef ZEND_WIN32
119126
char accel_uname_id[32];
120127
#endif
128+
bool accel_starting = false;
121129
bool accel_startup_ok = false;
122130
static const char *zps_failure_reason = NULL;
123131
const char *zps_api_failure_reason = NULL;
@@ -3154,8 +3162,21 @@ static void accel_move_code_to_huge_pages(void)
31543162
# endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */
31553163
#endif /* HAVE_HUGE_CODE_PAGES */
31563164

3165+
void start_accel_extension(void)
3166+
{
3167+
if (accel_starting) {
3168+
return;
3169+
}
3170+
3171+
accel_starting = true;
3172+
3173+
zend_register_extension(&opcache_extension_entry, NULL);
3174+
}
3175+
31573176
static int accel_startup(zend_extension *extension)
31583177
{
3178+
accel_starting = true;
3179+
31593180
#ifdef ZTS
31603181
accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor);
31613182
#else
@@ -3172,12 +3193,15 @@ static int accel_startup(zend_extension *extension)
31723193
# endif
31733194
#endif
31743195

3175-
if (start_accel_module() == FAILURE) {
3196+
zend_module_entry *module = start_accel_module();
3197+
if (module == NULL) {
31763198
accel_startup_ok = false;
31773199
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");
31783200
return FAILURE;
31793201
}
31803202

3203+
accel_register_ini_entries(module);
3204+
31813205
#ifdef ZEND_WIN32
31823206
if (UNEXPECTED(accel_gen_uname_id() == FAILURE)) {
31833207
zps_startup_failure("Unable to get user name", NULL, accelerator_remove_cb);
@@ -5037,7 +5061,11 @@ static void accel_activate(void) {
50375061
}
50385062
}
50395063

5064+
#ifdef COMPILE_DL_OPCACHE
50405065
ZEND_EXT_API zend_extension zend_extension_entry = {
5066+
#else
5067+
zend_extension opcache_extension_entry = {
5068+
#endif
50415069
ACCELERATOR_PRODUCT_NAME, /* name */
50425070
PHP_VERSION, /* version */
50435071
"Zend Technologies", /* author */

ext/opcache/ZendAccelerator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ extern const char *zps_api_failure_reason;
314314

315315
BEGIN_EXTERN_C()
316316

317+
void start_accel_extension(void);
317318
void accel_shutdown(void);
318319
ZEND_RINIT_FUNCTION(zend_accelerator);
319320
zend_result accel_post_deactivate(void);
@@ -336,6 +337,10 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str);
336337

337338
uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name);
338339

340+
#ifndef COMPILE_DL_OPCACHE
341+
extern zend_extension opcache_extension_entry;
342+
#endif
343+
339344
END_EXTERN_C()
340345

341346
/* memory write protection */

ext/opcache/config.m4

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ PHP_ARG_WITH([capstone],
2626
[no])
2727

2828
if test "$PHP_OPCACHE" != "no"; then
29-
dnl Always build as shared extension.
30-
ext_shared=yes
31-
3229
AS_VAR_IF([PHP_HUGE_CODE_PAGES], [yes],
3330
[AC_DEFINE([HAVE_HUGE_CODE_PAGES], [1],
3431
[Define to 1 to enable copying PHP CODE pages into HUGE PAGES.])])

ext/opcache/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ if (PHP_OPCACHE != "no") {
1515
zend_persist_calc.c \
1616
zend_file_cache.c \
1717
zend_shared_alloc.c \
18-
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
18+
shared_alloc_win32.c", PHP_OPCACHE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
1919

2020
ADD_EXTENSION_DEP('opcache', 'date');
2121
ADD_EXTENSION_DEP('opcache', 'hash');

ext/opcache/zend_accelerator_module.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "ZendAccelerator.h"
2626
#include "zend_API.h"
2727
#include "zend_closures.h"
28+
#include "zend_extensions.h"
29+
#include "zend_modules.h"
2830
#include "zend_shared_alloc.h"
2931
#include "zend_accelerator_blacklist.h"
3032
#include "php_ini.h"
@@ -55,6 +57,9 @@
5557
))
5658
#define TOKENTOSTR(X) #X
5759

60+
static zend_module_entry *accel_module_loaded = NULL;
61+
zend_module_entry opcache_module_entry;
62+
5863
static zif_handler orig_file_exists = NULL;
5964
static zif_handler orig_is_file = NULL;
6065
static zif_handler orig_is_readable = NULL;
@@ -405,13 +410,19 @@ static ZEND_NAMED_FUNCTION(accel_is_readable)
405410

406411
static ZEND_MINIT_FUNCTION(zend_accelerator)
407412
{
408-
(void)type; /* keep the compiler happy */
413+
accel_module_loaded = zend_hash_str_find_ptr_lc(&module_registry,
414+
opcache_module_entry.name, strlen(opcache_module_entry.name));
409415

410-
REGISTER_INI_ENTRIES();
416+
start_accel_extension();
411417

412418
return SUCCESS;
413419
}
414420

421+
void accel_register_ini_entries(zend_module_entry *module)
422+
{
423+
zend_register_ini_entries_ex(ini_entries, module->module_number, module->type);
424+
}
425+
415426
void zend_accel_override_file_functions(void)
416427
{
417428
zend_function *old_function;
@@ -554,7 +565,7 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS)
554565
DISPLAY_INI_ENTRIES();
555566
}
556567

557-
static zend_module_entry accel_module_entry = {
568+
zend_module_entry opcache_module_entry = {
558569
STANDARD_MODULE_HEADER,
559570
ACCELERATOR_PRODUCT_NAME,
560571
ext_functions,
@@ -569,9 +580,22 @@ static zend_module_entry accel_module_entry = {
569580
STANDARD_MODULE_PROPERTIES_EX
570581
};
571582

572-
int start_accel_module(void)
583+
zend_module_entry *start_accel_module(void)
573584
{
574-
return zend_startup_module(&accel_module_entry);
585+
if (accel_module_loaded) {
586+
return accel_module_loaded;
587+
}
588+
589+
accel_module_loaded = zend_register_internal_module(&opcache_module_entry);
590+
if (!accel_module_loaded) {
591+
return NULL;
592+
}
593+
594+
if (zend_startup_module_ex(accel_module_loaded) == FAILURE) {
595+
return NULL;
596+
}
597+
598+
return accel_module_loaded;
575599
}
576600

577601
/* {{{ Get the scripts which are accelerated by ZendAccelerator */

ext/opcache/zend_accelerator_module.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,14 @@
2222
#ifndef ZEND_ACCELERATOR_MODULE_H
2323
#define ZEND_ACCELERATOR_MODULE_H
2424

25-
int start_accel_module(void);
25+
#include "Zend/zend_modules.h"
26+
27+
#define phpext_opcache_ptr &opcache_module_entry
28+
extern zend_module_entry opcache_module_entry;
29+
30+
zend_module_entry *start_accel_module(void);
31+
32+
void accel_register_ini_entries(zend_module_entry *module);
2633

2734
void zend_accel_override_file_functions(void);
2835

0 commit comments

Comments
 (0)