Module Name:    src
Committed By:   rmind
Date:           Tue Jul 23 08:25:52 UTC 2019

Modified Files:
        src/sys/net/npf: npf_portmap.c

Log Message:
NPF portmap: add a workaround for archs without 64-bit CAS.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/net/npf/npf_portmap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/npf/npf_portmap.c
diff -u src/sys/net/npf/npf_portmap.c:1.1 src/sys/net/npf/npf_portmap.c:1.2
--- src/sys/net/npf/npf_portmap.c:1.1	Tue Jul 23 00:52:01 2019
+++ src/sys/net/npf/npf_portmap.c	Tue Jul 23 08:25:52 2019
@@ -35,7 +35,7 @@
 
 #ifdef _KERNEL
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.1 2019/07/23 00:52:01 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.2 2019/07/23 08:25:52 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -106,6 +106,8 @@ typedef struct {
 	int		max_port;
 } npf_portmap_params_t;
 
+static kmutex_t			portmap_lock;
+
 void
 npf_portmap_init(npf_t *npf)
 {
@@ -130,6 +132,8 @@ npf_portmap_init(npf_t *npf)
 	npf->portmap = kmem_zalloc(sizeof(npf_portmap_t), KM_SLEEP);
 	mutex_init(&npf->portmap->list_lock, MUTEX_DEFAULT, IPL_SOFTNET);
 	npf->portmap->addr_map = thmap_create(0, NULL, THMAP_NOCOPY);
+
+	mutex_init(&portmap_lock, MUTEX_DEFAULT, IPL_SOFTNET);
 }
 
 void
@@ -146,10 +150,31 @@ npf_portmap_fini(npf_t *npf)
 	thmap_destroy(pm->addr_map);
 	mutex_destroy(&pm->list_lock);
 	kmem_free(pm, sizeof(npf_portmap_t));
+
+	mutex_destroy(&portmap_lock);
 }
 
 /////////////////////////////////////////////////////////////////////////
 
+#if defined(_LP64)
+#define	__npf_atomic_cas_64	atomic_cas_64
+#else
+static uint64_t
+__npf_atomic_cas_64(volatile uint64_t *ptr, uint64_t old, uint64_t new)
+{
+	uint64_t prev;
+
+	mutex_enter(&portmap_lock);
+	prev = *ptr;
+	if (prev == old) {
+		*ptr = new;
+	}
+	mutex_exit(&portmap_lock);
+
+	return prev;
+}
+#endif
+
 /*
  * bitmap_word_isset: test whether the bit value is in the packed array.
  *
@@ -283,7 +308,7 @@ again:
 		 */
 		if ((nval = bitmap_word_cax(bval, -1, chunk_bit)) != 0) {
 			KASSERT((nval & PORTMAP_L1_TAG) == 0);
-			if (atomic_cas_64(&bm->bits0[i], bval, nval) != bval) {
+			if (__npf_atomic_cas_64(&bm->bits0[i], bval, nval) != bval) {
 				goto again;
 			}
 			return true;
@@ -315,7 +340,7 @@ again:
 		bm1p = (uintptr_t)bm1;
 		KASSERT((bm1p & PORTMAP_L1_TAG) == 0);
 		bm1p |= PORTMAP_L1_TAG;
-		if (atomic_cas_64(&bm->bits0[i], bval, bm1p) != bval) {
+		if (__npf_atomic_cas_64(&bm->bits0[i], bval, bm1p) != bval) {
 			kmem_intr_free(bm1, sizeof(bitmap_l1_t));
 			goto again;
 		}
@@ -332,7 +357,7 @@ again:
 		return false;
 	}
 	nval = oval | b;
-	if (atomic_cas_64(&bm1->bits1[i], oval, nval) != oval) {
+	if (__npf_atomic_cas_64(&bm1->bits1[i], oval, nval) != oval) {
 		goto again;
 	}
 	return true;
@@ -356,7 +381,7 @@ again:
 		}
 		nval = bitmap_word_cax(bval, chunk_bit, chunk_bit);
 		KASSERT((nval & PORTMAP_L1_TAG) == 0);
-		if (atomic_cas_64(&bm->bits0[i], bval, nval) != bval) {
+		if (__npf_atomic_cas_64(&bm->bits0[i], bval, nval) != bval) {
 			goto again;
 		}
 		return true;
@@ -372,7 +397,7 @@ again:
 		return false;
 	}
 	nval = oval & ~b;
-	if (atomic_cas_64(&bm1->bits1[i], oval, nval) != oval) {
+	if (__npf_atomic_cas_64(&bm1->bits1[i], oval, nval) != oval) {
 		goto again;
 	}
 	return true;

Reply via email to