atomic_read实现

typedef struct {
	int counter;
} atomic_t;

static inline int atomic_read(const atomic_t *v)
{
	return ACCESS_ONCE((v)->counter);
}

#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))

ACCESS_ONCE 宏的目的是为了确保对 x 的访问(读取或写入)是不可分割的,也就是说,保证在读取或写入时,操作是原子的,不会被编译器的优化所影响。这通常用在多线程或者需要考虑中断的情况下,当你必须确保变量的值在被访问时没有被其他代码路径同时修改。

下面是对这个宏的解释:

  • *(volatile typeof(x) *)&(x):
    • typeof(x):取得变量 x 所代表的类型。
    • (volatile typeof(x) *):这段代码将 x 的地址转换为一个指向 typeof(x) 类型的 volatile 指针。volatile 关键字告诉编译器,每次访问这个变量时都需要从内存重新读取数据,这防止了编译器可能会做的任何优化,例如将变量值缓存在寄存器中。
    • &:取得变量 x 的地址。
    • *(...):对转换为 volatile 类型的指针进行解引用操作,即 获取该地址上的值。

因此,ACCESS_ONCE(x) 宏实际上在提供对 x 的直接访问,同时通过将其作为 volatile 类型来抑制编译器的优化行为。这在并发编程中非常重要,因为这样的操作有可能改变多个线程的行为。 English

请注意,ACCESS_ONCE 宏通常用于内核或嵌入式系统编程,在普通的应用程序中并不常见。此外,随着编译器和处理器模型的发展,可能需要更先进的同步机制(如内存栅栏或原子操作)来保证操作的原子性和内存的一致性。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * Copyright (C) 2011-2014 MediaTek Inc. * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ #include <linux/module.h> #include <linux/list.h> #include <linux/spinlock.h> #include "SCP_power_monitor.h" #include "scp_helper.h" static LIST_HEAD(power_monitor_list); static DEFINE_SPINLOCK(pm_lock); static atomic_t power_status = ATOMIC_INIT(SENSOR_POWER_DOWN); void scp_power_monitor_notify(uint8_t action, void *data) { struct scp_power_monitor *c; unsigned long flags; spin_lock_irqsave(&pm_lock, flags); list_for_each_entry(c, &power_monitor_list, list) { WARN_ON(c->notifier_call == NULL); c->notifier_call(action, data); pr_debug("scp_power_monitor_notify, module name:%s notify\n", c->name); } switch (action) { case SENSOR_POWER_DOWN: atomic_set(&power_status, SENSOR_POWER_DOWN); break; case SENSOR_POWER_UP: atomic_set(&power_status, SENSOR_POWER_UP); break; } spin_unlock_irqrestore(&pm_lock, flags); } int scp_power_monitor_register(struct scp_power_monitor *monitor) { int err = 0; struct scp_power_monitor *c; WARN_ON(monitor->name == NULL || monitor->notifier_call == NULL); spin_lock_irq(&pm_lock); list_for_each_entry(c, &power_monitor_list, list) { if (!strcmp(c->name, monitor->name)) { err = -1; goto out; } } list_add(&monitor->list, &power_monitor_list); if (atomic_read(&power_status) == SENSOR_POWER_UP) { pr_debug("scp_power_monitor_notify, module name:%s notify\n", monitor->name); monitor->notifier_call(SENSOR_POWER_UP, NULL); } spin_unlock_irq(&pm_lock); return err; out: pr_err("%s scp_power_monitor_register fail\n", monitor->name); spin_unlock_irq(&pm_lock); return err; } int scp_power_monitor_deregister(struct scp_power_monitor *monitor) { if (WARN_ON(list_empty(&monitor->list))) return -1; spin_lock_irq(&pm_lock); list_del(&monitor->list); spin_unlock_irq(&pm_lock); return 0; }分析代码
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值