/src/php-src/Zend/zend_fibers.h
Line | Count | Source |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Zend Engine | |
4 | | +----------------------------------------------------------------------+ |
5 | | | Copyright © Zend Technologies Ltd., a subsidiary company of | |
6 | | | Perforce Software, Inc., and Contributors. | |
7 | | +----------------------------------------------------------------------+ |
8 | | | This source file is subject to the Modified BSD License that is | |
9 | | | bundled with this package in the file LICENSE, and is available | |
10 | | | through the World Wide Web at <https://www.php.net/license/>. | |
11 | | | | |
12 | | | SPDX-License-Identifier: BSD-3-Clause | |
13 | | +----------------------------------------------------------------------+ |
14 | | | Authors: Aaron Piotrowski <aaron@trowski.com> | |
15 | | | Martin Schröder <m.schroeder2007@gmail.com> | |
16 | | +----------------------------------------------------------------------+ |
17 | | */ |
18 | | |
19 | | #ifndef ZEND_FIBERS_H |
20 | | #define ZEND_FIBERS_H |
21 | | |
22 | | #include "zend_API.h" |
23 | | #include "zend_types.h" |
24 | | |
25 | 61 | #define ZEND_FIBER_GUARD_PAGES 1 |
26 | | |
27 | 18 | #define ZEND_FIBER_DEFAULT_C_STACK_SIZE (4096 * (((sizeof(void *)) < 8) ? 256 : 512)) |
28 | | |
29 | | BEGIN_EXTERN_C() |
30 | | |
31 | | typedef enum { |
32 | | ZEND_FIBER_STATUS_INIT, |
33 | | ZEND_FIBER_STATUS_RUNNING, |
34 | | ZEND_FIBER_STATUS_SUSPENDED, |
35 | | ZEND_FIBER_STATUS_DEAD, |
36 | | } zend_fiber_status; |
37 | | |
38 | | typedef enum { |
39 | | ZEND_FIBER_FLAG_THREW = 1 << 0, |
40 | | ZEND_FIBER_FLAG_BAILOUT = 1 << 1, |
41 | | ZEND_FIBER_FLAG_DESTROYED = 1 << 2, |
42 | | } zend_fiber_flag; |
43 | | |
44 | | typedef enum { |
45 | | ZEND_FIBER_TRANSFER_FLAG_ERROR = 1 << 0, |
46 | | ZEND_FIBER_TRANSFER_FLAG_BAILOUT = 1 << 1 |
47 | | } zend_fiber_transfer_flag; |
48 | | |
49 | | void zend_register_fiber_ce(void); |
50 | | void zend_fiber_init(void); |
51 | | void zend_fiber_shutdown(void); |
52 | | |
53 | | extern ZEND_API zend_class_entry *zend_ce_fiber; |
54 | | |
55 | | typedef struct _zend_fiber_stack zend_fiber_stack; |
56 | | |
57 | | /* Encapsulates data needed for a context switch. */ |
58 | | typedef struct _zend_fiber_transfer { |
59 | | /* Fiber that will be switched to / has resumed us. */ |
60 | | zend_fiber_context *context; |
61 | | |
62 | | /* Value to that should be send to (or was received from) a fiber. */ |
63 | | zval value; |
64 | | |
65 | | /* Bitmask of flags defined in enum zend_fiber_transfer_flag. */ |
66 | | uint8_t flags; |
67 | | } zend_fiber_transfer; |
68 | | |
69 | | /* Coroutine functions must populate the given transfer with a new context |
70 | | * and (optional) data before they return. */ |
71 | | typedef void (*zend_fiber_coroutine)(zend_fiber_transfer *transfer); |
72 | | typedef void (*zend_fiber_clean)(zend_fiber_context *context); |
73 | | |
74 | | struct _zend_fiber_context { |
75 | | /* Pointer to boost.context or ucontext_t data. */ |
76 | | void *handle; |
77 | | |
78 | | /* Pointer that identifies the fiber type. */ |
79 | | void *kind; |
80 | | |
81 | | /* Entrypoint function of the fiber. */ |
82 | | zend_fiber_coroutine function; |
83 | | |
84 | | /* Cleanup function for fiber. */ |
85 | | zend_fiber_clean cleanup; |
86 | | |
87 | | /* Assigned C stack. */ |
88 | | zend_fiber_stack *stack; |
89 | | |
90 | | /* Fiber status. */ |
91 | | zend_fiber_status status; |
92 | | |
93 | | /* Observer state */ |
94 | | zend_execute_data *top_observed_frame; |
95 | | |
96 | | /* Reserved for extensions */ |
97 | | void *reserved[ZEND_MAX_RESERVED_RESOURCES]; |
98 | | }; |
99 | | |
100 | | struct _zend_fiber { |
101 | | /* PHP object handle. */ |
102 | | zend_object std; |
103 | | |
104 | | /* Flags are defined in enum zend_fiber_flag. */ |
105 | | uint8_t flags; |
106 | | |
107 | | /* Native C fiber context. */ |
108 | | zend_fiber_context context; |
109 | | |
110 | | /* Fiber that resumed us. */ |
111 | | zend_fiber_context *caller; |
112 | | |
113 | | /* Fiber that suspended us. */ |
114 | | zend_fiber_context *previous; |
115 | | |
116 | | /* Callback and info / cache to be used when fiber is started. */ |
117 | | zend_fcall_info fci; |
118 | | zend_fcall_info_cache fci_cache; |
119 | | |
120 | | /* Current Zend VM execute data being run by the fiber. */ |
121 | | zend_execute_data *execute_data; |
122 | | |
123 | | /* Frame on the bottom of the fiber vm stack. */ |
124 | | zend_execute_data *stack_bottom; |
125 | | |
126 | | /* Active fiber vm stack. */ |
127 | | zend_vm_stack vm_stack; |
128 | | |
129 | | /* Storage for fiber return value. */ |
130 | | zval result; |
131 | | }; |
132 | | |
133 | | ZEND_API zend_result zend_fiber_start(zend_fiber *fiber, zval *return_value); |
134 | | ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_value); |
135 | | ZEND_API void zend_fiber_suspend(zend_fiber *fiber, zval *value, zval *return_value); |
136 | | |
137 | | /* These functions may be used to create custom fiber objects using the bundled fiber switching context. */ |
138 | | ZEND_API zend_result zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size); |
139 | | ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context); |
140 | | ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer); |
141 | | #ifdef ZEND_CHECK_STACK_LIMIT |
142 | | ZEND_API void* zend_fiber_stack_limit(zend_fiber_stack *stack); |
143 | | ZEND_API void* zend_fiber_stack_base(zend_fiber_stack *stack); |
144 | | #endif /* ZEND_CHECK_STACK_LIMIT */ |
145 | | |
146 | | ZEND_API void zend_fiber_switch_block(void); |
147 | | ZEND_API void zend_fiber_switch_unblock(void); |
148 | | ZEND_API bool zend_fiber_switch_blocked(void); |
149 | | |
150 | | END_EXTERN_C() |
151 | | |
152 | | static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context) |
153 | 10 | { |
154 | 10 | ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber"); |
155 | | |
156 | 10 | return ZEND_CONTAINER_OF(context, zend_fiber, context); |
157 | 10 | } Unexecuted instantiation: zend_accelerator_util_funcs.c:zend_fiber_from_context Unexecuted instantiation: ZendAccelerator.c:zend_fiber_from_context Unexecuted instantiation: zend_jit.c:zend_fiber_from_context Unexecuted instantiation: php_reflection.c:zend_fiber_from_context Unexecuted instantiation: main.c:zend_fiber_from_context Unexecuted instantiation: compact_vars.c:zend_fiber_from_context Unexecuted instantiation: optimize_temp_vars_5.c:zend_fiber_from_context Unexecuted instantiation: zend_API.c:zend_fiber_from_context Unexecuted instantiation: zend_compile.c:zend_fiber_from_context Unexecuted instantiation: zend_default_classes.c:zend_fiber_from_context Unexecuted instantiation: zend_enum.c:zend_fiber_from_context Unexecuted instantiation: zend_exceptions.c:zend_fiber_from_context Unexecuted instantiation: zend_execute_API.c:zend_fiber_from_context Unexecuted instantiation: zend_execute.c:zend_fiber_from_context zend_fibers.c:zend_fiber_from_context Line | Count | Source | 153 | 10 | { | 154 | 10 | ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber"); | 155 | | | 156 | 10 | return ZEND_CONTAINER_OF(context, zend_fiber, context); | 157 | 10 | } |
Unexecuted instantiation: zend_gc.c:zend_fiber_from_context Unexecuted instantiation: zend_generators.c:zend_fiber_from_context Unexecuted instantiation: zend_inheritance.c:zend_fiber_from_context Unexecuted instantiation: zend_object_handlers.c:zend_fiber_from_context Unexecuted instantiation: zend_objects_API.c:zend_fiber_from_context Unexecuted instantiation: zend_observer.c:zend_fiber_from_context Unexecuted instantiation: zend_opcode.c:zend_fiber_from_context Unexecuted instantiation: zend.c:zend_fiber_from_context |
158 | | |
159 | | static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber) |
160 | 0 | { |
161 | 0 | return &fiber->context; |
162 | 0 | } Unexecuted instantiation: zend_accelerator_util_funcs.c:zend_fiber_get_context Unexecuted instantiation: ZendAccelerator.c:zend_fiber_get_context Unexecuted instantiation: zend_jit.c:zend_fiber_get_context Unexecuted instantiation: php_reflection.c:zend_fiber_get_context Unexecuted instantiation: main.c:zend_fiber_get_context Unexecuted instantiation: compact_vars.c:zend_fiber_get_context Unexecuted instantiation: optimize_temp_vars_5.c:zend_fiber_get_context Unexecuted instantiation: zend_API.c:zend_fiber_get_context Unexecuted instantiation: zend_compile.c:zend_fiber_get_context Unexecuted instantiation: zend_default_classes.c:zend_fiber_get_context Unexecuted instantiation: zend_enum.c:zend_fiber_get_context Unexecuted instantiation: zend_exceptions.c:zend_fiber_get_context Unexecuted instantiation: zend_execute_API.c:zend_fiber_get_context Unexecuted instantiation: zend_execute.c:zend_fiber_get_context Unexecuted instantiation: zend_fibers.c:zend_fiber_get_context Unexecuted instantiation: zend_gc.c:zend_fiber_get_context Unexecuted instantiation: zend_generators.c:zend_fiber_get_context Unexecuted instantiation: zend_inheritance.c:zend_fiber_get_context Unexecuted instantiation: zend_object_handlers.c:zend_fiber_get_context Unexecuted instantiation: zend_objects_API.c:zend_fiber_get_context Unexecuted instantiation: zend_observer.c:zend_fiber_get_context Unexecuted instantiation: zend_opcode.c:zend_fiber_get_context Unexecuted instantiation: zend.c:zend_fiber_get_context |
163 | | |
164 | | #endif |