/* SPDX-License-Identifier: GPL-2.0-only */ /* * Simple cpumask implementation * * Copyright (C) 2015, Red Hat Inc, Andrew Jones */ #ifndef _CPUMASK_H_ #define _CPUMASK_H_ #include #include #include #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)); } /* true if src1 is a subset of src2 */ static inline bool cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) { if (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) return false; } return !lastmask || !((cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask); } /* false if dst is empty */ static inline bool cpumask_and(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; unsigned long ret = 0; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) { cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & cpumask_bits(src2)[i]; ret |= cpumask_bits(dst)[i]; } cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & cpumask_bits(src2)[i]) & lastmask; return ret | cpumask_bits(dst)[i]; } static inline void cpumask_or(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) cpumask_bits(dst)[i] = cpumask_bits(src1)[i] | cpumask_bits(src2)[i]; cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] | cpumask_bits(src2)[i]) & lastmask; } static inline void cpumask_xor(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) cpumask_bits(dst)[i] = cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i]; cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i]) & lastmask; } /* false if dst is empty */ static inline bool cpumask_andnot(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; unsigned long ret = 0; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) { cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]; ret |= cpumask_bits(dst)[i]; } cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask; return ret | cpumask_bits(dst)[i]; } static inline bool cpumask_equal(const struct cpumask *src1, const struct cpumask *src2) { unsigned long lastmask = BIT_MASK(nr_cpus) - 1; int i; for (i = 0; i < BIT_WORD(nr_cpus); ++i) { if (cpumask_bits(src1)[i] != cpumask_bits(src2)[i]) return false; } return !lastmask || (cpumask_bits(src1)[i] & lastmask) == (cpumask_bits(src2)[i] & lastmask); } 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_ */