}
}
-/* Allocate a new entry for pool <pool>, and return it for immediate use.
- * NULL is returned if no memory is available for a new creation.
+/* Allocates new entries for pool <pool> until there are at least <avail> + 1
+ * available, then returns the last one for immediate use, so that at least
+ * <avail> are left available in the pool upon return. NULL is returned if the
+ * last entry could not be allocated. It's important to note that at least one
+ * allocation is always performed even if there are enough entries in the pool.
+ * A call to the garbage collector is performed at most once in case malloc()
+ * returns an error, before returning NULL.
*/
-void *pool_refill_alloc(struct pool_head *pool);
+void *pool_refill_alloc(struct pool_head *pool, unsigned int avail);
/* Try to find an existing shared pool with the same characteristics and
* returns it, otherwise creates this one. NULL is returned if no memory
void *p;
if ((p = pool_get_first(pool)) == NULL)
- p = pool_refill_alloc(pool);
+ p = pool_refill_alloc(pool, 0);
return p;
}
return pool;
}
-/* Allocate a new entry for pool <pool>, and return it for immediate use.
- * NULL is returned if no memory is available for a new creation. A call
- * to the garbage collector is performed before returning NULL.
+/* Allocates new entries for pool <pool> until there are at least <avail> + 1
+ * available, then returns the last one for immediate use, so that at least
+ * <avail> are left available in the pool upon return. NULL is returned if the
+ * last entry could not be allocated. It's important to note that at least one
+ * allocation is always performed even if there are enough entries in the pool.
+ * A call to the garbage collector is performed at most once in case malloc()
+ * returns an error, before returning NULL.
*/
-void *pool_refill_alloc(struct pool_head *pool)
+void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
{
- void *ret;
-
- if (pool->limit && (pool->allocated >= pool->limit))
- return NULL;
- ret = CALLOC(1, pool->size);
- if (!ret) {
- pool_gc2();
- ret = CALLOC(1, pool->size);
- if (!ret)
+ void *ptr = NULL;
+ int failed = 0;
+
+ /* stop point */
+ avail += pool->used;
+
+ while (1) {
+ if (pool->limit && pool->allocated >= pool->limit)
return NULL;
+
+ ptr = MALLOC(pool->size);
+ if (!ptr) {
+ if (failed)
+ return NULL;
+ failed++;
+ pool_gc2();
+ continue;
+ }
+ if (++pool->allocated > avail)
+ break;
+
+ *(void **)ptr = (void *)pool->free_list;
+ pool->free_list = ptr;
}
- pool->allocated++;
pool->used++;
- return ret;
+ return ptr;
}
/*