diff --git a/libknet/handle.c b/libknet/handle.c
index 440eaba..15133df 100644
--- a/libknet/handle.c
+++ b/libknet/handle.c
@@ -110,6 +110,13 @@ static int _init_locks(knet_handle_t knet_h)
 		goto exit_fail;
 	}
 
+	savederrno = pthread_mutex_init(&knet_h->backoff_mutex, NULL);
+	if (savederrno) {
+		log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize pong timeout backoff mutex: %s",
+			strerror(savederrno));
+		goto exit_fail;
+	}
+
 	savederrno = pthread_mutex_init(&knet_h->tx_seq_num_mutex, NULL);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize tx_seq_num_mutex mutex: %s",
@@ -132,6 +139,7 @@ static void _destroy_locks(knet_handle_t knet_h)
 	pthread_cond_destroy(&knet_h->pmtud_cond);
 	pthread_mutex_destroy(&knet_h->hb_mutex);
 	pthread_mutex_destroy(&knet_h->tx_mutex);
+	pthread_mutex_destroy(&knet_h->backoff_mutex);
 	pthread_mutex_destroy(&knet_h->tx_seq_num_mutex);
 }
 
diff --git a/libknet/internals.h b/libknet/internals.h
index ce23e2a..622e0ee 100644
--- a/libknet/internals.h
+++ b/libknet/internals.h
@@ -185,6 +185,7 @@ struct knet_handle {
 	pthread_cond_t pmtud_cond;		/* conditional for above */
 	pthread_mutex_t tx_mutex;		/* used to protect knet_send_sync and TX thread */
 	pthread_mutex_t hb_mutex;		/* used to protect heartbeat thread and seq_num broadcasting */
+	pthread_mutex_t backoff_mutex;		/* used to protect dst_link->pong_timeout_adj */
 	struct crypto_instance *crypto_instance;
 	size_t sec_header_size;
 	size_t sec_block_size;
diff --git a/libknet/tests/knet_bench.c b/libknet/tests/knet_bench.c
index dc540d7..bf4e5bc 100644
--- a/libknet/tests/knet_bench.c
+++ b/libknet/tests/knet_bench.c
@@ -470,7 +470,7 @@ static void setup_knet(int argc, char *argv[])
 		exit(FAIL);
 	}
 
-	if (knet_handle_pmtud_setfreq(knet_h, 60) < 0) {
+	if (knet_handle_pmtud_setfreq(knet_h, 10) < 0) {
 		printf("knet_handle_pmtud_setfreq failed: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		exit(FAIL);
diff --git a/libknet/threads_heartbeat.c b/libknet/threads_heartbeat.c
index ffe2f99..3e4d32a 100644
--- a/libknet/threads_heartbeat.c
+++ b/libknet/threads_heartbeat.c
@@ -155,8 +155,8 @@ static void _adjust_pong_timeouts(knet_handle_t knet_h)
 	struct knet_link *dst_link;
 	int link_idx;
 
-	if (pthread_rwlock_wrlock(&knet_h->global_rwlock) != 0) {
-		log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get write lock");
+	if (pthread_mutex_lock(&knet_h->backoff_mutex)) {
+		log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get backoff_mutex");
 		return;
 	}
 
@@ -178,7 +178,7 @@ static void _adjust_pong_timeouts(knet_handle_t knet_h)
 		}
 	}
 
-	pthread_rwlock_unlock(&knet_h->global_rwlock);
+	pthread_mutex_unlock(&knet_h->backoff_mutex);
 }
 
 void *_handle_heartbt_thread(void *data)
@@ -194,6 +194,11 @@ void *_handle_heartbt_thread(void *data)
 	while (!shutdown_in_progress(knet_h)) {
 		usleep(KNET_THREADS_TIMERES);
 
+		if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
+			log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get read lock");
+			continue;
+		}
+
 		/*
 		 *  _adjust_pong_timeouts should execute approx once a second.
 		 */
@@ -204,11 +209,6 @@ void *_handle_heartbt_thread(void *data)
 			i++;
 		}
 
