[master] 69dfe4980 vsc: New VSC_Value() function to clamp gauges

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Jan 11 17:06:07 UTC 2021


commit 69dfe49809322242037dea26e883ed7d5a5d21a6
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Tue Oct 20 16:13:58 2020 +0200

    vsc: New VSC_Value() function to clamp gauges
    
    When gauges are incremented and decremented by different threads, there
    is a chance that decrements are published first, provoking an underflow
    of the VSC. Values with the MSB set are considered underflowed, adjusted
    to zero instead.

diff --git a/bin/varnishstat/varnishstat.c b/bin/varnishstat/varnishstat.c
index 75c88311f..695ca092c 100644
--- a/bin/varnishstat/varnishstat.c
+++ b/bin/varnishstat/varnishstat.c
@@ -67,7 +67,7 @@ do_xml_cb(void *priv, const struct VSC_point * const pt)
 	if (pt == NULL)
 		return (0);
 	AZ(strcmp(pt->ctype, "uint64_t"));
-	val = *(const volatile uint64_t*)pt->ptr;
+	val = VSC_Value(pt);
 
 	printf("\t<stat>\n");
 	printf("\t\t<name>%s</name>\n", pt->name);
@@ -106,7 +106,7 @@ do_json_cb(void *priv, const struct VSC_point * const pt)
 		return (0);
 
 	AZ(strcmp(pt->ctype, "uint64_t"));
-	val = (uintmax_t)*(const volatile uint64_t*)pt->ptr;
+	val = (uintmax_t)VSC_Value(pt);
 
 	sep = priv;
 
@@ -167,7 +167,7 @@ do_once_cb_first(void *priv, const struct VSC_point * const pt)
 	AZ(strcmp(pt->ctype, "uint64_t"));
 	if (strcmp(pt->name, "MAIN.uptime"))
 		return (0);
-	val = *(const volatile uint64_t*)pt->ptr;
+	val = VSC_Value(pt);
 	op->up = (double)val;
 	return (1);
 }
@@ -183,7 +183,7 @@ do_once_cb(void *priv, const struct VSC_point * const pt)
 		return (0);
 	op = priv;
 	AZ(strcmp(pt->ctype, "uint64_t"));
-	val = *(const volatile uint64_t*)pt->ptr;
+	val = VSC_Value(pt);
 	i = 0;
 	i += printf("%s", pt->name);
 	if (i >= op->pad)
diff --git a/bin/varnishstat/varnishstat_curses.c b/bin/varnishstat/varnishstat_curses.c
index f7c486db1..4c3ff9127 100644
--- a/bin/varnishstat/varnishstat_curses.c
+++ b/bin/varnishstat/varnishstat_curses.c
@@ -256,7 +256,7 @@ sample_points(void)
 	VTAILQ_FOREACH(pt, &ptlist, list) {
 		AN(pt->vpt);
 		AN(pt->vpt->ptr);
-		v = *pt->vpt->ptr;
+		v = VSC_Value(pt->vpt);
 		if (v == 0 && !pt->seen)
 			continue;
 		if (!pt->seen) {
@@ -1104,7 +1104,7 @@ newpt(void *priv, const struct VSC_point *const vpt)
 	rebuild |= REBUILD_NEXT;
 	AN(pt);
 	pt->vpt = vpt;
-	pt->last = *pt->vpt->ptr;
+	pt->last = VSC_Value(vpt);
 	pt->ma_10.nmax = 10;
 	pt->ma_100.nmax = 100;
 	pt->ma_1000.nmax = 1000;
diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c
index 4698aa4e9..b051b8e08 100644
--- a/bin/varnishtest/vtc_varnish.c
+++ b/bin/varnishtest/vtc_varnish.c
@@ -864,7 +864,7 @@ do_stat_dump_cb(void *priv, const struct VSC_point * const pt)
 
 	if (strcmp(pt->ctype, "uint64_t"))
 		return (0);
-	u = *pt->ptr;
+	u = VSC_Value(pt);
 
 	if (strcmp(dp->arg, "*")) {
 		if (fnmatch(dp->arg, pt->name, 0))
@@ -926,7 +926,7 @@ do_expect_cb(void *priv, const struct VSC_point * const pt)
 	if (!sp->lhs.good && stat_match(sp->lhs.pattern, pt->name) == 0) {
 		AZ(strcmp(pt->ctype, "uint64_t"));
 		AN(pt->ptr);
-		sp->lhs.val = *pt->ptr;
+		sp->lhs.val = VSC_Value(pt);
 		sp->lhs.good = 1;
 	}
 
@@ -936,7 +936,7 @@ do_expect_cb(void *priv, const struct VSC_point * const pt)
 	    stat_match(sp->rhs.pattern, pt->name) == 0) {
 		AZ(strcmp(pt->ctype, "uint64_t"));
 		AN(pt->ptr);
-		sp->rhs.val = *pt->ptr;
+		sp->rhs.val = VSC_Value(pt);
 		sp->rhs.good = 1;
 	}
 
diff --git a/include/vapi/vsc.h b/include/vapi/vsc.h
index c09d6b150..5eaa85c41 100644
--- a/include/vapi/vsc.h
+++ b/include/vapi/vsc.h
@@ -159,4 +159,15 @@ const struct VSC_level_desc *VSC_ChangeLevel(const struct VSC_level_desc*, int);
 	 * Change a level up or down.
 	 */
 
+static inline uint64_t
+VSC_Value(const struct VSC_point * const pt)
+{
+	uint64_t val;
+
+	val = *pt->ptr;
+	if (pt->semantics == 'g' && val > INT64_MAX)
+		val = 0;
+	return (val);
+}
+
 #endif /* VAPI_VSC_H_INCLUDED */


More information about the varnish-commit mailing list