summaryrefslogtreecommitdiff
path: root/ext/mysqlnd/mysqlnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd/mysqlnd.c')
-rw-r--r--ext/mysqlnd/mysqlnd.c368
1 files changed, 347 insertions, 21 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 5e32d7fda7..6e7441dcea 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -66,12 +66,205 @@ const char * mysqlnd_out_of_sync = "Commands out of sync; you can't run this com
MYSQLND_STATS *mysqlnd_global_stats = NULL;
static zend_bool mysqlnd_library_initted = FALSE;
+MYSQLND_MEMORY_POOL mysqlnd_memory_pool;
static enum_func_status mysqlnd_send_close(MYSQLND * conn TSRMLS_DC);
+#define MYSQLND_SILENT 1
+
+#ifdef MYSQLND_THREADED
+/* {{{ _mysqlnd_fetch_thread */
+void * _mysqlnd_fetch_thread(void *arg)
+{
+ MYSQLND *conn = (MYSQLND *) arg;
+ MYSQLND_RES * result = NULL;
+ void ***tsrm_ls = conn->tsrm_ls;
+#ifndef MYSQLND_SILENT
+ printf("conn=%p tsrm_ls=%p\n", conn, conn->tsrm_ls);
+#endif
+ do {
+ pthread_mutex_lock(&conn->LOCK_work);
+ while (conn->thread_killed == FALSE /* && there is work */) {
+#ifndef MYSQLND_SILENT
+ printf("Waiting for work in %s\n", __FUNCTION__);
+#endif
+ pthread_cond_wait(&conn->COND_work, &conn->LOCK_work);
+ }
+ if (conn->thread_killed == TRUE) {
+#ifndef MYSQLND_SILENT
+ printf("Thread killed in %s\n", __FUNCTION__);
+#endif
+ pthread_cond_signal(&conn->COND_thread_ended);
+ pthread_mutex_unlock(&conn->LOCK_work);
+ break;
+ }
+#ifndef MYSQLND_SILENT
+ printf("Got work in %s\n", __FUNCTION__);
+#endif
+ CONN_SET_STATE(conn, CONN_FETCHING_DATA);
+ result = conn->current_result;
+ conn->current_result = NULL;
+ pthread_mutex_unlock(&conn->LOCK_work);
+
+ mysqlnd_background_store_result_fetch_data(result TSRMLS_CC);
+
+ /* do fetch the data from the wire */
+
+ pthread_mutex_lock(&conn->LOCK_work);
+ CONN_SET_STATE(conn, CONN_READY);
+ pthread_cond_signal(&conn->COND_work_done);
+#ifndef MYSQLND_SILENT
+ printf("Signaling work done in %s\n", __FUNCTION__);
+#endif
+ pthread_mutex_unlock(&conn->LOCK_work);
+ } while (1);
+
+#ifndef MYSQLND_SILENT
+ printf("Exiting worker thread in %s\n", __FUNCTION__);
+#endif
+ return NULL;
+}
+/* }}} */
+#endif /* MYSQLND_THREADED */
+
+/************************************************************************************************/
+/* Let's don't use pool allocation for now */
+/* {{{ mysqlnd_mempool_free_chunk */
+static
+void mysqlnd_mempool_free_contents(MYSQLND_MEMORY_POOL * pool TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_mempool_dtor");
+ uint i;
+ for (i = 0; i < pool->free_chunk_list_elements; i++) {
+ MYSQLND_MEMORY_POOL_CHUNK * chunk = pool->free_chunk_list[i];
+ chunk->free_chunk(chunk, FALSE TSRMLS_CC);
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+/* Let's don't use pool allocation for now */
+/* {{{ mysqlnd_mempool_free_chunk */
+static
+void mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, zend_bool cache_it TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_mempool_free_chunk");
+ MYSQLND_MEMORY_POOL * pool = chunk->pool;
+ if (chunk->from_pool) {
+ /* Try to back-off and guess if this is the last block allocated */
+ if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
+ /*
+ This was the last allocation. Lucky us, we can free
+ a bit of memory from the pool. Next time we will return from the same ptr.
+ */
+ pool->free_size += chunk->size;
+ }
+ pool->refcount--;
+ } else {
+ mnd_free(chunk->ptr);
+ }
+ if (cache_it && pool->free_chunk_list_elements < MYSQLND_MEMORY_POOL_CHUNK_LIST_SIZE) {
+ chunk->ptr = NULL;
+ pool->free_chunk_list[pool->free_chunk_list_elements++] = chunk;
+ } else {
+ /* We did not cache it -> free it */
+ mnd_free(chunk);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_mempool_resize_chunk */
+static void
+mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, uint size TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_mempool_resize_chunk");
+ if (chunk->from_pool) {
+ MYSQLND_MEMORY_POOL * pool = chunk->pool;
+ /* Try to back-off and guess if this is the last block allocated */
+ if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
+ /*
+ This was the last allocation. Lucky us, we can free
+ a bit of memory from the pool. Next time we will return from the same ptr.
+ */
+ if ((chunk->size + pool->free_size) < size) {
+ zend_uchar *new_ptr;
+ new_ptr = mnd_malloc(size);
+ memcpy(new_ptr, chunk->ptr, chunk->size);
+ chunk->ptr = new_ptr;
+ pool->free_size += chunk->size;
+ chunk->size = size;
+ chunk->pool = NULL; /* now we have no pool memory */
+ pool->refcount--;
+ } else {
+ /* If the chunk is > than asked size then free_memory increases, otherwise decreases*/
+ pool->free_size += (chunk->size - size);
+ }
+ } else {
+ /* Not last chunk, if the user asks for less, give it to him */
+ if (chunk->size >= size) {
+ ; /* nop */
+ } else {
+ zend_uchar *new_ptr;
+ new_ptr = mnd_malloc(size);
+ memcpy(new_ptr, chunk->ptr, chunk->size);
+ chunk->ptr = new_ptr;
+ chunk->size = size;
+ chunk->pool = NULL; /* now we have no pool memory */
+ pool->refcount--;
+ }
+ }
+ } else {
+ chunk->ptr = mnd_realloc(chunk->ptr, size);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_mempool_get_chunk */
+static
+MYSQLND_MEMORY_POOL_CHUNK * mysqlnd_mempool_get_chunk(MYSQLND_MEMORY_POOL * pool, uint size TSRMLS_DC)
+{
+ MYSQLND_MEMORY_POOL_CHUNK *chunk = NULL;
+ DBG_ENTER("mysqlnd_mempool_get_chunk");
+
+ if (pool->free_chunk_list_elements) {
+ chunk = pool->free_chunk_list[--pool->free_chunk_list_elements];
+ } else {
+ chunk = mnd_malloc(sizeof(MYSQLND_MEMORY_POOL_CHUNK));
+ }
+
+ chunk->free_chunk = mysqlnd_mempool_free_chunk;
+ chunk->resize_chunk = mysqlnd_mempool_resize_chunk;
+ chunk->size = size;
+ /*
+ Should not go over MYSQLND_MAX_PACKET_SIZE, since we
+ expect non-arena memory in mysqlnd_wireprotocol.c . We
+ realloc the non-arena memory.
+ */
+ chunk->pool = pool;
+ if (size > pool->free_size) {
+ chunk->ptr = mnd_malloc(size);
+ chunk->from_pool = FALSE;
+ } else {
+ chunk->from_pool = TRUE;
+ ++pool->refcount;
+ chunk->ptr = pool->arena + (pool->arena_size - pool->free_size);
+ /* Last step, update free_size */
+ pool->free_size -= size;
+ }
+ DBG_RETURN(chunk);
+}
+/* }}} */
+/************************************************************************************************/
+
+
/* {{{ mysqlnd_library_init */
static
-void mysqlnd_library_init()
+void mysqlnd_library_init(TSRMLS_D)
{
if (mysqlnd_library_initted == FALSE) {
mysqlnd_library_initted = TRUE;
@@ -81,6 +274,13 @@ void mysqlnd_library_init()
#ifdef ZTS
mysqlnd_global_stats->LOCK_access = tsrm_mutex_alloc();
#endif
+ mysqlnd_memory_pool.arena_size = 16000;
+ mysqlnd_memory_pool.free_size = mysqlnd_memory_pool.arena_size;
+ mysqlnd_memory_pool.refcount = 0;
+ /* OOM ? */
+ mysqlnd_memory_pool.arena = mnd_malloc(mysqlnd_memory_pool.arena_size);
+ mysqlnd_memory_pool.get_chunk = mysqlnd_mempool_get_chunk;
+ mysqlnd_memory_pool.free_contents = mysqlnd_mempool_free_contents;
}
}
/* }}} */
@@ -88,9 +288,12 @@ void mysqlnd_library_init()
/* {{{ mysqlnd_library_end */
static
-void mysqlnd_library_end()
+void mysqlnd_library_end(TSRMLS_D)
{
if (mysqlnd_library_initted == TRUE) {
+ /* mnd_free will reference LOCK_access and won't crash...*/
+ mysqlnd_memory_pool.free_contents(&mysqlnd_memory_pool TSRMLS_CC);
+ free(mysqlnd_memory_pool.arena);
#ifdef ZTS
tsrm_mutex_free(mysqlnd_global_stats->LOCK_access);
#endif
@@ -229,6 +432,7 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
mnd_pefree(conn->net.cmd_buffer.buffer, pers);
conn->net.cmd_buffer.buffer = NULL;
}
+
conn->charset = NULL;
conn->greet_charset = NULL;
@@ -246,6 +450,22 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND *conn TSRMLS_DC)
conn->m->free_contents(conn TSRMLS_CC);
+#ifdef MYSQLND_THREADED
+ if (conn->thread_is_running) {
+ pthread_mutex_lock(&conn->LOCK_work);
+ conn->thread_killed = TRUE;
+ pthread_cond_signal(&conn->COND_work);
+ pthread_cond_wait(&conn->COND_thread_ended, &conn->LOCK_work);
+ pthread_mutex_unlock(&conn->LOCK_work);
+ }
+
+ tsrm_mutex_free(conn->LOCK_state);
+
+ pthread_cond_destroy(&conn->COND_work);
+ pthread_cond_destroy(&conn->COND_work_done);
+ pthread_mutex_destroy(&conn->LOCK_work);
+#endif
+
mnd_pefree(conn, conn->persistent);
DBG_VOID_RETURN;
@@ -363,7 +583,7 @@ mysqlnd_simple_command(MYSQLND *conn, enum php_mysqlnd_server_command command,
DBG_ENTER("mysqlnd_simple_command");
DBG_INF_FMT("command=%s ok_packet=%d silent=%d", mysqlnd_command_to_text[command], ok_packet, silent);
- switch (conn->state) {
+ switch (CONN_GET_STATE(conn)) {
case CONN_READY:
break;
case CONN_QUIT_SENT:
@@ -481,13 +701,13 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
DBG_ENTER("mysqlnd_connect");
DBG_INF_FMT("host=%s user=%s db=%s port=%d flags=%d persistent=%d state=%d",
host?host:"", user?user:"", db?db:"", port, mysql_flags,
- conn? conn->persistent:0, conn? conn->state:-1);
+ conn? conn->persistent:0, conn? CONN_GET_STATE(conn):-1);
- DBG_INF_FMT("state=%d", conn->state);
- if (conn && conn->state > CONN_ALLOCED && conn->state ) {
+ DBG_INF_FMT("state=%d", CONN_GET_STATE(conn));
+ if (conn && CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
DBG_INF("Connecting on a connected handle.");
- if (conn->state < CONN_QUIT_SENT) {
+ if (CONN_GET_STATE(conn) < CONN_QUIT_SENT) {
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_CLOSE_IMPLICIT);
reconnect = TRUE;
mysqlnd_send_close(conn TSRMLS_CC);
@@ -551,7 +771,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
self_alloced = TRUE;
}
- conn->state = CONN_ALLOCED;
+ CONN_SET_STATE(conn, CONN_ALLOCED);
conn->net.packet_no = 0;
if (conn->options.timeout_connect) {
@@ -663,7 +883,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
memcpy(auth_packet->server_scramble_buf, greet_packet.scramble_buf, SCRAMBLE_LENGTH);
if (!PACKET_WRITE(auth_packet, conn)) {
- conn->state = CONN_QUIT_SENT;
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
goto err;
}
@@ -687,7 +907,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
}
}
} else {
- conn->state = CONN_READY;
+ CONN_SET_STATE(conn, CONN_READY);
conn->user = pestrdup(user, conn->persistent);
conn->passwd = pestrndup(passwd, passwd_len, conn->persistent);
@@ -759,6 +979,23 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
DBG_INF("unicode set");
}
#endif
+#ifdef MYSQLND_THREADED
+ {
+ pthread_t th;
+ pthread_attr_t connection_attrib;
+ conn->tsrm_ls = tsrm_ls;
+
+ pthread_attr_init(&connection_attrib);
+ pthread_attr_setdetachstate(&connection_attrib, PTHREAD_CREATE_DETACHED);
+
+ conn->thread_is_running = TRUE;
+ if (pthread_create(&th, &connection_attrib, _mysqlnd_fetch_thread, (void*)conn)) {
+ conn->thread_is_running = FALSE;
+ }
+ }
+#endif
+
+
DBG_RETURN(conn);
}
err:
@@ -1081,7 +1318,7 @@ MYSQLND_METHOD(mysqlnd_conn, kill)(MYSQLND *conn, unsigned int pid TSRMLS_DC)
SET_ERROR_AFF_ROWS(conn);
} else if (PASS == (ret = mysqlnd_simple_command(conn, COM_PROCESS_KILL, buff,
4, PROT_LAST, FALSE TSRMLS_CC))) {
- conn->state = CONN_QUIT_SENT;
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
}
DBG_RETURN(ret);
}
@@ -1154,7 +1391,7 @@ MYSQLND_METHOD(mysqlnd_conn, shutdown)(MYSQLND * const conn, unsigned long level
/* {{{ mysqlnd_send_close */
-enum_func_status
+static enum_func_status
mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
{
enum_func_status ret = PASS;
@@ -1163,7 +1400,7 @@ mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
DBG_INF_FMT("conn=%llu conn->net.stream->abstract=%p",
conn->thread_id, conn->net.stream? conn->net.stream->abstract:NULL);
- switch (conn->state) {
+ switch (CONN_GET_STATE(conn)) {
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
ret = mysqlnd_simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST,
@@ -1199,7 +1436,7 @@ mysqlnd_send_close(MYSQLND * conn TSRMLS_DC)
We hold one reference, and every other object which needs the
connection does increase it by 1.
*/
- conn->state = CONN_QUIT_SENT;
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
DBG_RETURN(ret);
}
@@ -1236,7 +1473,6 @@ MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn, enum_connection_close_type c
ret = conn->m->free_reference(conn TSRMLS_CC);
-
DBG_RETURN(ret);
}
/* }}} */
@@ -1273,6 +1509,46 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS
/* }}} */
+/* {{{ mysqlnd_conn::get_state */
+#ifdef MYSQLND_THREADED
+static enum mysqlnd_connection_state
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
+{
+ enum mysqlnd_connection_state state;
+ DBG_ENTER("mysqlnd_conn::get_state");
+ tsrm_mutex_lock(conn->LOCK_state);
+ state = conn->state;
+ tsrm_mutex_unlock(conn->LOCK_state);
+ DBG_RETURN(state);
+}
+#else
+static enum mysqlnd_connection_state
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_conn::get_state");
+ DBG_RETURN(conn->state);
+}
+#endif
+/* }}} */
+
+
+/* {{{ mysqlnd_conn::set_state */
+static void
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_conn::set_state");
+#ifdef MYSQLND_THREADED
+ tsrm_mutex_lock(conn->LOCK_state);
+#endif
+ conn->state = new_state;
+#ifdef MYSQLND_THREADED
+ tsrm_mutex_unlock(conn->LOCK_state);
+#endif
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn::field_count */
static unsigned int
MYSQLND_METHOD(mysqlnd_conn, field_count)(const MYSQLND * const conn)
@@ -1420,7 +1696,7 @@ MYSQLND_METHOD(mysqlnd_conn, next_result)(MYSQLND * const conn TSRMLS_DC)
DBG_ENTER("mysqlnd_conn::next_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (conn->state != CONN_NEXT_RESULT_PENDING) {
+ if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
DBG_RETURN(FAIL);
}
@@ -1433,7 +1709,7 @@ MYSQLND_METHOD(mysqlnd_conn, next_result)(MYSQLND * const conn TSRMLS_DC)
if (FAIL == (ret = mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC))) {
DBG_ERR_FMT("Serious error. %s::%d", __FILE__, __LINE__);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid());
- conn->state = CONN_QUIT_SENT;
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
}
DBG_RETURN(ret);
@@ -1710,7 +1986,7 @@ MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
}
/* Nothing to store for UPSERT/LOAD DATA */
- if (conn->last_query_type != QUERY_SELECT || conn->state != CONN_FETCHING_DATA) {
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
DBG_ERR("Command out of sync");
@@ -1743,7 +2019,7 @@ MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
}
/* Nothing to store for UPSERT/LOAD DATA*/
- if (conn->last_query_type != QUERY_SELECT || conn->state != CONN_FETCHING_DATA) {
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
DBG_ERR("Command out of sync");
@@ -1761,6 +2037,44 @@ MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
/* }}} */
+/* {{{ mysqlnd_conn::background_store_result */
+MYSQLND_RES *
+MYSQLND_METHOD(mysqlnd_conn, background_store_result)(MYSQLND * const conn TSRMLS_DC)
+{
+ MYSQLND_RES *result;
+
+ DBG_ENTER("mysqlnd_conn::store_result");
+ DBG_INF_FMT("conn=%llu", conn->thread_id);
+
+ if (!conn->current_result) {
+ DBG_RETURN(NULL);
+ }
+
+ /* Nothing to store for UPSERT/LOAD DATA*/
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
+ mysqlnd_out_of_sync);
+ DBG_ERR("Command out of sync");
+ DBG_RETURN(NULL);
+ }
+
+ MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_BUFFERED_SETS);
+
+ result = conn->current_result;
+
+ result = result->m.background_store_result(result, conn, FALSE TSRMLS_CC);
+
+ /*
+ Should be here, because current_result is used by the fetching thread to get data info
+ The thread is contacted in mysqlnd_res::background_store_result().
+ */
+ conn->current_result = NULL;
+
+ DBG_RETURN(result);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn::get_connection_stats */
static void
MYSQLND_METHOD(mysqlnd_conn, get_connection_stats)(const MYSQLND * const conn,
@@ -1784,6 +2098,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
MYSQLND_METHOD(mysqlnd_conn, query),
MYSQLND_METHOD(mysqlnd_conn, use_result),
MYSQLND_METHOD(mysqlnd_conn, store_result),
+ MYSQLND_METHOD(mysqlnd_conn, background_store_result),
MYSQLND_METHOD(mysqlnd_conn, next_result),
MYSQLND_METHOD(mysqlnd_conn, more_results),
@@ -1829,6 +2144,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference),
MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state),
MYSQLND_CLASS_METHODS_END;
@@ -1846,6 +2163,15 @@ PHPAPI MYSQLND *_mysqlnd_init(zend_bool persistent TSRMLS_DC)
ret->m = & mysqlnd_mysqlnd_conn_methods;
ret->m->get_reference(ret);
+#ifdef MYSQLND_THREADED
+ ret->LOCK_state = tsrm_mutex_alloc();
+
+ pthread_mutex_init(&ret->LOCK_work, NULL);
+ pthread_cond_init(&ret->COND_work, NULL);
+ pthread_cond_init(&ret->COND_work_done, NULL);
+ pthread_cond_init(&ret->COND_thread_ended, NULL);
+#endif
+
DBG_RETURN(ret);
}
/* }}} */
@@ -1985,7 +2311,7 @@ static PHP_MINIT_FUNCTION(mysqlnd)
{
REGISTER_INI_ENTRIES();
- mysqlnd_library_init();
+ mysqlnd_library_init(TSRMLS_C);
return SUCCESS;
}
/* }}} */
@@ -1995,7 +2321,7 @@ static PHP_MINIT_FUNCTION(mysqlnd)
*/
static PHP_MSHUTDOWN_FUNCTION(mysqlnd)
{
- mysqlnd_library_end();
+ mysqlnd_library_end(TSRMLS_C);
UNREGISTER_INI_ENTRIES();
return SUCCESS;