changeset 3896:1d5fb739bf40

6509040 hang in sfmmu_hblk_steal()
author vb70745
date Mon, 26 Mar 2007 10:41:59 -0700
parents 811da2ad2260
children 278bade789ba
files usr/src/uts/sfmmu/vm/hat_sfmmu.c
diffstat 1 files changed, 17 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sfmmu/vm/hat_sfmmu.c	Mon Mar 26 10:13:33 2007 -0700
+++ b/usr/src/uts/sfmmu/vm/hat_sfmmu.c	Mon Mar 26 10:41:59 2007 -0700
@@ -9553,8 +9553,9 @@
 		mutex_enter(&freehblkp_lock);
 		if (freehblkp != NULL) {
 			/*
-			 * If the current thread is owning hblk_reserve,
-			 * let it succede even if freehblkcnt is really low.
+			 * If the current thread is owning hblk_reserve OR
+			 * critical request from sfmmu_hblk_steal()
+			 * let it succeed even if freehblkcnt is really low.
 			 */
 			if (freehblkcnt <= HBLK_RESERVE_MIN && !critical) {
 				SFMMU_STAT(sf_get_free_throttle);
@@ -10260,15 +10261,17 @@
 }
 
 #define	BUCKETS_TO_SEARCH_BEFORE_UNLOAD	30
+#define	SFMMU_HBLK_STEAL_THRESHOLD 5
 
 static uint_t sfmmu_hblk_steal_twice;
 static uint_t sfmmu_hblk_steal_count, sfmmu_hblk_steal_unload_count;
 
 /*
- * Steal a hmeblk
- * Enough hmeblks were allocated at startup (nucleus hmeblks) and also
- * hmeblks were added dynamically. We should never ever not be able to
- * find one. Look for an unused/unlocked hmeblk in user hash table.
+ * Steal a hmeblk from user or kernel hme hash lists.
+ * For 8K tte grab one from reserve pool (freehblkp) before proceeding to
+ * steal and if we fail to steal after SFMMU_HBLK_STEAL_THRESHOLD attempts
+ * tap into critical reserve of freehblkp.
+ * Note: We remain looping in this routine until we find one.
  */
 static struct hme_blk *
 sfmmu_hblk_steal(int size)
@@ -10278,8 +10281,16 @@
 	struct hme_blk *hmeblkp = NULL, *pr_hblk;
 	uint64_t hblkpa, prevpa;
 	int i;
+	uint_t loop_cnt = 0, critical;
 
 	for (;;) {
+		if (size == TTE8K) {
+			critical =
+			    (++loop_cnt > SFMMU_HBLK_STEAL_THRESHOLD) ? 1 : 0;
+			if (sfmmu_get_free_hblk(&hmeblkp, critical))
+				return (hmeblkp);
+		}
+
 		hmebp = (uhmehash_steal_hand == NULL) ? uhme_hash :
 			uhmehash_steal_hand;
 		ASSERT(hmebp >= uhme_hash && hmebp <= &uhme_hash[UHMEHASH_SZ]);