-		if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
-			log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get read lock");
-			continue;
-		}
-
 		_send_pings(knet_h, 1);
 
 		pthread_rwlock_unlock(&knet_h->global_rwlock);
@@ -216,4 +216,3 @@ void *_handle_heartbt_thread(void *data)
 
 	return NULL;
 }
-
diff --git a/libknet/threads_pmtud.c b/libknet/threads_pmtud.c
index 6e60dc5..817d541 100644
--- a/libknet/threads_pmtud.c
+++ b/libknet/threads_pmtud.c
@@ -36,6 +36,7 @@ static int _handle_check_link_pmtud(knet_handle_t knet_h, struct knet_host *dst_
 	ssize_t len;	     /* len of what we were able to sendto onwire */
 
 	struct timespec ts;
+	unsigned long long pong_timeout_adj_tmp;
 	unsigned char *outbuf = (unsigned char *)knet_h->pmtudbuf;
 
 	mutex_retry_limit = 0;
@@ -156,6 +157,11 @@ restart:
 		return -1;
 	}
 
+	savederrno = pthread_mutex_lock(&knet_h->tx_mutex);
+	if (savederrno) {
+		log_err(knet_h, KNET_SUB_PMTUD, "Unable to get TX mutex lock: %s", strerror(savederrno));
+		return -1;
+	}
 retry:
 	len = sendto(dst_link->outsock, outbuf, data_len,
 			MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *) &dst_link->dst_addr,
@@ -166,6 +172,7 @@ retry:
 	switch(err) {
 		case -1: /* unrecoverable error */
 			log_debug(knet_h, KNET_SUB_PMTUD, "Unable to send pmtu packet (sendto): %d %s", savederrno, strerror(savederrno));
+			pthread_mutex_unlock(&knet_h->tx_mutex);
 			pthread_mutex_unlock(&knet_h->pmtud_mutex);
 			dst_link->status.stats.tx_pmtu_errors++;
 			return -1;
@@ -177,8 +184,11 @@ retry:
 			break;
 	}
 
