os-windows: fix cpumask operations
authorRobert Elliott <elliott@hpe.com>
Tue, 14 Nov 2017 02:22:09 +0000 (20:22 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 16 Nov 2017 21:06:35 +0000 (14:06 -0700)
Fix cpumask manipulation on (64-bit) Windows systems.

cpus_allowed=nn values greater than 32 does not work, due to
* the compiler not promoting expressions like "1 << cpu" to
  64 bits
* the clear function clearing the wrong bit (using "cpu - 1"),
* the clear function using XOR to clear (which only works if the
  bit was previously set)
* the check function returning a 64-bit value through a 32-bit
  return value

Example problems (from extra debug prints):
* setting CPU 32 really sets bit 0 (CPU 0)
Set mask of 0000000000000000 to add 0000000000000001 (32)

* setting CPU 63 really sets bit 31 (CPU 31)
Set mask of 0000000000000000 to add 0000000080000000 (63)

* clearing CPU 0 really clears bit 63 (CPU 63)
Clear mask of 0000000055555555 to remove 8000000000000000 (0)

* clearing CPU 2 really clears bit 2 (CPU 2)
Clear mask of 0000000055555555 to remove 0000000000000002 (2)

* checking claims CPU 32 is not in a mask of CPUs {32,34,36,38}
for 0000005500000000 check if bit 32 is set ==> FALSE

Tested with x86_64-w64-mingw32-gcc 6.4.0 from cygwin on a system
with 64 CPU cores (all fitting in one Windows processor group).

Signed-off-by: Jens Axboe <axboe@kernel.dk>
os/os-windows.h

index 520da19aa1731f130a12ee4adac5fdd1484dd606..1b87771d2d7498a0ec6c2a1b49cb8bc0059f9965 100644 (file)
@@ -209,17 +209,17 @@ static inline int fio_getaffinity(int pid, os_cpu_mask_t *mask)
 
 static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)
 {
-       *mask ^= 1 << (cpu-1);
+       *mask &= ~(1ULL << cpu);
 }
 
 static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)
 {
-       *mask |= 1 << cpu;
+       *mask |= 1ULL << cpu;
 }
 
 static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu)
 {
-       return (*mask & (1U << cpu));
+       return (*mask & (1ULL << cpu)) > 0;
 }
 
 static inline int fio_cpu_count(os_cpu_mask_t *mask)