Re: Locking with per-cpu variables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 16 Oct 2005 02:42:45 +0200, 
Aritz Bastida <aritzbastida@xxxxxxxxx> wrote:
>...
>struct pcap_stats {
>        unsigned int captured;
>        unsigned int processed;
>        unsigned int dropped;
>        ...
>};
>DEFINE_PER_CPU(struct pcap_stats, pcap_stats);
>...
>Ok, I've done that. But now I have some questions about this:
>
>1.- Suppose that I want to read the statistics (per-cpu and the total
>numbers) via proc files. The proc read function would have to access
>other cpu's variables, which in turn, could be updated by its cpu at
>the same time. So i guess that, even if i'm just going to read the
>counters (so there is no corruption of data), some kind of locking
>would be required. But if I do that, then why did I need per-cpu
>variables? Weren't they for avoiding locks?

Adding up the per-cpu counters from a single cpu is always racy,
because the values are changing while you sum them.  But the only
effect of the race is to cause a small jitter in the total counter.
You may miss an update, like this :-

CPU 0 read cpu 0 value
      read cpu 1 value
      read cpu 2 value  CPU 1 update local value
      read cpu 3 value
      report total

and your total will be slightly low.  But the next time that you sum
the total, you will pick up the dropped value and the total will
reflect all the preceding activity.  In other words, you get some noise
in the individual total figures but the overall trend is correct.

>2.- Suppose that I also want to be able to reset the counters from
>user space (via proc files too). Now I would be changing the counters
>in the proc write function. This time the data could get corrupted
>because another cpu could be updating its data at the same time. So
>again locking would be required. Note that I just want to reset the
>counters, not anything strange or difficult (I guess that even if some
>other cpu would be incrementing one counter, instead of resetting to
>cero, its value would be one, or something similar).

As a rule, it is not safe to update lock free variables from multiple
cpus[*].  But there is one exception to that rule, where one cpu sets a
flag belonging to another cpu and the other cpu clears that flag.  To
clear the counters without a race, define another per cpu variable
called 'clear'.  From one cpu, set the 'clear' flag for all cpus.  In
the counter code that runs on each cpu, check the clear flag, if it is
set then clear the counters then zero the 'clear' flag.

You can store the 'clear' variable in your pcap_stats.  There will be
some cache line bouncing when the counters are cleared but that is a
very rare case, the rest of the time the pcap_stats will be cpu local.

[*] You can do lock free updates with compare and exchange, but that
    slows down all processing, including the fast path.  Also not all
    architectures have cmpxchg, instead they simulate it with locks,
    which rather defeats the purpose of lock free variables.

-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux