libbcc: add atomic_increment()
diff --git a/docs/reference_guide.md b/docs/reference_guide.md
index aa7db55..0c7ccfe 100644
--- a/docs/reference_guide.md
+++ b/docs/reference_guide.md
@@ -1305,6 +1305,10 @@
 
 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 0be3572..12072b0 100644
--- a/src/cc/export/helpers.h
+++ b/src/cc/export/helpers.h
@@ -101,6 +101,7 @@
   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 e78ceb3..27b1936 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -899,7 +899,7 @@
           }
           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 @@
           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 b1fb7e9..b62e905 100755
--- a/tests/python/test_clang.py
+++ b/tests/python/test_clang.py
@@ -1254,7 +1254,8 @@
 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 ec7950c..cb878c6 100755
--- a/tests/python/test_histogram.py
+++ b/tests/python/test_histogram.py
@@ -17,6 +17,7 @@
 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(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 @@
 #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 3f78f5b..882e71a 100755
--- a/tests/python/test_perf_event.py
+++ b/tests/python/test_perf_event.py
@@ -33,8 +33,10 @@
         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;
 }
 """