+	pthread_mutex_unlock(&knet_h->tx_mutex);
+
 	if (len != (ssize_t )data_len) {
 		if (savederrno == EMSGSIZE) {
+			log_debug(knet_h, KNET_SUB_PMTUD, "EMSGSIZE for: %zu", onwire_len);
 			dst_link->last_bad_mtu = onwire_len;
 		} else {
 			log_debug(knet_h, KNET_SUB_PMTUD, "Unable to send pmtu packet len: %zu err: %s", onwire_len, strerror(savederrno));
@@ -205,14 +215,33 @@ retry:
 		 * and add values to it that could overflow into seconds.
 		 */ 
 
-		ts.tv_sec += dst_link->pong_timeout_adj / 1000000;
-		ts.tv_nsec += (((dst_link->pong_timeout_adj) % 1000000) * 1000);
+		if (pthread_mutex_lock(&knet_h->backoff_mutex)) {
+			log_debug(knet_h, KNET_SUB_HEARTBEAT, "Unable to get backoff_mutex");
+			pthread_mutex_unlock(&knet_h->pmtud_mutex);
+			return -1;
+		}
+
+		if (knet_h->crypto_instance) {
+			/*
+			 * crypto, under pressure, is a royal PITA
+			 */
+			pong_timeout_adj_tmp = dst_link->pong_timeout_adj * 2;
+		} else {
+			pong_timeout_adj_tmp = dst_link->pong_timeout_adj;
+		}
+
+		ts.tv_sec += pong_timeout_adj_tmp / 1000000;
+		ts.tv_nsec += (((pong_timeout_adj_tmp) % 1000000) * 1000);
 		while (ts.tv_nsec > 1000000000) {
 			ts.tv_sec += 1;
 			ts.tv_nsec -= 1000000000;
 		}
 
+		pthread_mutex_unlock(&knet_h->backoff_mutex);
+
+		log_debug(knet_h, KNET_SUB_PMTUD, "Waiting for response: %u", dst_link->last_sent_mtu);
 		ret = pthread_cond_timedwait(&knet_h->pmtud_cond, &knet_h->pmtud_mutex, &ts);
+		log_debug(knet_h, KNET_SUB_PMTUD, "Response arrived: %d %u %zu", ret, dst_link->last_recv_mtu, onwire_len);
 
 		if (shutdown_in_progress(knet_h)) {
 			pthread_mutex_unlock(&knet_h->pmtud_mutex);
@@ -231,6 +260,7 @@ retry:
 		}
 
 		if ((dst_link->last_recv_mtu != onwire_len) || (ret)) {
+			log_debug(knet_h, KNET_SUB_PMTUD, "BAD MTU: %u %zu", dst_link->last_recv_mtu, onwire_len);
 			dst_link->last_bad_mtu = onwire_len;
 		} else {
 			int found_mtu = 0;
@@ -241,8 +271,10 @@ retry:
 					found_mtu = 1;
 				}
 			} else {
+				log_debug(knet_h, KNET_SUB_PMTUD, "GOOD MTU: %u %u %zu", dst_link->last_good_mtu, dst_link->last_bad_mtu, onwire_len + 1);
 				if ((onwire_len == max_mtu_len) ||
-				    ((dst_link->last_bad_mtu) && (dst_link->last_bad_mtu == (onwire_len + 1)))) {
+				    ((dst_link->last_bad_mtu) && (dst_link->last_bad_mtu == (onwire_len + 1))) ||
+				    (dst_link->last_bad_mtu == dst_link->last_good_mtu)) {
 					found_mtu = 1;
 				}
 			}
@@ -262,7 +294,7 @@ retry:
 
 	onwire_len = (dst_link->last_good_mtu + dst_link->last_bad_mtu) / 2;
 	pthread_mutex_unlock(&knet_h->pmtud_mutex);
-
+	usleep((dst_link->status.stats.latency_ave * 1000) / 4);
 	goto restart;
 }
 
@@ -335,7 +367,15 @@ static int _handle_check_pmtud(knet_handle_t knet_h, struct knet_host *dst_host,
 			if (dst_link->status.mtu < *min_mtu) {
 				*min_mtu = dst_link->status.mtu;
 			}
+
+			/*
+			 * set pmtud_last, if we can, after we are done with the PMTUd process
+			 * because it can take a very long time.
+			 */
 			dst_link->pmtud_last = clock_now;
+			if (!clock_gettime(CLOCK_MONOTONIC, &clock_now)) {
+				dst_link->pmtud_last = clock_now;
+			}
 		}
 	}
 
diff --git a/libknet/threads_rx.c b/libknet/threads_rx.c
index f7b17a5..c3f924d 100644
--- a/libknet/threads_rx.c
+++ b/libknet/threads_rx.c
@@ -660,6 +660,11 @@ retry_pong:
 			knet_h->stats_extra.tx_crypt_pmtu_reply_packets++;
 		}
 
+		savederrno = pthread_mutex_lock(&knet_h->tx_mutex);
+		if (savederrno) {
+			log_err(knet_h, KNET_SUB_RX, "Unable to get TX mutex lock: %s", strerror(savederrno));
+			goto out_pmtud;
+		}
 retry_pmtud:
 		len = sendto(src_link->outsock, outbuf, outlen, MSG_DONTWAIT | MSG_NOSIGNAL,
 				(struct sockaddr *) &src_link->dst_addr,
@@ -685,7 +690,8 @@ retry_pmtud:
 					break;
 			}
 		}
-
+		pthread_mutex_unlock(&knet_h->tx_mutex);
+out_pmtud:
 		break;
 	case KNET_HEADER_TYPE_PMTUD_REPLY:
 		src_link->status.stats.rx_pmtu_packets++;
