Merge tag 'bitmap-for-7.3' of https://github.com/norov/linux

Pull bitmap updates from Yury Norov:
 "The usual set of fixes, cleanups and performance improvements together
  with a couple of new tests:

   - bitmap_find_next_zero_area_off() optimization (Sunyi)

   - bitmap_find_next_zero_area_off(): return size when no zero area is
     found (Yury)

   - bitmap vs IDA vs Maple Tree performance test (Yury)

   - get rid of cpumap_print_to_pagebuf() (Yury)

   - use nr_node_ids in __nodemask_pr_numnodes() (Li RongQing)

   - bitops: make the *_bit_le functions use unsigned long (Benjamin)

   - bitmap scatter & gather test fix (Christophe)

   - use __ASSEMBLER__ in bitmap header files (Thomas)"

* tag 'bitmap-for-7.3' of https://github.com/norov/linux: (25 commits)
  lib: test bitmap vs IDA vs Maple Tree performance for region allocations
  bitmap: Return size when no zero area is found
  media: s5p-mfc: Treat bitmap size as allocation failure
  crypto: ccp: Treat bitmap size as allocation failure
  powerpc/msi: Treat bitmap size as allocation failure
  ARM: dma-mapping: Treat bitmap size as allocation failure
  bitmap: drop bitmap_next_set_region()
  nodemask: reduce bitmap width to nr_node_ids in __nodemask_pr_numnodes()
  bitmap: Properly initialise destination bitmap for scatter & gather test
  lib/bitmap-str: get rid of cpumap_print_to_pagebuf()
  perf: Use sysfs_emit() for cpumask show callbacks
  PCI/sysfs: Use sysfs_emit() for cpumask show callbacks
  RDMA/hfi1: Use sysfs_emit() for cpumask show helper
  hwtracing: hisi_ptt: Use sysfs_emit() for cpumask show
  fpga: dfl-fme-perf: Use sysfs_emit() for cpumask show
  devfreq: Use sysfs_emit() for cpumask show callbacks
  cpu: Use sysfs_emit() for cpumask show callback
  x86/events: Use sysfs_emit() for cpumask show callbacks
  powerpc: Use sysfs_emit() for cpumask show callbacks
  arm: Use sysfs_emit() for cpumask show callbacks
  ...
This commit is contained in:
Linus Torvalds
2026-08-20 11:41:46 -07:00
68 changed files with 402 additions and 138 deletions

View File

@@ -4614,6 +4614,7 @@ F: lib/bitmap.c
F: lib/cpumask.c
F: lib/find_bit.c
F: lib/find_bit_benchmark.c
F: lib/region_alloc_benchmark.c
F: lib/test_bitmap.c
F: lib/tests/cpumask_kunit.c
F: tools/include/linux/bitfield.h
@@ -15608,6 +15609,7 @@ F: Documentation/core-api/maple_tree.rst
F: include/linux/maple_tree.h
F: include/trace/events/maple_tree.h
F: lib/maple_tree.c
F: lib/region_alloc_benchmark.c
F: lib/test_maple_tree.c
F: rust/helpers/maple_tree.c
F: rust/kernel/maple_tree.rs
@@ -29448,6 +29450,7 @@ F: Documentation/core-api/xarray.rst
F: include/linux/idr.h
F: include/linux/xarray.h
F: lib/idr.c
F: lib/region_alloc_benchmark.c
F: lib/test_xarray.c
F: lib/xarray.c
F: tools/testing/radix-tree

View File

@@ -127,7 +127,7 @@ static ssize_t mmdc_pmu_cpumask_show(struct device *dev,
{
struct mmdc_pmu *pmu_mmdc = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, &pmu_mmdc->cpu);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu_mmdc->cpu));
}
static struct device_attribute mmdc_pmu_cpumask_attr =

View File

@@ -390,7 +390,7 @@ static struct attribute_group l2x0_pmu_event_attrs_group = {
static ssize_t l2x0_pmu_cpumask_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return cpumap_print_to_pagebuf(true, buf, &pmu_cpu);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu_cpu));
}
static struct device_attribute l2x0_pmu_cpumask_attr =

View File

@@ -773,7 +773,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
start = bitmap_find_next_zero_area(mapping->bitmaps[i],
mapping->bits, 0, count, align);
if (start > mapping->bits)
if (start >= mapping->bits)
continue;
bitmap_set(mapping->bitmaps[i], start, count);
@@ -794,7 +794,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
start = bitmap_find_next_zero_area(mapping->bitmaps[i],
mapping->bits, 0, count, align);
if (start > mapping->bits) {
if (start >= mapping->bits) {
spin_unlock_irqrestore(&mapping->lock, flags);
return DMA_MAPPING_ERROR;
}

View File

@@ -690,7 +690,8 @@ show_shared_cpumap(struct kobject *k, struct kobj_attribute *attr, char *buf, bo
mask = &cache->shared_cpu_map;
return cpumap_print_to_pagebuf(list, buf, mask);
return sysfs_emit(buf, list ? "%*pbl\n" : "%*pb\n",
cpumask_pr_args(mask));
}
static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf)

View File

@@ -429,7 +429,7 @@ static char *memdup_to_str(char *maybe_str, int max_len, gfp_t gfp)
static ssize_t cpumask_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return cpumap_print_to_pagebuf(true, buf, &hv_24x7_cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&hv_24x7_cpumask));
}
static ssize_t sockets_show(struct device *dev,

View File

@@ -100,7 +100,7 @@ static ssize_t kernel_version_show(struct device *dev,
static ssize_t cpumask_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return cpumap_print_to_pagebuf(true, buf, &hv_gpci_cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&hv_gpci_cpumask));
}
/* Interface attribute array index to store system information */

