percpu pool: Move robust flag to atttribute
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 7 Mar 2024 21:12:37 +0000 (16:12 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 7 Mar 2024 21:12:37 +0000 (16:12 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Ie83fff22b71dc9be39d90e4be97d094b90542715

include/rseq/percpu-alloc.h
src/rseq-percpu-alloc.c
tests/param_test.c

index 1532ed6bcfca17cf7d19caa5d9a54386e1b8786d..d3b1149b48290b5318f69752fb1cd87f9e6b50f8 100644 (file)
@@ -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
index daccf868ead563d59273314bcf0aa56df75e2c43..0a509c6c57f1956e207d2a42bf2096ca071067e9 100644 (file)
@@ -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;
+}
index a3a338cac5513a6ba0166d7a4d4588c7e2c7649a..3ed1981551032702b93d9170ae9750360ef49a3f 100644 (file)
@@ -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();
This page took 0.027452 seconds and 4 git commands to generate.