Skip to content

Commit 7c4285e

Browse files
committed
Fix apc_sma_get_avail_size() to look for a contiguous block of memory
apc_sma_get_avail_size() is used by apc_cache_default_expunge() to check if enough memory is available to store the next cache entry. Therefore, it is not enough to check the total amount of available memory. The memory must be available in one contiguous block.
1 parent 0415f0a commit 7c4285e

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

apc_sma.c

+27-3
Original file line numberDiff line numberDiff line change
@@ -629,13 +629,37 @@ PHP_APCU_API size_t apc_sma_get_avail_mem(apc_sma_t* sma) {
629629

630630
PHP_APCU_API zend_bool apc_sma_get_avail_size(apc_sma_t* sma, size_t size) {
631631
int32_t i;
632+
sma_header_t* header;
633+
void *shmaddr;
634+
block_t *cur, *prv;
632635

633636
for (i = 0; i < sma->num; i++) {
634-
sma_header_t* header = SMA_HDR(sma, i);
635-
if (header->avail > size) {
636-
return 1;
637+
header = SMA_HDR(sma, i);
638+
639+
/* If total size of available memory is too small, we can skip the contiguous-block check */
640+
if (header->avail < size) {
641+
continue;
642+
}
643+
644+
SMA_LOCK(sma, i);
645+
shmaddr = header;
646+
prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
647+
648+
/* Look for a contiguous block of memory */
649+
while (prv->fnext) {
650+
cur = BLOCKAT(prv->fnext);
651+
652+
if (cur->size >= size) {
653+
SMA_UNLOCK(sma, i);
654+
return 1;
655+
}
656+
657+
prv = cur;
637658
}
659+
660+
SMA_UNLOCK(sma, i);
638661
}
662+
639663
return 0;
640664
}
641665

0 commit comments

Comments
 (0)