View File

@@ -117,7 +117,7 @@ static ssize_t imc_pmu_cpumask_get_attr(struct device *dev,
return 0;
}
return cpumap_print_to_pagebuf(true, buf, active_mask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(active_mask));
}
static DEVICE_ATTR(cpumask, S_IRUGO, imc_pmu_cpumask_get_attr, NULL);

View File

@@ -21,7 +21,7 @@ int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num)
offset = bitmap_find_next_zero_area(bmp->bitmap, bmp->irq_count, 0,
num, (1 << order) - 1);
if (offset > bmp->irq_count)
if (offset >= bmp->irq_count)
goto err;
bitmap_set(bmp->bitmap, offset, num);

View File

@@ -137,7 +137,7 @@ static ssize_t _iommu_cpumask_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return cpumap_print_to_pagebuf(true, buf, &iommu_cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&iommu_cpumask));
}
static DEVICE_ATTR(cpumask, S_IRUGO, _iommu_cpumask_show, NULL);

View File

@@ -150,7 +150,7 @@ static void pmu_event_read(struct perf_event *event)
static ssize_t
get_attr_cpumask(struct device *dev, struct device_attribute *attr, char *buf)
{
return cpumap_print_to_pagebuf(true, buf, &cpu_mask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&cpu_mask));
}
static DEVICE_ATTR(cpumask, S_IRUGO, get_attr_cpumask, NULL);

View File

@@ -353,7 +353,7 @@ static ssize_t amd_uncore_attr_show_cpumask(struct device *dev,
struct pmu *ptr = dev_get_drvdata(dev);
struct amd_uncore_pmu *pmu = container_of(ptr, struct amd_uncore_pmu, pmu);
return cpumap_print_to_pagebuf(true, buf, &pmu->active_mask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu->active_mask));
}
static DEVICE_ATTR(cpumask, S_IRUGO, amd_uncore_attr_show_cpumask, NULL);

View File

@@ -7590,7 +7590,7 @@ static ssize_t intel_hybrid_get_attr_cpus(struct device *dev,
struct x86_hybrid_pmu *pmu =
container_of(dev_get_drvdata(dev), struct x86_hybrid_pmu, pmu);
return cpumap_print_to_pagebuf(true, buf, &pmu->supported_cpus);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu->supported_cpus));
}
static DEVICE_ATTR(cpus, S_IRUGO, intel_hybrid_get_attr_cpus, NULL);

View File

@@ -861,7 +861,7 @@ static ssize_t uncore_get_attr_cpumask(struct device *dev,
{
struct intel_uncore_pmu *pmu = container_of(dev_get_drvdata(dev), struct intel_uncore_pmu, pmu);
return cpumap_print_to_pagebuf(true, buf, &pmu->cpu_mask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu->cpu_mask));
}
static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL);

View File

@@ -218,7 +218,7 @@ static ssize_t show_cpus_attr(struct device *dev,
{
struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
return cpumap_print_to_pagebuf(true, buf, ca->map);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(ca->map));
}
#define _CPU_ATTR(name, map) \

View File

