summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/strsubr.c
diff options
context:
space:
mode:
authorDavid Plauger <Dave.Plauger@Sun.COM>2010-02-26 13:23:17 -0800
committerDavid Plauger <Dave.Plauger@Sun.COM>2010-02-26 13:23:17 -0800
commitf4aaef0b4acbb24db90105d229cc89ccea3aa1e1 (patch)
tree6e4b6a41c2c7382de66bc3cdb6ff00f7ef95aca1 /usr/src/uts/common/os/strsubr.c
parent4890a7493fa5781f7cd15fa207cbcb58cc418882 (diff)
downloadillumos-joyent-f4aaef0b4acbb24db90105d229cc89ccea3aa1e1.tar.gz
6652443 system_esbq lock contention
Diffstat (limited to 'usr/src/uts/common/os/strsubr.c')
-rw-r--r--usr/src/uts/common/os/strsubr.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/usr/src/uts/common/os/strsubr.c b/usr/src/uts/common/os/strsubr.c
index 13ccd0263a..75bd481d21 100644
--- a/usr/src/uts/common/os/strsubr.c
+++ b/usr/src/uts/common/os/strsubr.c
@@ -328,7 +328,16 @@ struct kmem_cache *ciputctrl_cache = NULL;
static linkinfo_t *linkinfo_list;
/* Global esballoc throttling queue */
-static esb_queue_t system_esbq;
+static esb_queue_t system_esbq;
+
+/* Array of esballoc throttling queues, of length esbq_nelem */
+static esb_queue_t *volatile system_esbq_array;
+static int esbq_nelem;
+static kmutex_t esbq_lock;
+static int esbq_log2_cpus_per_q = 0;
+
+/* Scale the system_esbq length by setting number of CPUs per queue. */
+uint_t esbq_cpus_per_q = 1;
/*
* esballoc tunable parameters.
@@ -3904,14 +3913,34 @@ sqenable(syncq_t *sq)
* closing pipes it can avoid stack overflow in case of daisy-chained
* pipes, and also avoid deadlock in case of fifonode_t pairs (which
* share the same fifolock_t).
+ *
+ * No need to kpreempt_disable to access cpu_seqid. If we migrate and
+ * the esb queue does not match the new CPU, that is OK.
*/
-
void
freebs_enqueue(mblk_t *mp, dblk_t *dbp)
{
- esb_queue_t *eqp = &system_esbq;
+ int qindex = CPU->cpu_seqid >> esbq_log2_cpus_per_q;
+ esb_queue_t *eqp;
ASSERT(dbp->db_mblk == mp);
+ ASSERT(qindex < esbq_nelem);
+
+ eqp = system_esbq_array;
+ if (eqp != NULL) {
+ eqp += qindex;
+ } else {
+ mutex_enter(&esbq_lock);
+ if (kmem_ready && system_esbq_array == NULL)
+ system_esbq_array = (esb_queue_t *)kmem_zalloc(
+ esbq_nelem * sizeof (esb_queue_t), KM_NOSLEEP);
+ mutex_exit(&esbq_lock);
+ eqp = system_esbq_array;
+ if (eqp != NULL)
+ eqp += qindex;
+ else
+ eqp = &system_esbq;
+ }
/*
* Check data sanity. The dblock should have non-empty free function.
@@ -4037,9 +4066,17 @@ esballoc_set_timer(esb_queue_t *eqp, clock_t eq_timeout)
}
}
+/*
+ * Setup esbq array length based upon NCPU scaled by CPUs per
+ * queue. Use static system_esbq until kmem_ready and we can
+ * create an array in freebs_enqueue().
+ */
void
esballoc_queue_init(void)
{
+ esbq_log2_cpus_per_q = highbit(esbq_cpus_per_q - 1);
+ esbq_cpus_per_q = 1 << esbq_log2_cpus_per_q;
+ esbq_nelem = howmany(NCPU, esbq_cpus_per_q);
system_esbq.eq_len = 0;
system_esbq.eq_head = system_esbq.eq_tail = NULL;
system_esbq.eq_flags = 0;