Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fdf1e73

Browse files
add gc and shutdown callbacks
1 parent fd47cd8 commit fdf1e73

12 files changed

+324
-20
lines changed

‎Zend/zend_alloc.c‎

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "zend_multiply.h"
5959
#include "zend_bitset.h"
6060
#include "zend_mmap.h"
61+
#include "zend_portability.h"
6162
#include <signal.h>
6263

6364
#ifdef HAVE_UNISTD_H
@@ -273,11 +274,15 @@ struct _zend_mm_heap {
273274
void *(*_malloc)(size_t);
274275
void (*_free)(void*);
275276
void *(*_realloc)(void*, size_t);
277+
size_t (*_gc)(void);
278+
void (*_shutdown)(bool full, bool silent);
276279
} std;
277280
struct {
278281
void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
279282
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
280283
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
284+
size_t (*_gc)(void);
285+
void (*_shutdown)(bool full, bool silent);
281286
} debug;
282287
} custom_heap;
283288
HashTable *tracked_allocs;
@@ -1968,6 +1973,10 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
19681973

19691974
#if ZEND_MM_CUSTOM
19701975
if (heap->use_custom_heap) {
1976+
size_t (*gc)(void) = heap->custom_heap.std._gc;
1977+
if (gc) {
1978+
return gc();
1979+
}
19711980
return 0;
19721981
}
19731982
#endif
@@ -2262,10 +2271,10 @@ static void zend_mm_check_leaks(zend_mm_heap *heap)
22622271

22632272
#if ZEND_MM_CUSTOM
22642273
static void *tracked_malloc(size_t size);
2265-
static void tracked_free_all(void);
2274+
static void tracked_free_all(zend_mm_heap*heap);
22662275
#endif
22672276

2268-
void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
2277+
ZEND_APIvoid zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
22692278
{
22702279
zend_mm_chunk *p;
22712280
zend_mm_huge_list *list;
@@ -2274,7 +2283,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
22742283
if (heap->use_custom_heap) {
22752284
if (heap->custom_heap.std._malloc == tracked_malloc) {
22762285
if (silent) {
2277-
tracked_free_all();
2286+
tracked_free_all(heap);
22782287
}
22792288
zend_hash_clean(heap->tracked_allocs);
22802289
if (full) {
@@ -2286,13 +2295,20 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
22862295
heap->size = 0;
22872296
}
22882297

2298+
void (*shutdown)(bool, bool) = heap->custom_heap.std._shutdown;
2299+
22892300
if (full) {
22902301
if (ZEND_DEBUG && heap->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
22912302
heap->custom_heap.debug._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
22922303
} else {
22932304
heap->custom_heap.std._free(heap);
22942305
}
22952306
}
2307+
2308+
if (shutdown) {
2309+
shutdown(full, silent);
2310+
}
2311+
22962312
return;
22972313
}
22982314
#endif
@@ -2895,8 +2911,8 @@ static void *tracked_realloc(void *ptr, size_t new_size) {
28952911
return ptr;
28962912
}
28972913

2898-
static void tracked_free_all(void) {
2899-
HashTable *tracked_allocs = AG(mm_heap)->tracked_allocs;
2914+
static void tracked_free_all(zend_mm_heap*heap) {
2915+
HashTable *tracked_allocs = heap->tracked_allocs;
29002916
zend_ulong h;
29012917
ZEND_HASH_FOREACH_NUM_KEY(tracked_allocs, h) {
29022918
void *ptr = (void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2);
@@ -2980,6 +2996,16 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void)
29802996
return AG(mm_heap);
29812997
}
29822998

2999+
ZEND_API zend_mm_heap *zend_mm_heap_create(void)
3000+
{
3001+
return zend_mm_init();
3002+
}
3003+
3004+
ZEND_API void zend_mm_heap_free(zend_mm_heap *heap)
3005+
{
3006+
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
3007+
}
3008+
29833009
ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap)
29843010
{
29853011
#if ZEND_MM_CUSTOM
@@ -2990,9 +3016,11 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap)
29903016
}
29913017

29923018
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
2993-
void* (*_malloc)(size_t),
2994-
void (*_free)(void*),
2995-
void* (*_realloc)(void*, size_t))
3019+
void* (*_malloc)(size_t),
3020+
void (*_free)(void*),
3021+
void* (*_realloc)(void*, size_t),
3022+
size_t (*_gc)(void),
3023+
void (*_shutdown)(bool, bool))
29963024
{
29973025
#if ZEND_MM_CUSTOM
29983026
zend_mm_heap *_heap = (zend_mm_heap*)heap;
@@ -3004,14 +3032,18 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
30043032
_heap->custom_heap.std._malloc = _malloc;
30053033
_heap->custom_heap.std._free = _free;
30063034
_heap->custom_heap.std._realloc = _realloc;
3035+
_heap->custom_heap.std._gc = _gc;
3036+
_heap->custom_heap.std._shutdown = _shutdown;
30073037
}
30083038
#endif
30093039
}
30103040

