[RFC 04/13] cpumask: add cpumask_ptr operations

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Mike Travis
Date: Saturday, September 6, 2008 - 4:50 pm

* 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@sgi.com>
---
 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 */

-- 
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[RFC 04/13] cpumask: add cpumask_ptr operations, Mike Travis, (Sat Sep 6, 4:50 pm)