summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranton <anton@openbsd.org>2020-07-31 07:11:35 +0000
committeranton <anton@openbsd.org>2020-07-31 07:11:35 +0000
commita187908a04ce8f5cfcfdf32566b94a3dad43464f (patch)
treef5d2e690a693f1085f2583f0d62fe629ffded6b6
parentAlso compare username when checking for JumpHost loops. bz#3057, ok djm@ (diff)
downloadwireguard-openbsd-a187908a04ce8f5cfcfdf32566b94a3dad43464f.tar.xz
wireguard-openbsd-a187908a04ce8f5cfcfdf32566b94a3dad43464f.zip
Make writes to the coverage buffer MP-safe using atomic operations.
The new routine kd_claim() returns the next available entry in the buffer. Since the first element in the buffer is reserved to hold the number of entries, zero can be used as a sentinel value meaning that the buffer is full. A mere preparation for upcoming remote coverage support in which the buffer can be accessed by multiple threads concurrently. ok mpi@ as part of a larger diff
-rw-r--r--sys/dev/kcov.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/sys/dev/kcov.c b/sys/dev/kcov.c
index 9f6d16c827b..991e53285ba 100644
--- a/sys/dev/kcov.c
+++ b/sys/dev/kcov.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kcov.c,v 1.20 2020/06/07 19:23:33 anton Exp $ */
+/* $OpenBSD: kcov.c,v 1.21 2020/07/31 07:11:35 anton Exp $ */
/*
* Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
@@ -54,6 +54,7 @@ void kd_free(struct kcov_dev *);
struct kcov_dev *kd_lookup(int);
static struct kcov_dev *kd_curproc(int);
+static uint64_t kd_claim(struct kcov_dev *, int);
TAILQ_HEAD(, kcov_dev) kd_list = TAILQ_HEAD_INITIALIZER(kd_list);
@@ -80,11 +81,8 @@ __sanitizer_cov_trace_pc(void)
if (kd == NULL)
return;
- idx = kd->kd_buf[0];
- if (idx + 1 <= kd->kd_nmemb) {
- kd->kd_buf[idx + 1] = (uintptr_t)__builtin_return_address(0);
- kd->kd_buf[0] = idx + 1;
- }
+ if ((idx = kd_claim(kd, 1)))
+ kd->kd_buf[idx] = (uintptr_t)__builtin_return_address(0);
}
/*
@@ -105,13 +103,11 @@ trace_cmp(uint64_t type, uint64_t arg1, uint64_t arg2, uintptr_t pc)
if (kd == NULL)
return;
- idx = kd->kd_buf[0];
- if (idx * 4 + 4 <= kd->kd_nmemb) {
- kd->kd_buf[idx * 4 + 1] = type;
- kd->kd_buf[idx * 4 + 2] = arg1;
- kd->kd_buf[idx * 4 + 3] = arg2;
- kd->kd_buf[idx * 4 + 4] = pc;
- kd->kd_buf[0] = idx + 1;
+ if ((idx = kd_claim(kd, 4))) {
+ kd->kd_buf[idx] = type;
+ kd->kd_buf[idx + 1] = arg1;
+ kd->kd_buf[idx + 2] = arg2;
+ kd->kd_buf[idx + 3] = pc;
}
}
@@ -418,3 +414,25 @@ kd_curproc(int mode)
return (kd);
}
+
+/*
+ * Claim stride number of elements in the coverage buffer. Returns the index of
+ * the first claimed element. If the claim cannot be fulfilled, zero is
+ * returned.
+ */
+static uint64_t
+kd_claim(struct kcov_dev *kd, int stride)
+{
+ uint64_t idx, was;
+
+ idx = kd->kd_buf[0];
+ for (;;) {
+ if (idx * stride + stride > kd->kd_nmemb)
+ return (0);
+
+ was = atomic_cas_ulong(&kd->kd_buf[0], idx, idx + 1);
+ if (was == idx)
+ return (idx * stride + 1);
+ idx = was;
+ }
+}