30113041
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
3012-
void* (**_malloc)(size_t),
3013-
void (**_free)(void*),
3014-
void* (**_realloc)(void*, size_t))
3042+
void* (**_malloc)(size_t),
3043+
void (**_free)(void*),
3044+
void* (**_realloc)(void*, size_t),
3045+
size_t (**_gc)(void),
3046+
void (**_shutdown)(bool, bool))
30153047
{
30163048
#if ZEND_MM_CUSTOM
30173049
zend_mm_heap *_heap = (zend_mm_heap*)heap;
@@ -3020,15 +3052,29 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
30203052
*_malloc = _heap->custom_heap.std._malloc;
30213053
*_free = _heap->custom_heap.std._free;
30223054
*_realloc = _heap->custom_heap.std._realloc;
3055+
if (_gc != NULL) {
3056+
*_gc = _heap->custom_heap.std._gc;
3057+
}
3058+
if (_shutdown != NULL) {
3059+
*_shutdown = _heap->custom_heap.std._shutdown;
3060+
}
30233061
} else {
30243062
*_malloc = NULL;
30253063
*_free = NULL;
30263064
*_realloc = NULL;
3065+
if (_gc != NULL) {
3066+
*_gc = NULL;
3067+
}
3068+
if (_shutdown != NULL) {
3069+
*_shutdown = NULL;
3070+
}
30273071
}
30283072
#else
30293073
*_malloc = NULL;
30303074
*_free = NULL;
30313075
*_realloc = NULL;
3076+
*_gc = NULL;
3077+
*_shutdown = NULL;
30323078
#endif
30333079
}
30343080

‎Zend/zend_alloc.h‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZE
261261
#define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
262262
#define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
263263

264+
ZEND_API zend_mm_heap *zend_mm_heap_create(void);
265+
ZEND_API void zend_mm_heap_free(zend_mm_heap* heap);
264266
ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap);
265267
ZEND_API zend_mm_heap *zend_mm_get_heap(void);
266268

@@ -274,11 +276,15 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap);
274276
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
275277
void* (*_malloc)(size_t),
276278
void (*_free)(void*),
277-
void* (*_realloc)(void*, size_t));
279+
void* (*_realloc)(void*, size_t),
280+
size_t (*gc)(void),
281+
void (*shutdown)(bool full, bool silent));
278282
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
279283
void* (**_malloc)(size_t),
280284
void (**_free)(void*),
281-
void* (**_realloc)(void*, size_t));
285+
void* (**_realloc)(void*, size_t),
286+
size_t (**gc)(void),
287+
void (**shutdown)(bool full, bool silent));
282288

283289
#if ZEND_DEBUG
284290
ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,

‎ext/zend_test/config.m4‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ PHP_ARG_ENABLE([zend-test],
44
[Enable zend_test extension])])
55

