Permalink
61a5e8f Jan 23, 2017
@krakjoe @2072 @hfedcba @reeze
915 lines (814 sloc) 35.2 KB
/*
+----------------------------------------------------------------------+
| pthreads |
+----------------------------------------------------------------------+
| Copyright (c) Joe Watkins 2012 - 2014 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Joe Watkins <joe.watkins@live.co.uk> |
+----------------------------------------------------------------------+
*/
#ifndef HAVE_PHP_PTHREADS
#define HAVE_PHP_PTHREADS
#ifndef HAVE_PTHREADS_H
# include <src/pthreads.h>
#endif
#ifndef HAVE_PHP_PTHREADS_H
# include <php_pthreads.h>
#endif
#ifndef HAVE_PTHREADS_OBJECT_H
# include <src/object.h>
#endif
#ifndef ZTS
# error "pthreads requires that Thread Safety is enabled, add --enable-maintainer-zts to your PHP build configuration"
#endif
#if COMPILE_DL_PTHREADS
ZEND_TSRMLS_CACHE_DEFINE();
ZEND_GET_MODULE(pthreads)
#endif
#ifndef HAVE_PTHREADS_GLOBALS_H
# include <src/globals.h>
#endif
#ifndef HAVE_PTHREADS_COPY_H
# include <src/copy.h>
#endif
ZEND_BEGIN_ARG_INFO_EX(pthreads_no_sleeping_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, timeout)
ZEND_END_ARG_INFO()
PHP_FUNCTION(pthreads_no_sleeping) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0,
"%s is not suitable for use in multi threaded applications, use synchronized Threaded::wait",
ZSTR_VAL(EX(func)->common.function_name));
}
static zend_function_entry pthreads_functions[] = {
PHP_FE(pthreads_no_sleeping, pthreads_no_sleeping_arginfo)
PHP_FE_END
};
zend_module_entry pthreads_module_entry = {
STANDARD_MODULE_HEADER,
PHP_PTHREADS_EXTNAME,
pthreads_functions,
PHP_MINIT(pthreads),
PHP_MSHUTDOWN(pthreads),
PHP_RINIT(pthreads),
PHP_RSHUTDOWN(pthreads),
PHP_MINFO(pthreads),
PHP_PTHREADS_VERSION,
NO_MODULE_GLOBALS,
ZEND_MODULE_POST_ZEND_DEACTIVATE_N(pthreads),
STANDARD_MODULE_PROPERTIES_EX
};
zend_class_entry *pthreads_threaded_entry;
zend_class_entry *pthreads_volatile_entry;
zend_class_entry *pthreads_thread_entry;
zend_class_entry *pthreads_worker_entry;
zend_class_entry *pthreads_collectable_entry;
zend_class_entry *pthreads_pool_entry;
zend_class_entry *pthreads_socket_entry;
zend_object_handlers pthreads_handlers;
zend_object_handlers pthreads_socket_handlers;
zend_object_handlers *zend_handlers;
void ***pthreads_instance = NULL;
#ifndef HAVE_SPL
zend_class_entry *spl_ce_InvalidArgumentException;
zend_class_entry *spl_ce_Countable;
zend_class_entry *spl_ce_RuntimeException;
#endif
#ifndef HAVE_PTHREADS_OBJECT_H
# include <src/object.h>
#endif
ZEND_DECLARE_MODULE_GLOBALS(pthreads)
typedef struct _pthreads_supported_sapi_t {
const char *name;
size_t nlen;
} pthreads_supported_sapi_t;
const static pthreads_supported_sapi_t whitelist[] = {
{ZEND_STRL("cli")},
{ZEND_STRL("phpdbg")}, /* not really supported, needs work */
{ZEND_STRL("homegear")},
{NULL, 0}
};
static inline zend_bool pthreads_is_supported_sapi(char *name) {
const pthreads_supported_sapi_t *sapi = whitelist;
zend_long nlen = strlen(name);
while (sapi->name) {
if (nlen == sapi->nlen &&
memcmp(sapi->name, name, nlen) == SUCCESS) {
return 1;
}
sapi++;
}
return 0;
}
typedef void (*zend_execute_ex_function)(zend_execute_data *);
zend_execute_ex_function zend_execute_ex_hook = NULL;
static inline void pthreads_globals_ctor(zend_pthreads_globals *pg) {
ZVAL_UNDEF(&pg->this);
pg->pid = 0L;
pg->signal = 0;
pg->resources = NULL;
}
/* {{{ */
static inline void pthreads_execute_ex(zend_execute_data *data) {
if (zend_execute_ex_hook) {
zend_execute_ex_hook(data);
} else execute_ex(data);
if (Z_TYPE(PTHREADS_ZG(this)) != IS_UNDEF) {
if (EG(exception) &&
(!EG(current_execute_data) || !EG(current_execute_data)->prev_execute_data))
zend_try_exception_handler();
}
} /* }}} */
/* {{{ */
static inline zend_bool pthreads_verify_type(zend_execute_data *execute_data, zval *var, zend_arg_info *info) {
pthreads_object_t *threaded = NULL;
if (!var ||
#if PHP_VERSION_ID >= 70200
!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(info->type), Z_TYPE_P(var)) &&
!ZEND_TYPE_IS_CLASS(info->type) ||
#else
!ZEND_SAME_FAKE_TYPE(info->type_hint, Z_TYPE_P(var)) ||
info->type_hint != IS_OBJECT ||
#endif
!instanceof_function(Z_OBJCE_P(var), pthreads_threaded_entry)) {
return 0;
}
threaded = PTHREADS_FETCH_FROM(Z_OBJ_P(var));
if (!PTHREADS_IN_CREATOR(threaded)) {
zend_class_entry **cached =
(zend_class_entry**) CACHE_ADDR(EX(opline)->op2.num),
*ce = NULL,
*instance = NULL;
ce = *cached ?
*cached :
#if PHP_VERSION_ID >= 70200
zend_lookup_class(ZEND_TYPE_NAME(info->type));
#else
zend_lookup_class(info->class_name);
#endif
if (!ce)
return 0;
if (*cached == NULL)
*cached = ce;
instance = zend_lookup_class(threaded->std.ce->name);
if (instanceof_function(instance, ce)) {
return 1;
}
}
return 0;
} /* }}} */
/* {{{ */
static inline int php_pthreads_recv(ZEND_OPCODE_HANDLER_ARGS) {
if (Z_TYPE(PTHREADS_ZG(this)) != IS_UNDEF) {
zend_execute_data *execute_data = EG(current_execute_data);
uint32_t arg_num = EX(opline)->op1.num;
zval *var = NULL;
if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
return ZEND_USER_OPCODE_DISPATCH;
}
#if ZEND_USE_ABS_CONST_ADDR
if (EX(opline)->result_type == IS_CONST) {
var = (zval*) EX(opline)->result.var;
} else var = EX_VAR(EX(opline)->result.num);
#else
var = EX_VAR(EX(opline)->result.num);
#endif
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
if (pthreads_verify_type(execute_data,
var,
&EX(func)->common.arg_info[arg_num-1])) {
EX(opline)++;
return ZEND_USER_OPCODE_CONTINUE;
}
}
}
return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */
/* {{{ */
static inline int php_pthreads_verify_return_type(ZEND_OPCODE_HANDLER_ARGS) {
if (Z_TYPE(PTHREADS_ZG(this)) != IS_UNDEF) {
zend_execute_data *execute_data = EG(current_execute_data);
zval *var = NULL;
if (EX(opline)->op1_type == IS_UNUSED) {
return ZEND_USER_OPCODE_DISPATCH;
}
#if ZEND_USE_ABS_CONST_ADDR
if (EX(opline)->op1_type & IS_CONST) {
var = (zval*) EX(opline)->op1.var;
} else var = EX_VAR(EX(opline)->op1.num);
#else
var = EX_VAR(EX(opline)->op1.num);
#endif
if (pthreads_verify_type(execute_data,
var,
EX(func)->common.arg_info - 1)) {
EX(opline)++;
return ZEND_USER_OPCODE_CONTINUE;
}
}
return ZEND_USER_OPCODE_DISPATCH;
} /* }}} */
PHP_MINIT_FUNCTION(pthreads)
{
zend_class_entry ce;
if (!pthreads_is_supported_sapi(sapi_module.name)) {
zend_error(E_ERROR, "The %s SAPI is not supported by pthreads",
sapi_module.name);
return FAILURE;
}
zend_execute_ex_hook = zend_execute_ex;
zend_execute_ex = pthreads_execute_ex;
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_ALL", PTHREADS_INHERIT_ALL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_NONE", PTHREADS_INHERIT_NONE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_INI", PTHREADS_INHERIT_INI, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_CONSTANTS", PTHREADS_INHERIT_CONSTANTS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_CLASSES", PTHREADS_INHERIT_CLASSES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_FUNCTIONS", PTHREADS_INHERIT_FUNCTIONS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_INCLUDES", PTHREADS_INHERIT_INCLUDES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_INHERIT_COMMENTS", PTHREADS_INHERIT_COMMENTS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PTHREADS_ALLOW_HEADERS", PTHREADS_ALLOW_HEADERS, CONST_CS | CONST_PERSISTENT);
INIT_CLASS_ENTRY(ce, "Collectable", pthreads_collectable_methods);
pthreads_collectable_entry = zend_register_internal_interface(&ce);
INIT_CLASS_ENTRY(ce, "Threaded", pthreads_threaded_methods);
pthreads_threaded_entry=zend_register_internal_class(&ce);
pthreads_threaded_entry->get_iterator = pthreads_object_iterator_create;
pthreads_threaded_entry->create_object = pthreads_threaded_ctor;
pthreads_threaded_entry->serialize = pthreads_threaded_serialize;
pthreads_threaded_entry->unserialize = pthreads_threaded_unserialize;
zend_class_implements(pthreads_threaded_entry, 2, zend_ce_traversable, pthreads_collectable_entry);
INIT_CLASS_ENTRY(ce, "Volatile", NULL);
pthreads_volatile_entry = zend_register_internal_class_ex(&ce, pthreads_threaded_entry);
INIT_CLASS_ENTRY(ce, "Thread", pthreads_thread_methods);
pthreads_thread_entry=zend_register_internal_class_ex(&ce, pthreads_threaded_entry);
pthreads_thread_entry->create_object = pthreads_thread_ctor;
INIT_CLASS_ENTRY(ce, "Worker", pthreads_worker_methods);
pthreads_worker_entry=zend_register_internal_class_ex(&ce, pthreads_thread_entry);
pthreads_worker_entry->create_object = pthreads_worker_ctor;
INIT_CLASS_ENTRY(ce, "Pool", pthreads_pool_methods);
pthreads_pool_entry=zend_register_internal_class(&ce);
zend_declare_property_long(pthreads_pool_entry, ZEND_STRL("size"), 1, ZEND_ACC_PROTECTED);
zend_declare_property_null(pthreads_pool_entry, ZEND_STRL("class"), ZEND_ACC_PROTECTED);
zend_declare_property_null(pthreads_pool_entry, ZEND_STRL("workers"), ZEND_ACC_PROTECTED);
zend_declare_property_null(pthreads_pool_entry, ZEND_STRL("ctor"), ZEND_ACC_PROTECTED);
zend_declare_property_long(pthreads_pool_entry, ZEND_STRL("last"), 0, ZEND_ACC_PROTECTED);
INIT_CLASS_ENTRY(ce, "Socket", pthreads_socket_methods);
pthreads_socket_entry = zend_register_internal_class_ex(&ce, pthreads_threaded_entry);
pthreads_socket_entry->create_object = pthreads_socket_ctor;
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("AF_UNIX"), AF_UNIX);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("AF_INET"), AF_INET);
#ifdef HAVE_IPV6
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("AF_INET6"), AF_INET6);
#endif
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOCK_STREAM"), SOCK_STREAM);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOCK_DGRAM"), SOCK_DGRAM);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOCK_RAW"), SOCK_RAW);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOCK_SEQPACKET"), SOCK_SEQPACKET);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOCK_RDM"), SOCK_RDM);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_DEBUG"), SO_DEBUG);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_REUSEADDR"), SO_REUSEADDR);
#ifdef SO_REUSEPORT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_REUSEPORT"), SO_REUSEPORT);
#endif
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_KEEPALIVE"), SO_KEEPALIVE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_DONTROUTE"), SO_DONTROUTE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_LINGER"), SO_LINGER);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_BROADCAST"), SO_BROADCAST);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_OOBINLINE"), SO_OOBINLINE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_SNDBUF"), SO_SNDBUF);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_RECBUF"), SO_RCVBUF);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_SNDLOWAT"), SO_SNDLOWAT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_RCVLOWAT"), SO_RCVLOWAT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_SNDTIMEO"), SO_SNDTIMEO);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_RCVTIMEO"), SO_RCVTIMEO);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_TYPE"), SO_TYPE);
#ifdef SO_FAMILY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_FAMILY"), SO_FAMILY);
#endif
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_ERROR"), SO_ERROR);
#ifdef SO_BINDTODEVICE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SO_BINDTODEVICE"), SO_BINDTODEVICE);
#endif
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOMAXCONN"), SOMAXCONN);
#ifdef TCP_NODELAY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("TCP_NODELAY"), TCP_NODELAY);
#endif
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOL_SOCKET"), SOL_SOCKET);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOL_TCP"), IPPROTO_TCP);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SOL_UDP"), IPPROTO_UDP);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_OOB"), MSG_OOB);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_WAITALL"), MSG_WAITALL);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_CTRUNC"), MSG_CTRUNC);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_TRUNC"), MSG_TRUNC);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_PEEK"), MSG_PEEK);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_DONTROUTE"), MSG_DONTROUTE);
#ifdef MSG_EOR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_EOR"), MSG_EOR);
#endif
#ifdef MSG_EOF
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_EOF"), MSG_EOF);
#endif
#ifdef MSG_CONFIRM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_CONFIRM"), MSG_CONFIRM);
#endif
#ifdef MSG_ERRQUEUE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_ERRQUEUE"), MSG_ERRQUEUE);
#endif
#ifdef MSG_NOSIGNAL
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_NOSIGNAL"), MSG_NOSIGNAL);
#endif
#ifdef MSG_MORE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_MORE"), MSG_MORE);
#endif
#ifdef MSG_WAITFORONE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_WAITFORONE"), MSG_WAITFORONE);
#endif
#ifdef MSG_CMSG_CLOEXEC
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("MSG_CMSG_CLOEXEC"), MSG_CMSG_CLOEXEC);
#endif
#ifndef _WIN32
#ifdef EPERM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPERM"), EPERM);
#endif
#ifdef ENOENT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOENT"), ENOENT);
#endif
#ifdef EINTR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINTR"), EINTR);
#endif
#ifdef EIO
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EIO"), EIO);
#endif
#ifdef ENXIO
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENXIO"), ENXIO);
#endif
#ifdef E2BIG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("E2BIG"), E2BIG);
#endif
#ifdef EBADF
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADF"), EBADF);
#endif
#ifdef EAGAIN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EAGAIN"), EAGAIN);
#endif
#ifdef ENOMEM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOMEM"), ENOMEM);
#endif
#ifdef EACCES
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EACCES"), EACCES);
#endif
#ifdef EFAULT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EFAULT"), EFAULT);
#endif
#ifdef ENOTBLK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTBLK"), ENOTBLK);
#endif
#ifdef EBUSY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBUSY"), EBUSY);
#endif
#ifdef EEXIST
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EEXIST"), EEXIST);
#endif
#ifdef EXDEV
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EXDEV"), EXDEV);
#endif
#ifdef ENODEV
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENODEV"), ENODEV);
#endif
#ifdef ENOTDIR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTDIR"), ENOTDIR);
#endif
#ifdef EISDIR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EISDIR"), EISDIR);
#endif
#ifdef EINVAL
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINVAL"), EINVAL);
#endif
#ifdef ENFILE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENFILE"), ENFILE);
#endif
#ifdef EMFILE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMFILE"), EMFILE);
#endif
#ifdef ENOTTY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTTY"), ENOTTY);
#endif
#ifdef ENOSPC
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOSPC"), ENOSPC);
#endif
#ifdef ESPIPE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESPIPE"), ESPIPE);
#endif
#ifdef EROFS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EROFS"), EROFS);
#endif
#ifdef EMLINK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMLINK"), EMLINK);
#endif
#ifdef EPIPE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPIPE"), EPIPE);
#endif
#ifdef ENAMETOOLONG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENAMETOOLONG"), ENAMETOOLONG);
#endif
#ifdef ENOLCK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOLCK"), ENOLCK);
#endif
#ifdef ENOSYS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOSYS"), ENOSYS);
#endif
#ifdef ENOTEMPTY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTEMPTY"), ENOTEMPTY);
#endif
#ifdef ELOOP
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ELOOP"), ELOOP);
#endif
#ifdef EWOULDBLOCK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EWOULDBLOCK"), EWOULDBLOCK);
#endif
#ifdef ENOMSG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOMSG"), ENOMSG);
#endif
#ifdef EIDRM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EIDRM"), EIDRM);
#endif
#ifdef ECHRNG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECHRNG"), ECHRNG);
#endif
#ifdef EL2NSYNC
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EL2NSYNC"), EL2NSYNC);
#endif
#ifdef EL3HLT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EL3HLT"), EL3HLT);
#endif
#ifdef EL3RST
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EL3RST"), EL3RST);
#endif
#ifdef ELNRNG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ELNRNG"), ELNRNG);
#endif
#ifdef EUNATCH
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EUNATCH"), EUNATCH);
#endif
#ifdef ENOCSI
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOCSI"), ENOCSI);
#endif
#ifdef EL2HLT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EL2HLT"), EL2HLT);
#endif
#ifdef EBADE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADE"), EBADE);
#endif
#ifdef EBADR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADR"), EBADR);
#endif
#ifdef EXFULL
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EXFULL"), EXFULL);
#endif
#ifdef ENOANO
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOANO"), ENOANO);
#endif
#ifdef EBADRQC
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADRQC"), EBADRQC);
#endif
#ifdef EBADSLT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADSLT"), EBADSLT);
#endif
#ifdef ENOSTR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOSTR"), ENOSTR);
#endif
#ifdef ENODATA
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENODATA"), ENODATA);
#endif
#ifdef ETIME
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ETIME"), ETIME);
#endif
#ifdef ENOSR
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOSR"), ENOSR);
#endif
#ifdef ENONET
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENONET"), ENONET);
#endif
#ifdef EREMOTE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EREMOTE"), EREMOTE);
#endif
#ifdef ENOLINK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOLINK"), ENOLINK);
#endif
#ifdef EADV
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EADV"), EADV);
#endif
#ifdef ESRMNT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESRMNT"), ESRMNT);
#endif
#ifdef ECOMM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECOMM"), ECOMM);
#endif
#ifdef EPROTO
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROTO"), EPROTO);
#endif
#ifdef EMULTIHOP
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMULTIHOP"), EMULTIHOP);
#endif
#ifdef EBADMSG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADMSG"), EBADMSG);
#endif
#ifdef ENOTUNIQ
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTUNIQ"), ENOTUNIQ);
#endif
#ifdef EBADFD
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADFD"), EBADFD);
#endif
#ifdef EREMCHG
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EREMCHG"), EREMCHG);
#endif
#ifdef ERESTART
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ERESTART"), ERESTART);
#endif
#ifdef ESTRPIPE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESTRPIPE"), ESTRPIPE);
#endif
#ifdef EUSERS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EUSERS"), EUSERS);
#endif
#ifdef ENOTSOCK
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTSOCK"), ENOTSOCK);
#endif
#ifdef EDESTADDRREQ
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EDESTADDRREQ"), EDESTADDRREQ);
#endif
#ifdef EMSGSIZE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMSGSIZE"), EMSGSIZE);
#endif
#ifdef EPROTOTYPE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROTOTYPE"), EPROTOTYPE);
#endif
#ifdef ENOPROTOOPT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOPROTOOPT"), ENOPROTOOPT);
#endif
#ifdef EPROTONOSUPPORT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROTONOSUPPORT"), EPROTONOSUPPORT);
#endif
#ifdef ESOCKTNOSUPPORT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESOCKTNOSUPPORT"), ESOCKTNOSUPPORT);
#endif
#ifdef EOPNOTSUPP
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EOPNOTSUPP"), EOPNOTSUPP);
#endif
#ifdef EPFNOSUPPORT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPFNOSUPPORT"), EPFNOSUPPORT);
#endif
#ifdef EAFNOSUPPORT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EAFNOSUPPORT"), EAFNOSUPPORT);
#endif
#ifdef EADDRINUSE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EADDRINUSE"), EADDRINUSE);
#endif
#ifdef EADDRNOTAVAIL
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EADDRNOTAVAIL"), EADDRNOTAVAIL);
#endif
#ifdef ENETDOWN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETDOWN"), ENETDOWN);
#endif
#ifdef ENETUNREACH
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETUNREACH"), ENETUNREACH);
#endif
#ifdef ENETRESET
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETRESET"), ENETRESET);
#endif
#ifdef ECONNABORTED
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNABORTED"), ECONNABORTED);
#endif
#ifdef ECONNRESET
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNRESET"), ECONNRESET);
#endif
#ifdef ENOBUFS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOBUFS"), ENOBUFS);
#endif
#ifdef EISCONN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EISCONN"), EISCONN);
#endif
#ifdef ENOTCONN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTCONN"), ENOTCONN);
#endif
#ifdef ESHUTDOWN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESHUTDOWN"), ESHUTDOWN);
#endif
#ifdef ETOOMANYREFS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ETOOMANYREFS"), ETOOMANYREFS);
#endif
#ifdef ETIMEDOUT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ETIMEDOUT"), ETIMEDOUT);
#endif
#ifdef ECONNREFUSED
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNREFUSED"), ECONNREFUSED);
#endif
#ifdef EHOSTDOWN
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EHOSTDOWN"), EHOSTDOWN);
#endif
#ifdef EHOSTUNREACH
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EHOSTUNREACH"), EHOSTUNREACH);
#endif
#ifdef EALREADY
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EALREADY"), EALREADY);
#endif
#ifdef EINPROGRESS
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINPROGRESS"), EINPROGRESS);
#endif
#ifdef EISNAM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EISNAM"), EISNAM);
#endif
#ifdef EREMOTEIO
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EREMOTEIO"), EREMOTEIO);
#endif
#ifdef EDQUOT
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EDQUOT"), EDQUOT);
#endif
#ifdef ENOMEDIUM
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOMEDIUM"), ENOMEDIUM);
#endif
#ifdef EMEDIUMTYPE
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMEDIUMTYPE"), EMEDIUMTYPE);
#endif
#else
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINTR"), WSAEINTR);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EBADF"), WSAEBADF);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EACCES"), WSAEACCES);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EFAULT"), WSAEFAULT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINVAL"), WSAEINVAL);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMFILE"), WSAEMFILE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EWOULDBLOCK"), WSAEWOULDBLOCK);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EINPROGRESS"), WSAEINPROGRESS);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EALREADY"), WSAEALREADY);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTSOCK"), WSAENOTSOCK);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EDESTADDRREQ"), WSAEDESTADDRREQ);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EMSGSIZE"), WSAEMSGSIZE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROTOTYPE"), WSAEPROTOTYPE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOPROTOOPT"), WSAENOPROTOOPT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROTONOSUPPORT"), WSAEPROTONOSUPPORT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESOCKTNOSUPPORT"), WSAESOCKTNOSUPPORT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EOPNOTSUPP"), WSAEOPNOTSUPP);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPFNOSUPPORT"), WSAEPFNOSUPPORT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EAFNOSUPPORT"), WSAEAFNOSUPPORT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EADDRINUSE"), WSAEADDRINUSE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EADDRNOTAVAIL"), WSAEADDRNOTAVAIL);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETDOWN"), WSAENETDOWN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETUNREACH"), WSAENETUNREACH);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENETRESET"), WSAENETRESET);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNABORTED"), WSAECONNABORTED);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNRESET"), WSAECONNRESET);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOBUFS"), WSAENOBUFS);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EISCONN"), WSAEISCONN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTCONN"), WSAENOTCONN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESHUTDOWN"), WSAESHUTDOWN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ETOOMANYREFS"), WSAETOOMANYREFS);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ETIMEDOUT"), WSAETIMEDOUT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ECONNREFUSED"), WSAECONNREFUSED);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ELOOP"), WSAELOOP);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENAMETOOLONG"), WSAENAMETOOLONG);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EHOSTDOWN"), WSAEHOSTDOWN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EHOSTUNREACH"), WSAEHOSTUNREACH);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ENOTEMPTY"), WSAENOTEMPTY);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EPROCLIM"), WSAEPROCLIM);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EUSERS"), WSAEUSERS);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EDQUOT"), WSAEDQUOT);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("ESTALE"), WSAESTALE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EREMOTE"), WSAEREMOTE);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("EDISCON"), WSAEDISCON);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("SYSNOTREADY"), WSASYSNOTREADY);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("VERNOTSUPPORTED"), WSAVERNOTSUPPORTED);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("NOTINITIALISED"), WSANOTINITIALISED);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("HOST_NOT_FOUND"), WSAHOST_NOT_FOUND);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("TRY_AGAIN"), WSATRY_AGAIN);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("NO_RECOVERY"), WSANO_RECOVERY);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("NO_DATA"), WSANO_DATA);
zend_declare_class_constant_long(pthreads_socket_entry, ZEND_STRL("NO_ADDRESS"), WSANO_ADDRESS);
#endif
/*
* Setup object handlers
*/
zend_handlers = zend_get_std_object_handlers();
memcpy(&pthreads_handlers, zend_handlers, sizeof(zend_object_handlers));
pthreads_handlers.offset = XtOffsetOf(pthreads_object_t, std);
pthreads_handlers.free_obj = pthreads_base_free;
pthreads_handlers.cast_object = pthreads_cast_object;
pthreads_handlers.count_elements = pthreads_count_properties;
pthreads_handlers.get_debug_info = pthreads_read_debug;
pthreads_handlers.get_properties = pthreads_read_properties;
pthreads_handlers.read_property = pthreads_read_property;
pthreads_handlers.write_property = pthreads_write_property;
pthreads_handlers.has_property = pthreads_has_property;
pthreads_handlers.unset_property = pthreads_unset_property;
pthreads_handlers.read_dimension = pthreads_read_dimension;
pthreads_handlers.write_dimension = pthreads_write_dimension;
pthreads_handlers.has_dimension = pthreads_has_dimension;
pthreads_handlers.unset_dimension = pthreads_unset_dimension;
pthreads_handlers.get_property_ptr_ptr = NULL;
pthreads_handlers.get = NULL;
pthreads_handlers.set = NULL;
pthreads_handlers.get_gc = pthreads_base_gc;
pthreads_handlers.clone_obj = pthreads_base_clone;
pthreads_handlers.compare_objects = pthreads_compare_objects;
memcpy(&pthreads_socket_handlers, &pthreads_handlers, sizeof(zend_object_handlers));
pthreads_socket_handlers.count_elements = pthreads_count_properties_disallow;
pthreads_socket_handlers.cast_object = zend_handlers->cast_object;
pthreads_socket_handlers.get_properties = pthreads_read_properties_disallow;
pthreads_socket_handlers.read_property = pthreads_read_property_disallow;
pthreads_socket_handlers.write_property = pthreads_write_property_disallow;
pthreads_socket_handlers.has_property = pthreads_has_property_disallow;
pthreads_socket_handlers.unset_property = pthreads_unset_property_disallow;
pthreads_socket_handlers.read_dimension = pthreads_read_dimension_disallow;
pthreads_socket_handlers.write_dimension = pthreads_write_dimension_disallow;
pthreads_socket_handlers.has_dimension = pthreads_has_dimension_disallow;
pthreads_socket_handlers.unset_dimension = pthreads_unset_dimension_disallow;
ZEND_INIT_MODULE_GLOBALS(pthreads, pthreads_globals_ctor, NULL);
if (pthreads_globals_init()) {
TSRMLS_CACHE_UPDATE();
/*
* Global Init
*/
pthreads_instance = TSRMLS_CACHE;
}
#ifndef HAVE_SPL
spl_ce_InvalidArgumentException = zend_exception_get_default();
spl_ce_Countable = zend_exception_get_default();
spl_ce_RuntimeException = zend_exception_get_default();
#endif
zend_set_user_opcode_handler(ZEND_RECV, php_pthreads_recv);
zend_set_user_opcode_handler(ZEND_VERIFY_RETURN_TYPE, php_pthreads_verify_return_type);
return SUCCESS;
}
static inline int sapi_cli_deactivate(void)
{
fflush(stdout);
if (SG(request_info).argv0) {
free(SG(request_info).argv0);
SG(request_info).argv0 = NULL;
}
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(pthreads)
{
if (pthreads_instance == TSRMLS_CACHE) {
pthreads_globals_shutdown();
if (memcmp(sapi_module.name, ZEND_STRL("cli")) == SUCCESS) {
sapi_module.deactivate = sapi_cli_deactivate;
}
}
zend_execute_ex = zend_execute_ex_hook;
return SUCCESS;
}
ZEND_MODULE_POST_ZEND_DEACTIVATE_D(pthreads)
{
if (PTHREADS_ZG(resources)) {
zend_hash_destroy(PTHREADS_ZG(resources));
FREE_HASHTABLE(PTHREADS_ZG(resources));
PTHREADS_ZG(resources) = NULL;
}
return SUCCESS;
}
PHP_RINIT_FUNCTION(pthreads) {
ZEND_TSRMLS_CACHE_UPDATE();
zend_hash_init(&PTHREADS_ZG(resolve), 15, NULL, NULL, 0);
if (pthreads_instance != TSRMLS_CACHE) {
if (memcmp(sapi_module.name, ZEND_STRL("cli")) == SUCCESS) {
sapi_module.deactivate = NULL;
}
}
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(pthreads) {
zend_hash_destroy(&PTHREADS_ZG(resolve));
return SUCCESS;
}
PHP_MINFO_FUNCTION(pthreads)
{
php_info_print_table_start();
php_info_print_table_row(2, "Version", PHP_PTHREADS_VERSION);
php_info_print_table_end();
}
#ifndef HAVE_PTHREADS_CLASS_THREADED
# include <classes/threaded.h>
#endif
#ifndef HAVE_PTHREADS_CLASS_THREAD
# include <classes/thread.h>
#endif
#ifndef HAVE_PTHREADS_CLASS_COLLECTABLE
# include <classes/collectable.h>
#endif
#ifndef HAVE_PTHREADS_CLASS_WORKER
# include <classes/worker.h>
#endif
#ifndef HAVE_PTHREADS_CLASS_POOL
# include <classes/pool.h>
#endif
#ifndef HAVE_PTHREADS_CLASS_SOCKET
# include <classes/socket.h>
#endif
#endif