| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Simple cpumask implementation |
| * |
| * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com> |
| */ |
| #ifndef _CPUMASK_H_ |
| #define _CPUMASK_H_ |
| #include <bitops.h> |
| #include <limits.h> |
| #include <asm/setup.h> |
| |
| #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG) |
| |
| typedef struct cpumask { |
| unsigned long bits[CPUMASK_NR_LONGS]; |
| } cpumask_t; |
| |
| #define cpumask_bits(maskp) ((maskp)->bits) |
| |
| static inline void cpumask_set_cpu(int cpu, cpumask_t *mask) |
| { |
| assert(cpu >= 0 && cpu < nr_cpus); |
| set_bit(cpu, cpumask_bits(mask)); |
| } |
| |
| static inline void cpumask_clear_cpu(int cpu, cpumask_t *mask) |
| { |
| assert(cpu >= 0 && cpu < nr_cpus); |
| clear_bit(cpu, cpumask_bits(mask)); |
| } |
| |
| static inline int cpumask_test_cpu(int cpu, const cpumask_t *mask) |
| { |
| assert(cpu >= 0 && cpu < nr_cpus); |
| return test_bit(cpu, cpumask_bits(mask)); |
| } |
| |
| static inline int cpumask_test_and_set_cpu(int cpu, cpumask_t *mask) |
| { |
| assert(cpu >= 0 && cpu < nr_cpus); |
| return test_and_set_bit(cpu, cpumask_bits(mask)); |
| } |
| |
| static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask) |
| { |
| assert(cpu >= 0 && cpu < nr_cpus); |
| return test_and_clear_bit(cpu, cpumask_bits(mask)); |
| } |
| |
| static inline void cpumask_setall(cpumask_t *mask) |
| { |
| memset(mask, 0xff, sizeof(*mask)); |
| } |
| |
| static inline void cpumask_clear(cpumask_t *mask) |
| { |
| memset(mask, 0, sizeof(*mask)); |
| } |
| |
| static inline bool cpumask_empty(const cpumask_t *mask) |
| { |
| unsigned long lastmask = BIT_MASK(nr_cpus) - 1; |
| |
| for (int i = 0; i < BIT_WORD(nr_cpus); ++i) |
| if (cpumask_bits(mask)[i]) |
| return false; |
| |
| return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask); |
| } |
| |
| static inline bool cpumask_full(const cpumask_t *mask) |
| { |
| unsigned long lastmask = BIT_MASK(nr_cpus) - 1; |
| |
| for (int i = 0; i < BIT_WORD(nr_cpus); ++i) |
| if (cpumask_bits(mask)[i] != ULONG_MAX) |
| return false; |
| |
| return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask; |
| } |
| |
| static inline int cpumask_weight(const cpumask_t *mask) |
| { |
| int w = 0, i; |
| |
| for (i = 0; i < nr_cpus; ++i) |
| if (cpumask_test_cpu(i, mask)) |
| ++w; |
| return w; |
| } |
| |
| static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src) |
| { |
| memcpy(cpumask_bits(dst), cpumask_bits(src), |
| CPUMASK_NR_LONGS * sizeof(long)); |
| } |
| |
| static inline int cpumask_next(int cpu, const cpumask_t *mask) |
| { |
| while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask)) |
| ; |
| return cpu; |
| } |
| |
| #define for_each_cpu(cpu, mask) \ |
| for ((cpu) = cpumask_next(-1, mask); \ |
| (cpu) < nr_cpus; \ |
| (cpu) = cpumask_next(cpu, mask)) |
| |
| extern cpumask_t cpu_present_mask; |
| extern cpumask_t cpu_online_mask; |
| extern cpumask_t cpu_idle_mask; |
| #define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask) |
| #define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask) |
| #define cpu_idle(cpu) cpumask_test_cpu(cpu, &cpu_idle_mask) |
| #define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask) |
| #define for_each_online_cpu(cpu) for_each_cpu(cpu, &cpu_online_mask) |
| |
| static inline void set_cpu_present(int cpu, bool present) |
| { |
| if (present) |
| cpumask_set_cpu(cpu, &cpu_present_mask); |
| else |
| cpumask_clear_cpu(cpu, &cpu_present_mask); |
| } |
| |
| static inline void set_cpu_online(int cpu, bool online) |
| { |
| if (online) |
| cpumask_set_cpu(cpu, &cpu_online_mask); |
| else |
| cpumask_clear_cpu(cpu, &cpu_online_mask); |
| } |
| |
| static inline void set_cpu_idle(int cpu, bool idle) |
| { |
| if (idle) |
| cpumask_set_cpu(cpu, &cpu_idle_mask); |
| else |
| cpumask_clear_cpu(cpu, &cpu_idle_mask); |
| } |
| |
| #endif /* _CPUMASK_H_ */ |