17
17
+----------------------------------------------------------------------+
18
18
*/
19
19
20
- #include "php.h"
21
20
#include "zend.h"
22
21
#include "zend_API.h"
22
+ #include "zend_ini.h"
23
23
#include "zend_vm.h"
24
24
#include "zend_interfaces.h"
25
25
#include "zend_exceptions.h"
29
29
#include "zend_fibers_arginfo.h"
30
30
31
31
#ifdef HAVE_VALGRIND
32
- #include "valgrind/valgrind.h"
32
+ #include <valgrind/valgrind.h>
33
+ #endif
34
+
35
+ #ifndef PHP_WIN32
36
+ #include <unistd.h>
37
+ #include <sys/mman.h>
38
+ #include <limits.h>
33
39
#endif
34
40
35
41
ZEND_API zend_class_entry * zend_ce_fiber ;
@@ -52,6 +58,8 @@ typedef struct _transfer_t {
52
58
extern fcontext_t make_fcontext (void * sp , size_t size , void (* fn )(transfer_t ));
53
59
extern transfer_t jump_fcontext (fcontext_t to , void * vp );
54
60
61
+ #define ZEND_FIBER_DEFAULT_PAGE_SIZE 4096
62
+
55
63
#define ZEND_FIBER_BACKUP_EG (stack , stack_page_size , execute_data , error_reporting , trace_num ) do { \
56
64
stack = EG(vm_stack); \
57
65
stack->top = EG(vm_stack_top); \
@@ -86,7 +94,7 @@ ZEND_API void zend_observer_fiber_switch_register(zend_observer_fiber_switch_han
86
94
}
87
95
/* }}} */
88
96
89
- zend_always_inline static void zend_observer_fiber_switch_notify (zend_fiber * from , zend_fiber * to ) /* {{{ */
97
+ static zend_always_inline void zend_observer_fiber_switch_notify (zend_fiber * from , zend_fiber * to ) /* {{{ */
90
98
{
91
99
zend_llist_element * element ;
92
100
zend_observer_fiber_switch_handler callback ;
@@ -98,7 +106,22 @@ zend_always_inline static void zend_observer_fiber_switch_notify(zend_fiber *fro
98
106
}
99
107
/* }}} */
100
108
101
- static zend_bool zend_fiber_stack_allocate (zend_fiber_stack * stack , size_t size ) /* {{{ */
109
+ size_t zend_fiber_page_size ()
110
+ {
111
+ #if _POSIX_MAPPED_FILES
112
+ static size_t page_size ;
113
+
114
+ if (!page_size ) {
115
+ page_size = sysconf (_SC_PAGESIZE );
116
+ }
117
+
118
+ return page_size ;
119
+ #else
120
+ return ZEND_FIBER_DEFAULT_PAGE_SIZE ;
121
+ #endif
122
+ }
123
+
124
+ static bool zend_fiber_stack_allocate (zend_fiber_stack * stack , size_t size ) /* {{{ */
102
125
{
103
126
void * pointer ;
104
127
const size_t page_size = zend_fiber_page_size ();
@@ -112,28 +135,28 @@ static zend_bool zend_fiber_stack_allocate(zend_fiber_stack *stack, size_t size)
112
135
pointer = VirtualAlloc (0 , msize , MEM_COMMIT , PAGE_READWRITE );
113
136
114
137
if (!pointer ) {
115
- return 0 ;
138
+ return false ;
116
139
}
117
140
118
141
# if ZEND_FIBER_GUARD_PAGES
119
142
DWORD protect ;
120
143
121
144
if (!VirtualProtect (pointer , ZEND_FIBER_GUARD_PAGES * page_size , PAGE_READWRITE | PAGE_GUARD , & protect )) {
122
145
VirtualFree (pointer , 0 , MEM_RELEASE );
123
- return 0 ;
146
+ return false ;
124
147
}
125
148
# endif
126
149
#else
127
150
pointer = mmap (NULL , msize , PROT_READ | PROT_WRITE , ZEND_FIBER_STACK_FLAGS , -1 , 0 );
128
151
129
152
if (pointer == MAP_FAILED ) {
130
- return 0 ;
153
+ return false ;
131
154
}
132
155
133
156
# if ZEND_FIBER_GUARD_PAGES
134
157
if (mprotect (pointer , ZEND_FIBER_GUARD_PAGES * page_size , PROT_NONE ) < 0 ) {
135
158
munmap (pointer , msize );
136
- return 0 ;
159
+ return false ;
137
160
}
138
161
# endif
139
162
#endif
@@ -145,7 +168,7 @@ static zend_bool zend_fiber_stack_allocate(zend_fiber_stack *stack, size_t size)
145
168
stack -> valgrind = VALGRIND_STACK_REGISTER (base , base + msize - ZEND_FIBER_GUARD_PAGES * page_size );
146
169
#endif
147
170
148
- return 1 ;
171
+ return true ;
149
172
}
150
173
/* }}} */
151
174
@@ -195,10 +218,10 @@ static ZEND_NORETURN void zend_fiber_trampoline(transfer_t transfer) /* {{{ */
195
218
}
196
219
/* }}} */
197
220
198
- ZEND_API zend_bool zend_fiber_init_context (zend_fiber_context * context , zend_fiber_coroutine coroutine , size_t stack_size ) /* {{{ */
221
+ ZEND_API bool zend_fiber_init_context (zend_fiber_context * context , zend_fiber_coroutine coroutine , size_t stack_size ) /* {{{ */
199
222
{
200
223
if (UNEXPECTED (!zend_fiber_stack_allocate (& context -> stack , stack_size ))) {
201
- return 0 ;
224
+ return false ;
202
225
}
203
226
204
227
// Stack grows down, calculate the top of the stack. make_fcontext then shifts pointer to lower 16-byte boundary.
@@ -208,22 +231,18 @@ ZEND_API zend_bool zend_fiber_init_context(zend_fiber_context *context, zend_fib
208
231
209
232
if (UNEXPECTED (!context -> self )) {
210
233
zend_fiber_stack_free (& context -> stack );
211
- return 0 ;
234
+ return false ;
212
235
}
213
236
214
237
context -> function = coroutine ;
215
238
context -> caller = NULL ;
216
239
217
- return 1 ;
240
+ return true ;
218
241
}
219
242
/* }}} */
220
243
221
244
ZEND_API void zend_fiber_destroy_context (zend_fiber_context * context ) /* {{{ */
222
245
{
223
- if (!context ) {
224
- return ;
225
- }
226
-
227
246
zend_fiber_stack_free (& context -> stack );
228
247
}
229
248
/* }}} */
@@ -352,7 +371,7 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context) /
352
371
353
372
fiber -> execute_data = (zend_execute_data * ) stack -> top ;
354
373
355
- ZEND_SECURE_ZERO (fiber -> execute_data , sizeof (zend_execute_data ));
374
+ memset (fiber -> execute_data , 0 , sizeof (zend_execute_data ));
356
375
357
376
EG (current_execute_data ) = fiber -> execute_data ;
358
377
EG (jit_trace_num ) = 0 ;
@@ -392,15 +411,13 @@ static zend_object *zend_fiber_object_create(zend_class_entry *ce) /* {{{ */
392
411
zend_fiber * fiber ;
393
412
394
413
fiber = emalloc (sizeof (zend_fiber ));
395
- ZEND_SECURE_ZERO (fiber , sizeof (zend_fiber ));
414
+ memset (fiber , 0 , sizeof (zend_fiber ));
396
415
397
416
fiber -> id = EG (next_fiber_id )++ ;
398
417
399
418
zend_object_std_init (& fiber -> std , ce );
400
419
fiber -> std .handlers = & zend_fiber_handlers ;
401
420
402
- ZVAL_UNDEF (& fiber -> value );
403
-
404
421
zend_hash_index_add_ptr (& EG (fibers ), fiber -> id , fiber );
405
422
406
423
return & fiber -> std ;
@@ -458,7 +475,7 @@ ZEND_METHOD(Fiber, __construct)
458
475
zend_fiber * fiber = (zend_fiber * ) Z_OBJ_P (getThis ());
459
476
460
477
ZEND_PARSE_PARAMETERS_START (1 , 1 )
461
- Z_PARAM_FUNC_EX (fiber -> fci , fiber -> fci_cache , 0 , 0 )
478
+ Z_PARAM_FUNC (fiber -> fci , fiber -> fci_cache )
462
479
ZEND_PARSE_PARAMETERS_END ();
463
480
464
481
// Keep a reference to closures or callable objects until the fiber is started.
@@ -470,14 +487,22 @@ ZEND_METHOD(Fiber, __construct)
470
487
ZEND_METHOD (Fiber , start )
471
488
{
472
489
zend_fiber * fiber = (zend_fiber * ) Z_OBJ_P (getThis ());
490
+ zval * params ;
491
+ uint32_t param_count ;
492
+ zend_array * named_params ;
493
+
494
+ ZEND_PARSE_PARAMETERS_START (0 , -1 )
495
+ Z_PARAM_VARIADIC_WITH_NAMED (params , param_count , named_params );
496
+ ZEND_PARSE_PARAMETERS_END ();
473
497
474
498
if (fiber -> status != ZEND_FIBER_STATUS_INIT ) {
475
499
zend_throw_error (zend_ce_fiber_error , "Cannot start a fiber that has already been started" );
476
500
return ;
477
501
}
478
502
479
- fiber -> fci .params = ZEND_CALL_ARG (execute_data , 1 );
480
- fiber -> fci .param_count = ZEND_CALL_NUM_ARGS (execute_data );
503
+ fiber -> fci .params = params ;
504
+ fiber -> fci .param_count = param_count ;
505
+ fiber -> fci .named_params = named_params ;
481
506
482
507
if (!zend_fiber_init_context (& fiber -> context , zend_fiber_execute , EG (fiber_stack_size ))) {
483
508
zend_throw_error (NULL , "Could not create fiber context" );
@@ -505,6 +530,11 @@ ZEND_METHOD(Fiber, suspend)
505
530
zend_fiber * fiber = EG (current_fiber );
506
531
zval * error , * value = NULL ;
507
532
533
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
534
+ Z_PARAM_OPTIONAL
535
+ Z_PARAM_ZVAL (value );
536
+ ZEND_PARSE_PARAMETERS_END ();
537
+
508
538
if (UNEXPECTED (!fiber )) {
509
539
zend_throw_error (zend_ce_fiber_error , "Cannot suspend outside of a fiber" );
510
540
return ;
@@ -519,11 +549,6 @@ ZEND_METHOD(Fiber, suspend)
519
549
return ;
520
550
}
521
551
522
- ZEND_PARSE_PARAMETERS_START (0 , 1 )
523
- Z_PARAM_OPTIONAL
524
- Z_PARAM_ZVAL (value );
525
- ZEND_PARSE_PARAMETERS_END ();
526
-
527
552
if (value ) {
528
553
ZVAL_COPY (& fiber -> value , value );
529
554
} else {
0 commit comments