diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 66e38597afb3e..e3276a28bf326 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -199,7 +199,7 @@ static ZEND_NORETURN void zend_fiber_trampoline(transfer_t transfer) abort(); } -ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size) +ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size) { if (UNEXPECTED(!zend_fiber_stack_allocate(&context->stack, stack_size))) { return false; @@ -211,6 +211,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co context->handle = make_fcontext(stack, context->stack.size, zend_fiber_trampoline); ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL"); + context->kind = kind; context->function = coroutine; return true; @@ -256,7 +257,7 @@ static void zend_fiber_suspend_from(zend_fiber *fiber) ZEND_ASSERT(fiber->caller && "Fiber has no caller"); zend_fiber_capture_vm_state(&state); - zend_fiber_switch_context(zend_fiber_get_context(fiber->caller)); + zend_fiber_switch_context(fiber->caller); zend_fiber_restore_vm_state(&state); } @@ -267,7 +268,7 @@ static void zend_fiber_switch_to(zend_fiber *fiber) zend_observer_fiber_switch_notify(EG(current_fiber), context); - fiber->caller = zend_fiber_from_context(EG(current_fiber)); + fiber->caller = EG(current_fiber); zend_fiber_capture_vm_state(&state); zend_fiber_switch_context(context); @@ -352,7 +353,7 @@ static ZEND_STACK_ALIGNED zend_fiber_context *zend_fiber_execute(zend_fiber_cont fiber->execute_data = NULL; fiber->stack_bottom = NULL; - return zend_fiber_get_context(fiber->caller); + return fiber->caller; } static zend_object *zend_fiber_object_create(zend_class_entry *ce) @@ -451,7 +452,7 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c fiber->fci.param_count = param_count; fiber->fci.named_params = named_params; - if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_fiber_execute, EG(fiber_stack_size))) { + if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) { RETURN_THROWS(); } @@ -481,7 +482,7 @@ ZEND_METHOD(Fiber, start) ZEND_API void zend_fiber_suspend(zval *value, zval *return_value) { - if (UNEXPECTED(EG(current_fiber) == EG(main_fiber))) { + if (UNEXPECTED(EG(current_fiber)->kind != zend_ce_fiber)) { zend_throw_error(zend_ce_fiber_error, "Cannot suspend outside of a fiber"); RETURN_THROWS(); } @@ -692,7 +693,7 @@ ZEND_METHOD(Fiber, this) { ZEND_PARSE_PARAMETERS_NONE(); - if (EG(current_fiber) == EG(main_fiber)) { + if (EG(current_fiber)->kind != zend_ce_fiber) { RETURN_NULL(); } diff --git a/Zend/zend_fibers.h b/Zend/zend_fibers.h index 84148f0431886..df909b55c4e1e 100644 --- a/Zend/zend_fibers.h +++ b/Zend/zend_fibers.h @@ -72,7 +72,10 @@ typedef zend_fiber_context *(*zend_fiber_coroutine)(zend_fiber_context *context) /* Defined as a macro to allow anonymous embedding. */ #define ZEND_FIBER_CONTEXT_FIELDS \ + /* Handle to fiber state as needed by boost.context */ \ void *handle; \ + /* Pointer that identifies the fiber type. */ \ + void *kind; \ zend_fiber_coroutine function; \ zend_fiber_stack stack; \ zend_fiber_status status; \ @@ -98,7 +101,7 @@ struct _zend_fiber { zend_object std; /* Fiber that resumed us. */ - zend_fiber *caller; + zend_fiber_context *caller; /* Fiber context fields (embedded to avoid memory allocation). */ ZEND_FIBER_CONTEXT_FIELDS; @@ -128,7 +131,7 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_value); /* These functions may be used to create custom fibers (coroutines) using the bundled fiber switching context. */ -ZEND_API zend_bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size); +ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size); ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context); ZEND_API void zend_fiber_switch_context(zend_fiber_context *to); @@ -136,6 +139,8 @@ END_EXTERN_C() static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context) { + ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber"); + return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle)); }