* next power of two). The reserved allocation size is @percpu_len, and
* the maximum CPU value expected is (@max_nr_cpus - 1).
*
- * The @pool_attr pointer used to specify the pool attributes. If NULL,
- * use a default attribute values. The @pool_attr can be destroyed
- * immediately after rseq_percpu_pool_create() returns. The caller keeps
- * ownership of @pool_attr.
+ * The @attr pointer used to specify the pool attributes. If NULL, use a
+ * default attribute values. The @attr can be destroyed immediately
+ * after rseq_percpu_pool_create() returns. The caller keeps ownership
+ * of @attr.
*
* The argument @pool_name can be used to given a name to the pool for
* debugging purposes. It can be NULL if no name is given.
*
- * Argument @flags is a bitwise-or'd selector of:
- * - RSEQ_POOL_ROBUST
- *
* Returns a pointer to the created percpu pool. Return NULL on error,
* with errno set accordingly:
* EINVAL: Invalid argument.
*/
struct rseq_percpu_pool *rseq_percpu_pool_create(const char *pool_name,
size_t item_len, size_t percpu_len, int max_nr_cpus,
- const struct rseq_pool_attr *attr,
- int flags);
+ const struct rseq_pool_attr *attr);
/*
* rseq_percpu_pool_destroy: Destroy a per-cpu memory pool.
int (*munmap_func)(void *priv, void *ptr, size_t len),
void *mmap_priv);
+/*
+ * rseq_pool_attr_set_robust: Set pool robust attribute.
+ *
+ * The robust pool attribute enables runtime validation of the pool:
+ *
+ * - Check for double-free of pointers.
+ *
+ * - Detect memory leaks on pool destruction.
+ *
+ * - Detect free-list corruption on pool destruction.
+ *
+ * There is a marginal runtime overhead on malloc/free operations.
+ *
+ * The memory overhead is (pool->percpu_len / pool->item_len) / CHAR_BIT
+ * bytes, over the lifetime of the pool.
+ *
+ * Returns 0 on success, -1 with errno=EINVAL if arguments are invalid.
+ */
+int rseq_pool_attr_set_robust(struct rseq_pool_attr *attr);
+
#ifdef __cplusplus
}
#endif
*/
#define FIRST_POOL 1
-#define RSEQ_POOL_FLAGS (RSEQ_POOL_ROBUST)
-
#define BIT_PER_ULONG (8 * sizeof(unsigned long))
struct free_list_node;
void *(*mmap_func)(void *priv, size_t len);
int (*munmap_func)(void *priv, void *ptr, size_t len);
void *mmap_priv;
+
+ bool robust_set;
};
struct rseq_percpu_pool {
struct rseq_percpu_pool *rseq_percpu_pool_create(const char *pool_name,
size_t item_len, size_t percpu_len, int max_nr_cpus,
- const struct rseq_pool_attr *_attr,
- int flags)
+ const struct rseq_pool_attr *_attr)
{
struct rseq_percpu_pool *pool;
struct rseq_pool_attr attr = {};
unsigned int i;
int order;
- if (flags & ~RSEQ_POOL_FLAGS) {
- errno = EINVAL;
- return NULL;
- }
-
/* Make sure each item is large enough to contain free list pointers. */
if (item_len < sizeof(void *))
item_len = sizeof(void *);
goto error_alloc;
}
- if (RSEQ_POOL_ROBUST & flags) {
+ if (attr.robust_set) {
if (create_alloc_bitmap(pool))
goto error_alloc;
}
attr->mmap_priv = mmap_priv;
return 0;
}
+
+int rseq_pool_attr_set_robust(struct rseq_pool_attr *attr)
+{
+ if (!attr) {
+ errno = EINVAL;
+ return -1;
+ }
+ attr->robust_set = true;
+ return 0;
+}
mempool = rseq_percpu_pool_create("spinlock_test_data",
sizeof(struct spinlock_test_data),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();
mempool = rseq_percpu_pool_create("inc_test_data",
sizeof(struct inc_test_data),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();
struct rseq_percpu_pool *mempool;
mempool = rseq_percpu_pool_create("percpu_list", sizeof(struct percpu_list),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();
struct rseq_percpu_pool *mempool;
mempool = rseq_percpu_pool_create("percpu_buffer", sizeof(struct percpu_buffer),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();
mempool = rseq_percpu_pool_create("percpu_memcpy_buffer",
sizeof(struct percpu_memcpy_buffer),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();
long long total_count = 0;
mempool = rseq_percpu_pool_create("percpu_list", sizeof(struct percpu_list),
- PERCPU_POOL_LEN, CPU_SETSIZE, NULL, 0);
+ PERCPU_POOL_LEN, CPU_SETSIZE, NULL);
if (!mempool) {
perror("rseq_percpu_pool_create");
abort();