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