一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
今日看代码的过程中,发现kernel一个实现未遵循该守则,极为疑惑。。。
代码位置为linux内核代码根目录下 kernel/sched.c
void fastcall __sched wait_for_completion(struct completion *x)
{
might_sleep();
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
__set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
schedule();
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
spin_unlock_irq(&x->wait.lock);
}
代码中红色的 x->done 作为do-while循环的条件,却在循环体中没有修改
显然,这属于volatile的1或者2情况,难道这里编译器就不会将之优化掉??
另外 c语言中取地址然后在取内容
即 * & val 是否也能达到一定读取的目的??