Skip to content

Commit c0d92b2

Browse files
make observer less complex
1 parent a954662 commit c0d92b2

File tree

3 files changed

+81
-187
lines changed

3 files changed

+81
-187
lines changed

Zend/zend_alloc.c

Lines changed: 77 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
* with more specialized routines when the requested size is known.
5252
*/
5353

54-
#include "php.h"
5554
#include "zend.h"
5655
#include "zend_alloc.h"
5756
#include "zend_globals.h"
@@ -200,6 +199,13 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list;
200199

201200
static bool zend_mm_use_huge_pages = false;
202201

202+
struct _zend_mm_observer {
203+
void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
204+
void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
205+
void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
206+
zend_mm_observer *next;
207+
};
208+
203209
/*
204210
* Memory is retrieved from OS by chunks of fixed size 2MB.
205211
* Inside chunk it's managed by pages of fixed size 4096B.
@@ -231,23 +237,6 @@ static bool zend_mm_use_huge_pages = false;
231237
* (5 bits) bin number (e.g. 0 for sizes 0-2, 1 for 3-4,
232238
* 2 for 5-8, 3 for 9-16 etc) see zend_alloc_sizes.h
233239
*/
234-
235-
236-
struct _zend_mm_observer {
237-
void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
238-
void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
239-
void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
240-
zend_mm_observer *next;
241-
};
242-
zend_mm_observer *zend_mm_observers = NULL;
243-
244-
typedef struct _zend_mm_heap_observer zend_mm_heap_observer;
245-
struct _zend_mm_heap_observer {
246-
zend_mm_observer *observer;
247-
bool enabled;
248-
zend_mm_heap_observer *next;
249-
};
250-
251240
struct _zend_mm_heap {
252241
#if ZEND_MM_CUSTOM
253242
int use_custom_heap; /* bitflag */
@@ -295,7 +284,7 @@ struct _zend_mm_heap {
295284
} debug;
296285
} custom_heap;
297286
HashTable *tracked_allocs;
298-
zend_mm_heap_observer *observers;
287+
zend_mm_observer *observers;
299288
#endif
300289
};
301290

