1dfc1fec2SAndrew Jones /* SPDX-License-Identifier: GPL-2.0-only */ 2f20e2561SAndrew Jones /* 3f20e2561SAndrew Jones * Simple cpumask implementation 4f20e2561SAndrew Jones * 5f20e2561SAndrew Jones * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com> 6f20e2561SAndrew Jones */ 7dfc1fec2SAndrew Jones #ifndef _CPUMASK_H_ 8dfc1fec2SAndrew Jones #define _CPUMASK_H_ 96ed97c50SPeter Feiner #include <bitops.h> 107213c4d6SAndrew Jones #include <limits.h> 117213c4d6SAndrew Jones #include <asm/setup.h> 12f20e2561SAndrew Jones 13f20e2561SAndrew Jones #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG) 14f20e2561SAndrew Jones 15f20e2561SAndrew Jones typedef struct cpumask { 16f20e2561SAndrew Jones unsigned long bits[CPUMASK_NR_LONGS]; 17f20e2561SAndrew Jones } cpumask_t; 18f20e2561SAndrew Jones 19f20e2561SAndrew Jones #define cpumask_bits(maskp) ((maskp)->bits) 20f20e2561SAndrew Jones 21f20e2561SAndrew Jones static inline void cpumask_set_cpu(int cpu, cpumask_t *mask) 22f20e2561SAndrew Jones { 23adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus); 24f20e2561SAndrew Jones set_bit(cpu, cpumask_bits(mask)); 25f20e2561SAndrew Jones } 26f20e2561SAndrew Jones 27f20e2561SAndrew Jones static inline void cpumask_clear_cpu(int cpu, cpumask_t *mask) 28f20e2561SAndrew Jones { 29adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus); 30f20e2561SAndrew Jones clear_bit(cpu, cpumask_bits(mask)); 31f20e2561SAndrew Jones } 32f20e2561SAndrew Jones 33f20e2561SAndrew Jones static inline int cpumask_test_cpu(int cpu, const cpumask_t *mask) 34f20e2561SAndrew Jones { 35adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus); 36f20e2561SAndrew Jones return test_bit(cpu, cpumask_bits(mask)); 37f20e2561SAndrew Jones } 38f20e2561SAndrew Jones 39f20e2561SAndrew Jones static inline int cpumask_test_and_set_cpu(int cpu, cpumask_t *mask) 40f20e2561SAndrew Jones { 41adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus); 42f20e2561SAndrew Jones return test_and_set_bit(cpu, cpumask_bits(mask)); 43f20e2561SAndrew Jones } 44f20e2561SAndrew Jones 45f20e2561SAndrew Jones static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask) 46f20e2561SAndrew Jones { 47adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus); 48f20e2561SAndrew Jones return test_and_clear_bit(cpu, cpumask_bits(mask)); 49f20e2561SAndrew Jones } 50f20e2561SAndrew Jones 51f20e2561SAndrew Jones static inline void cpumask_setall(cpumask_t *mask) 52f20e2561SAndrew Jones { 537213c4d6SAndrew Jones memset(mask, 0xff, sizeof(*mask)); 54f20e2561SAndrew Jones } 55f20e2561SAndrew Jones 56f20e2561SAndrew Jones static inline void cpumask_clear(cpumask_t *mask) 57f20e2561SAndrew Jones { 587213c4d6SAndrew Jones memset(mask, 0, sizeof(*mask)); 59f20e2561SAndrew Jones } 60f20e2561SAndrew Jones 61*9c86d8cdSAndrew Jones /* true if src1 is a subset of src2 */ 62*9c86d8cdSAndrew Jones static inline bool cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) 63*9c86d8cdSAndrew Jones { 64*9c86d8cdSAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 65*9c86d8cdSAndrew Jones int i; 66*9c86d8cdSAndrew Jones 67*9c86d8cdSAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i) { 68*9c86d8cdSAndrew Jones if (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) 69*9c86d8cdSAndrew Jones return false; 70*9c86d8cdSAndrew Jones } 71*9c86d8cdSAndrew Jones 72*9c86d8cdSAndrew Jones return !lastmask || !((cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask); 73*9c86d8cdSAndrew Jones } 74*9c86d8cdSAndrew Jones 75f20e2561SAndrew Jones static inline bool cpumask_empty(const cpumask_t *mask) 76f20e2561SAndrew Jones { 777213c4d6SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 787213c4d6SAndrew Jones 797213c4d6SAndrew Jones for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 807213c4d6SAndrew Jones if (cpumask_bits(mask)[i]) 81f20e2561SAndrew Jones return false; 827213c4d6SAndrew Jones 837213c4d6SAndrew Jones return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask); 84f20e2561SAndrew Jones } 85f20e2561SAndrew Jones 86f20e2561SAndrew Jones static inline bool cpumask_full(const cpumask_t *mask) 87f20e2561SAndrew Jones { 887213c4d6SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 897213c4d6SAndrew Jones 907213c4d6SAndrew Jones for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 917213c4d6SAndrew Jones if (cpumask_bits(mask)[i] != ULONG_MAX) 92f20e2561SAndrew Jones return false; 937213c4d6SAndrew Jones 947213c4d6SAndrew Jones return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask; 95f20e2561SAndrew Jones } 96f20e2561SAndrew Jones 97f20e2561SAndrew Jones static inline int cpumask_weight(const cpumask_t *mask) 98f20e2561SAndrew Jones { 99f20e2561SAndrew Jones int w = 0, i; 100f20e2561SAndrew Jones 101f20e2561SAndrew Jones for (i = 0; i < nr_cpus; ++i) 102f20e2561SAndrew Jones if (cpumask_test_cpu(i, mask)) 103f20e2561SAndrew Jones ++w; 104f20e2561SAndrew Jones return w; 105f20e2561SAndrew Jones } 106f20e2561SAndrew Jones 107f20e2561SAndrew Jones static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src) 108f20e2561SAndrew Jones { 109f20e2561SAndrew Jones memcpy(cpumask_bits(dst), cpumask_bits(src), 110f20e2561SAndrew Jones CPUMASK_NR_LONGS * sizeof(long)); 111f20e2561SAndrew Jones } 112f20e2561SAndrew Jones 113f20e2561SAndrew Jones static inline int cpumask_next(int cpu, const cpumask_t *mask) 114f20e2561SAndrew Jones { 115fdab948bSNikos Nikoleris while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask)) 116f20e2561SAndrew Jones ; 117f20e2561SAndrew Jones return cpu; 118f20e2561SAndrew Jones } 119f20e2561SAndrew Jones 120f20e2561SAndrew Jones #define for_each_cpu(cpu, mask) \ 121f20e2561SAndrew Jones for ((cpu) = cpumask_next(-1, mask); \ 122f20e2561SAndrew Jones (cpu) < nr_cpus; \ 123f20e2561SAndrew Jones (cpu) = cpumask_next(cpu, mask)) 124f20e2561SAndrew Jones 125905b0e66SAndrew Jones extern cpumask_t cpu_present_mask; 126905b0e66SAndrew Jones extern cpumask_t cpu_online_mask; 127905b0e66SAndrew Jones extern cpumask_t cpu_idle_mask; 128905b0e66SAndrew Jones #define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask) 129905b0e66SAndrew Jones #define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask) 130905b0e66SAndrew Jones #define cpu_idle(cpu) cpumask_test_cpu(cpu, &cpu_idle_mask) 131905b0e66SAndrew Jones #define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask) 132905b0e66SAndrew Jones #define for_each_online_cpu(cpu) for_each_cpu(cpu, &cpu_online_mask) 133905b0e66SAndrew Jones 134905b0e66SAndrew Jones static inline void set_cpu_present(int cpu, bool present) 135905b0e66SAndrew Jones { 136905b0e66SAndrew Jones if (present) 137905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_present_mask); 138905b0e66SAndrew Jones else 139905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_present_mask); 140905b0e66SAndrew Jones } 141905b0e66SAndrew Jones 142905b0e66SAndrew Jones static inline void set_cpu_online(int cpu, bool online) 143905b0e66SAndrew Jones { 144905b0e66SAndrew Jones if (online) 145905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_online_mask); 146905b0e66SAndrew Jones else 147905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_online_mask); 148905b0e66SAndrew Jones } 149905b0e66SAndrew Jones 150905b0e66SAndrew Jones static inline void set_cpu_idle(int cpu, bool idle) 151905b0e66SAndrew Jones { 152905b0e66SAndrew Jones if (idle) 153905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_idle_mask); 154905b0e66SAndrew Jones else 155905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_idle_mask); 156905b0e66SAndrew Jones } 157905b0e66SAndrew Jones 158dfc1fec2SAndrew Jones #endif /* _CPUMASK_H_ */ 159