@@ -28,7 +28,7 @@ static u32 ccp_alloc_ksb(struct ccp_cmd_queue *cmd_q, unsigned int count)
ccp->sb_count,
ccp->sb_start,
count, 0);
if (start <= ccp->sb_count) {
if (start < ccp->sb_count) {
bitmap_set(ccp->sb, start, count);
mutex_unlock(&ccp->sb_mutex);

View File

@@ -47,7 +47,7 @@ static u32 ccp_lsb_alloc(struct ccp_cmd_queue *cmd_q, unsigned int count)
MAX_LSB_CNT * LSB_SIZE,
0,
count, 0);
if (start <= MAX_LSB_CNT * LSB_SIZE) {
if (start < MAX_LSB_CNT * LSB_SIZE) {
bitmap_set(ccp->lsbmap, start, count);
mutex_unlock(&ccp->sb_mutex);

View File

@@ -354,7 +354,7 @@ static ssize_t ddr_perf_cpumask_show(struct device *dev,
struct pmu *pmu = dev_get_drvdata(dev);
struct rockchip_dfi *dfi = container_of(pmu, struct rockchip_dfi, pmu);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(dfi->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(dfi->cpu)));
}
static struct device_attribute ddr_perf_cpumask_attr =

View File

@@ -540,7 +540,7 @@ static ssize_t related_cpus_show(struct device *dev,
{
struct hisi_uncore_freq *uncore = dev_get_drvdata(dev->parent);
return cpumap_print_to_pagebuf(true, buf, &uncore->related_cpus);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&uncore->related_cpus));
}
static DEVICE_ATTR_RO(related_cpus);

View File

@@ -186,7 +186,6 @@ static int hotplug_tests(void)
{
int i, nb_cpu_group, err = -ENOMEM;
cpumask_var_t offlined_cpus, *cpu_groups;
char *page_buf;
if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
return err;
@@ -194,10 +193,6 @@ static int hotplug_tests(void)
nb_cpu_group = alloc_init_cpu_groups(&cpu_groups);
if (nb_cpu_group < 0)
goto out_free_cpus;
page_buf = (char *)__get_free_page(GFP_KERNEL);
if (!page_buf)
goto out_free_cpu_groups;
/*
* Of course the last CPU cannot be powered down and cpu_down() should
* refuse doing that.
@@ -210,17 +205,11 @@ static int hotplug_tests(void)
* off, the cpu group itself should shut down.
*/
for (i = 0; i < nb_cpu_group; ++i) {
ssize_t len = cpumap_print_to_pagebuf(true, page_buf,
cpu_groups[i]);
/* Remove trailing newline. */
page_buf[len - 1] = '\0';
pr_info("Trying to turn off and on again group %d (CPUs %s)\n",
i, page_buf);
pr_info("Trying to turn off and on again group %d (CPUs %*pbl)\n",
i, cpumask_pr_args(cpu_groups[i]));
err += down_and_up_cpus(cpu_groups[i], offlined_cpus);
}
free_page((unsigned long)page_buf);
out_free_cpu_groups:
free_cpu_groups(nb_cpu_group, &cpu_groups);
out_free_cpus:
free_cpumask_var(offlined_cpus);

View File

@@ -183,7 +183,7 @@ static ssize_t cpumask_show(struct device *dev,
priv = to_fme_perf_priv(pmu);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(priv->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(priv->cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -780,7 +780,7 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr,
struct hisi_ptt *hisi_ptt = to_hisi_ptt(dev_get_drvdata(dev));
const cpumask_t *cpumask = cpumask_of_node(dev_to_node(&hisi_ptt->pdev->dev));
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -11,6 +11,7 @@
#include <linux/timer.h>
#include <linux/vmalloc.h>
#include <linux/highmem.h>
#include <linux/sysfs.h>
#include "hfi.h"
#include "common.h"
@@ -1049,7 +1050,7 @@ ssize_t sdma_get_cpu_to_sde_map(struct sdma_engine *sde, char *buf)
if (cpumask_empty(&sde->cpu_mask))
snprintf(buf, PAGE_SIZE, "%s\n", "empty");
else
cpumap_print_to_pagebuf(true, buf, &sde->cpu_mask);
sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&sde->cpu_mask));
mutex_unlock(&process_to_sde_mutex);
return strnlen(buf, PAGE_SIZE);
}

View File

@@ -43,7 +43,7 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
if (dev->mem_virt) {
start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align);
if (start > bits)
if (start >= bits)
goto no_mem;
bitmap_set(dev->mem_bitmap, start, count);

View File

@@ -112,7 +112,8 @@ static ssize_t pci_dev_show_local_cpu(struct device *dev, bool list,
#else
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
#endif
return cpumap_print_to_pagebuf(list, buf, mask);
return sysfs_emit(buf, list ? "%*pbl\n" : "%*pb\n",
cpumask_pr_args(mask));
}
static ssize_t local_cpus_show(struct device *dev,
@@ -137,7 +138,7 @@ static ssize_t cpuaffinity_show(struct device *dev,
{
const struct cpumask *cpumask = cpumask_of_pcibus(to_pci_bus(dev));
return cpumap_print_to_pagebuf(false, buf, cpumask);
return sysfs_emit(buf, "%*pb\n", cpumask_pr_args(cpumask));
}
static DEVICE_ATTR_RO(cpuaffinity);
@@ -146,7 +147,7 @@ static ssize_t cpulistaffinity_show(struct device *dev,
{
const struct cpumask *cpumask = cpumask_of_pcibus(to_pci_bus(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
static DEVICE_ATTR_RO(cpulistaffinity);

View File

@@ -221,7 +221,7 @@ static ssize_t ali_drw_pmu_cpumask_show(struct device *dev,
{
struct ali_drw_pmu *drw_pmu = to_ali_drw_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(drw_pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(drw_pmu->cpu)));
}
static struct device_attribute ali_drw_pmu_cpumask_attr =

View File

@@ -191,7 +191,7 @@ static ssize_t meson_ddr_perf_cpumask_show(struct device *dev,
{
struct ddr_pmu *pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pmu->cpu)));
}
static struct device_attribute meson_ddr_perf_cpumask_attr =

View File

@@ -1351,7 +1351,7 @@ static ssize_t pmu_cpumask_attr_show(struct device *dev,
struct pmu *pmu = dev_get_drvdata(dev);
struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(cci_pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(cci_pmu->cpu)));
}
static struct device_attribute pmu_cpumask_attr =

View File

@@ -537,7 +537,7 @@ static ssize_t arm_ccn_pmu_cpumask_show(struct device *dev,
{
struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(ccn->dt.cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(ccn->dt.cpu)));
}
static struct device_attribute arm_ccn_pmu_cpumask_attr =

View File

@@ -1516,7 +1516,7 @@ static ssize_t arm_cmn_cpumask_show(struct device *dev,
{
struct arm_cmn *cmn = to_cmn(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(cmn->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(cmn->cpu)));
}
static struct device_attribute arm_cmn_cpumask_attr =

View File

@@ -239,7 +239,7 @@ static ssize_t arm_ni_cpumask_show(struct device *dev,
{
struct arm_ni *ni = cd_to_ni(pmu_to_cd(dev_get_drvdata(dev)));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(ni->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(ni->cpu)));
}
static struct device_attribute arm_ni_cpumask_attr =

View File

@@ -337,7 +337,7 @@ static ssize_t arm_cspmu_cpumask_show(struct device *dev,
default:
return 0;
}
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
static struct attribute *arm_cspmu_cpumask_attrs[] = {

View File

@@ -237,8 +237,8 @@ static ssize_t dmc620_pmu_cpumask_show(struct device *dev,
{
struct dmc620_pmu *dmc620_pmu = to_dmc620_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf,
cpumask_of(dmc620_pmu->irq->cpu));
return sysfs_emit(buf, "%*pbl\n",
cpumask_pr_args(cpumask_of(dmc620_pmu->irq->cpu)));
}
static struct device_attribute dmc620_pmu_cpumask_attr =

View File

@@ -157,7 +157,7 @@ static ssize_t dsu_pmu_cpumask_show(struct device *dev,
default:
return 0;
}
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
static struct attribute *dsu_pmu_format_attrs[] = {

View File

@@ -570,7 +570,7 @@ static ssize_t cpus_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct arm_pmu *armpmu = to_arm_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &armpmu->supported_cpus);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&armpmu->supported_cpus));
}
static DEVICE_ATTR_RO(cpus);

View File

@@ -537,7 +537,7 @@ static ssize_t smmu_pmu_cpumask_show(struct device *dev,
{
struct smmu_pmu *smmu_pmu = to_smmu_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(smmu_pmu->on_cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(smmu_pmu->on_cpu)));
}
static struct device_attribute smmu_pmu_cpumask_attr =

View File

@@ -343,7 +343,7 @@ static ssize_t cpumask_show(struct device *dev,
{
struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, &spe_pmu->supported_cpus);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&spe_pmu->supported_cpus));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -568,7 +568,7 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr,
{
struct cxl_pmu_info *info = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(info->on_cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(info->on_cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -121,7 +121,7 @@ static ssize_t cpumask_show(struct device *dev,
{
struct dwc_pcie_pmu *pcie_pmu = to_dwc_pcie_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pcie_pmu->on_cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pcie_pmu->on_cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -237,7 +237,7 @@ static ssize_t ddr_perf_cpumask_show(struct device *dev,
{
struct ddr_pmu *pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pmu->cpu)));
}
static struct device_attribute ddr_perf_cpumask_attr =

View File

@@ -159,7 +159,7 @@ static ssize_t ddr_perf_cpumask_show(struct device *dev,
{
struct ddr_pmu *pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pmu->cpu)));
}
static struct device_attribute ddr_perf_cpumask_attr =

View File

@@ -373,7 +373,7 @@ static ssize_t cpumask_show(struct device *dev,
{
struct uncore_pmu *uncorepmu = to_uncore_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(uncorepmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(uncorepmu->cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -121,7 +121,7 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, c
{
struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pcie_pmu->on_cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pcie_pmu->on_cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -56,7 +56,7 @@ static ssize_t hisi_associated_cpus_sysfs_show(struct device *dev,
{
struct hisi_pmu *hisi_pmu = to_hisi_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &hisi_pmu->associated_cpus);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&hisi_pmu->associated_cpus));
}
static DEVICE_ATTR(associated_cpus, 0444, hisi_associated_cpus_sysfs_show, NULL);

View File

@@ -471,7 +471,7 @@ static ssize_t cn10k_ddr_perf_cpumask_show(struct device *dev,
{
struct cn10k_ddr_pmu *pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pmu->cpu)));
}
static struct device_attribute cn10k_ddr_perf_cpumask_attr =

View File

@@ -258,7 +258,7 @@ static ssize_t tad_pmu_cpumask_show(struct device *dev,
{
struct tad_pmu *tad_pmu = to_tad_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(tad_pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(tad_pmu->cpu)));
}
static DEVICE_ATTR(cpumask, 0444, tad_pmu_cpumask_show, NULL);

View File

@@ -164,7 +164,7 @@ static ssize_t pem_perf_cpumask_show(struct device *dev,
{
struct pem_pmu *pmu = dev_get_drvdata(dev);
return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(pmu->cpu)));
}
static struct device_attribute pem_perf_cpumask_attr =

View File

@@ -658,7 +658,7 @@ static ssize_t nv_c2c_pmu_cpumask_show(struct device *dev,
default:
return 0;
}
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
#define NV_C2C_PMU_CPUMASK_ATTR(_name, _config) \

View File

@@ -501,7 +501,7 @@ static ssize_t cmem_lat_pmu_cpumask_show(struct device *dev,
default:
return 0;
}
return cpumap_print_to_pagebuf(true, buf, cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask));
}
#define NV_PMU_CPUMASK_ATTR(_name, _config) \

View File

@@ -638,7 +638,7 @@ static ssize_t l2_cache_pmu_cpumask_show(struct device *dev,
{
struct l2cache_pmu *l2cache_pmu = to_l2cache_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &l2cache_pmu->cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&l2cache_pmu->cpumask));
}
static struct device_attribute l2_cache_pmu_cpumask_attr =

View File

@@ -663,7 +663,7 @@ static ssize_t cpumask_show(struct device *dev,
{
struct l3cache_pmu *l3pmu = to_l3cache_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &l3pmu->cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&l3pmu->cpumask));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -130,7 +130,7 @@ cpumask_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct starlink_pmu *starlink_pmu = to_starlink_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &starlink_pmu->cpumask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&starlink_pmu->cpumask));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -254,7 +254,7 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr,
struct tx2_uncore_pmu *tx2_pmu;
tx2_pmu = pmu_to_tx2_pmu(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, cpumask_of(tx2_pmu->cpu));
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpumask_of(tx2_pmu->cpu)));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -595,7 +595,7 @@ static ssize_t cpumask_show(struct device *dev,
{
struct xgene_pmu_dev *pmu_dev = to_pmu_dev(dev_get_drvdata(dev));
return cpumap_print_to_pagebuf(true, buf, &pmu_dev->parent->cpu);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&pmu_dev->parent->cpu));
}
static DEVICE_ATTR_RO(cpumask);

