The ACCESS_ONCE() macro (2012)
1–10 of 12 posts
Re: The ACCESS_ONCE() macro (2012)
#2Re: The ACCESS_ONCE() macro (2012)
#3The silly thing here is that this macro is not guaranteed to accomplish anything. The C standard limits how compilers can optimize accesses to volatile objects , but says nothing about accesses to non-volatile objects which are accessed via volatile-qualified pointers.
Re: The ACCESS_ONCE() macro (2012)
#4The silly thing here is that this macro is not guaranteed to accomplish anything. The C standard limits how compilers can optimize accesses to volatile objects , but says nothing about accesses to non-volatile objects which are accessed via volatile-qualified pointers.
It is not in the C standard but the way GCC implements it is that it is hands-off with optimizations to any volatile variables and pointers. And since Linux is only compiled with GCC, it works.
Re: The ACCESS_ONCE() macro (2012)
#5In fact, the very example given in the article shows that without the ACCESS_ONCE, the compiler moved the access outside of the loop---thereby ensuring that it's accessed just once, ironically!!! Whereas by using ACCESS_ONCE, we ensure that it's accessed as many times as the loop is iterated, not only once.
Basically this just does some kind of volatile access, and so the name should reflect that:
foo = VOLATILE_READ(bar);
Then the number of times it is accessed is implied from the agreement between abstract and actual semantics. In the abstract semantics, and expression is evaluated once for each invocation of whatever encloses it. If an expression is unconditionally evaluated in a loop that iterates 100 times, then it is evaluated 100 times. Hoisting it out of the loop would be an optimization which is forbidden by agreement with the abstract semantics.Re: The ACCESS_ONCE() macro (2012)
#6Earlier quoted context omitted.
It is not in the C standard but the way GCC implements it is that it is hands-off with optimizations to any volatile variables and pointers. And since Linux is only compiled with GCC, it works.
Linux is also compiled with llvm as well as icc
ISO C standard conformance isn't entirely irrelevant, but thereabouts.
There is no such thing as building systems from the ground up without controlling compilers beyond what is specified in the applicable language standards.
Re: The ACCESS_ONCE() macro (2012)
#7It has a confusing name, suggesting that it is intended to prevent multiple accesses. (Contrast with `pthread_once` for instance: a mechanism for once-only initialization.) In fact, the very example given in the article shows that without the ACCESS_ONCE, the compiler moved the access outside of the loop---thereby ensuring that it's accessed just once, ironically!!! Whereas by using ACCESS_ONCE, we ensure that it's a…
But that is just a consequence of putting a call to ACCESS_ONCE inside a loop. But it is retaining the property that it is only read from memory once per iteration.
It would be way more confusing if the programmer only wanted read once for the whole loop and still put the statement inside the loop.
I do think that knowing that it is being called in a loop context, implies that it should only be accessed once per iteration
Re: The ACCESS_ONCE() macro (2012)
#8It has a confusing name, suggesting that it is intended to prevent multiple accesses. (Contrast with `pthread_once` for instance: a mechanism for once-only initialization.) In fact, the very example given in the article shows that without the ACCESS_ONCE, the compiler moved the access outside of the loop---thereby ensuring that it's accessed just once, ironically!!! Whereas by using ACCESS_ONCE, we ensure that it's a…
"In fact, the very example given in the article shows that without the ACCESS_ONCE, the compiler moved the access outside of the loop---thereby ensuring that it's accessed just once, ironically!!! Whereas by using ACCESS_ONCE, we ensure that it's accessed as many times as the loop is iterated, not only once." But that is just a consequence of putting a call to ACCESS_ONCE inside a loop. But it is retaining the proper…
for (;;) {
/* ... */
if (pthread_once(&once_var, once_routine))
/* error */;
/* ... */
}
Here, we are ensuring that once_routine is called exactly once.ACCESS_ONCE to me strongly suggests that the value is accessed once and cached forever. E.g. ACCESS_ONCE(x) could expand to something like:
({
static __flag;
static typeof(x) __cached;
if (!__flag) {
__cached = (x);
__flag = 1;
}
__cached;
})
ANSI Common Lisp has load-time-value. You can use this anywhere: (defun myfunc ()
(let ((foo (bar))
... ;; deeply nested
(let ((x (load-time-value (whatever))))
...))))
The load-time-value form is evaluated when the module is loaded and the value is stashed. Then whenever myfunc is called and that code is evaluated, the previously stashed value is retrieved; the (whatever) is not evaluated any more.Re: The ACCESS_ONCE() macro (2012)
#9The silly thing here is that this macro is not guaranteed to accomplish anything. The C standard limits how compilers can optimize accesses to volatile objects , but says nothing about accesses to non-volatile objects which are accessed via volatile-qualified pointers.
But if you always access a certain object through casts to ((volatile )&x), I don't see how this should be different than accesses to a globally declared "volatile x" variable, as pointers are guaranteed to not change if casted hence-and-forth (§6.3.2.3/7).
Re: The ACCESS_ONCE() macro (2012)
#10The silly thing here is that this macro is not guaranteed to accomplish anything. The C standard limits how compilers can optimize accesses to volatile objects , but says nothing about accesses to non-volatile objects which are accessed via volatile-qualified pointers.
That's certainly true if you mix accesses to the same object via volatile and non-volatile pointers. It's even explicitly undefined in the standard. (C99 §6.7.3/5). [while in practice it will work most of the time] But if you always access a certain object through casts to ((volatile )&x), I don't see how this should be different than accesses to a globally declared "volatile x" variable, as pointers are guaranteed t…