ok
Direktori : /proc/self/root/opt/alt/php80/usr/include/php/ext/swoole/ext-src/ |
Current File : //proc/self/root/opt/alt/php80/usr/include/php/ext/swoole/ext-src/php_swoole_coroutine.h |
/* +----------------------------------------------------------------------+ | Swoole | +----------------------------------------------------------------------+ | This source file is subject to version 2.0 of the Apache license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.apache.org/licenses/LICENSE-2.0.html | | If you did not receive a copy of the Apache2.0 license and are unable| | to obtain it through the world-wide-web, please send a note to | | license@swoole.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Xinyu Zhu <xyzhu1120@gmail.com> | | shiguangqi <shiguangqi2008@gmail.com> | | Twosee <twose@qq.com> | | Tianfeng Han <rango@swoole.com> | +----------------------------------------------------------------------+ */ #pragma once #include "swoole_coroutine.h" #include "swoole_coroutine_socket.h" #include "swoole_coroutine_system.h" #include "zend_vm.h" #include "zend_closures.h" #include <stack> #include <thread> #define SW_DEFAULT_MAX_CORO_NUM 100000 #define SW_DEFAULT_PHP_STACK_PAGE_SIZE 8192 #define SWOG ((zend_output_globals *) &OG(handlers)) SW_EXTERN_C_BEGIN PHP_METHOD(swoole_coroutine_scheduler, set); PHP_METHOD(swoole_coroutine_scheduler, getOptions); SW_EXTERN_C_END namespace zend { struct Function; } namespace swoole { struct PHPContext; struct FutureTask { zval coro_params; zval *current_coro_return_value_ptr; void *private_data; TimerNode *timer; PHPContext *current_task; }; struct PHPContext { JMP_BUF *bailout; zval *vm_stack_top; zval *vm_stack_end; zend_vm_stack vm_stack; size_t vm_stack_page_size; zend_execute_data *execute_data; #if PHP_VERSION_ID >= 80000 uint32_t jit_trace_num; #endif zend_error_handling_t error_handling; zend_class_entry *exception_class; zend_object *exception; zend_output_globals *output_ptr; #if PHP_VERSION_ID < 80100 /* for array_walk non-reentrancy */ zend::Function *array_walk_fci; #endif /* for error control `@` */ bool in_silence; bool enable_scheduler; int ori_error_reporting; int tmp_error_reporting; Coroutine *co; std::stack<zend::Function *> *defer_tasks; long pcid; zend_object *context; int64_t last_msec; }; class PHPCoroutine { public: struct Args { zend_fcall_info_cache *fci_cache; zval *argv; uint32_t argc; }; struct Config { uint64_t max_num; uint32_t hook_flags; bool enable_preemptive_scheduler; bool enable_deadlock_check; }; static zend_array *options; enum HookType { HOOK_NONE = 0, HOOK_TCP = 1u << 1, HOOK_UDP = 1u << 2, HOOK_UNIX = 1u << 3, HOOK_UDG = 1u << 4, HOOK_SSL = 1u << 5, HOOK_TLS = 1u << 6, HOOK_STREAM_FUNCTION = 1u << 7, HOOK_FILE = 1u << 8, HOOK_SLEEP = 1u << 9, HOOK_PROC = 1u << 10, HOOK_CURL = 1u << 11, HOOK_NATIVE_CURL = 1u << 12, HOOK_BLOCKING_FUNCTION = 1u << 13, HOOK_SOCKETS = 1u << 14, HOOK_STDIO = 1u << 15, #ifdef SW_USE_CURL HOOK_ALL = 0x7fffffff ^ HOOK_CURL, #else HOOK_ALL = 0x7fffffff ^ HOOK_NATIVE_CURL, #endif }; static const uint8_t MAX_EXEC_MSEC = 10; static void init(); static void shutdown(); static long create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv); static void defer(zend::Function *fci); static void deadlock_check(); static bool enable_hook(uint32_t flags); static bool disable_hook(); static void disable_unsafe_function(); static void enable_unsafe_function(); static void interrupt_thread_stop(); // TODO: remove old coro APIs (Manual) static void yield_m(zval *return_value, FutureTask *task); static void resume_m(FutureTask *task, zval *retval); static inline long get_cid() { return sw_likely(activated) ? Coroutine::get_current_cid() : -1; } static inline long get_pcid(long cid = 0) { PHPContext *task = cid == 0 ? get_context() : get_context_by_cid(cid); return sw_likely(task) ? task->pcid : 0; } static inline long get_elapsed(long cid = 0) { return sw_likely(activated) ? Coroutine::get_elapsed(cid) : -1; } static inline PHPContext *get_context() { PHPContext *task = (PHPContext *) Coroutine::get_current_task(); return task ? task : &main_task; } static inline PHPContext *get_origin_context(PHPContext *task) { Coroutine *co = task->co->get_origin(); return co ? (PHPContext *) co->get_task() : &main_task; } static inline PHPContext *get_context_by_cid(long cid) { return cid == -1 ? &main_task : (PHPContext *) Coroutine::get_task_by_cid(cid); } static inline uint64_t get_max_num() { return config.max_num; } static inline void set_max_num(uint64_t n) { config.max_num = n; } static inline void set_deadlock_check(bool value = true) { config.enable_deadlock_check = value; } static inline bool is_schedulable(PHPContext *task) { return task->enable_scheduler && (Timer::get_absolute_msec() - task->last_msec > MAX_EXEC_MSEC); } static inline bool enable_scheduler() { PHPContext *task = (PHPContext *) Coroutine::get_current_task(); if (task && !task->enable_scheduler) { task->enable_scheduler = true; return true; } return false; } static inline bool disable_scheduler() { PHPContext *task = (PHPContext *) Coroutine::get_current_task(); if (task && task->enable_scheduler) { task->enable_scheduler = false; return true; } return false; } static void set_hook_flags(uint32_t flags); static inline uint32_t get_hook_flags() { return config.hook_flags; } static inline void enable_preemptive_scheduler(bool value) { config.enable_preemptive_scheduler = value; } static inline bool is_activated() { return activated; } protected: static bool activated; static PHPContext main_task; static Config config; static bool interrupt_thread_running; static std::thread interrupt_thread; static void activate(); static void deactivate(void *ptr); static inline void vm_stack_init(void); static inline void vm_stack_destroy(void); static inline void save_vm_stack(PHPContext *task); static inline void restore_vm_stack(PHPContext *task); static inline void save_og(PHPContext *task); static inline void restore_og(PHPContext *task); static inline void save_task(PHPContext *task); static inline void restore_task(PHPContext *task); static void on_yield(void *arg); static void on_resume(void *arg); static void on_close(void *arg); static void main_func(void *arg); static void interrupt_thread_start(); static inline void record_last_msec(PHPContext *task) { if (interrupt_thread_running) { task->last_msec = Timer::get_absolute_msec(); } } }; } // namespace swoole /** * for gdb */ zend_executor_globals *php_swoole_get_executor_globals();