3

I'm writing a module for Linux kernel, and I want to store a int value in the file private data.

Essentially, what I do is: file->private_data = (void*) x where x is some int value.

Now, I want to access the int back as a value.

Using int val = (int) file->private_data gives out a cast from pointer to integer of different size warning during compilation, which is reasonable since it may cause problems on a 64bit systems.

I also cannot use uintptr_t since I'm working in kernel and I do not have access to libraries.

Using double seems inappropriate.

My question is: What should be the best practice to do so?

alk
  • 69,737
  • 10
  • 105
  • 255
Mickey
  • 1,405
  • 2
  • 13
  • 33
  • 2
    IMHO, best practice would be to prevent such things. I remember that I saw X11 callbacks (long long ago - I believe even in the O'Reilly X books) where the callback client data pointer was abused to provide an `int` - accessed via similar hackish casting. (That people probably tried to come around allocation/storage effort for client data this way.) May be, there might be even a rule that a pointer has at least `sizeof (int)` but I would not bet my house for it... (though it is surely true for Intel x86). Btw. to come around the warning `int val = (int)(ssize_t)file->private_data;` might help. – Scheff's Cat May 12 '18 at 08:15
  • @Fredrik: "*you are storing the value wrong*" No, as the OP does not want to store an address. But (misuse) the pointer to store an integer. – alk May 12 '18 at 09:19
  • Related: https://softwareengineering.stackexchange.com/q/290574/35384 – alk May 12 '18 at 09:30
  • Related: https://stackoverflow.com/q/6825640/694576 – alk May 12 '18 at 09:41
  • FIrst question is can you make sure that a `void *` can hold all the possible values of your int parameter on all architectures you target? As you a writing a **Linux** kernel module wide portability is not really a concern. If the answer is yes, then the conversion is implementation dependent according to the standard, and any *normal* implementation will ensure that casting forth and back will return original value. – Serge Ballesta May 12 '18 at 09:44

2 Answers2

5

In gcc world (Linux kernel is compiled by gcc), long (or unsigned long) has the the same size as a pointer. You may use this feature when convert pointers to integer and back:

// store
file->private_data = (void*)(long) x;
// load
int val = (int) (long) file->private_data;

Note: This answer addresses specifically Linux kernel programming.

For user-space application suggested approach could be treated as a bad practice, or simply being wrong.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • thanks, I used a casting through (ssize_t) at the end and it worked, long seems to be ok as well. – Mickey May 12 '18 at 19:36
0

Can you please elaborate how come you got yourself into a situation where storing an int there is reasonable?

Normally this would be a pointer to a reference-counted object. In particular, if you are using that to look up another object, this very field should probably just point to that object.