View File

@@ -16,47 +16,47 @@
#endif
static inline int test_bit_le(int nr, const void *addr)
static inline int test_bit_le(unsigned long nr, const void *addr)
{
return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void set_bit_le(int nr, void *addr)
static inline void set_bit_le(unsigned long nr, void *addr)
{
set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void clear_bit_le(int nr, void *addr)
static inline void clear_bit_le(unsigned long nr, void *addr)
{
clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void __set_bit_le(int nr, void *addr)
static inline void __set_bit_le(unsigned long nr, void *addr)
{
__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline void __clear_bit_le(int nr, void *addr)
static inline void __clear_bit_le(unsigned long nr, void *addr)
{
__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int test_and_set_bit_le(int nr, void *addr)
static inline int test_and_set_bit_le(unsigned long nr, void *addr)
{
return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int test_and_clear_bit_le(int nr, void *addr)
static inline int test_and_clear_bit_le(unsigned long nr, void *addr)
{
return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int __test_and_set_bit_le(int nr, void *addr)
static inline int __test_and_set_bit_le(unsigned long nr, void *addr)
{
return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}
static inline int __test_and_clear_bit_le(int nr, void *addr)
static inline int __test_and_clear_bit_le(unsigned long nr, void *addr)
{
return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
}

View File

@@ -2,7 +2,7 @@
#ifndef __LINUX_BITMAP_H
#define __LINUX_BITMAP_H
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__
#include <linux/align.h>
#include <linux/bitops.h>
@@ -209,6 +209,9 @@ unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
* The @align_mask should be one less than a power of 2; the effect is that
* the bit offset of all zero areas this function finds is multiples of that
* power of 2. A @align_mask of 0 means no alignment is required.
*
* Return: The bit offset of the found area or a value >= @size
* if no area is found.
*/
static __always_inline
unsigned long bitmap_find_next_zero_area(unsigned long *map,
@@ -697,14 +700,6 @@ void bitmap_gather(unsigned long *dst, const unsigned long *src,
__assign_bit(n++, dst, test_bit(bit, src));
}
static __always_inline
void bitmap_next_set_region(unsigned long *bitmap, unsigned int *rs,
unsigned int *re, unsigned int end)
{
*rs = find_next_bit(bitmap, end, *rs);
*re = find_next_zero_bit(bitmap, end, *rs + 1);
}
/**
* bitmap_release_region - release allocated bitmap region
* @bitmap: array of unsigned longs corresponding to the bitmap
@@ -894,6 +889,6 @@ void bitmap_write(unsigned long *map, unsigned long value,
#define bitmap_set_value8(map, value, start) \
bitmap_write(map, value, start, BITS_PER_BYTE)
#endif /* __ASSEMBLY__ */
#endif /* __ASSEMBLER__ */
#endif /* __LINUX_BITMAP_H */

View File

@@ -17,7 +17,7 @@
* position @h. For example
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
#if !defined(__ASSEMBLY__)
#if !defined(__ASSEMBLER__)
/*
* Missing asm support
@@ -75,7 +75,7 @@
#define BIT_U32(nr) BIT_TYPE(u32, nr)
#define BIT_U64(nr) BIT_TYPE(u64, nr)
#else /* defined(__ASSEMBLY__) */
#else /* defined(__ASSEMBLER__) */
/*
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
@@ -84,6 +84,6 @@
#define GENMASK(h, l) __GENMASK(h, l)
#define GENMASK_ULL(h, l) __GENMASK_ULL(h, l)
#endif /* !defined(__ASSEMBLY__) */
#endif /* !defined(__ASSEMBLER__) */
#endif /* __LINUX_BITS_H */

View File

@@ -13,7 +13,6 @@
#include <linux/cpumask_types.h>
#include <linux/gfp_types.h>
#include <linux/numa.h>
#include <linux/sprintf.h>
#include <linux/threads.h>
#include <linux/types.h>
#include <vdso/page.h>
@@ -1315,24 +1314,6 @@ static __always_inline bool cpu_dying(unsigned int cpu)
}
#endif /* NR_CPUS > BITS_PER_LONG */
/**
* cpumap_print_to_pagebuf - copies the cpumask into the buffer either
* as comma-separated list of cpus or hex values of cpumask
* @list: indicates whether the cpumap must be list
* @mask: the cpumask to copy
* @buf: the buffer to copy into
*
* Return: the length of the (null-terminated) @buf string, zero if
* nothing is copied.
*/
static __always_inline ssize_t
cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask)
{
/* Opencode offset_in_page(buf) to not include linux/mm.h */
return scnprintf(buf, PAGE_SIZE - ((unsigned long)buf & ~PAGE_MASK),
list ? "%*pbl\n" : "%*pb\n", cpumask_pr_args(mask));
}
/**
* cpumap_print_bitmask_to_buf - copies the cpumask into the buffer as
* hex values of cpumask

View File

@@ -95,6 +95,14 @@
extern nodemask_t _unused_nodemask_arg_;
#if MAX_NUMNODES > 1
extern unsigned int nr_node_ids;
extern unsigned int nr_online_nodes;
#else
#define nr_node_ids 1U
#define nr_online_nodes 1U
#endif
/**
* nodemask_pr_args - printf args to output a nodemask
* @maskp: nodemask to be printed
@@ -105,7 +113,7 @@ extern nodemask_t _unused_nodemask_arg_;
__nodemask_pr_bits(maskp)
static __always_inline unsigned int __nodemask_pr_numnodes(const nodemask_t *m)
{
return m ? MAX_NUMNODES : 0;
return m ? nr_node_ids : 0;
}
static __always_inline const unsigned long *__nodemask_pr_bits(const nodemask_t *m)
{
@@ -438,9 +446,6 @@ static __always_inline unsigned int next_memory_node(int nid)
return next_node(nid, node_states[N_MEMORY]);
}
extern unsigned int nr_node_ids;
extern unsigned int nr_online_nodes;
static __always_inline void node_set_online(int nid)
{
node_set_state(nid, N_ONLINE);
@@ -480,8 +485,6 @@ static __always_inline int num_node_state(enum node_states state)
#define first_memory_node 0
#define next_online_node(nid) (MAX_NUMNODES)
#define next_memory_node(nid) (MAX_NUMNODES)
#define nr_node_ids 1U
#define nr_online_nodes 1U
#define node_set_online(node) node_set_state((node), N_ONLINE)
#define node_set_offline(node) node_clear_state((node), N_ONLINE)

View File

@@ -12726,7 +12726,7 @@ static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr,
struct cpumask *mask = perf_scope_cpumask(pmu->scope);
if (mask)
return cpumap_print_to_pagebuf(true, buf, mask);
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
return 0;
}

View File

@@ -2683,6 +2683,19 @@ config FIND_BIT_BENCHMARK
If unsure, say N.
config REGION_ALLOC_BENCHMARK
tristate "Benchmark bitmap, IDA and Maple Tree region allocation"
help
This builds a microbenchmark comparing variable-sized region
allocation using bitmaps, IDA and Maple Tree. The benchmark
runs at initialization time.
Usage:
insmod region_alloc_benchmark.ko
insmod region_alloc_benchmark.ko capacities=1024,2048,4096,65536
If unsure, say N.
config FIND_BIT_BENCHMARK_RUST
tristate "Test find_bit functions in Rust"
depends on RUST

View File

@@ -64,6 +64,7 @@ obj-y += hexdump.o
obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
obj-y += kstrtox.o
obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
obj-$(CONFIG_REGION_ALLOC_BENCHMARK) += region_alloc_benchmark.o
obj-$(CONFIG_FIND_BIT_BENCHMARK_RUST) += find_bit_benchmark_rust.o
obj-$(CONFIG_TEST_BPF) += test_bpf.o
test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o

View File

@@ -75,8 +75,7 @@ static int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp,
* @off: in the string from which we are copying, We copy to @buf
* @count: the maximum number of bytes to print
*
* The sprintf("%*pb[l]") is used indirectly via its cpumap wrapper
* cpumap_print_to_pagebuf() or directly by drivers to export hexadecimal
* The sprintf("%*pb[l]") format is used by drivers to export hexadecimal
* bitmask and decimal list to userspace by sysfs ABI.
* Drivers might be using a normal attribute for this kind of ABIs. A
* normal attribute typically has show entry as below::
@@ -115,9 +114,9 @@ static int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp,
* parameters such as off, count from bin_attribute show entry to this API.
*
* The role of cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf()
* is similar with cpumap_print_to_pagebuf(), the difference is that
* scnprintf("%*pb[l]") mainly serves sysfs attribute with the assumption
* the destination buffer is exactly one page and won't be more than one page.
* is similar to direct sysfs_emit("%*pb[l]") formatting, but the latter
* assumes the destination buffer is exactly one page and won't be more than
* one page.
* cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf(), on the other
* hand, mainly serves bin_attribute which doesn't work with exact one page,
* and it can break the size limit of converted decimal list and hexadecimal

View File

@@ -424,6 +424,9 @@ EXPORT_SYMBOL(__bitmap_clear);
* The @align_mask should be one less than a power of 2; the effect is that
* the bit offset of all zero areas this function finds plus @align_offset
* is multiple of that power of 2.
*
* Return: The bit offset of the found area or a value greater than or equal
* to @size if no area is found.
*/
unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long size,
@@ -432,22 +435,23 @@ unsigned long bitmap_find_next_zero_area_off(unsigned long *map,
unsigned long align_mask,
unsigned long align_offset)
{
unsigned long index, end, i;
again:
index = find_next_zero_bit(map, size, start);
unsigned long end, i, off;
/* Align allocation */
index = __ALIGN_MASK(index + align_offset, align_mask) - align_offset;
for_each_clear_bit_from(start, map, size) {
start = __ALIGN_MASK(start + align_offset, align_mask) - align_offset;
end = start + nr;
if (end > size)
break;
end = index + nr;
if (end > size)
return end;
i = find_next_bit(map, end, index);
if (i < end) {
start = i + 1;
goto again;
off = round_down(start, BITS_PER_LONG);
i = find_last_bit(map + start / BITS_PER_LONG, end - off) + off;
if (i >= end || i < start)
return start;
start = i;
}
return index;
return size;
}
EXPORT_SYMBOL(bitmap_find_next_zero_area_off);

View File

@@ -149,6 +149,21 @@ static int __init test_find_next_and_bit(const void *bitmap,
return 0;
}
static int __init
test_bitmap_find_next_zero_area_off(unsigned long *bitmap, unsigned long len)
{
unsigned long i, cnt;
ktime_t time;
time = ktime_get();
for (cnt = i = 0; i < BITMAP_LEN; cnt++)
i = bitmap_find_next_zero_area_off(bitmap, BITMAP_LEN, i, 8, 0, 0) + 1;
time = ktime_get() - time;
pr_err("bitmap_find_next_zero_area_off:%7llu ns, %6ld iterations\n", time, cnt);
return 0;
}
static int __init find_bit_test(void)
{
unsigned long nbits = BITMAP_LEN / SPARSE;
@@ -158,6 +173,7 @@ static int __init find_bit_test(void)
get_random_bytes(bitmap, sizeof(bitmap));
get_random_bytes(bitmap2, sizeof(bitmap2));
test_bitmap_find_next_zero_area_off(bitmap, BITMAP_LEN);
test_find_next_bit(bitmap, BITMAP_LEN);
test_find_next_zero_bit(bitmap, BITMAP_LEN);
test_find_last_bit(bitmap, BITMAP_LEN);
@@ -181,6 +197,7 @@ static int __init find_bit_test(void)
__set_bit(get_random_u32_below(BITMAP_LEN), bitmap2);
}
test_bitmap_find_next_zero_area_off(bitmap, BITMAP_LEN);
test_find_next_bit(bitmap, BITMAP_LEN);
test_find_next_zero_bit(bitmap, BITMAP_LEN);
test_find_last_bit(bitmap, BITMAP_LEN);

View File

@@ -0,0 +1,217 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Benchmark bitmap, IDA and Maple Tree allocation of variable-sized regions. */
#include <linux/bitmap.h>
#include <linux/idr.h>
#include <linux/kernel.h>
#include <linux/maple_tree.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/xarray.h>
#define REGION_MAX_SIZE 32
static unsigned long *bitmap __initdata;
/* One more request guarantees that even an all-ones trace reaches ENOSPC. */
static u8 *reg_sz __initdata;
static unsigned long *reg_idx __initdata;
static unsigned long capacities[64] = { 1000000, 100000, 10000, 1000, 100, 10 };
static unsigned int cap_cnt = 6;
module_param_array(capacities, ulong, &cap_cnt, 0400);
MODULE_PARM_DESC(capacities, "Region capacities to benchmark");
static unsigned long __init benchmark_bitmap(unsigned long cap)
{
unsigned long cnt, idx;
ktime_t alloc_time, free_time;
size_t sz;
bitmap_zero(bitmap, cap);
alloc_time = ktime_get();
for (cnt = 0; cnt <= cap; cnt++) {
idx = bitmap_find_next_zero_area(bitmap, cap, 0, reg_sz[cnt], 0);
if (idx >= cap)
break;
reg_idx[cnt] = idx;
bitmap_set(bitmap, idx, reg_sz[cnt]);
}
alloc_time = ktime_get() - alloc_time;
idx = cnt;
free_time = ktime_get();
while (idx--)
bitmap_clear(bitmap, reg_idx[idx], reg_sz[idx]);
free_time = ktime_get() - free_time;
WARN_ON(!bitmap_empty(bitmap, cap));
sz = BITS_TO_LONGS(cap) * sizeof(unsigned long);
pr_err("Bitmap %12llu %12llu %8lu %8lu %10zu\n",
alloc_time, free_time, cnt, cap, sz);
return cnt;
}
static size_t __init ida_size(unsigned long nr_ids)
{
unsigned long entries = DIV_ROUND_UP(nr_ids, IDA_BITMAP_BITS);
unsigned long bitmaps = nr_ids / IDA_BITMAP_BITS;
unsigned long nodes = 0;
if (nr_ids % IDA_BITMAP_BITS > BITS_PER_XA_VALUE)
bitmaps++;
while (entries > 1) {
entries = DIV_ROUND_UP(entries, XA_CHUNK_SIZE);
nodes += entries;
}
return sizeof(struct ida) +
bitmaps * sizeof(struct ida_bitmap) +
nodes * sizeof(struct xa_node);
}
static unsigned long __init benchmark_ida(unsigned long cap)
{
struct ida ida = IDA_INIT(ida);
unsigned long cnt, idx, off, nr_ids = 0;
ktime_t alloc_time, free_time;
int id = -ENOSPC;
alloc_time = ktime_get();
for (cnt = 0; cnt <= cap; cnt++) {
for (off = 0; off < reg_sz[cnt]; off++) {
id = ida_alloc_max(&ida, cap - 1, GFP_KERNEL);
if (id < 0)
break;
if (!off)
reg_idx[cnt] = id;
}
if (id < 0) {
while (off--)
ida_free(&ida, reg_idx[cnt] + off);
break;
}
WARN_ON(id != reg_idx[cnt] + reg_sz[cnt] - 1);
nr_ids += reg_sz[cnt];
}
alloc_time = ktime_get() - alloc_time;
WARN_ON(id != -ENOSPC);
idx = cnt;
free_time = ktime_get();
while (idx--) {
for (off = 0; off < reg_sz[idx]; off++)
ida_free(&ida, reg_idx[idx] + off);
}
free_time = ktime_get() - free_time;
WARN_ON(!ida_is_empty(&ida));
pr_err("IDA %12llu %12llu %8lu %8lu %10zu\n",
alloc_time, free_time, cnt, cap, ida_size(nr_ids));
ida_destroy(&ida);
return cnt;
}
static unsigned long __init benchmark_maple_tree(unsigned long cap)
{
struct maple_tree mt = MTREE_INIT(mt, MT_FLAGS_ALLOC_RANGE);
unsigned long cnt, idx;
ktime_t alloc_time, free_time;
size_t sz;
int ret;
alloc_time = ktime_get();
for (cnt = 0; cnt <= cap; cnt++) {
ret = mtree_alloc_range(&mt, &idx, xa_mk_value(cnt + 1),
reg_sz[cnt], 0, cap - 1, GFP_KERNEL);
if (ret)
break;
reg_idx[cnt] = idx;
}
alloc_time = ktime_get() - alloc_time;
WARN_ON(ret != -EBUSY);
idx = cnt;
free_time = ktime_get();
while (idx--)
mtree_erase(&mt, reg_idx[idx]);
free_time = ktime_get() - free_time;
WARN_ON(!mtree_empty(&mt));
/* Minimum storage assuming fully occupied allocation-range leaf nodes. */
sz = sizeof(mt) + DIV_ROUND_UP(cnt, MAPLE_ARANGE64_SLOTS) * sizeof(struct maple_node);
pr_err("Maple %12llu %12llu %8lu %8lu %10zu\n",
alloc_time, free_time, cnt, cap, sz);
mtree_destroy(&mt);
return cnt;
}
static int __init region_alloc_benchmark(void)
{
unsigned long bitmap_count, ida_count, maple_count;
unsigned long i, max_cap = 0;
int ret = -ENOMEM;
for (i = 0; i < cap_cnt; i++) {
if (capacities[i] == 0) {
pr_err("capacity must be nonzero\n");
return -EINVAL;
}
max_cap = max(max_cap, capacities[i]);
}
bitmap = kvmalloc_array(BITS_TO_LONGS(max_cap), sizeof(*bitmap), GFP_KERNEL);
reg_sz = kvmalloc_array(max_cap + 1, sizeof(*reg_sz), GFP_KERNEL);
reg_idx = kvmalloc_array(max_cap, sizeof(*reg_idx), GFP_KERNEL);
if (!bitmap || !reg_sz || !reg_idx)
goto out;
pr_err("\nStart testing bitmap vs IDA vs Maple Tree region allocation\n");
pr_err("memory: bitmap is exact; IDA and Maple Tree are lower bounds\n");
pr_err("Type alloc (ns) free (ns) regions capacity memory (B)\n");
for (i = 0; i < cap_cnt; i++) {
unsigned long idx, max_size;
max_size = min(REGION_MAX_SIZE, capacities[i] / 10) ? : 1;
for (idx = 0; idx <= capacities[i]; idx++)
reg_sz[idx] = get_random_u32_below(max_size) + 1;
bitmap_count = benchmark_bitmap(capacities[i]);
maple_count = benchmark_maple_tree(capacities[i]);
ida_count = benchmark_ida(capacities[i]);
WARN_ON(bitmap_count != ida_count);
WARN_ON(bitmap_count != maple_count);
}
/* Return an error so the benchmark can run repeatedly without rmmod. */
pr_info("Region allocation benchmark complete\n");
ret = -EAGAIN;
out:
kvfree(reg_idx);
kvfree(reg_sz);
kvfree(bitmap);
return ret;
}
module_init(region_alloc_benchmark);
MODULE_AUTHOR("Yury Norov <ynorov@nvidia.com>");
MODULE_DESCRIPTION("Benchmark bitmap, IDA and Maple Tree region allocation");
MODULE_LICENSE("GPL");

View File

@@ -234,6 +234,43 @@ static void __init test_find_nth_bit(void)
}
}
static void __init
test_bitmap_find_next_zero_area_off(void)
{
DECLARE_BITMAP(bmap, 192);
bitmap_set(bmap, 0, 192);
bitmap_clear(bmap, 0, 8);
__clear_bit(50, bmap);
bitmap_clear(bmap, 60, 18);
__set_bit(69, bmap);
__clear_bit(80, bmap);
bitmap_clear(bmap, 100, 10);
__clear_bit(120, bmap);
bitmap_clear(bmap, 145, 8);
bitmap_clear(bmap, 160, 32);
expect_eq_uint(0,
bitmap_find_next_zero_area_off(bmap, 192, 0, 8, 0, 0));
expect_eq_uint(0,
bitmap_find_next_zero_area_off(bmap, 192, 0, 8, 3, 0));
expect_eq_uint(163,
bitmap_find_next_zero_area_off(bmap, 192, 0, 8, 3, 1));
expect_eq_uint(60,
bitmap_find_next_zero_area_off(bmap, 192, 1, 8, 0, 0));
expect_eq_uint(160,
bitmap_find_next_zero_area_off(bmap, 192, 1, 8, 7, 0));
expect_eq_uint(60,
bitmap_find_next_zero_area_off(bmap, 192, 1, 8, 7, 4));
expect_eq_uint(100,
bitmap_find_next_zero_area_off(bmap, 192, 0, 10, 0, 0));
expect_eq_uint(160,
bitmap_find_next_zero_area_off(bmap, 192, 0, 32, 0, 0));
expect_eq_uint(1,
!!(bitmap_find_next_zero_area_off(bmap, 192, 0, 33, 0, 0) >= 192));
}
static void __init test_fill_set(void)
{
DECLARE_BITMAP(bmap, 1024);
@@ -392,6 +429,7 @@ static void __init test_bitmap_sg(void)
/* Scatter/gather relationship */
bitmap_zero(bmap_tmp, 100);
bitmap_zero(bmap_res, 100);
bitmap_gather(bmap_tmp, bmap_scatter, sg_mask, nbits);
bitmap_scatter(bmap_res, bmap_tmp, sg_mask, nbits);
expect_eq_bitmap(bmap_scatter, bmap_res, 100);
@@ -1559,6 +1597,7 @@ static void __init selftest(void)
test_for_each_clear_bitrange_from();
test_for_each_set_clump8();
test_for_each_set_bit_wrap();
test_bitmap_find_next_zero_area_off();
}
KSTM_MODULE_LOADERS(test_bitmap);

View File

@@ -17,7 +17,7 @@
* position @h. For example
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
#if !defined(__ASSEMBLY__)
#if !defined(__ASSEMBLER__)
/*
* Missing asm support
@@ -75,7 +75,7 @@
#define BIT_U32(nr) BIT_TYPE(u32, nr)
#define BIT_U64(nr) BIT_TYPE(u64, nr)
#else /* defined(__ASSEMBLY__) */
#else /* defined(__ASSEMBLER__) */
/*
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
@@ -84,6 +84,6 @@
#define GENMASK(h, l) __GENMASK(h, l)
#define GENMASK_ULL(h, l) __GENMASK_ULL(h, l)
#endif /* !defined(__ASSEMBLY__) */
#endif /* !defined(__ASSEMBLER__) */
#endif /* __LINUX_BITS_H */