From: chenyuezhou Date: Fri, 18 Jun 2021 20:31:52 +0000 (-0400) Subject: libbcc: add atomic_increment() X-Git-Tag: v0.21.0~29 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8b1c973f01f74c7229d84417454b7c91ade6e7f5;p=platform%2Fupstream%2Fbcc.git libbcc: add atomic_increment() --- diff --git a/docs/reference_guide.md b/docs/reference_guide.md index aa7db55e..0c7ccfeb 100644 --- a/docs/reference_guide.md +++ b/docs/reference_guide.md @@ -1305,6 +1305,10 @@ Syntax: ```map.increment(key[, increment_amount])``` Increments the key's value by `increment_amount`, which defaults to 1. Used for histograms. +```map.increment()``` are not atomic. In the concurrency case. If you want more accurate results, use ```map.atomic_increment()``` instead of ```map.increment()```. The overhead of ```map.increment()``` and ```map.atomic_increment()``` is similar. + +Note. When using ```map.atomic_increment()``` to operate on a BPF map of type ```BPF_MAP_TYPE_HASH```, ```map.atomic_increment()``` does not guarantee the atomicity of the operation when the specified key does not exist. + Examples in situ: [search /examples](https://github.com/iovisor/bcc/search?q=increment+path%3Aexamples&type=Code), [search /tools](https://github.com/iovisor/bcc/search?q=increment+path%3Atools&type=Code) diff --git a/src/cc/export/helpers.h b/src/cc/export/helpers.h index 0be3572b..12072b06 100644 --- a/src/cc/export/helpers.h +++ b/src/cc/export/helpers.h @@ -101,6 +101,7 @@ struct _name##_table_t { \ int (*delete) (_key_type *); \ void (*call) (void *, int index); \ void (*increment) (_key_type, ...); \ + void (*atomic_increment) (_key_type, ...); \ int (*get_stackid) (void *, u64); \ u32 max_entries; \ int flags; \ diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index e78ceb3c..27b19360 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -899,7 +899,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { } txt += "}"; txt += "leaf;})"; - } else if (memb_name == "increment") { + } else if (memb_name == "increment" || memb_name == "atomic_increment") { string name = string(Ref->getDecl()->getName()); string arg0 = rewriter_.getRewrittenText(expansionRange(Call->getArg(0)->getSourceRange())); @@ -913,8 +913,13 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) { string update = "bpf_map_update_elem_(bpf_pseudo_fd(1, " + fd + ")"; txt = "({ typeof(" + name + ".key) _key = " + arg0 + "; "; txt += "typeof(" + name + ".leaf) *_leaf = " + lookup + ", &_key); "; + txt += "if (_leaf) "; - txt += "if (_leaf) (*_leaf) += " + increment_value + ";"; + if (memb_name == "atomic_increment") { + txt += "lock_xadd(_leaf, " + increment_value + ");"; + } else { + txt += "(*_leaf) += " + increment_value + ";"; + } if (desc->second.type == BPF_MAP_TYPE_HASH) { txt += "else { typeof(" + name + ".leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); "; txt += "_zleaf += " + increment_value + ";"; diff --git a/tests/python/test_clang.py b/tests/python/test_clang.py index b1fb7e96..b62e905a 100755 --- a/tests/python/test_clang.py +++ b/tests/python/test_clang.py @@ -1254,7 +1254,8 @@ int test(struct pt_regs *ctx, struct mm_struct *mm) { struct bpf_map; BPF_HASH(map); int map_delete(struct pt_regs *ctx, struct bpf_map *bpfmap, u64 *k) { - map.increment(42, 10); + map.increment(42, 5); + map.atomic_increment(42, 5); return 0; } """) diff --git a/tests/python/test_histogram.py b/tests/python/test_histogram.py index ec7950c9..cb878c6d 100755 --- a/tests/python/test_histogram.py +++ b/tests/python/test_histogram.py @@ -17,6 +17,7 @@ BPF_HISTOGRAM(hist1); BPF_HASH(stub); int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { hist1.increment(bpf_log2l(*k)); + hist1.atomic_increment(bpf_log2l(*k)); return 0; } """) @@ -43,6 +44,7 @@ BPF_HASH(stub1); BPF_HASH(stub2); int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { hist1.increment((Key){map, bpf_log2l(*k)}); + hist1.atomic_increment((Key){map, bpf_log2l(*k)}); return 0; } """) @@ -68,8 +70,10 @@ int kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) { #else Key k = {.slot = bpf_log2l(prev->start_boottime)}; #endif - if (!bpf_get_current_comm(&k.name, sizeof(k.name))) + if (!bpf_get_current_comm(&k.name, sizeof(k.name))) { hist1.increment(k); + hist1.atomic_increment(k); + } return 0; } """) diff --git a/tests/python/test_perf_event.py b/tests/python/test_perf_event.py index 3f78f5b3..882e71a1 100755 --- a/tests/python/test_perf_event.py +++ b/tests/python/test_perf_event.py @@ -33,8 +33,10 @@ int do_ret_sys_getuid(void *ctx) { return 0; u64 *prevp = prev.lookup(&cpu); - if (prevp) + if (prevp) { dist.increment(bpf_log2l(val - *prevp)); + dist.atomic_increment(bpf_log2l(val - *prevp)); + } return 0; } """