@@ -1957,7 +1946,6 @@ static zend_mm_heap *zend_mm_init(void)
19571946
#if ZEND_MM_CUSTOM
19581947
heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE;
19591948
heap->observers = NULL;
1960-
zend_mm_observers_startup(heap);
19611949
#endif
19621950
#if ZEND_MM_STORAGE
19631951
heap->storage = NULL;
@@ -2500,10 +2488,10 @@ static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_D
25002488
ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25012489
}
25022490
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) {
2503-
zend_mm_heap_observer *current = heap->observers;
2491+
zend_mm_observer *current = heap->observers;
25042492
while (current != NULL) {
2505-
if (current->enabled && current->observer != NULL && current->observer->malloc != NULL) {
2506-
current->observer->malloc(size, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2493+
if (current->malloc != NULL) {
2494+
current->malloc(size, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25072495
}
25082496
current = current->next;
25092497
}
@@ -2517,10 +2505,10 @@ static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZE
25172505
int use_custom_heap = heap->use_custom_heap;
25182506

25192507
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) {
2520-
zend_mm_heap_observer *current = heap->observers;
2508+
zend_mm_observer *current = heap->observers;
25212509
while (current != NULL) {
2522-
if (current->enabled && current->observer != NULL && current->observer->free != NULL) {
2523-
current->observer->free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2510+
if (current->free != NULL) {
2511+
current->free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25242512
}
25252513
current = current->next;
25262514
}
@@ -2550,10 +2538,10 @@ static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND
25502538
new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25512539
}
25522540
if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) {
2553-
zend_mm_heap_observer *current = heap->observers;
2541+
zend_mm_observer *current = heap->observers;
25542542
while (current != NULL) {
2555-
if (current->enabled && current->observer != NULL && current->observer->realloc != NULL) {
2556-
current->observer->realloc(ptr, size, new_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2543+
if (current->realloc != NULL) {
2544+
current->realloc(ptr, size, new_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
25572545
}
25582546
current = current->next;
25592547
}
@@ -2977,7 +2965,6 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
29772965
mm_heap->tracked_allocs = malloc(sizeof(HashTable));
29782966
zend_hash_init(mm_heap->tracked_allocs, 1024, NULL, NULL, 1);
29792967
}
2980-
zend_mm_observers_startup(mm_heap);
29812968
return;
29822969
}
29832970
#endif
@@ -3036,10 +3023,13 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap)
30363023
#endif
30373024
}
30383025

3039-
ZEND_API bool zend_mm_is_observed(zend_mm_heap *new_heap)
3026+
ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap)
30403027
{
30413028
#if ZEND_MM_CUSTOM
3042-
return (AG(mm_heap)->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0;
3029+
if (!heap && !(heap = AG(mm_heap))) {
3030+
return false;
3031+
}
3032+
return (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0;
30433033
#else
30443034
return false;
30453035
#endif
@@ -3092,199 +3082,111 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
30923082
}
30933083

30943084
/*
3095-
* Use this function to register observers to the ZendMM. Make sure to call this
3096-
* function only during PHP module startup phase and not later. Observers will
3097-
* not be called directly after registering them, but only after
3098-
* `zend_mm_observers_startup()` was run, which will take place after the PHP
3099-
* module startup phase.
3085+
* Use this function to register observers to the ZendMM.
3086+
* This function operates on the thread local heap and is meant to be called in
3087+
* RINIT. Calling it in MINIT works only in NTS builds, but not in ZTS.
31003088
*/
31013089
ZEND_API zend_mm_observer* zend_mm_observer_register(
3090+
zend_mm_heap* heap,
31023091
void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
31033092
void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
31043093
void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
31053094
) {
31063095
#if ZEND_MM_CUSTOM
3096+
if (!heap && !(heap = AG(mm_heap))) {
3097+
return false;
3098+
}
3099+
31073100
zend_mm_observer *node = pemalloc(sizeof(zend_mm_observer), 1);
31083101
node->malloc = malloc;
31093102
node->free = free;
31103103
node->realloc = realloc;
31113104
node->next = NULL;
3112-
if (zend_mm_observers == NULL) {
3113-
zend_mm_observers = node;
3114-
return zend_mm_observers;
3105+
3106+
// set bitflag for observers being around
3107+
heap->use_custom_heap |= ZEND_MM_CUSTOM_HEAP_OBSERVED;
3108+
3109+
if (heap->observers == NULL) {
3110+
heap->observers = node;
3111+
return node;
31153112
}
3116-
zend_mm_observer *current = zend_mm_observers;
3113+
zend_mm_observer *current = heap->observers;
31173114
while (current->next != NULL) {
31183115
current = current->next;
31193116
}
31203117
current->next = node;
3118+
31213119
return node;
31223120
#else
31233121
return NULL;
31243122
#endif
31253123
}
31263124

31273125
/*
3128-
* This function will activate the global registered observers for the current
3129-
* heap. After this has been run, observering functions will be called.
3126+
* Use this function to unregister your observer at any given time. In case your
3127+
* observer was the last one to be unregistered, this will also reset the
3128+
* `heap->use_custom_heap` bitflag.
31303129
*/
3131-
void zend_mm_observers_startup(zend_mm_heap *heap)
3130+
ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer)
31323131
{
31333132
#if ZEND_MM_CUSTOM
3134-
if (heap == NULL) {
3135-
heap = AG(mm_heap);
3136-
}
3137-
zend_mm_observer *current_observer = zend_mm_observers;
3138-
if (current_observer == NULL) {
3139-
// no observers installed
3140-
return;
3133+
if (!heap && !(heap = AG(mm_heap))) {
3134+
return false;
31413135
}
3142-
// copy observers into heap
3143-
zend_mm_heap_observer *node = NULL;
3144-
zend_mm_heap_observer *current_heap_observer = NULL;
3145-
while (current_observer != NULL) {
3146-
node = pemalloc(sizeof(zend_mm_heap_observer), 1);
3147-
node->observer = current_observer;
3148-
node->enabled = true;
3149-
node->next = NULL;
3150-
if (current_heap_observer == NULL) {
3151-
heap->observers = node;
3152-
} else {
3153-
current_heap_observer->next = node;
3136+
3137+
zend_mm_observer *current = heap->observers, *prev = NULL;
3138+
3139+
if (current == observer) {
3140+
heap->observers = observer->next;
3141+
pefree(observer, 1);
3142+
if (!heap->observers)
3143+
{
3144+
// this was the one and only installed observer
3145+
heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED;
31543146
}
3155-
current_heap_observer = node;
3156-
current_observer = current_observer->next;
3147+
return true;
31573148
}
3158-
// set bitflag for observers being around
3159-
heap->use_custom_heap |= ZEND_MM_CUSTOM_HEAP_OBSERVED;
3149+
3150+
while (current != NULL && current != observer) {
3151+
prev = current;
3152+
current = current->next;
3153+
}
3154+
3155+
// did not find observer or NULL was given
3156+
if (current == NULL)
3157+
return false;
3158+
3159+
prev->next = current->next;
3160+
pefree(observer, 1);
3161+
return true;
3162+
#else
3163+
return false;
31603164
#endif
31613165
}
31623166

31633167
/*
31643168
* This function will shutdown the observers for the current heap and free
3165-
* global structures. This will be called before PHP module shutdown phase.
3169+
* memory
31663170
*/
31673171
void zend_mm_observers_shutdown(zend_mm_heap *heap)
31683172
{
31693173
#if ZEND_MM_CUSTOM
3170-
if (heap == NULL) {
3171-
heap = AG(mm_heap);
3172-
if (heap == NULL) {
3173-
return;
3174-
}
3175-
}
3176-
zend_mm_heap_observer *current_heap_observer = heap->observers;
3177-
zend_mm_heap_observer *next_heap_observer = NULL;
3178-
while (current_heap_observer != NULL) {
3179-
next_heap_observer = current_heap_observer->next;
3180-
pefree(current_heap_observer, 1);
3181-
current_heap_observer = next_heap_observer;
3174+
if (!heap && !(heap = AG(mm_heap))) {
3175+
return;
31823176
}
3183-
heap->observers = NULL;
3184-
return;
3185-
#endif
3186-
}
3187-
3188-
void zend_mm_observers_unregister(void)
3189-
{
3190-
#if ZEND_MM_CUSTOM
3191-
zend_mm_observer *current = zend_mm_observers;
3177+
zend_mm_observer *current = heap->observers;
31923178
zend_mm_observer *next = NULL;
31933179
while (current != NULL) {
31943180
next = current->next;
31953181
pefree(current, 1);
31963182
current = next;
31973183
}
3198-
zend_mm_observers = NULL;
3199-
#endif
3200-
}
3201-
3202-
/*
3203-
* This internal function will check if there are still enabled observer on the
3204-
* heap. In case there are, it will set the `ZEND_MM_CUSTOM_HEAP_OBSERVED` flag
3205-
* otherwise it will unset the flag.
3206-
*/
3207-
void zend_mm_observer_sync_flag(bool enabled_observer) {
3208-
#if ZEND_MM_CUSTOM
3209-
zend_mm_heap *heap = AG(mm_heap);
3210-
if (heap == NULL) {
3211-
return;
3212-
}
3213-
if (enabled_observer) {
3214-
// When an observer was enabled, we don't need to find if there were
3215-
// enabled observers
3216-
heap->use_custom_heap |= ZEND_MM_CUSTOM_HEAP_OBSERVED;
3217-
return;
3218-
}
3219-
// An observer got disabled, so we need to check if there are still enabled
3220-
// observers left in the list
3221-
zend_mm_heap_observer *current = heap->observers;
3222-
while (current != NULL) {
3223-
if (current->enabled == true) {
3224-
// in case we find an enabled observer there is nothing to do
3225-
return;
3226-
}
3227-
current = current->next;
3228-
}
3184+
heap->observers = NULL;
32293185
heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED;
3186+
return;
32303187
#endif
32313188
}
32323189

3233-
zend_mm_heap_observer* zend_mm_observer_find_heap_observer(zend_mm_heap *heap, zend_mm_observer *node) {
3234-
if (heap == NULL) {
3235-
heap = AG(mm_heap);
3236-
if (heap == NULL) {
3237-
return NULL;
3238-
}
3239-
}
3240-
zend_mm_heap_observer *current = heap->observers;
3241-
while (current != NULL) {
3242-
if (current->observer == node) {
3243-
return current;
3244-
}
3245-
current = current->next;
3246-
}
3247-
return NULL;
3248-
}
3249-
3250-
ZEND_API bool zend_mm_observer_enabled(zend_mm_heap *heap, zend_mm_observer *node) {
3251-
#if ZEND_MM_CUSTOM
3252-
zend_mm_heap_observer *heap_observer = zend_mm_observer_find_heap_observer(heap, node);
3253-
if (heap_observer == NULL) {
3254-
return false;
3255-
}
3256-
return heap_observer->enabled;
3257-
#endif
3258-
return false;
3259-
}
3260-
3261-
ZEND_API bool zend_mm_observer_set_state(zend_mm_heap *heap, zend_mm_observer *node, bool state) {
3262-
#if ZEND_MM_CUSTOM
3263-
zend_mm_heap_observer *heap_observer = zend_mm_observer_find_heap_observer(heap, node);
3264-
if (heap_observer == NULL) {
3265-
false;
3266-
}
3267-
heap_observer->enabled = state;
3268-
zend_mm_observer_sync_flag(state);
3269-
return true;
3270-
#endif
3271-
return false;
3272-
}
3273-
3274-
ZEND_API bool zend_mm_observer_enable(zend_mm_heap *heap, zend_mm_observer *node) {
3275-
#if ZEND_MM_CUSTOM
3276-
return zend_mm_observer_set_state(heap, node, true);
3277-
#endif
3278-
return false;
3279-
}
3280-
3281-
ZEND_API bool zend_mm_observer_disable(zend_mm_heap *heap, zend_mm_observer *node) {
3282-
#if ZEND_MM_CUSTOM
3283-
return zend_mm_observer_set_state(heap, node, false);
3284-
#endif
3285-
return false;
3286-
}
3287-
32883190
#if ZEND_DEBUG
32893191
ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,
32903192
void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),

0 commit comments

Comments
 (0)