多核中percpu的数据分配

linux2.6 为了方便创建和操作每个CPU数据,引进了新的操作接口,percpu(),该接口简化了创建了操作每个CPU的数据。

定义于<linux/percpu.h> 和<mm/slab.c> 中

1. 定义和声明每个CPU变量:

[cpp]  view plain copy
  1. DEFINE_PER_CPU(type, name);  
这语句为系统的每个CPU都创建了一个类型为type,名字为name的变量。

如果需要在别处声明此变量,以防编译时的警告,可使用下面的宏:

[cpp]  view plain copy
  1. DECLARE_PER_CPU(type, name);  
2. 操作每个CPU的变量和指针:
get_cpu_var(name);  //返回当前处理器上的指定变量name的值, 同时将他禁止抢占;

put_cpu_var(name); //与get_cpu_var(name)相对应,重新激活抢占;

[cpp]  view plain copy
  1. /* 
  2.  * Must be an lvalue. Since @var must be a simple identifier, 
  3.  * we force a syntax error here if it isn't. 
  4.  */  
  5. #define get_cpu_var(var) (*({               \  
  6.     preempt_disable();              \  
  7.     &__get_cpu_var(var); }))  

[cpp]  view plain copy
  1. /* 
  2.  * The weird & is necessary because sparse considers (void)(var) to be 
  3.  * a direct dereference of percpu variable (var). 
  4.  */  
  5. #define put_cpu_var(var) do {               \  
  6.     (void)&(var);                   \  
  7.     preempt_enable();               \  
  8. while (0)  

通过指针来操作每个CPU的数据:

get_cpu_ptr(var); --- 返回一个void类型的指针,指向CPU ptr处的数据

put_cpu_ptr(var); --- 操作完成后,重新激活内核抢占。

[cpp]  view plain copy
  1. #define get_cpu_ptr(var) ({             \  
  2.     preempt_disable();              \  
  3.     this_cpu_ptr(var); })  
  4.   
  5. #define put_cpu_ptr(var) do {               \  
  6.     (void)(var);                    \  
  7.     preempt_enable();               \  
  8. while (0)  
3. 获得别的处理器上的name变量的值

per_cpu(name, cpu) ;   //返回别的处理器cpu上变量name的值;

4. 给系统中每个处理器分配一个指定类型的对象: alloc_percpu();

[cpp]  view plain copy
  1. #define alloc_percpu(type)  \  
  2.     (typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))  
[cpp]  view plain copy
  1. /** 
  2.  * __alloc_percpu - allocate dynamic percpu area 
  3.  * @size: size of area to allocate in bytes 
  4.  * @align: alignment of area (max PAGE_SIZE) 
  5.  * 
  6.  * Allocate zero-filled percpu area of @size bytes aligned at @align. 
  7.  * Might sleep.  Might trigger writeouts. 
  8.  * 
  9.  * CONTEXT: 
  10.  * Does GFP_KERNEL allocation. 
  11.  * 
  12.  * RETURNS: 
  13.  * Percpu pointer to the allocated area on success, NULL on failure. 
  14.  */  
  15. void __percpu *__alloc_percpu(size_t size, size_t align)  
  16. {  
  17.     return pcpu_alloc(size, align, false);  
  18. }  
  19. EXPORT_SYMBOL_GPL(__alloc_percpu);  
参数为type, 就是指定的需要分配的类型,通过类型,可以得出__alloc_percpu()的两个参数:

size =  sizeof(type);

align = __alignof__(type);

__alignof__()是gcc的一个功能,它会返回指定类型或lvalue所需的对齐字节数。

相应的释放所有处理器上指定的每个CPU数据:free_percpu();

[cpp]  view plain copy
  1. /** 
  2.  * free_percpu - free percpu area 
  3.  * @ptr: pointer to area to free 
  4.  * 
  5.  * Free percpu area @ptr. 
  6.  * 
  7.  * CONTEXT: 
  8.  * Can be called from atomic context. 
  9.  */  
  10. void free_percpu(void __percpu *ptr)  
  11. {  
  12.     void *addr;  
  13.     struct pcpu_chunk *chunk;  
  14.     unsigned long flags;  
  15.     int off;  
  16.   
  17.     if (!ptr)  
  18.         return;  
  19.   
  20.     addr = __pcpu_ptr_to_addr(ptr);  
  21.   
  22.     spin_lock_irqsave(&pcpu_lock, flags);  
  23.   
  24.     chunk = pcpu_chunk_addr_search(addr);  
  25.     off = addr - chunk->base_addr;  
  26.   
  27.     pcpu_free_area(chunk, off);  
  28.   
  29.     /* if there are more than one fully free chunks, wake up grim reaper */  
  30.     if (chunk->free_size == pcpu_unit_size) {  
  31.         struct pcpu_chunk *pos;  
  32.   
  33.         list_for_each_entry(pos, &pcpu_slot[pcpu_nr_slots - 1], list)  
  34.             if (pos != chunk) {  
  35.                 schedule_work(&pcpu_reclaim_work);  
  36.                 break;  
  37.             }  
  38.     }  
  39.   
  40.     spin_unlock_irqrestore(&pcpu_lock, flags);  
  41. }  
  42. EXPORT_SYMBOL_GPL(free_percpu);  

5. get_cpu()/put_cpu() --- 获得处理器编号

get_cpu() 在返回当前处理器编号之前,先回关闭内核抢占。

put_cpu() 重新打开内核抢占。

函数定义如下:

[cpp]  view plain copy
  1. #define get_cpu()       ({ preempt_disable(); smp_processor_id(); })  
  2. #define put_cpu()       preempt_enable()  
使用案例如下:
[cpp]  view plain copy
  1. int cpu;  
  2.   
  3. cpu = get_cpu();   //禁止抢占内核,并将CPU设置为当前处理器。  
  4.   
  5. //对每个处理器的数据进行操作,  
  6.   
  7. put_cpu();   //使能内核抢占  

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值