/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 | 0 | #define ZEND_FIBER_GUARD_PAGES 1 |
26 | | |
27 | 2 | #define ZEND_FIBER_DEFAULT_C_STACK_SIZE (4096 * (((sizeof(void *)) < 8) ? 256 : 512)) |
28 | 0 | #define ZEND_FIBER_VM_STACK_SIZE (1024 * sizeof(zval)) |
29 | | |
30 | | BEGIN_EXTERN_C() |
31 | | |
32 | | typedef enum { |
33 | | ZEND_FIBER_STATUS_INIT, |
34 | | ZEND_FIBER_STATUS_RUNNING, |
35 | | ZEND_FIBER_STATUS_SUSPENDED, |
36 | | ZEND_FIBER_STATUS_DEAD, |
37 | | } zend_fiber_status; |
38 | | |
39 | | typedef enum { |
40 | | ZEND_FIBER_FLAG_THREW = 1 << 0, |
41 | | ZEND_FIBER_FLAG_BAILOUT = 1 << 1, |
42 | | ZEND_FIBER_FLAG_DESTROYED = 1 << 2, |
43 | | } zend_fiber_flag; |
44 | | |
45 | | typedef enum { |
46 | | ZEND_FIBER_TRANSFER_FLAG_ERROR = 1 << 0, |
47 | | ZEND_FIBER_TRANSFER_FLAG_BAILOUT = 1 << 1 |
48 | | } zend_fiber_transfer_flag; |
49 | | |
50 | | void zend_register_fiber_ce(void); |
51 | | void zend_fiber_init(void); |
52 | | void zend_fiber_shutdown(void); |
53 | | |
54 | | extern ZEND_API zend_class_entry *zend_ce_fiber; |
55 | | |
56 | | typedef struct _zend_fiber_stack zend_fiber_stack; |
57 | | |
58 | | /* Encapsulates data needed for a context switch. */ |
59 | | typedef struct _zend_fiber_transfer { |
60 | | /* Fiber that will be switched to / has resumed us. */ |
61 | | zend_fiber_context *context; |
62 | | |
63 | | /* Value to that should be send to (or was received from) a fiber. */ |
64 | | zval value; |
65 | | |
66 | | /* Bitmask of flags defined in enum zend_fiber_transfer_flag. */ |
67 | | uint8_t flags; |
68 | | } zend_fiber_transfer; |
69 | | |
70 | | /* Coroutine functions must populate the given transfer with a new context |
71 | | * and (optional) data before they return. */ |
72 | | typedef void (*zend_fiber_coroutine)(zend_fiber_transfer *transfer); |
73 | | typedef void (*zend_fiber_clean)(zend_fiber_context *context); |
74 | | |
75 | | struct _zend_fiber_context { |
76 | | /* Pointer to boost.context or ucontext_t data. */ |
77 | | void *handle; |
78 | | |
79 | | /* Pointer that identifies the fiber type. */ |
80 | | void *kind; |
81 | | |
82 | | /* Entrypoint function of the fiber. */ |
83 | | zend_fiber_coroutine function; |
84 | | |
85 | | /* Cleanup function for fiber. */ |
86 | | zend_fiber_clean cleanup; |
87 | | |
88 | | /* Assigned C stack. */ |
89 | | zend_fiber_stack *stack; |
90 | | |
91 | | /* Fiber status. */ |
92 | | zend_fiber_status status; |
93 | | |
94 | | /* Observer state */ |
95 | | zend_execute_data *top_observed_frame; |
96 | | |
97 | | /* Reserved for extensions */ |
98 | | void *reserved[ZEND_MAX_RESERVED_RESOURCES]; |
99 | | }; |
100 | | |
101 | | struct _zend_fiber { |
102 | | /* PHP object handle. */ |
103 | | zend_object std; |
104 | | |
105 | | /* Flags are defined in enum zend_fiber_flag. */ |
106 | | uint8_t flags; |
107 | | |
108 | | /* Native C fiber context. */ |
109 | | zend_fiber_context context; |
110 | | |
111 | | /* Fiber that resumed us. */ |
112 | | zend_fiber_context *caller; |
113 | | |
114 | | /* Fiber that suspended us. */ |
115 | | zend_fiber_context *previous; |
116 | | |
117 | | /* Callback and info / cache to be used when fiber is started. */ |
118 | | zend_fcall_info fci; |
119 | | zend_fcall_info_cache fci_cache; |
120 | | |
121 | | /* Current Zend VM execute data being run by the fiber. */ |
122 | | zend_execute_data *execute_data; |
123 | | |
124 | | /* Frame on the bottom of the fiber vm stack. */ |
125 | | zend_execute_data *stack_bottom; |
126 | | |
127 | | /* Active fiber vm stack. */ |
128 | | zend_vm_stack vm_stack; |
129 | | |
130 | | /* Storage for fiber return value. */ |
131 | | zval result; |
132 | | }; |
133 | | |
134 | | ZEND_API zend_result zend_fiber_start(zend_fiber *fiber, zval *return_value); |
135 | | ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_value); |
136 | | ZEND_API void zend_fiber_suspend(zend_fiber *fiber, zval *value, zval *return_value); |
137 | | |
138 | | /* These functions may be used to create custom fiber objects using the bundled fiber switching context. */ |
139 | | ZEND_API zend_result zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size); |
140 | | ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context); |
141 | | ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer); |
142 | | #ifdef ZEND_CHECK_STACK_LIMIT |
143 | | ZEND_API void* zend_fiber_stack_limit(zend_fiber_stack *stack); |
144 | | ZEND_API void* zend_fiber_stack_base(zend_fiber_stack *stack); |
145 | | #endif /* ZEND_CHECK_STACK_LIMIT */ |
146 | | |
147 | | ZEND_API void zend_fiber_switch_block(void); |
148 | | ZEND_API void zend_fiber_switch_unblock(void); |
149 | | ZEND_API bool zend_fiber_switch_blocked(void); |
150 | | |
151 | | END_EXTERN_C() |
152 | | |
153 | | static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context) |
154 | 0 | { |
155 | 0 | ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber"); |
156 | |
|
157 | 0 | return ZEND_CONTAINER_OF(context, zend_fiber, context); |
158 | 0 | } 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 Unexecuted instantiation: zend_fibers.c:zend_fiber_from_context 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 |
159 | | |
160 | | static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber) |
161 | 0 | { |
162 | 0 | return &fiber->context; |
163 | 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 |
164 | | |
165 | | #endif |