diff --git a/apc.h b/apc.h index 4a011ee..a00f560 100644 --- a/apc.h +++ b/apc.h @@ -76,13 +76,6 @@ PHP_APCU_API void apc_debug(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(print /* apc_flip_hash flips keys and values for faster searching */ PHP_APCU_API HashTable* apc_flip_hash(HashTable *hash); -#define apc_time() \ - (APCG(use_request_time) \ - ? (APCG(request_time) \ - ? APCG(request_time) \ - : (APCG(request_time) = (time_t) sapi_get_request_time())) \ - : time(0)) - #if defined(__GNUC__) # define APC_UNUSED __attribute__((unused)) # define APC_USED __attribute__((used)) @@ -131,7 +124,7 @@ PHP_APCU_API int _apc_register_serializer( /* {{{ apc_get_serializers fetches the list of serializers */ -PHP_APCU_API apc_serializer_t* apc_get_serializers(); /* }}} */ +PHP_APCU_API apc_serializer_t* apc_get_serializers(void); /* }}} */ /* {{{ apc_find_serializer finds a previously registered serializer by name */ diff --git a/apc.php b/apc.php index 76c7a6b..dd143b3 100644 --- a/apc.php +++ b/apc.php @@ -228,48 +228,53 @@ if (isset($MYREQUEST['IMG'])) function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) { $r=$diameter/2; - $w=deg2rad((360+$start+($end-$start)/2)%360); - + $w=deg2rad(round(360+$start+($end-$start)/2)%360); if (function_exists("imagefilledarc")) { // exists only if GD 2.0.1 is available - imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE); - imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE); - imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, round($start), round($end), $color1, IMG_ARC_PIE); + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, round($start), round($end), $color2, IMG_ARC_PIE); + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, round($start), round($end), $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); } else { - imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2); - imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); - imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); - imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); - imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); - imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2); + imagearc($im, $centerX, $centerY, $diameter, $diameter, round($start), round($end), $color2); + imageline($im, $centerX, $centerY, $centerX + round(cos(deg2rad($start)) * $r), $centerY + round(sin(deg2rad($start)) * $r), $color2); + imageline($im, $centerX, $centerY, $centerX + round(cos(deg2rad($start+1)) * $r), $centerY + round(sin(deg2rad($start)) * $r), $color2); + imageline($im, $centerX, $centerY, $centerX + round(cos(deg2rad($end-1)) * $r), $centerY + round(sin(deg2rad($end)) * $r), $color2); + imageline($im, $centerX, $centerY, $centerX + round(cos(deg2rad($end)) * $r), $centerY + round(sin(deg2rad($end)) * $r), $color2); + imagefill($im,$centerX + round($r*cos($w)/2), $centerY + round($r*sin($w)/2), $color2); } if ($text) { if ($placeindex>0) { - imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); + imageline($im,$centerX + round($r*cos($w)/2), $centerY + round($r*sin($w)/2),$diameter, $placeindex*12,$color1); imagestring($im,4,$diameter, $placeindex*12,$text,$color1); } else { - imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); + imagestring($im,4,$centerX + round($r*cos($w)/2), $centerY + round($r*sin($w)/2),$text,$color1); } } } function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) { $r=$diameter/2; - $w=deg2rad((360+$start+($end-$start)/2)%360); + $w=deg2rad((360+round($start)+round(($end-$start)/2))%360); if ($placeindex>0) { - imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); + imageline($im,$centerX + round($r*cos($w)/2), $centerY + round($r*sin($w)/2),$diameter, $placeindex*12,$color1); imagestring($im,4,$diameter, $placeindex*12,$text,$color1); } else { - imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); + imagestring($im,4,$centerX + round($r*cos($w)/2), $centerY + round($r*sin($w)/2),$text,$color1); } } function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') { global $col_black; + + $x = round($x); + $y = round($y); + $w = round($w); + $h = round($h); + $x1=$x+$w-1; $y1=$y+$h-1; @@ -285,7 +290,7 @@ if (isset($MYREQUEST['IMG'])) $px=5; $py=$placeindex*12+6; imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2); - imageline($im,$x,$y+$h/2,$px+90,$py,$color2); + imageline($im,$x,$y+round($h/2),$px+90,$py,$color2); imagestring($im,2,$px,$py-6,$text,$color1); } else { @@ -297,7 +302,7 @@ if (isset($MYREQUEST['IMG'])) $py=($placeindex%15)*12+6; } imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2); - imageline($im,$x+$w,$y+$h/2,$px,$py,$color2); + imageline($im,$x+$w,$y+round($h/2),$px,$py,$color2); imagestring($im,2,$px+2,$py-6,$text,$color1); } } else { @@ -707,7 +712,7 @@ input {

- +
User Cache

@@ -807,7 +812,7 @@ EOB; $j = 0; foreach (ini_get_all('apcu') as $k => $v) { - echo "",$k,"",str_replace(',',',
',$v['local_value']),"\n"; + echo "",$k,"",str_replace(',',',
',$v['local_value'] ?? ''),"\n"; $j = 1 - $j; } @@ -1094,9 +1099,9 @@ case OB_VERSION_CHECK: EOB; if (defined('PROXY')) { $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => true ) ) ); - $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss", false, $ctxt); + $rss = @file_get_contents("https://pecl.php.net/feeds/pkg_apcu.rss", false, $ctxt); } else { - $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apcu.rss"); + $rss = @file_get_contents("https://pecl.php.net/feeds/pkg_apcu.rss"); } if (!$rss) { echo 'Unable to fetch version information.'; @@ -1110,8 +1115,8 @@ EOB; $i = 3; } else { echo '
You are running an older version of APCu ('.$apcversion.'), - newer version '.$match[1].' is available at - http://pecl.php.net/package/APCu/'.$match[1].' + newer version '.$match[1].' is available at + https://pecl.php.net/package/APCu/'.$match[1].'
'; $i = -1; } @@ -1130,7 +1135,7 @@ EOB; break; } $changes = $changelog[$j + 1]; - echo "".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."
"; + echo "".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."
"; echo nl2br(htmlspecialchars($changes, ENT_QUOTES, 'UTF-8'))."
"; } echo ''; diff --git a/apc_cache.c b/apc_cache.c index 480dd00..e5333f3 100644 --- a/apc_cache.c +++ b/apc_cache.c @@ -32,6 +32,7 @@ #include "apc_sma.h" #include "apc_globals.h" #include "apc_strings.h" +#include "apc_time.h" #include "php_scandir.h" #include "SAPI.h" #include "TSRM.h" @@ -115,7 +116,7 @@ static inline void free_entry(apc_cache_t *cache, apc_cache_entry_t *entry) { /* {{{ apc_cache_hash_slot Note: These calculations can and should be done outside of a lock */ static inline void apc_cache_hash_slot( - apc_cache_t* cache, zend_string *key, zend_ulong* hash, zend_ulong* slot) { + apc_cache_t* cache, zend_string *key, zend_ulong* hash, size_t* slot) { *hash = ZSTR_HASH(key); *slot = *hash % cache->nslots; } /* }}} */ @@ -272,7 +273,7 @@ PHP_APCU_API int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS) PHP_APCU_API apc_cache_t* apc_cache_create(apc_sma_t* sma, apc_serializer_t* serializer, zend_long size_hint, zend_long gc_ttl, zend_long ttl, zend_long smart, zend_bool defend) { apc_cache_t* cache; zend_long cache_size; - zend_long nslots; + size_t nslots; /* calculate number of slots */ nslots = make_prime(size_hint > 0 ? size_hint : 2000); @@ -332,7 +333,8 @@ static inline zend_bool apc_cache_wlocked_insert( /* make the insertion */ { apc_cache_entry_t **entry; - zend_ulong h, s; + zend_ulong h; + size_t s; /* calculate hash and entry */ apc_cache_hash_slot(cache, key, &h, &s); @@ -413,7 +415,8 @@ static inline zend_bool apc_cache_store_internal( static inline apc_cache_entry_t *apc_cache_rlocked_find_nostat( apc_cache_t *cache, zend_string *key, time_t t) { apc_cache_entry_t *entry; - zend_ulong h, s; + zend_ulong h; + size_t s; /* calculate hash and slot */ apc_cache_hash_slot(cache, key, &h, &s); @@ -440,7 +443,8 @@ static inline apc_cache_entry_t *apc_cache_rlocked_find_nostat( static inline apc_cache_entry_t *apc_cache_rlocked_find( apc_cache_t *cache, zend_string *key, time_t t) { apc_cache_entry_t *entry; - zend_ulong h, s; + zend_ulong h; + size_t s; /* calculate hash and slot */ apc_cache_hash_slot(cache, key, &h, &s); @@ -670,14 +674,10 @@ static void apc_cache_wlocked_real_expunge(apc_cache_t* cache) { cache->header->nexpunges++; /* expunge */ - { - zend_ulong i; - - for (i = 0; i < cache->nslots; i++) { - apc_cache_entry_t **entry = &cache->slots[i]; - while (*entry) { - apc_cache_wlocked_remove_entry(cache, entry); - } + for (size_t i = 0; i < cache->nslots; i++) { + apc_cache_entry_t **entry = &cache->slots[i]; + while (*entry) { + apc_cache_wlocked_remove_entry(cache, entry); } } @@ -754,10 +754,8 @@ PHP_APCU_API void apc_cache_default_expunge(apc_cache_t* cache, size_t size) } else { /* check that expunge is necessary */ if (available < suitable) { - zend_ulong i; - /* look for junk */ - for (i = 0; i < cache->nslots; i++) { + for (size_t i = 0; i < cache->nslots; i++) { apc_cache_entry_t **entry = &cache->slots[i]; while (*entry) { if (apc_cache_entry_expired(cache, *entry, t)) { @@ -959,7 +957,8 @@ retry_update: PHP_APCU_API zend_bool apc_cache_delete(apc_cache_t *cache, zend_string *key) { apc_cache_entry_t **entry; - zend_ulong h, s; + zend_ulong h; + size_t s; if (!cache) { return 0; @@ -1061,7 +1060,7 @@ PHP_APCU_API zend_bool apc_cache_info(zval *info, apc_cache_t *cache, zend_bool zval gc; zval slots; apc_cache_entry_t *p; - zend_ulong i, j; + zend_ulong j; ZVAL_NULL(info); if (!cache) { @@ -1095,7 +1094,7 @@ PHP_APCU_API zend_bool apc_cache_info(zval *info, apc_cache_t *cache, zend_bool array_init(&list); array_init(&slots); - for (i = 0; i < cache->nslots; i++) { + for (size_t i = 0; i < cache->nslots; i++) { p = cache->slots[i]; j = 0; for (; p != NULL; p = p->next) { @@ -1132,7 +1131,8 @@ PHP_APCU_API zend_bool apc_cache_info(zval *info, apc_cache_t *cache, zend_bool fetches information about the key provided */ PHP_APCU_API void apc_cache_stat(apc_cache_t *cache, zend_string *key, zval *stat) { - zend_ulong h, s; + zend_ulong h; + size_t s; ZVAL_NULL(stat); if (!cache) { diff --git a/apc_cache.h b/apc_cache.h index c05e091..e987a54 100644 --- a/apc_cache.h +++ b/apc_cache.h @@ -86,7 +86,7 @@ typedef struct _apc_cache_t { apc_cache_entry_t** slots; /* array of cache slots (stored in SHM) */ apc_sma_t* sma; /* shared memory allocator */ apc_serializer_t* serializer; /* serializer */ - zend_long nslots; /* number of slots in cache */ + size_t nslots; /* number of slots in cache */ zend_long gc_ttl; /* maximum time on GC list for a entry */ zend_long ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */ zend_long smart; /* smart parameter for gc */ diff --git a/apc_iterator.c b/apc_iterator.c index a268718..23f4334 100644 --- a/apc_iterator.c +++ b/apc_iterator.c @@ -21,6 +21,7 @@ #include "apc_iterator.h" #include "apc_cache.h" #include "apc_strings.h" +#include "apc_time.h" #if PHP_VERSION_ID >= 80000 # include "apc_iterator_arginfo.h" #else @@ -209,8 +210,8 @@ static int apc_iterator_check_expiry(apc_cache_t* cache, apc_cache_entry_t *entr /* }}} */ /* {{{ apc_iterator_fetch_active */ -static int apc_iterator_fetch_active(apc_iterator_t *iterator) { - int count = 0; +static size_t apc_iterator_fetch_active(apc_iterator_t *iterator) { + size_t count = 0; apc_iterator_item_t *item; time_t t = apc_time(); @@ -249,8 +250,8 @@ static int apc_iterator_fetch_active(apc_iterator_t *iterator) { /* }}} */ /* {{{ apc_iterator_fetch_deleted */ -static int apc_iterator_fetch_deleted(apc_iterator_t *iterator) { - int count = 0; +static size_t apc_iterator_fetch_deleted(apc_iterator_t *iterator) { + size_t count = 0; apc_iterator_item_t *item; if (!apc_cache_rlock(apc_user_cache)) { @@ -287,14 +288,13 @@ static int apc_iterator_fetch_deleted(apc_iterator_t *iterator) { /* {{{ apc_iterator_totals */ static void apc_iterator_totals(apc_iterator_t *iterator) { time_t t = apc_time(); - int i; if (!apc_cache_rlock(apc_user_cache)) { return; } php_apc_try { - for (i=0; i < apc_user_cache->nslots; i++) { + for (size_t i=0; i < apc_user_cache->nslots; i++) { apc_cache_entry_t *entry = apc_user_cache->slots[i]; while (entry) { if (apc_iterator_check_expiry(apc_user_cache, entry, t)) { @@ -314,18 +314,13 @@ static void apc_iterator_totals(apc_iterator_t *iterator) { } /* }}} */ -void apc_iterator_obj_init(apc_iterator_t *iterator, zval *search, zend_long format, zend_long chunk_size, zend_long list) +void apc_iterator_obj_init(apc_iterator_t *iterator, zval *search, zend_long format, size_t chunk_size, zend_long list) { if (!APCG(enabled)) { zend_throw_error(NULL, "APC must be enabled to use APCUIterator"); return; } - if (chunk_size < 0) { - apc_error("APCUIterator chunk size must be 0 or greater"); - return; - } - if (format > APC_ITER_ALL) { apc_error("APCUIterator format is invalid"); return; @@ -383,6 +378,11 @@ PHP_METHOD(APCUIterator, __construct) { return; } + if (chunk_size < 0) { + apc_error("APCUIterator chunk size must be 0 or greater"); + return; + } + apc_iterator_obj_init(iterator, search, format, chunk_size, list); } diff --git a/apc_iterator.h b/apc_iterator.h index d9537b4..9feda38 100644 --- a/apc_iterator.h +++ b/apc_iterator.h @@ -50,10 +50,10 @@ typedef struct _apc_iterator_t { short int initialized; /* sanity check in case __construct failed */ zend_long format; /* format bitmask of the return values ie: key, value, info */ - int (*fetch)(struct _apc_iterator_t *iterator); + size_t (*fetch)(struct _apc_iterator_t *iterator); /* fetch callback to fetch items from cache slots or lists */ - zend_long slot_idx; /* index to the slot array or linked list */ - zend_long chunk_size; /* number of entries to pull down per fetch */ + size_t slot_idx; /* index to the slot array or linked list */ + size_t chunk_size; /* number of entries to pull down per fetch */ apc_stack_t *stack; /* stack of entries pulled from cache */ int stack_idx; /* index into the current stack */ pcre_cache_entry *pce; /* regex filter on entry identifiers */ @@ -85,7 +85,7 @@ PHP_APCU_API void apc_iterator_obj_init( apc_iterator_t *iterator, zval *search, zend_long format, - zend_long chunk_size, + size_t chunk_size, zend_long list); PHP_APCU_API zend_class_entry* apc_iterator_get_ce(void); PHP_APCU_API int apc_iterator_init(int module_number); diff --git a/apc_lock.h b/apc_lock.h index 5b96755..7288cb9 100644 --- a/apc_lock.h +++ b/apc_lock.h @@ -72,8 +72,8 @@ typedef apc_windows_cs_rwlock_t apc_lock_t; apc_lock_cleanup destroys those attributes This saves us from having to create and destroy attributes for every lock we use at runtime */ -PHP_APCU_API zend_bool apc_lock_init(); -PHP_APCU_API void apc_lock_cleanup(); +PHP_APCU_API zend_bool apc_lock_init(void); +PHP_APCU_API void apc_lock_cleanup(void); /* The following functions should be self explanitory: */ diff --git a/apc_mmap.c b/apc_mmap.c index b56658a..9337d45 100644 --- a/apc_mmap.c +++ b/apc_mmap.c @@ -111,6 +111,12 @@ apc_segment_t apc_mmap(char *file_mask, size_t size) zend_error_noreturn(E_CORE_ERROR, "apc_mmap: Failed to mmap %zu bytes. Is your apc.shm_size too large?", size); } +#ifdef MADV_HUGEPAGE + /* enable transparent huge pages to reduce TLB misses (Linux + only) */ + madvise(segment.shmaddr, size, MADV_HUGEPAGE); +#endif + if (fd != -1) close(fd); return segment; diff --git a/apc_mutex.h b/apc_mutex.h index 1f3ee87..45983ea 100644 --- a/apc_mutex.h +++ b/apc_mutex.h @@ -27,8 +27,8 @@ typedef pthread_mutex_t apc_mutex_t; -PHP_APCU_API zend_bool apc_mutex_init(); -PHP_APCU_API void apc_mutex_cleanup(); +PHP_APCU_API zend_bool apc_mutex_init(void); +PHP_APCU_API void apc_mutex_cleanup(void); PHP_APCU_API zend_bool apc_mutex_create(apc_mutex_t *lock); PHP_APCU_API zend_bool apc_mutex_lock(apc_mutex_t *lock); PHP_APCU_API zend_bool apc_mutex_unlock(apc_mutex_t *lock); diff --git a/apc_persist.c b/apc_persist.c index cc21f57..0f8ac53 100644 --- a/apc_persist.c +++ b/apc_persist.c @@ -127,26 +127,39 @@ static zend_bool apc_persist_calc_ht(apc_persist_context_t *ctxt, const HashTabl /* TODO Too sparse hashtables could be compacted here */ ADD_SIZE(HT_USED_SIZE(ht)); - for (idx = 0; idx < ht->nNumUsed; idx++) { - Bucket *p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; - - /* This can only happen if $GLOBALS is placed in the cache. - * Don't bother with this edge-case, fall back to serialization. */ - if (Z_TYPE(p->val) == IS_INDIRECT) { - ctxt->use_serialization = 1; - return 0; +#if PHP_VERSION_ID >= 80200 + if (HT_IS_PACKED(ht)) { + for (idx = 0; idx < ht->nNumUsed; idx++) { + zval *val = ht->arPacked + idx; + ZEND_ASSERT(Z_TYPE_P(val) != IS_INDIRECT && "INDIRECT in packed array?"); + if (!apc_persist_calc_zval(ctxt, val)) { + return 0; + } } + } else +#endif + { + for (idx = 0; idx < ht->nNumUsed; idx++) { + Bucket *p = ht->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) continue; + + /* This can only happen if $GLOBALS is placed in the cache. + * Don't bother with this edge-case, fall back to serialization. */ + if (Z_TYPE(p->val) == IS_INDIRECT) { + ctxt->use_serialization = 1; + return 0; + } - /* TODO These strings can be reused - if (p->key && !apc_persist_calc_is_handled(ctxt, (zend_refcounted *) p->key)) { - ADD_SIZE_STR(ZSTR_LEN(p->key)); - }*/ - if (p->key) { - ADD_SIZE_STR(ZSTR_LEN(p->key)); - } - if (!apc_persist_calc_zval(ctxt, &p->val)) { - return 0; + /* TODO These strings can be reused + if (p->key && !apc_persist_calc_is_handled(ctxt, (zend_refcounted *) p->key)) { + ADD_SIZE_STR(ZSTR_LEN(p->key)); + }*/ + if (p->key) { + ADD_SIZE_STR(ZSTR_LEN(p->key)); + } + if (!apc_persist_calc_zval(ctxt, &p->val)) { + return 0; + } } } @@ -322,22 +335,42 @@ static zend_array *apc_persist_copy_ht(apc_persist_context_t *ctxt, const HashTa ht->nNextFreeElement = 0; ht->nInternalPointer = HT_INVALID_IDX; HT_SET_DATA_ADDR(ht, COPY(HT_GET_DATA_ADDR(ht), HT_USED_SIZE(ht))); - for (idx = 0; idx < ht->nNumUsed; idx++) { - Bucket *p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; +#if PHP_VERSION_ID >= 80200 + if (HT_IS_PACKED(ht)) { + for (idx = 0; idx < ht->nNumUsed; idx++) { + zval *val = ht->arPacked + idx; + if (Z_TYPE_P(val) == IS_UNDEF) continue; + + if (ht->nInternalPointer == HT_INVALID_IDX) { + ht->nInternalPointer = idx; + } - if (ht->nInternalPointer == HT_INVALID_IDX) { - ht->nInternalPointer = idx; - } + if ((zend_long) idx >= (zend_long) ht->nNextFreeElement) { + ht->nNextFreeElement = idx + 1; + } - if (p->key) { - p->key = apc_persist_copy_zstr_no_add(ctxt, p->key); - ht->u.flags &= ~HASH_FLAG_STATIC_KEYS; - } else if ((zend_long) p->h >= (zend_long) ht->nNextFreeElement) { - ht->nNextFreeElement = p->h + 1; + apc_persist_copy_zval(ctxt, val); } + } else +#endif + { + for (idx = 0; idx < ht->nNumUsed; idx++) { + Bucket *p = ht->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) continue; + + if (ht->nInternalPointer == HT_INVALID_IDX) { + ht->nInternalPointer = idx; + } + + if (p->key) { + p->key = apc_persist_copy_zstr_no_add(ctxt, p->key); + ht->u.flags &= ~HASH_FLAG_STATIC_KEYS; + } else if ((zend_long) p->h >= (zend_long) ht->nNextFreeElement) { + ht->nNextFreeElement = p->h + 1; + } - apc_persist_copy_zval(ctxt, &p->val); + apc_persist_copy_zval(ctxt, &p->val); + } } return ht; @@ -541,6 +574,15 @@ static zend_array *apc_unpersist_ht( HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht))); memcpy(HT_GET_DATA_ADDR(ht), HT_GET_DATA_ADDR(orig_ht), HT_HASH_SIZE(ht->nTableMask)); +#if PHP_VERSION_ID >= 80200 + if (HT_IS_PACKED(ht)) { + zval *p = ht->arPacked, *q = orig_ht->arPacked, *p_end = p + ht->nNumUsed; + for (; p < p_end; p++, q++) { + *p = *q; + apc_unpersist_zval(ctxt, p); + } + } else +#endif if (ht->u.flags & HASH_FLAG_STATIC_KEYS) { Bucket *p = ht->arData, *q = orig_ht->arData, *p_end = p + ht->nNumUsed; for (; p < p_end; p++, q++) { diff --git a/apc_signal.h b/apc_signal.h index aeace18..1f5f73f 100644 --- a/apc_signal.h +++ b/apc_signal.h @@ -34,8 +34,8 @@ typedef struct apc_signal_info_t { apc_signal_entry_t **prev; /* Previous signal handlers */ } apc_signal_info_t; -void apc_set_signals(); -void apc_shutdown_signals(); +void apc_set_signals(void); +void apc_shutdown_signals(void); #endif diff --git a/apc_sma.c b/apc_sma.c index 3150d92..51a3198 100644 --- a/apc_sma.c +++ b/apc_sma.c @@ -169,13 +169,13 @@ static APC_HOTSPOT size_t sma_allocate(sma_header_t *header, size_t size, size_t shmaddr = header; if (header->avail < realsize) { - return -1; + return SIZE_MAX; } cur = find_block(header, realsize); if (!cur) { /* No suitable block found */ - return -1; + return SIZE_MAX; } if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE + fragment)))) { @@ -414,7 +414,7 @@ restart: off = sma_allocate(SMA_HDR(sma, last), n, fragment, allocated); - if (off != -1) { + if (off != SIZE_MAX) { void* p = (void *)(SMA_ADDR(sma, last) + off); SMA_UNLOCK(sma, last); #ifdef VALGRIND_MALLOCLIKE_BLOCK @@ -435,7 +435,7 @@ restart: } off = sma_allocate(SMA_HDR(sma, i), n, fragment, allocated); - if (off != -1) { + if (off != SIZE_MAX) { void* p = (void *)(SMA_ADDR(sma, i) + off); sma->last = i; SMA_UNLOCK(sma, i); diff --git a/apc_stack.c b/apc_stack.c index a0b6bfa..22d81b9 100644 --- a/apc_stack.c +++ b/apc_stack.c @@ -30,11 +30,11 @@ struct apc_stack_t { void** data; - int capacity; - int size; + size_t capacity; + size_t size; }; -apc_stack_t* apc_stack_create(int size_hint) +apc_stack_t* apc_stack_create(size_t size_hint) { apc_stack_t* stack = emalloc(sizeof(apc_stack_t)); @@ -81,7 +81,7 @@ void* apc_stack_top(apc_stack_t* stack) return stack->data[stack->size-1]; } -void* apc_stack_get(apc_stack_t* stack, int n) +void* apc_stack_get(apc_stack_t* stack, size_t n) { assert(stack != NULL && stack->size > n); return stack->data[n]; diff --git a/apc_stack.h b/apc_stack.h index 152136a..20fdd2a 100644 --- a/apc_stack.h +++ b/apc_stack.h @@ -34,13 +34,13 @@ #define T apc_stack_t* typedef struct apc_stack_t apc_stack_t; /* opaque stack type */ -extern T apc_stack_create(int size_hint); +extern T apc_stack_create(size_t size_hint); extern void apc_stack_destroy(T stack); extern void apc_stack_clear(T stack); extern void apc_stack_push(T stack, void* item); extern void* apc_stack_pop(T stack); extern void* apc_stack_top(T stack); -extern void* apc_stack_get(T stack, int n); +extern void* apc_stack_get(T stack, size_t n); extern int apc_stack_size(T stack); #undef T diff --git a/apc_time.c b/apc_time.c new file mode 100644 index 0000000..2866929 --- /dev/null +++ b/apc_time.c @@ -0,0 +1,54 @@ +/* + +----------------------------------------------------------------------+ + | APC | + +----------------------------------------------------------------------+ + | Copyright (c) 2006-2011 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. | + +----------------------------------------------------------------------+ + + This software was contributed to PHP by Community Connect Inc. in 2002 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. + Future revisions and derivatives of this source code must acknowledge + Community Connect Inc. as the original contributor of this module by + leaving this note intact in the source code. + + All other licensing and usage conditions are those of the PHP Group. + + */ + +#include "apc_time.h" +#include "apc_globals.h" +#include "SAPI.h" + +time_t apc_time(void) +{ + if (APCG(use_request_time)) { + if (!APCG(request_time)) + APCG(request_time) = (time_t) sapi_get_request_time(); + return APCG(request_time); + } else { +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec; +#else + return time(0); +#endif + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim>600: noexpandtab sw=4 ts=4 sts=4 fdm=marker + * vim<600: noexpandtab sw=4 ts=4 sts=4 + */ diff --git a/apc_time.h b/apc_time.h new file mode 100644 index 0000000..3e26403 --- /dev/null +++ b/apc_time.h @@ -0,0 +1,42 @@ +/* + +----------------------------------------------------------------------+ + | APC | + +----------------------------------------------------------------------+ + | Copyright (c) 2006-2011 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. | + +----------------------------------------------------------------------+ + + This software was contributed to PHP by Community Connect Inc. in 2002 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. + Future revisions and derivatives of this source code must acknowledge + Community Connect Inc. as the original contributor of this module by + leaving this note intact in the source code. + + All other licensing and usage conditions are those of the PHP Group. + + */ + +#ifndef APC_TIME_H +#define APC_TIME_H + +#include + +time_t apc_time(void); + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim>600: noexpandtab sw=4 ts=4 sts=4 fdm=marker + * vim<600: noexpandtab sw=4 ts=4 sts=4 + */ diff --git a/config.m4 b/config.m4 index 9d320ec..d991186 100644 --- a/config.m4 +++ b/config.m4 @@ -5,8 +5,8 @@ AC_MSG_CHECKING(if APCu should be allowed to use rwlocks) AC_ARG_ENABLE(apcu-rwlocks, [ --disable-apcu-rwlocks Disable rwlocks in APCu], [ - PHP_APCU_RWLOCKS=no - AC_MSG_RESULT(no) + PHP_APCU_RWLOCKS=$enableval + AC_MSG_RESULT($enableval) ], [ PHP_APCU_RWLOCKS=yes @@ -200,6 +200,7 @@ if test "$PHP_APCU" != "no"; then fi fi + AC_CHECK_FUNCS(clock_gettime) AC_CHECK_FUNCS(sigaction) AC_CACHE_CHECK(for union semun, php_cv_semun, [ @@ -230,6 +231,10 @@ if test "$PHP_APCU" != "no"; then [AC_DEFINE([HAVE_VALGRIND_MEMCHECK_H],1, [enable valgrind memchecks])]) ]) + for i in -Wall -Wextra -Wno-unused-parameter; do + AX_CHECK_COMPILE_FLAG([$i], [APCU_CFLAGS="$APCU_CFLAGS $i"]) + done + apc_sources="apc.c apc_lock.c apc_mutex.c php_apc.c \ apc_cache.c \ apc_mmap.c \ @@ -237,6 +242,7 @@ if test "$PHP_APCU" != "no"; then apc_sma.c \ apc_stack.c \ apc_signal.c \ + apc_time.c \ apc_iterator.c \ apc_persist.c" diff --git a/php_apc.c b/php_apc.c index 27139cc..211dd33 100644 --- a/php_apc.c +++ b/php_apc.c @@ -36,6 +36,7 @@ #include "apc_lock.h" #include "apc_mutex.h" #include "apc_strings.h" +#include "apc_time.h" #include "php_globals.h" #include "php_ini.h" #include "ext/standard/info.h" @@ -92,13 +93,14 @@ static void php_apc_init_globals(zend_apcu_globals* apcu_globals) static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */ { + zend_long shm_segments = ZEND_STRTOL(new_value->val, NULL, 10); #if APC_MMAP - if (zend_atoi(new_value->val, new_value->len)!=1) { + if (shm_segments != 1) { php_error_docref(NULL, E_WARNING, "apc.shm_segments setting ignored in MMAP mode"); } APCG(shm_segments) = 1; #else - APCG(shm_segments) = zend_atoi(new_value->val, new_value->len); + APCG(shm_segments) = shm_segments; #endif return SUCCESS; } @@ -106,7 +108,11 @@ static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */ static PHP_INI_MH(OnUpdateShmSize) /* {{{ */ { +#if PHP_VERSION_ID >= 80200 + zend_long s = zend_ini_parse_quantity_warn(new_value, entry->name); +#else zend_long s = zend_atol(new_value->val, new_value->len); +#endif if (s <= 0) { return FAILURE; diff --git a/tests/apc_002.phpt b/tests/apc_002.phpt index a395707..37e0927 100644 --- a/tests/apc_002.phpt +++ b/tests/apc_002.phpt @@ -8,6 +8,7 @@ apc.enable_cli=1 --FILE-- a = true; var_dump($bar); +#[AllowDynamicProperties] class bar extends foo { public $pub = 'bar'; diff --git a/tests/apc_entry_002.phpt b/tests/apc_entry_002.phpt index c207d45..61f833a 100644 --- a/tests/apc_entry_002.phpt +++ b/tests/apc_entry_002.phpt @@ -15,6 +15,6 @@ $value = apcu_entry("test", function($key){ Fatal error: Uncaught Exception: test in %s:3 Stack trace: #0 [internal function]: {closure}('test') -#1 %s(4): apcu_entry('test', Object(Closure)) +#1 %s(%d): apcu_entry('test', Object(Closure)) #2 {main} thrown in %s on line 3 diff --git a/tests/bug63224.phpt b/tests/bug63224.phpt index d711f8f..92ea3c9 100644 --- a/tests/bug63224.phpt +++ b/tests/bug63224.phpt @@ -57,6 +57,7 @@ $args = array( 'apc.enabled=1', 'apc.cache_by_default=1', 'apc.enable_cli=1', + 'session.gc_probability=0', ); server_start($file, $args);