1

volatile seems to be a never ending question of every one. I thought I knew everything about it, but then I encountered this:

So, I have a piece of memory shared between threads and I defined it like this:

volatile type *name;

If it makes you feel better, you can imagine type is just an int.

This means I have a pointer (that is not volatile) to some data that are volatile. So, for example when it comes to optimizing, the compiler can cache the value of name but not name[0]. Am I right?

So, now I am vfreeing this pointer (it's in a Linux kernel module) and it tells me that vfree expects const void * while I am passing it volatile type *.

I understand how it can be dangerous to pass a volatile type * as a type * because in that function, the values of name[i] could be cached (as a result of optimization) which is not desirable.

I don't understand why though, vfree expects me to send it a pointer necessarily to non-volatile data. Is there something I am missing there? Or is it just the guys who wrote vfree not thinking about this situation?

I assume me simply casting my pointer to void * would not cause any harm, is that right?

Shahbaz
  • 46,337
  • 19
  • 116
  • 182

2 Answers2

2

The vfree function (and every sane deallocation function in general) does not care about your actual data (be it volatile or not). It just expects a (valid) pointer (think: passing the pointer as a long value in a CPU register).

Based on that value, the function will:

  1. call the SLAB/SLUB to free the memory
  2. remove the memory mapping

So yes, casting to a void * will not cause any harm at runtime.

Mircea
  • 1,841
  • 15
  • 18
  • Well yeah, but why doesn't `vfree` accept `volatile type *`? Do you think the coders who wrote that forgot about it or does it actually matter to them? – Shahbaz Oct 18 '11 at 14:46
  • I think I agree with Mircea here. `free()` shouldn't care if the data is volatile or not. If you're using `volatile` because it's shared memory between tasks, then you had better make sure no one is using it by the time you free it, and then you have nothing to worry about. If you're using `volatile` because it's memory-mapped I/O, then I'm not sure why you would be freeing. The `vfree` function doesn't take a `volatile void *` because the "v" in `vmalloc` stands for "virtual", not "volatile". – Brian McFarland Oct 18 '11 at 15:26
  • 1
    @Shahbaz: It does not matter to those developers if the memory you allocated contains volatile data. The vfree() function just needs a pointer to that memory. The developers did not forget anything. – Mircea Oct 18 '11 at 15:32
  • @BrianMcFarland, I think you are taking me for an idiot! :)) I know what `vmalloc` is and I know no one should be accessing the array when I'm freeing it!! I also don't say `vfree` should care if my data are volatile or not. (read next comment) – Shahbaz Oct 18 '11 at 16:20
  • @MirceaGherzan, What I was saying was "Why don't they declare `vfree` as `void vfree(const volatile void *);` so that it accepts both kinds of pointers?" Exactly since the behavior with both types shouldn't matter. – Shahbaz Oct 18 '11 at 16:20
  • @Shahbaz: Didn't mean to offend. I should hope you knew all that if you're writing kernel code :). So my best guesses are: 1) To avoid unnecessary restrictions on compiler optimization, 2) because they are declared the same way as `malloc` and `free`, or 3) No one has ever been bothered enough by the compiler warning and/or explicit cast to change it. Like I said, these are guesses. I'd be curious if a kernel developer involved in maintaining vmalloc could give a real answer. – Brian McFarland Oct 18 '11 at 20:09
  • @Shahbaz: Because it would be _wrong_ for them to do so (declare the argument with some extra qualifier(s)). They only provide you with the minimal "interface". It's your job to do the casts. It's also a question of coding "style": think about functions with more pointer arguments and the line length of 80 characters :) – Mircea Oct 18 '11 at 21:01
  • I don't think it would be _wrong_, because the extra qualifier is in fact making it more general (or maybe I'm wrong, not sure). I do agree with @BrianMcFarland though, seems like it's enough like this, so they never cared. I did try to find the author of `vmalloc` though, and I couldn't find him. You got any clues? – Shahbaz Oct 19 '11 at 12:29
  • Adding qualifiers to a value doesn't make it more general, on the contrary. A `const volatile void *` is not really compatible to a `const void *`, nor vice versa. Using `const`, `volatile` and `restrict` (C99), eight differently qualified variables can be declared. In your case, the `const` for the `vfree` parameter just indicates that the `vfree` function doesn't change the value pointed at. Therefore you may fearlessly cast you pointer to `void *`, the additional `volatile` is irrelevant, since the value is not changed (or even used) by the `vfree` function. Or do you still expect problems? – Johan Bezem Nov 07 '11 at 09:12
0

My conclusion was that just casting the pointer to void * would not cause a problem and the fact that free and vfree don't directly accept pointers to volatile data is just something that was overlooked.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182