Each-CPU variable

Source: Internet
Author: User

Each-CPU variable is an interesting 2.6 kernel feature. When you create a per-CPU variable, each processor in the system obtains its own copy of this variable.
This may look like a strange thing to do, but it has its own advantages. you do not need to lock every-CPU variable because each processor uses its own copy. per-CPU
Variables can also be stored in the cache of their respective processors, which significantly improves the performance of frequently updated quantum.

A good example of each-CPU variable can be found in the network subsystem. The kernel maintains a non-ending counter to track the number of received packets of each type;
These counters may be updated several thousand times per second. Instead of processing the cache and lock issues, network developers put the statistical counters into each-CPU variable. Now the update is lockless and fast.
In rare cases, it is easy to see the counter value in user space requests, add the version of each processor, and return the total number.

The declaration of each-CPU variable can be found in <Linux/percpu. h>. To create a per-CPU variable at the Compilation Time, use this macro definition:

DEFINE_PER_CPU(type, name);

If this variable (called name) is an array that contains dimension information of this type, each-CPU array with three integers should be created and used:

DEFINE_PER_CPU(int[3], my_percpu_array); 

Each-CPU variable hardly needs to be operated using a clear lock. Remember that the 2.6 kernel can be preemptible. For a single processor,
It should not be preemptible in the critical section for modifying each-CPU variable, and it is not good if your process will be moved to another processor when accessing each-CPU variable.
For this reason, you must explicitly use the get_cpu_var macro to access the given variable copy of the current processor, and call put_cpu_var when you finish.
Call get_cpu_var to return an lvalue to the variable version of the current processor and prohibit preemption. Because an lvalue is returned,
It can be assigned or operated directly. For example, when a counter in a network code is incremented by using these two statements:

get_cpu_var(sockets_in_use)++;
put_cpu_var(sockets_in_use);

You can access the variable copy of another processor and use:

per_cpu(variable, int cpu_id); 

If you write code that makes the processor involve each other's CPU variables, you must implement a locking mechanism to secure access.

It is also possible to dynamically allocate each-CPU variable. These variables can be allocated and used:

void *alloc_percpu(type);
void *__alloc_percpu(size_t size, size_t align);

In most cases, alloc_percpu does a good job; you can call _ alloc_percpu when a special alignment is required.
In any case, a per-CPU variable can be returned to the system using free_percpu. Access a dynamically allocated per-CPU variable through
Per_cpu_ptr:

per_cpu_ptr(void *per_cpu_var, int cpu_id);

This macro returns a pointer pointing to the version of per_cpu_var corresponding to the given cpu_id. If you are simply reading the version of this variable of another CPU,
You can reference this pointer and use it to complete it. If, however, you are operating on the current processor version, you may need to first ensure that you cannot be removed from that processor.
If you access each-CPU variable and all hold a spin lock, everything is fine. Often, however, you need to use get_cpu to prevent preemption when using the variable.
Therefore, the code that uses dynamic CPU variables will look like this:

int cpu; 
cpu = get_cpu()
ptr = per_cpu_ptr(per_cpu_var, cpu);
/* work with ptr */
put_cpu();

The get_cpu_var and put_cpu_var macros take care of these details when each-CPU variable is used during compilation. Dynamic each-CPU variable requires more explicit protection.

Each-CPU variable can be output to each module, but you must use a special macro version:

EXPORT_PER_CPU_SYMBOL(per_cpu_var);
EXPORT_PER_CPU_SYMBOL_GPL(per_cpu_var);

To get such a variable in the memory of a module, declare it and use:

DECLARE_PER_CPU(type, name); 

Declare_per_cpu usage (not define_per_cpu) tells the compiler to make an external reference.

If you want to use each-CPU variable to create a simple integer counter, see <Linux/percpu_counter.h>
Ready-made implementation in. finally, note that some systems have a limited number of address space variables for each-CPU variable. if you create each-CPU variable in your own code, you should try to make them small.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.