Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/lib/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  cpumask.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/cpumask.h>
#include <linux/export.h>
#include <linux/memblock.h>
#include <linux/numa.h>

/* These are not inline because of header tangles. */
#ifdef CONFIG_CPUMASK_OFFSTACK
/**
 * alloc_cpumask_var_node - allocate a struct cpumask on a given node
 * @mask: pointer to cpumask_var_t where the cpumask is returned
 * @flags: GFP_ flags
 * @node: memory node from which to allocate or %NUMA_NO_NODE
 *
 * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
 * a nop returning a constant 1 (in <linux/cpumask.h>).
 *
 * Return: TRUE if memory allocation succeeded, FALSE otherwise.
 *
 * In addition, mask will be NULL if this fails.  Note that gcc is
 * usually smart enough to know that mask can never be NULL if
 * CONFIG_CPUMASK_OFFSTACK=n, so does code elimination in that case
 * too.
 */

bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node)
{
 *mask = kmalloc_node(cpumask_size(), flags, node);

#ifdef CONFIG_DEBUG_PER_CPU_MAPS
 if (!*mask) {
  printk(KERN_ERR "=> alloc_cpumask_var: failed!\n");
  dump_stack();
 }
#endif

 return *mask != NULL;
}
EXPORT_SYMBOL(alloc_cpumask_var_node);

/**
 * alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena.
 * @mask: pointer to cpumask_var_t where the cpumask is returned
 *
 * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
 * a nop (in <linux/cpumask.h>).
 * Either returns an allocated (zero-filled) cpumask, or causes the
 * system to panic.
 */

void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
{
 *mask = memblock_alloc_or_panic(cpumask_size(), SMP_CACHE_BYTES);
}

/**
 * free_cpumask_var - frees memory allocated for a struct cpumask.
 * @mask: cpumask to free
 *
 * This is safe on a NULL mask.
 */

void free_cpumask_var(cpumask_var_t mask)
{
 kfree(mask);
}
EXPORT_SYMBOL(free_cpumask_var);

/**
 * free_bootmem_cpumask_var - frees result of alloc_bootmem_cpumask_var
 * @mask: cpumask to free
 */

void __init free_bootmem_cpumask_var(cpumask_var_t mask)
{
 memblock_free(mask, cpumask_size());
}
#endif

/**
 * cpumask_local_spread - select the i'th cpu based on NUMA distances
 * @i: index number
 * @node: local numa_node
 *
 * Return: online CPU according to a numa aware policy; local cpus are returned
 * first, followed by non-local ones, then it wraps around.
 *
 * For those who wants to enumerate all CPUs based on their NUMA distances,
 * i.e. call this function in a loop, like:
 *
 * for (i = 0; i < num_online_cpus(); i++) {
 * cpu = cpumask_local_spread(i, node);
 * do_something(cpu);
 * }
 *
 * There's a better alternative based on for_each()-like iterators:
 *
 * for_each_numa_hop_mask(mask, node) {
 * for_each_cpu_andnot(cpu, mask, prev)
 * do_something(cpu);
 * prev = mask;
 * }
 *
 * It's simpler and more verbose than above. Complexity of iterator-based
 * enumeration is O(sched_domains_numa_levels * nr_cpu_ids), while
 * cpumask_local_spread() when called for each cpu is
 * O(sched_domains_numa_levels * nr_cpu_ids * log(nr_cpu_ids)).
 */

unsigned int cpumask_local_spread(unsigned int i, int node)
{
 unsigned int cpu;

 /* Wrap: we always want a cpu. */
 i %= num_online_cpus();

 cpu = sched_numa_find_nth_cpu(cpu_online_mask, i, node);

 WARN_ON(cpu >= nr_cpu_ids);
 return cpu;
}
EXPORT_SYMBOL(cpumask_local_spread);

static DEFINE_PER_CPU(int, distribute_cpu_mask_prev);

/**
 * cpumask_any_and_distribute - Return an arbitrary cpu within src1p & src2p.
 * @src1p: first &cpumask for intersection
 * @src2p: second &cpumask for intersection
 *
 * Iterated calls using the same srcp1 and srcp2 will be distributed within
 * their intersection.
 *
 * Return: >= nr_cpu_ids if the intersection is empty.
 */

unsigned int cpumask_any_and_distribute(const struct cpumask *src1p,
          const struct cpumask *src2p)
{
 unsigned int next, prev;

 /* NOTE: our first selection will skip 0. */
 prev = __this_cpu_read(distribute_cpu_mask_prev);

 next = cpumask_next_and_wrap(prev, src1p, src2p);
 if (next < nr_cpu_ids)
  __this_cpu_write(distribute_cpu_mask_prev, next);

 return next;
}
EXPORT_SYMBOL(cpumask_any_and_distribute);

/**
 * cpumask_any_distribute - Return an arbitrary cpu from srcp
 * @srcp: &cpumask for selection
 *
 * Return: >= nr_cpu_ids if the intersection is empty.
 */

unsigned int cpumask_any_distribute(const struct cpumask *srcp)
{
 unsigned int next, prev;

 /* NOTE: our first selection will skip 0. */
 prev = __this_cpu_read(distribute_cpu_mask_prev);
 next = cpumask_next_wrap(prev, srcp);
 if (next < nr_cpu_ids)
  __this_cpu_write(distribute_cpu_mask_prev, next);

 return next;
}
EXPORT_SYMBOL(cpumask_any_distribute);

Messung V0.5
C=95 H=88 G=91

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.