66
if test "$PHP_ZEND_TEST" != "no"; then
7-
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
7+
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
88
fi

‎ext/zend_test/config.w32‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
ARG_ENABLE("zend-test", "enable zend_test extension", "no");
44

55
if (PHP_ZEND_TEST != "no") {
6-
EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
6+
EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
77
ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS ");
88
}

‎ext/zend_test/php_test.h‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
6262
zend_long quantity_value;
6363
zend_string *str_test;
6464
zend_string *not_empty_str_test;
65+
int zend_mm_custom_handlers_enabled;
66+
67+
// the previous heap that was found in ZendMM
68+
zend_mm_heap* original_heap;
69+
// the custom handlers that might have been found in the previous heap
70+
void* (*custom_malloc)(size_t);
71+
void (*custom_free)(void*);
72+
void* (*custom_realloc)(void *, size_t);
73+
size_t (*custom_gc)(void);
74+
void (*custom_shutdown)(bool, bool);
75+
// this is our heap that we install our custom handlers on and inject into
76+
// ZendMM
77+
zend_mm_heap* observed_heap;
6578
ZEND_END_MODULE_GLOBALS(zend_test)
6679

6780
extern ZEND_DECLARE_MODULE_GLOBALS(zend_test)

‎ext/zend_test/test.c‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
+----------------------------------------------------------------------+
1515
*/
1616

17+
#include "zend_modules.h"
1718
#ifdef HAVE_CONFIG_H
1819
# include "config.h"
1920
#endif
@@ -35,6 +36,7 @@
3536
#include "test_arginfo.h"
3637
#include "zend_call_stack.h"
3738
#include "zend_exceptions.h"
39+
#include "zend_mm_custom_handlers.h"
3840

3941
// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from
4042
// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we
@@ -682,7 +684,9 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
682684
ZT_G(zend_test_heap),
683685
zend_test_custom_malloc,
684686
zend_test_custom_free,
685-
zend_test_custom_realloc
687+
zend_test_custom_realloc,
688+
NULL,
689+
NULL
686690
);
687691
ZT_G(zend_orig_heap) = zend_mm_get_heap();
688692
zend_mm_set_heap(ZT_G(zend_test_heap));
@@ -1189,6 +1193,7 @@ PHP_MINIT_FUNCTION(zend_test)
11891193
}
11901194

11911195
zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU);
1196+
zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS_PASSTHRU);
11921197
zend_test_fiber_init();
11931198
zend_test_iterators_init();
11941199
zend_test_object_handlers_init();
@@ -1217,6 +1222,7 @@ PHP_RINIT_FUNCTION(zend_test)
12171222
{
12181223
zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
12191224
ZT_G(observer_nesting_depth) = 0;
1225+
zend_test_mm_custom_handlers_rinit();
12201226
return SUCCESS;
12211227
}
12221228

@@ -1234,6 +1240,7 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
12341240
zend_mm_set_heap(ZT_G(zend_orig_heap));
12351241
}
12361242

1243+
zend_test_mm_custom_handlers_rshutdown();
12371244
return SUCCESS;
12381245
}
12391246

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
ZendMM Custom Handlers: garbage collection
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 1);
8+
$string = str_repeat('String', rand(1,100));
9+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 0);
10+
?>
11+
--EXPECTREGEX--
12+
.*Allocated \d+ bytes at.*
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
ZendMM Custom Handlers: garbage collection
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
$string = str_repeat('String', rand(1,100));
8+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 1);
9+
unset($string);
10+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 0);
11+
?>
12+
--EXPECTREGEX--
13+
.*Freed memory at.*
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
ZendMM Custom Handlers: garbage collection
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 1);
8+
gc_mem_caches();
9+
ini_set('zend_test.zend_mm_custom_handlers.enabled', 0);
10+
?>
11+
--EXPECTREGEX--
12+
.*ZendMM GC freed \d+ bytes.*

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /