Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Aug 2016 21:20:05 +0000 (UTC)
From:      "Landon J. Fuller" <landonf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r304242 - head/sys/dev/bhnd/bhndb
Message-ID:  <201608162120.u7GLK53I076266@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: landonf
Date: Tue Aug 16 21:20:05 2016
New Revision: 304242
URL: https://svnweb.freebsd.org/changeset/base/304242

Log:
  bhndb(4): Drop MIPS-incompatible __builtin_ctz dependency.
  
  This replaces the bitfield representation of the bhndb register window
  freelist with the bitstring API, eliminating a dependency on
  (MIPS-unsupported) __builtin_ctz().
  
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D7495

Modified:
  head/sys/dev/bhnd/bhndb/bhndb_private.h
  head/sys/dev/bhnd/bhndb/bhndb_subr.c

Modified: head/sys/dev/bhnd/bhndb/bhndb_private.h
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_private.h	Tue Aug 16 21:17:51 2016	(r304241)
+++ head/sys/dev/bhnd/bhndb/bhndb_private.h	Tue Aug 16 21:20:05 2016	(r304242)
@@ -33,6 +33,7 @@
 #define _BHND_BHNDB_PRIVATE_H_
 
 #include <sys/param.h>
+#include <sys/bitstring.h>
 #include <sys/bus.h>
 #include <sys/systm.h>
 
@@ -184,21 +185,23 @@ struct bhndb_resources {
 
 	struct bhndb_dw_alloc		*dw_alloc;	/**< dynamic window allocation records */
 	size_t				 dwa_count;	/**< number of dynamic windows available. */
-	uint32_t			 dwa_freelist;	/**< dynamic window free list */
+	bitstr_t			*dwa_freelist;	/**< dynamic window free list */
 	bhndb_priority_t		 min_prio;	/**< minimum resource priority required to
 							     allocate a dynamic window */
 };
 
 /**
- * Returns true if the all dynamic windows have been exhausted, false
+ * Returns true if the all dynamic windows are marked free, false
  * otherwise.
  * 
  * @param br The resource state to check.
  */
 static inline bool
-bhndb_dw_exhausted(struct bhndb_resources *br)
+bhndb_dw_all_free(struct bhndb_resources *br)
 {
-	return (br->dwa_freelist == 0);
+	int bit;
+	bit_ffs(br->dwa_freelist, br->dwa_count, &bit);
+	return (bit == -1);
 }
 
 /**
@@ -209,12 +212,14 @@ bhndb_dw_exhausted(struct bhndb_resource
 static inline struct bhndb_dw_alloc *
 bhndb_dw_next_free(struct bhndb_resources *br)
 {
-	struct bhndb_dw_alloc *dw_free;
+	struct bhndb_dw_alloc	*dw_free;
+	int			 bit;
 
-	if (bhndb_dw_exhausted(br))
+	bit_ffc(br->dwa_freelist, br->dwa_count, &bit);
+	if (bit == -1)
 		return (NULL);
 
-	dw_free = &br->dw_alloc[__builtin_ctz(br->dwa_freelist)];
+	dw_free = &br->dw_alloc[bit];
 
 	KASSERT(LIST_EMPTY(&dw_free->refs),
 	    ("free list out of sync with refs"));
@@ -233,7 +238,7 @@ bhndb_dw_is_free(struct bhndb_resources 
 {
 	bool is_free = LIST_EMPTY(&dwa->refs);
 
-	KASSERT(is_free == ((br->dwa_freelist & (1 << dwa->rnid)) != 0),
+	KASSERT(is_free == !bit_test(br->dwa_freelist, dwa->rnid),
 	    ("refs out of sync with free list"));
 
 	return (is_free);

Modified: head/sys/dev/bhnd/bhndb/bhndb_subr.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_subr.c	Tue Aug 16 21:17:51 2016	(r304241)
+++ head/sys/dev/bhnd/bhndb/bhndb_subr.c	Tue Aug 16 21:20:05 2016	(r304242)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/limits.h>
 
 #include "bhndb_private.h"
 #include "bhndbvar.h"
@@ -264,7 +265,7 @@ bhndb_alloc_resources(device_t dev, devi
 	const struct bhndb_regwin	*win;
 	bus_size_t			 last_window_size;
 	size_t				 res_num;
-	u_int				 rnid;
+	int				 rnid;
 	int				 error;
 	bool				 free_parent_res;
 	bool				 free_ht_mem, free_br_mem;
@@ -371,10 +372,10 @@ bhndb_alloc_resources(device_t dev, devi
 	}
 
 	/* Fetch the dynamic regwin count and verify that it does not exceed
-	 * what is representable via our freelist bitmask. */
+	 * what is representable via our freelist bitstring. */
 	r->dwa_count = bhndb_regwin_count(cfg->register_windows,
 	    BHNDB_REGWIN_T_DYN);
-	if (r->dwa_count >= (8 * sizeof(r->dwa_freelist))) {
+	if (r->dwa_count >= INT_MAX) {
 		device_printf(r->dev, "max dynamic regwin count exceeded\n");
 		goto failed;
 	}
@@ -385,8 +386,12 @@ bhndb_alloc_resources(device_t dev, devi
 	if (r->dw_alloc == NULL)
 		goto failed;
 
-	/* Initialize the dynamic window table and freelist. */
-	r->dwa_freelist = 0;
+	/* Allocate the dynamic window allocation freelist */
+	r->dwa_freelist = bit_alloc(r->dwa_count, M_BHND, M_NOWAIT);
+	if (r->dwa_freelist == NULL)
+		goto failed;
+
+	/* Initialize the dynamic window table */
 	rnid = 0;
 	last_window_size = 0;
 	for (win = cfg->register_windows;
@@ -446,9 +451,6 @@ bhndb_alloc_resources(device_t dev, devi
 			goto failed;
 		}
 
-		/* Add to freelist */
-		r->dwa_freelist |= (1 << rnid);
-
 		rnid++;
 	}
 
@@ -473,6 +475,9 @@ failed:
 	if (r->dw_alloc != NULL)
 		free(r->dw_alloc, M_BHND);
 
+	if (r->dwa_freelist != NULL)
+		free(r->dwa_freelist, M_BHND);
+
 	free (r, M_BHND);
 
 	return (NULL);
@@ -491,9 +496,17 @@ bhndb_free_resources(struct bhndb_resour
 	struct bhndb_dw_rentry	*dwr, *dwr_next;
 
 	/* No window regions may still be held */
-	if (__builtin_popcount(br->dwa_freelist) != br->dwa_count) {
-		device_printf(br->dev, "leaked %llu dynamic register regions\n",
-		    (unsigned long long) br->dwa_count - br->dwa_freelist);
+	if (!bhndb_dw_all_free(br)) {
+		for (int i = 0; i < br->dwa_count; i++) {
+			dwa = &br->dw_alloc[i];
+
+			/* Skip free dynamic windows */
+			if (bhndb_dw_is_free(br, dwa))
+				continue;
+
+			device_printf(br->dev,
+			    "leaked dynamic register window %d\n", dwa->rnid);
+		}
 	}
 
 	/* Release resources allocated through our parent. */
@@ -523,6 +536,7 @@ bhndb_free_resources(struct bhndb_resour
 	free(br->res, M_BHND);
 	free(br->res_spec, M_BHND);
 	free(br->dw_alloc, M_BHND);
+	free(br->dwa_freelist, M_BHND);
 }
 
 /**
@@ -765,7 +779,7 @@ bhndb_dw_retain(struct bhndb_resources *
 	LIST_INSERT_HEAD(&dwa->refs, rentry, dw_link);
 
 	/* Update the free list */
-	br->dwa_freelist &= ~(1 << (dwa->rnid));
+	bit_set(br->dwa_freelist, dwa->rnid);
  
 	return (0);
 }
@@ -794,7 +808,7 @@ bhndb_dw_release(struct bhndb_resources 
 
 	/* If this was the last reference, update the free list */
 	if (LIST_EMPTY(&dwa->refs))
-		br->dwa_freelist |= (1 << (dwa->rnid));
+		bit_clear(br->dwa_freelist, dwa->rnid);
 }
 
 /**



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608162120.u7GLK53I076266>