aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>2024-03-07 16:12:37 -0500
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>2024-03-07 16:12:37 -0500
commitd6acc8aac98139340f010efde53c6e71239ae1fa (patch)
treee9ed8d9e0bc0fd5f79bf779ce7586f9166acd84c
parent8118247ec2f3912f2fb59db3a77eca5b3723f330 (diff)
downloadlibrseq-d6acc8aac98139340f010efde53c6e71239ae1fa.tar.gz
percpu pool: Move robust flag to atttribute
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: Ie83fff22b71dc9be39d90e4be97d094b90542715
-rw-r--r--include/rseq/percpu-alloc.h34
-rw-r--r--src/rseq-percpu-alloc.c24
-rw-r--r--tests/param_test.c12
3 files changed, 45 insertions, 25 deletions
diff --git a/include/rseq/percpu-alloc.h b/include/rseq/percpu-alloc.h
index 1532ed6..d3b1149 100644
--- a/include/rseq/percpu-alloc.h
+++ b/include/rseq/percpu-alloc.h
@@ -65,17 +65,14 @@ struct rseq_percpu_pool;
* 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.
@@ -90,8 +87,7 @@ 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);
/*
* rseq_percpu_pool_destroy: Destroy a per-cpu memory pool.
@@ -311,6 +307,26 @@ int rseq_pool_attr_set_mmap(struct rseq_pool_attr *attr,
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
diff --git a/src/rseq-percpu-alloc.c b/src/rseq-percpu-alloc.c
index daccf86..0a509c6 100644
--- a/src/rseq-percpu-alloc.c
+++ b/src/rseq-percpu-alloc.c
@@ -66,8 +66,6 @@
*/
#define FIRST_POOL 1
-#define RSEQ_POOL_FLAGS (RSEQ_POOL_ROBUST)
-
#define BIT_PER_ULONG (8 * sizeof(unsigned long))
struct free_list_node;
@@ -84,6 +82,8 @@ struct rseq_pool_attr {
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 {
@@ -342,8 +342,7 @@ int rseq_percpu_pool_destroy(struct rseq_percpu_pool *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 = {};
@@ -351,11 +350,6 @@ struct rseq_percpu_pool *rseq_percpu_pool_create(const char *pool_name,
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 *);
@@ -415,7 +409,7 @@ found_empty:
goto error_alloc;
}
- if (RSEQ_POOL_ROBUST & flags) {
+ if (attr.robust_set) {
if (create_alloc_bitmap(pool))
goto error_alloc;
}
@@ -666,3 +660,13 @@ int rseq_pool_attr_set_mmap(struct rseq_pool_attr *attr,
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;
+}
diff --git a/tests/param_test.c b/tests/param_test.c
index a3a338c..3ed1981 100644
--- a/tests/param_test.c
+++ b/tests/param_test.c
@@ -501,7 +501,7 @@ static void test_percpu_spinlock(void)
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();
@@ -597,7 +597,7 @@ static void test_percpu_inc(void)
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();
@@ -770,7 +770,7 @@ static void test_percpu_list(void)
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();
@@ -981,7 +981,7 @@ static void test_percpu_buffer(void)
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();
@@ -1222,7 +1222,7 @@ static void test_percpu_memcpy_buffer(void)
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();
@@ -1468,7 +1468,7 @@ void *test_membarrier_manager_thread(void *arg)
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();