* General Public License version 2 for more details (a copy is included
* in the LICENSE file that accompanied this code).
*
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA
- *
* GPL HEADER END
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
- * Copyright (c) 2012, 2015, Intel Corporation.
+ * Copyright (c) 2012, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Example: if there are 8 cores on the system, while creating a CPT
* with cpu_npartitions=4:
- * core[0, 1] = partition[0], core[2, 3] = partition[1]
- * core[4, 5] = partition[2], core[6, 7] = partition[3]
+ * core[0, 1] = partition[0], core[2, 3] = partition[1]
+ * core[4, 5] = partition[2], core[6, 7] = partition[3]
*
* cpu_npartitions=1:
- * core[0, 1, ... 7] = partition[0]
+ * core[0, 1, ... 7] = partition[0]
*
* . User can also specify CPU partitions by string pattern
*
* Examples: cpu_partitions="0[0,1], 1[2,3]"
- * cpu_partitions="N 0[0-3], 1[4-8]"
+ * cpu_partitions="N 0[0-3], 1[4-8]"
*
* The first character "N" means following numbers are numa ID
*
* . NUMA allocators, CPU affinity threads are built over CPU partitions,
* instead of HW CPUs or HW nodes.
*
- * . By default, Lustre modules should refer to the global cfs_cpt_table,
+ * . By default, Lustre modules should refer to the global cfs_cpt_tab,
* instead of accessing HW CPUs directly, so concurrency of Lustre can be
- * configured by cpu_npartitions of the global cfs_cpt_table
+ * configured by cpu_npartitions of the global cfs_cpt_tab
*
* . If cpu_npartitions=1(all CPUs in one pool), lustre should work the
* same way as 2.2 or earlier versions
#ifndef __LIBCFS_CPU_H__
#define __LIBCFS_CPU_H__
-#ifndef HAVE_LIBCFS_CPT
-
-struct cfs_cpt_table {
- /* # of CPU partitions */
- int ctb_nparts;
- /* cpu mask */
- cpumask_t ctb_mask;
- /* node mask */
- nodemask_t ctb_nodemask;
- /* version */
- __u64 ctb_version;
-};
+#include <linux/cpu.h>
+#include <linux/cpuset.h>
+#include <linux/slab.h>
+#include <linux/topology.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
-#endif /* !HAVE_LIBCFS_CPT */
+#include <libcfs/linux/linux-cpu.h>
/* any CPU partition */
#define CFS_CPT_ANY (-1)
-extern struct cfs_cpt_table *cfs_cpt_table;
+struct cfs_cpt_table;
+
+#ifdef CONFIG_SMP
+extern struct cfs_cpt_table *cfs_cpt_tab;
/**
* destroy a CPU partition table
/**
* create a cfs_cpt_table with \a ncpt number of partitions
*/
-struct cfs_cpt_table *cfs_cpt_table_alloc(unsigned int ncpt);
+struct cfs_cpt_table *cfs_cpt_table_alloc(int ncpt);
/**
* print string information of cpt-table
*/
int cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len);
/**
+ * print distance information of cpt-table
+ */
+int cfs_cpt_distance_print(struct cfs_cpt_table *cptab, char *buf, int len);
+/**
* return total number of CPU partitions in \a cptab
*/
-int
-cfs_cpt_number(struct cfs_cpt_table *cptab);
+int cfs_cpt_number(struct cfs_cpt_table *cptab);
/**
- * return number of HW cores or hypter-threadings in a CPU partition \a cpt
+ * return number of HW cores or hyper-threadings in a CPU partition \a cpt
*/
int cfs_cpt_weight(struct cfs_cpt_table *cptab, int cpt);
/**
/**
* return cpumask of CPU partition \a cpt
*/
-cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
+cpumask_var_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt);
/**
* return nodemask of CPU partition \a cpt
*/
*/
int cfs_cpt_of_cpu(struct cfs_cpt_table *cptab, int cpu);
/**
+ * shadow HW node ID \a NODE to CPU-partition ID by \a cptab
+ */
+int cfs_cpt_of_node(struct cfs_cpt_table *cptab, int node);
+/**
+ * NUMA distance between \a cpt1 and \a cpt2 in \a cptab
+ */
+unsigned int cfs_cpt_distance(struct cfs_cpt_table *cptab, int cpt1, int cpt2);
+/**
* bind current thread on a CPU-partition \a cpt of \a cptab
*/
int cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt);
/**
- * add \a cpu to CPU partion @cpt of \a cptab, return 1 for success,
+ * add \a cpu to CPU partition @cpt of \a cptab, return 1 for success,
* otherwise 0 is returned
*/
int cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu);
* add all cpus in \a mask to CPU partition \a cpt
* return 1 if successfully set all CPUs, otherwise return 0
*/
-int cfs_cpt_set_cpumask(struct cfs_cpt_table *cptab,
- int cpt, cpumask_t *mask);
+int cfs_cpt_set_cpumask(struct cfs_cpt_table *cptab, int cpt,
+ const cpumask_t *mask);
/**
* remove all cpus in \a mask from CPU partition \a cpt
*/
-void cfs_cpt_unset_cpumask(struct cfs_cpt_table *cptab,
- int cpt, cpumask_t *mask);
+void cfs_cpt_unset_cpumask(struct cfs_cpt_table *cptab, int cpt,
+ const cpumask_t *mask);
/**
* add all cpus in NUMA node \a node to CPU partition \a cpt
* return 1 if successfully set all CPUs, otherwise return 0
* remove all cpus in NUMA node \a node from CPU partition \a cpt
*/
void cfs_cpt_unset_node(struct cfs_cpt_table *cptab, int cpt, int node);
-
/**
* add all cpus in node mask \a mask to CPU partition \a cpt
* return 1 if successfully set all CPUs, otherwise return 0
*/
-int cfs_cpt_set_nodemask(struct cfs_cpt_table *cptab,
- int cpt, nodemask_t *mask);
+int cfs_cpt_set_nodemask(struct cfs_cpt_table *cptab, int cpt,
+ const nodemask_t *mask);
/**
* remove all cpus in node mask \a mask from CPU partition \a cpt
*/
-void cfs_cpt_unset_nodemask(struct cfs_cpt_table *cptab,
- int cpt, nodemask_t *mask);
-/**
- * unset all cpus for CPU partition \a cpt
- */
-void cfs_cpt_clear(struct cfs_cpt_table *cptab, int cpt);
+void cfs_cpt_unset_nodemask(struct cfs_cpt_table *cptab, int cpt,
+ const nodemask_t *mask);
/**
* convert partition id \a cpt to numa node id, if there are more than one
* nodes in this partition, it might return a different node id each time.
*/
int cfs_cpt_spread_node(struct cfs_cpt_table *cptab, int cpt);
-/**
- * return number of HTs in the same core of \a cpu
- */
-int cfs_cpu_ht_nsiblings(int cpu);
+int cfs_cpu_init(void);
+void cfs_cpu_fini(void);
+
+#else /* !CONFIG_SMP */
+
+#define cfs_cpt_tab ((struct cfs_cpt_table *)NULL)
+
+static inline void cfs_cpt_table_free(struct cfs_cpt_table *cptab)
+{
+}
+
+static inline struct cfs_cpt_table *cfs_cpt_table_alloc(int ncpt)
+{
+ return NULL;
+}
+
+static inline int cfs_cpt_table_print(struct cfs_cpt_table *cptab,
+ char *buf, int len)
+{
+ int rc;
+
+ rc = snprintf(buf, len, "0\t: 0\n");
+ len -= rc;
+ if (len <= 0)
+ return -EFBIG;
+
+ return rc;
+}
+
+static inline int cfs_cpt_distance_print(struct cfs_cpt_table *cptab,
+ char *buf, int len)
+{
+ int rc;
+
+ rc = snprintf(buf, len, "0\t: 0:1\n");
+ len -= rc;
+ if (len <= 0)
+ return -EFBIG;
+
+ return rc;
+}
+
+static inline cpumask_var_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab,
+ int cpt)
+{
+ return (cpumask_var_t *) cpu_online_mask;
+}
+
+static inline int cfs_cpt_number(struct cfs_cpt_table *cptab)
+{
+ return 1;
+}
+
+static inline int cfs_cpt_weight(struct cfs_cpt_table *cptab, int cpt)
+{
+ return 1;
+}
+
+static inline nodemask_t *cfs_cpt_nodemask(struct cfs_cpt_table *cptab,
+ int cpt)
+{
+ return &node_online_map;
+}
+
+static inline unsigned int cfs_cpt_distance(struct cfs_cpt_table *cptab,
+ int cpt1, int cpt2)
+{
+ return 1;
+}
+
+static inline int cfs_cpt_set_node(struct cfs_cpt_table *cptab, int cpt,
+ int node)
+{
+ return 1;
+}
+
+static inline int cfs_cpt_spread_node(struct cfs_cpt_table *cptab, int cpt)
+{
+ return 0;
+}
+
+static inline int cfs_cpt_current(struct cfs_cpt_table *cptab, int remap)
+{
+ return 0;
+}
+
+static inline int cfs_cpt_of_node(struct cfs_cpt_table *cptab, int node)
+{
+ return 0;
+}
+
+static inline int cfs_cpt_bind(struct cfs_cpt_table *cptab, int cpt)
+{
+ return 0;
+}
+
+static inline int cfs_cpu_init(void)
+{
+ return 0;
+}
+
+static inline void cfs_cpu_fini(void)
+{
+}
+
+#endif /* CONFIG_SMP */
+
+static inline
+struct workqueue_struct *cfs_cpt_bind_workqueue(const char *wq_name,
+ struct cfs_cpt_table *tbl,
+ int flags, int cpt, int nthrs)
+{
+ cpumask_var_t *mask = cfs_cpt_cpumask(tbl, cpt);
+ struct workqueue_attrs attrs = { };
+ struct workqueue_struct *wq;
+
+ wq = alloc_workqueue(wq_name, WQ_UNBOUND | flags, nthrs);
+ if (!wq)
+ return ERR_PTR(-ENOMEM);
+
+ if (mask && alloc_cpumask_var(&attrs.cpumask, GFP_KERNEL)) {
+ cpumask_copy(attrs.cpumask, *mask);
+ cpus_read_lock();
+ cfs_apply_workqueue_attrs(wq, &attrs);
+ cpus_read_unlock();
+ free_cpumask_var(attrs.cpumask);
+ }
+
+ return wq;
+}
/*
* allocate per-cpu-partition data, returned value is an array of pointers,
* variable can be indexed by CPU ID.
- * cptab != NULL: size of array is number of CPU partitions
- * cptab == NULL: size of array is number of HW cores
+ * cptab != NULL: size of array is number of CPU partitions
+ * cptab == NULL: size of array is number of HW cores
*/
void *cfs_percpt_alloc(struct cfs_cpt_table *cptab, unsigned int size);
/*
- * destory per-cpu-partition variable
+ * destroy per-cpu-partition variable
*/
-void cfs_percpt_free(void *vars);
-int cfs_percpt_number(void *vars);
+void cfs_percpt_free(void *vars);
+int cfs_percpt_number(void *vars);
#define cfs_percpt_for_each(var, i, vars) \
for (i = 0; i < cfs_percpt_number(vars) && \
/* lock private lock \a index of \a pcl */
void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index);
+
/* unlock private lock \a index of \a pcl */
void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index);
-#define CFS_PERCPT_LOCK_KEYS 256
+#define CFS_PERCPT_LOCK_KEYS 256
/* NB: don't allocate keys dynamically, lockdep needs them to be in ".data" */
#define cfs_percpt_lock_alloc(cptab) \
({ \
- static struct lock_class_key ___keys[CFS_PERCPT_LOCK_KEYS]; \
- struct cfs_percpt_lock *___lk; \
+ static struct lock_class_key ___keys[CFS_PERCPT_LOCK_KEYS]; \
+ struct cfs_percpt_lock *___lk; \
\
if (cfs_cpt_number(cptab) > CFS_PERCPT_LOCK_KEYS) \
___lk = cfs_percpt_lock_create(cptab, NULL); \
#define cfs_cpt_for_each(i, cptab) \
for (i = 0; i < cfs_cpt_number(cptab); i++)
-#ifndef __read_mostly
-# define __read_mostly
-#endif
-
-#ifndef ____cacheline_aligned
-#define ____cacheline_aligned
-#endif
-
-int cfs_cpu_init(void);
-void cfs_cpu_fini(void);
-
#endif /* __LIBCFS_CPU_H__ */