[RFC 04/13] cpumask: add cpumask_ptr operations

From: Mike Travis
Date: Sat Sep 06 2008 - 19:51:00 EST


* Define a generic cpumask_ptr type and some helper functions that
* do not add any overhead to low count NR_CPUS systems. Essentially
* for NR_CPUS <= BITS_PER_LONG, an array of one cpumask is created on
* the stack. For larger count systems, a pointer is defined. In both
* cases the pointer variable can be used as C will optimize out the
* pointer derefence in the small system case.
*
* Add a simple kmalloc to allocate a temporary cpumask variable.
* (Note, kmalloc should be defined before including this file.)
*
* Add a simple per_cpu variable to facilitate those cases where a
* kmalloc failure cannot be reasonable handled (or we're using it
* before the mm system is initialized.)
*
* This is useful for getting temporary per_cpu cpumask_t variables.
* Note there are no locks, so these are _extremely_ temporary cpumask
* vars, with only preemption disabled, while in use.
*
* Many thanks to Linus Torvalds for the typedef/alloc idea.
*
* Adds the following cpumask_ptr operations for NR_CPUS > BITS_PER_LONG:
*
* cpumask_ptr p; Declares p to be a cpumask_t pointer
*
* alloc_cpumask_ptr(p); allocates and assigns memory to p
* free_cpumask_ptr(p); frees memory used by p
*
* DEFINE_PER_CPUMASK(p, v) Defines a PER_CPUMASK variable v
* DECLARE_PER_CPUMASK(p, v) Declares a PER_CPUMASK variable v
* get_cpumask_var(p, v) Obtains possession of PER_CPUMASK variable v
* and assignes it to p
* put_cpumask_var(p, v) Relenquishs possession of PER_CPUMASK variable v
*
* If NR_CPUS <= BITS_PER_LONG then the above are all essentially NOP's.

Applies to linux-2.6.tip/master.

Signed-off-by: Mike Travis <travis@xxxxxxx>
---
include/linux/cpumask_ptr.h | 78 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)

--- /dev/null
+++ linux-2.6.tip/include/linux/cpumask_ptr.h
@@ -0,0 +1,78 @@
+#ifndef __LINUX_CPUMASK_PTR_H
+#define __LINUX_CPUMASK_PTR_H
+
+/*
+ * Define a generic cpumask_ptr type and some helper functions that
+ * do not add any overhead to low count NR_CPUS systems. Essentially
+ * for NR_CPUS <= BITS_PER_LONG, an array of one cpumask is created on
+ * the stack. For larger count systems, a pointer is defined. In both
+ * cases the pointer variable can be used as C will optimize out the
+ * pointer derefence in the small system case.
+ *
+ * Add a simple kmalloc to allocate a temporary cpumask variable.
+ * (Note, kmalloc should be defined before including this file.)
+ *
+ * Add a simple per_cpu variable to facilitate those cases where a
+ * kmalloc failure cannot be reasonable handled (or we're using it
+ * before the mm system is initialized.)
+ *
+ * This is useful for getting temporary per_cpu cpumask_t variables.
+ * Note there are no locks, so these are _extremely_ temporary cpumask
+ * vars, with only preemption disabled, while in use.
+ *
+ * Many thanks to Linus Torvalds for the typedef/alloc idea.
+ *
+ * Adds the following cpumask_ptr operations for NR_CPUS > BITS_PER_LONG:
+ *
+ * cpumask_ptr p; Declares p to be a cpumask_t pointer
+ *
+ * alloc_cpumask_ptr(p); allocates and assigns memory to p
+ * free_cpumask_ptr(p); frees memory used by p
+ *
+ * DEFINE_PER_CPUMASK(p, v) Defines a PER_CPUMASK variable v
+ * DECLARE_PER_CPUMASK(p, v) Declares a PER_CPUMASK variable v
+ * get_cpumask_var(p, v) Obtains possession of PER_CPUMASK variable v
+ * and assignes it to p
+ * put_cpumask_var(p, v) Relenquishs possession of PER_CPUMASK variable v
+ *
+ * If NR_CPUS <= BITS_PER_LONG then the above are all essentially NOP's.
+ */
+
+#if NR_CPUS <= BITS_PER_LONG
+
+typedef cpumask_t cpumask_ptr[1];
+static inline void alloc_cpumask_ptr(cpumask_ptr *p)
+{
+}
+static inline void free_cpumask_ptr(cpumask_ptr *p)
+{
+}
+#define DEFINE_PER_CPUMASK(v) void *unused_##v __maybe_unused
+#define DECLARE_PER_CPUMASK(v)
+#define get_cpumask_var(p, v) do { } while(0)
+#define put_cpumask_var(p, v) do { } while(0)
+
+#else /* NR_CPUS > BITS_PER_LONG */
+
+#include <linux/slab.h>
+typedef cpumask_t *cpumask_ptr;
+static inline void _get_cpumask_ptr(cpumask_ptr *p, cpumask_t *m)
+{
+ *p = m;
+}
+static inline void alloc_cpumask_ptr(cpumask_ptr *p)
+{
+ _get_cpumask_ptr(p, kmalloc(sizeof(cpumask_t), GFP_KERNEL));
+}
+static inline void free_cpumask_ptr(cpumask_ptr *p)
+{
+ kfree(*p);
+}
+#define DEFINE_PER_CPUMASK(v) DEFINE_PER_CPU(cpumask_t, v)
+#define DECLARE_PER_CPUMASK(v) DECLARE_PER_CPU(cpumask_t, v)
+#define get_cpumask_var(p, v) _get_cpumask_ptr(&(p), &get_cpu_var(v))
+#define put_cpumask_var(p, v) put_cpu_var(v)
+
+#endif /* NR_CPUS > BITS_PER_LONG */
+
+#endif /* __LINUX_CPUMASK_PTR_H */

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/