1

I am writing a linux security module, and I use a bitmap structure in the code. I have two candidate structures as follows

struct bitmap {
    unsigned long val[DIV_ROUND_UP(CONFIG_BITMAP_MAX_BITS, sizeof(unsigned long) * 8)];
}

vs

struct bitmap {
    u64 val[DIV_ROUND_UP(CONFIG_BITMAP_MAX_BITS, 64)];
}

The underlying type used is just an implementation detail, and not exposed to anything that uses the bitmap structure. Instead, there are helper functions which do bitmap_union, bitmap_intersection, add_bit_to_bitmap, remove_bit_from_bitmap, ...

Hence, I'd like to know if it is a better choice to use unsigned long, considering only performance implications of bit operations (bitwise-and, bitwise-or, bitwise-xor, ..) across architectures.

Edit: Since this is a linux security module, it is intended to support all architectures supported by linux kernel (both 32-bit and 64-bit). Since uint64_t and unsigned long only differ in 32-bit processors (as far as I know), the comparision only makes sense for 32-bit architectures. A list of architectures supported by linux kernel is available at this wiki page and here. The main focus is on x86 and arm processors.

Saurav Yadav
  • 115
  • 9
  • 2
    Are you aware of _fast_t types, e.g. uint64_fast_t? These are supposed to be a default type if you need performance and size that is capable of fitting at least x bits. EDIT: unless you need to use one of those two structures, then of course it’s a different story. – alagner May 23 '21 at 09:25
  • @alagner fast types aren't available in linux kernel code. Also, the main motive for using `unsigned long` specifically is because for linux, it is the native type of the architecture if the kernel is compiled properly (32 bits on 32-bit compilation, 64 bits on 64-bit compilation of the kernel) – Saurav Yadav May 23 '21 at 09:33
  • 2
    Does this help? https://stackoverflow.com/questions/16841382/what-is-the-performance-impact-of-using-int64-t-instead-of-int32-t-on-32-bit-sys – John Zwinck May 23 '21 at 09:36
  • [This link](https://stackoverflow.com/questions/60944840/fixed-64-bit-integer-in-linux-kernel) says the size of `unsigned long` is implementation dependent and so this type isn't portable. Good luck ! – Siddhartha Shivshankar May 23 '21 at 10:04
  • 1
    @SiddharthaShivshankar: `unsigned long` is guaranteed to be available on all C implementations. It's portable, as long as your code correctly uses `sizeof(unsigned long) * CHAR_BIT` to find the size. (Well, portable to implementations that don't have any padding bits in `unsigned long`, otherwise you'd need to figure out the bit-width from `ULONG_MAX`... But I think it's portable enough to assume no padding bits) – Peter Cordes May 23 '21 at 15:52
  • 2
    If you are only doing logic operations with the bitmaps, then **maybe** using u64 may still be good for 32-bit architectures, if the compiler can correctly split the operations between the lower and upper 32-bit halves. This is kind of like an unrolling. However, the best way to find out is probably by benchmarking with the help of a VM. If the operations are more complex and doesn't scale linearly with the number of bits, maybe `unsigned long` is better. – Margaret Bloom May 25 '21 at 11:57

0 Answers0