diff options
author | Jani Taskinen <jani@php.net> | 2007-07-25 23:47:33 +0000 |
---|---|---|
committer | Jani Taskinen <jani@php.net> | 2007-07-25 23:47:33 +0000 |
commit | f3c2a33f4232b60b67e584ad94aeea3c3f8f7cf4 (patch) | |
tree | 4bef837b820227aafd16043ef700601588d9ac23 /ext/mysqli/mysqlnd/mysqlnd_palloc.c | |
parent | e0849ab010c287912986698230cb02ef74bddfb8 (diff) | |
download | php-git-f3c2a33f4232b60b67e584ad94aeea3c3f8f7cf4.tar.gz |
- Moved mysqnd to it's own directory: It is sort of an extension itself.
(Similar to what ext/libxml is..)
Diffstat (limited to 'ext/mysqli/mysqlnd/mysqlnd_palloc.c')
-rw-r--r-- | ext/mysqli/mysqlnd/mysqlnd_palloc.c | 558 |
1 files changed, 0 insertions, 558 deletions
diff --git a/ext/mysqli/mysqlnd/mysqlnd_palloc.c b/ext/mysqli/mysqlnd/mysqlnd_palloc.c deleted file mode 100644 index a5df45c82e..0000000000 --- a/ext/mysqli/mysqlnd/mysqlnd_palloc.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 6 | - +----------------------------------------------------------------------+ - | Copyright (c) 2006-2007 The PHP Group | - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | Authors: Georg Richter <georg@mysql.com> | - | Andrey Hristov <andrey@mysql.com> | - | Ulf Wendel <uwendel@mysql.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ -#include "php.h" -#include "mysqlnd.h" -#include "mysqlnd_priv.h" -#include "mysqlnd_palloc.h" - -#define MYSQLND_SILENT - - -#ifdef ZTS -#define LOCK_PCACHE(cache) tsrm_mutex_lock((cache)->LOCK_access) -#define UNLOCK_PCACHE(cache) tsrm_mutex_unlock((cache)->LOCK_access) -#else -#define LOCK_PCACHE(cache) -#define UNLOCK_PCACHE(cache) -#endif - - -#if PHP_MAJOR_VERSION < 6 -#define IS_UNICODE_DISABLED (1) -#else -#define IS_UNICODE_DISABLED (!UG(unicode)) -#endif - - -/* {{{ mysqlnd_palloc_init_cache */ -PHPAPI MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_init_cache(unsigned int cache_size) -{ - MYSQLND_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_ZVAL_PCACHE)); - unsigned int i; -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_init_cache %p]\n", ret); -#endif - -#ifdef ZTS - ret->LOCK_access = tsrm_mutex_alloc(); -#endif - - ret->max_items = cache_size; - ret->free_items = cache_size; - ret->references = 1; - - /* 1. First initialize the free list part of the structure */ - /* One more for empty position of last_added - always 0x0, bounds checking */ - ret->free_list.ptr_line = calloc(ret->max_items + 1, sizeof(mysqlnd_zval *)); - ret->free_list.last_added = ret->free_list.ptr_line + ret->max_items; - - /* 3. Allocate and initialize our zvals and initialize the free list */ - ret->block = calloc(ret->max_items, sizeof(mysqlnd_zval)); - ret->last_in_block = &(ret->block[ret->max_items]); - for (i = 0; i < ret->max_items; i++) { - /* 1. Initialize */ - INIT_PZVAL(&(ret->block[i].zv)); - ZVAL_NULL(&(ret->block[i].zv)); - /* Assure it will never be freed before MSHUTDOWN */ - ZVAL_ADDREF(&(ret->block[i].zv)); - /* 2. Add to the free list */ - *(--ret->free_list.last_added) = &(ret->block[i]); - } - - - return ret; -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_get_cache_reference */ -MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * const cache) -{ - if (cache) { - LOCK_PCACHE(cache); - cache->references++; - UNLOCK_PCACHE(cache); - } - return cache; -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_free_cache */ -/* - As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with - copy_ctor but scrap what they point to with zval_dtor() and then just free our - pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them - to the free list after usage. We ZVAL_NULL() them when we allocate them in the - constructor of the cache. -*/ -void mysqlnd_palloc_free_cache(MYSQLND_ZVAL_PCACHE *cache) -{ -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_free_cache %p]\n", cache); -#endif - -#ifdef ZTS - tsrm_mutex_free(cache->LOCK_access); -#endif - - /* Data in pointed by 'block' was cleaned in RSHUTDOWN */ - free(cache->block); - free(cache->free_list.ptr_line); - free(cache); -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_init_thd_cache */ -PHPAPI MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache) -{ - MYSQLND_THD_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE)); -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_init_thd_cache %p]\n", ret); -#endif - ret->parent = mysqlnd_palloc_get_cache_reference(cache); - -#ifdef ZTS - ret->thread_id = tsrm_thread_id(); -#endif - - ret->references = 1; - - /* 1. Initialize the GC list */ - ret->gc_list.ptr_line = calloc(cache->max_items, sizeof(mysqlnd_zval *)); - /* Backward and forward looping is possible */ - ret->gc_list.last_added = ret->gc_list.ptr_line; - - return ret; -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_get_thd_cache_reference */ -MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache) -{ - if (cache) { - ++cache->references; - mysqlnd_palloc_get_cache_reference(cache->parent); - } - return cache; -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_free_cache */ -/* - As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with - copy_ctor but scrap what they point to with zval_dtor() and then just free our - pre-allocated block. Precondition is that we ZVAL_NULL() the zvals when we put them - to the free list after usage. We ZVAL_NULL() them when we allocate them in the - constructor of the cache. -*/ -static -void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *cache) -{ -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_free_thd_cache %p]\n", cache); -#endif - - free(cache->gc_list.ptr_line); - free(cache); -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_free_thd_cache_reference */ -PHPAPI void mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache) -{ - if (*cache) { -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_free_thd_cache_reference %p] refs=%d\n", *cache, (*cache)->references); -#endif - --(*cache)->parent->references; - - if (--(*cache)->references == 0) { - mysqlnd_palloc_free_thd_cache(*cache); - } - *cache = NULL; - } -} -/* }}} */ - - -/* - The cache line is a big contiguous array of zval pointers. - Because the CPU cache will cache starting from an address, and not - before it, then we have to organize our structure according to this. - Thus, if 'last_added' is valid pointer (not NULL) then last_added is - increased. When zval is cached, if there is room, last_added is decreased - and then the zval pointer will be assigned to it. This means that some - positions may become hot points and stay in the cache. - Imagine we have 5 pointers in a line - 1. last_added = list_item->ptr_line + cache->max_items; - 2. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL - 3. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL - 4. get_zval -> *last_added = NULL. Use MAKE_STD_ZVAL - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - --- - empty_position, always 0x0 <-- last_added - - 5. free_zval -> if (free_items++ != max_items) {// we can add more - *(--last_added) = zval_ptr; - } - (memory addresses increase downwards) - 0x0 - 0x0 - 0x0 - 0x0 - 0xA <-- last_added - --- - 0x0 - - 6. free_zval -> if (free_items++ != max_items) {// we can add more - *(--last_added) = zval_ptr; - } - 0x0 - 0x0 - 0x0 - 0xB <-- last_added - 0xA - --- - 0x0 - - 7. free_zval -> if (free_items++ != max_items) {// we can add more - *(--last_added) = zval_ptr; - } - 0x0 - 0x0 - 0xC <-- last_added - 0xB - 0xA - --- - 0x0 - - 8. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL; - 0x0 - 0x0 - 0x0 - 0xB <-- last_added - 0xA - --- - 0x0 - - 9. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL; - 0x0 - 0x0 - 0x0 - 0x0 - 0xA <-- last_added - --- - 0x0 - - 10. get_zval -> *last_added != NULL. -> p = *last_added; *last_added++ = NULL; - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - --- - 0x0 <-- last_added - -*/ - - -/* {{{ mysqlnd_palloc_get_zval */ -void *mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const thd_cache, zend_bool *allocated) -{ - void *ret = NULL; - -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_get_zval %p] *last_added=%p free_items=%d\n", - thd_cache, thd_cache? thd_cache->parent->free_list.last_added:NULL, - thd_cache->parent->free_items); -#endif - - if (thd_cache) { - MYSQLND_ZVAL_PCACHE *cache = thd_cache->parent; - LOCK_PCACHE(cache); - - if ((ret = *cache->free_list.last_added)) { - *cache->free_list.last_added++ = NULL; - *allocated = FALSE; -#ifdef ZTS - ((mysqlnd_zval *) ret)->thread_id = thd_cache->thread_id; -#endif - --cache->free_items; - ++cache->get_hits; - } else { - ++cache->get_misses; - } - UNLOCK_PCACHE(cache); - } - if (!ret) { - /* - We allocate a bit more. The user of this function will use it, but at - end it will use only the zval part. Because the zval part is first then - when freeing the zval part the whole allocated block will be cleaned, not - only the zval part (by the Engine when destructing the zval). - */ - ALLOC_ZVAL(ret); - INIT_PZVAL((zval *) ret); - *allocated = TRUE; - } else { - /* This will set the refcount to 1, increase it, to keep the variable */ - INIT_PZVAL(&((mysqlnd_zval *) ret)->zv); - ZVAL_ADDREF(&(((mysqlnd_zval *)ret)->zv)); - } - - return ret; -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_zval_ptr_dtor */ -void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const thd_cache, - enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC) -{ - MYSQLND_ZVAL_PCACHE *cache; -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_zval_ptr_dtor %p] parent_block=%p last_in_block=%p *zv=%p type=%d refc=%d\n", - thd_cache, - thd_cache->parent? thd_cache->parent->block:NULL, - thd_cache->parent? thd_cache->parent->last_in_block:NULL, - *zv, type, ZVAL_REFCOUNT(*zv)); -#endif - *copy_ctor_called = FALSE; - /* Check whether cache is used and the zval is from the cache */ - if (!thd_cache || !(cache = thd_cache->parent) || ((char *)*zv < (char *)thd_cache->parent->block || - (char *)*zv > (char *)thd_cache->parent->last_in_block)) { - /* - This zval is not from the cache block. - Thus the refcount is -1 than of a zval from the cache, - because the zvals from the cache are owned by it. - */ - if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) { - ; /* do nothing, zval_ptr_dtor will do the job*/ - } else if (ZVAL_REFCOUNT(*zv) > 1) { - /* - Not a prepared statement, then we have to - call copy_ctor and then zval_ptr_dtor() - - In Unicode mode the destruction of the zvals should not call - zval_copy_ctor() because then we will leak. - I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set - to check if we need to call copy_ctor(). - - If the type is IS_UNICODE, which can happen with PHP6, then we don't - need to copy_ctor, as the data doesn't point to our internal buffers. - If it's string (in PHP5 always) and in PHP6 if data is binary, then - it still points to internal buffers and has to be copied. - */ - if (Z_TYPE_PP(zv) == IS_STRING) { - zval_copy_ctor(*zv); - } - *copy_ctor_called = TRUE; - } else { - if (Z_TYPE_PP(zv) == IS_STRING) { - ZVAL_NULL(*zv); - } - } - zval_ptr_dtor(zv); - return; - } - - /* The zval is from our cache */ - /* refcount is always > 1, because we call ZVAL_ADDREF(). Thus test refcount > 2 */ - if (ZVAL_REFCOUNT(*zv) > 2) { - /* - Because the zval is first element in mysqlnd_zval structure, then we can - do upcasting from zval to mysqlnd_zval here. Because we know that this - zval is part of our pre-allocated block. - - Now check whether this zval points to ZE allocated memory or to our - buffers. If it points to the internal buffers, call copy_ctor() - which will do estrndup for strings. And nothing for null, int, double. - - This branch will be skipped for PS, because there is no need to copy - what is pointed by them, as they don't point to the internal buffers. - */ - if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_INT_BUFFER) { - zval_copy_ctor(*zv); - *copy_ctor_called = TRUE; - ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_EXT_BUFFER; - } - /* - This will decrease the counter of the user-level (mysqlnd). When the engine - layer (the script) has finished working this this zval, when the variable is - no more used, out of scope whatever, then it will try zval_ptr_dtor() but - and the refcount will reach 1 and the engine won't try to destruct the - memory allocated by us. - */ - zval_ptr_dtor(zv); - - /* - Unfortunately, we can't return this variable to the free_list - because it's still used. And this cleaning up will happen at request - shutdown :(. - */ - LOCK_PCACHE(cache); - ++cache->put_misses; - *(thd_cache->gc_list.last_added++) = (mysqlnd_zval *)*zv; - UNLOCK_PCACHE(cache); - } else { - /* No user reference */ - if (((mysqlnd_zval *)*zv)->point_type == MYSQLND_POINTS_EXT_BUFFER) { - /* PS are here and also in Unicode mode, for non-binary */ - zval_dtor(*zv); - } - LOCK_PCACHE(cache); - ++cache->put_hits; - ++cache->free_items; - ((mysqlnd_zval *)*zv)->point_type = MYSQLND_POINTS_FREE; - ZVAL_DELREF(*zv); /* Make it 1 */ - ZVAL_NULL(*zv); -#ifdef ZTS - memset(&((mysqlnd_zval *)*zv)->thread_id, 0, sizeof(THREAD_T)); -#endif - *(--cache->free_list.last_added) = (mysqlnd_zval *)*zv; - - UNLOCK_PCACHE(cache); - } -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_rinit */ -PHPAPI MYSQLND_THD_ZVAL_PCACHE * mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache) -{ - return mysqlnd_palloc_init_thd_cache(cache); -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_rshutdown */ -PHPAPI void mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache) -{ - MYSQLND_ZVAL_PCACHE *cache; - mysqlnd_zval **p; -#ifndef MYSQLND_SILENT - php_printf("[mysqlnd_palloc_rshutdown %p]\n", thd_cache); -#endif - if (!thd_cache || !(cache = thd_cache->parent)) { - return; - } - - /* - Keep in mind that for pthreads pthread_equal() should be used to be - fully standard compliant. However, the PHP code all-around, incl. the - the Zend MM uses direct comparison. - */ - p = thd_cache->gc_list.ptr_line; - while (p < thd_cache->gc_list.last_added) { - zval_dtor(&(*p)->zv); - p++; - } - - p = thd_cache->gc_list.ptr_line; - LOCK_PCACHE(cache); - while (p < thd_cache->gc_list.last_added) { - (*p)->point_type = MYSQLND_POINTS_FREE; - *(--cache->free_list.last_added) = *p; - ++cache->free_items; -#ifdef ZTS - memset(&((*p)->thread_id), 0, sizeof(THREAD_T)); -#endif - p++; - } - UNLOCK_PCACHE(cache); - - mysqlnd_palloc_free_thd_cache_reference(&thd_cache); -} -/* }}} */ - - -/* {{{ mysqlnd_palloc_rshutdown */ -PHPAPI void mysqlnd_palloc_stats(const MYSQLND_ZVAL_PCACHE * const cache, zval *return_value) -{ - if (cache) { -#if PHP_MAJOR_VERSION >= 6 - TSRMLS_FETCH(); -#endif - - LOCK_PCACHE(cache); - array_init(return_value); -#if PHP_MAJOR_VERSION >= 6 - if (UG(unicode)) { - UChar *ustr; - int ulen; - - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_hits", sizeof("put_hits") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "put_misses", sizeof("put_misses") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_hits", sizeof("get_hits") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "get_misses", sizeof("get_misses") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "size", sizeof("size") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "free_items", sizeof("free_items") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, "references", sizeof("references") TSRMLS_CC); - add_u_assoc_long_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen + 1, cache->put_hits); - efree(ustr); - } else -#endif - { - add_assoc_long_ex(return_value, "put_hits", sizeof("put_hits"), cache->put_hits); - add_assoc_long_ex(return_value, "put_misses", sizeof("put_misses"), cache->put_misses); - add_assoc_long_ex(return_value, "get_hits", sizeof("get_hits"), cache->get_hits); - add_assoc_long_ex(return_value, "get_misses", sizeof("get_misses"), cache->get_misses); - add_assoc_long_ex(return_value, "size", sizeof("size"), cache->max_items); - add_assoc_long_ex(return_value, "free_items", sizeof("free_items"), cache->free_items); - add_assoc_long_ex(return_value, "references", sizeof("references"), cache->references); - } - UNLOCK_PCACHE(cache); - } else { - ZVAL_NULL(return_value); - } -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ |