How Linux kernel percpu precise variable values?

I chose signed int type variable as the statistical value of percpu half the number of connections in the Linux kernel, I have no choice atomic types of global variables, but I did not use a spinlock to protect the general global variable of type unsigned int.

Signed int type was chosen because of percpu variable to take into account migration process between different CPU connections.

So far, everything is perfect percpu variables, lightweight and no lock operation is its biggest advantage as a statistical counter. As the statistics counters, when we are reading is to allow a certain degree of error, so we generally use the lock-free way to read:

for_each_possible_cpu(i) {
	res += per_cpu_ptr(ptr, i);
}

We know that the implementation of the above statement takes time, no matter how fast traverse all the CPU, but it takes time, during this time, percpu variables traverse the cumulative change logic can not be captured during execution may occur.

Fortunately, these statistics are giving to read, and the purpose of man is to read these statistics to derive value by some rules, usually it requires data resolution is not reached milliseconds or less.

However, if the kernel needs these values ​​how to do?

Such as whether to release the core logic to perform a data object in accordance with the values ​​of these variables:

for_each_possible_cpu(i) {
	res += per_cpu_ptr(ptr, i);
}
if (res == 0) 
	free_something(...);

The above code is clearly dangerous ⚠️, then how do?

Very simple, a read-write locks can be. But usually read-write locks and usage of just the opposite:

  • Take read lock when updating percpu variables.
  • Take write lock when reading percpu variables.

Update logic is as follows:

signed int *per_cpu_counter = per_cpu_ptr(..., this_cpu);
...
read_lock(&percpu_wrlock);
*per_cpu_counter ++;
read_unlock(&percpu_wrlock);

Read logic is as follows:

write_lock(&percpu_wrlock);

for_each_possible_cpu(i) {
	res += per_cpu_ptr(ptr, i);
}
if (res == 0) 
	free_something(...);

write_unlock(&percpu_wrlock);

Although, disabled during read / write lock seize, and will insert the barrier, but specific to a particular architecture of the Linux kernel and the specific platform, these seemingly will affect the performance of the operating mostly negligible, say, most of the servers are closed kernel preemption option to compile the kernel.


If the point of view rather than from the general to pull the details, through all the process and remove the CPU percpu variable accumulation is very fast, at least this is a THE ( 1 ) O (1) operation, not to mention, most of the machine's CPU is essentially the order of 3 digits or less, so this THE ( 1 ) O (1) is a constant value itself is very small.

Managers not wait to see trick, do not wait to see the manager to traverse, even for a 20 too.

In the summer of 2007, the manager said that the first slow, manager regardless of DNS, so a worker took a room in Beijing died in the server IP write a code. Later this server relocation, the workers left, things to me, and I found this hard-coded, but I very much agree with this approach, although I prefer to use the configuration file rather than code macros ...

I wrote in the configuration file and dies 20 commonly used IP address, the first 10 are IP servers, the 10 is my preferred 10 DNS, and then on the last line, the effect is really good!

But the manager to look at the code, the manager saw a for, for the 20 IP, the manager said this cycle is time-consuming, managers have to let me change my one hundred Nanbian, so I changed it to look like this:

if (是IP1)
	...
else if (是IP2)
	...
else if (是IP3)
	...
else if (是IP4)
	...
else if (是IP5)
	...
else if (是IP6)
	...
	...
else if (是IP20)
	...
else 
	...

OK, eliminating the circulation, increase the amount of code, everyone singing off work.


Wenzhou shoes wet, rain water will not be fat.

Released 1580 original articles · won praise 5111 · Views 11,130,000 +

Guess you like

Origin blog.csdn.net/dog250/article/details/105087167