percpu 可以的接口可以分为新接口和旧接口
目前旧借口的sample code如下:
int cpu;
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
if (!tuners)
return -ENOMEM;
cpu = get_cpu();
idle_time = get_cpu_idle_time_us(cpu, NULL);
put_cpu();
这code 中可以通过get_cpu 得到当前cpu
#define get_cpu() ({ preempt_disable(); smp_processor_id(); })
可以看到get_cpu 首先会通过preempt_disable 禁止内核抢占,然后调用smp_processor_id 返回当前cpu id。
而与之对应的put_cpu 就是使能内核抢占.#define put_cpu() preempt_enable()
新的percpu接口可以分为静态申请和动态申请
静态percpu 可以通过DECLARE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); 来申请
可以通过 fps = &per_cpu(bnx2fc_percpu, cpu);来读到这个percpu的数据到fps中
而这里的#define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu))
可见per_cpu 只是per_cpu_ptr的一个包装,因此能用per_cpu访问的,都可以通过per_cpu_ptr 来访问
#define per_cpu_ptr(ptr, cpu) \
({ \
__verify_pcpu_ptr(ptr); \
SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))); \
})
例如下例子中就通过per_cpu_ptr得到acpi_perf_data 这个变量在cpu上的值
static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
perf = per_cpu_ptr(acpi_perf_data, cpu);
}
更进一步是采用get_cpu_ptr得到percpu的值
#define get_cpu_ptr(var) \
({ \
preempt_disable(); \
this_cpu_ptr(var); \
})
get_cpu_ptr 默认是获取当前cpu上的值
int squashfs_decompress(struct squashfs_sb_info *msblk, struct buffer_head **bh,
int b, int offset, int length, struct squashfs_page_actor *output)
{
struct squashfs_stream *stream = get_cpu_ptr(percpu);
}
除了静态定义外,percpu变量可以在运行是创建
alloc_percpu 可以在运行是创建percpu变量,释放percpu占用的空间可以采用free_percpu
使用的例子如下:
static __net_init int ipv4_mib_init_net(struct net *net)
{
int i;
net->mib.tcp_statistics = alloc_percpu(struct tcp_mib);
if (!net->mib.tcp_statistics)
goto err_tcp_mib;
net->mib.ip_statistics = alloc_percpu(struct ipstats_mib);
if (!net->mib.ip_statistics)
goto err_ip_mib;
for_each_possible_cpu(i) {
struct ipstats_mib *af_inet_stats;
af_inet_stats = per_cpu_ptr(net->mib.ip_statistics, i);
u64_stats_init(&af_inet_stats->syncp);
}
net->mib.net_statistics = alloc_percpu(struct linux_mib);
if (!net->mib.net_statistics)
goto err_net_mib;
net->mib.udp_statistics = alloc_percpu(struct udp_mib);
if (!net->mib.udp_statistics)
goto err_udp_mib;
net->mib.udplite_statistics = alloc_percpu(struct udp_mib);
if (!net->mib.udplite_statistics)
goto err_udplite_mib;
net->mib.icmp_statistics = alloc_percpu(struct icmp_mib);
if (!net->mib.icmp_statistics)
goto err_icmp_mib;
net->mib.icmpmsg_statistics = kzalloc(sizeof(struct icmpmsg_mib),
GFP_KERNEL);
if (!net->mib.icmpmsg_statistics)
goto err_icmpmsg_mib;
tcp_mib_init(net);
return 0;
err_icmpmsg_mib:
free_percpu(net->mib.icmp_statistics);
err_icmp_mib:
free_percpu(net->mib.udplite_statistics);
err_udplite_mib:
free_percpu(net->mib.udp_statistics);
err_udp_mib:
free_percpu(net->mib.net_statistics);
err_net_mib:
free_percpu(net->mib.ip_statistics);
err_ip_mib:
free_percpu(net->mib.tcp_statistics);
err_tcp_mib:
return -ENOMEM;
}
percpu 变量总结
最新推荐文章于 2024-08-22 15:24:16 发布