summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2012-02-20 08:59:07 +0000
committerRobert Mustacchi <rm@joyent.com>2013-11-15 07:59:45 -0800
commit1ddb55e64530b7536b48b3ce8a2a9ad78793aa40 (patch)
tree6e09a21045bf5c3c6aeb901ac1266bb1514433f6
parent39cddb10a31c1c2e66aed69e6871d09caa4c8147 (diff)
downloadillumos-joyent-1ddb55e64530b7536b48b3ce8a2a9ad78793aa40.tar.gz
4302 stack overflow from squeue_drain()
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Dan McDonald <danmcd@nexenta.com> Reviewed by: Sebastien Roy <seb@delphix.com> Approved by: Eric Schrock <eric.schrock@delphix.com>
-rw-r--r--usr/src/uts/common/inet/squeue.c23
-rw-r--r--usr/src/uts/intel/ip/ip.global-objs.debug642
-rw-r--r--usr/src/uts/intel/ip/ip.global-objs.obj642
-rw-r--r--usr/src/uts/sparc/ip/ip.global-objs.debug642
-rw-r--r--usr/src/uts/sparc/ip/ip.global-objs.obj642
5 files changed, 31 insertions, 0 deletions
diff --git a/usr/src/uts/common/inet/squeue.c b/usr/src/uts/common/inet/squeue.c
index 4108931c36..2e08dc359b 100644
--- a/usr/src/uts/common/inet/squeue.c
+++ b/usr/src/uts/common/inet/squeue.c
@@ -23,6 +23,10 @@
*/
/*
+ * Copyright 2012 Joyent, Inc. All rights reserved.
+ */
+
+/*
* Squeues: General purpose serialization mechanism
* ------------------------------------------------
*
@@ -120,6 +124,8 @@
#include <sys/sdt.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
+#include <sys/stack.h>
+#include <sys/archsystm.h>
#include <inet/ipclassifier.h>
#include <inet/udp_impl.h>
@@ -142,6 +148,9 @@ int squeue_workerwait_ms = 0;
static int squeue_drain_ns = 0;
static int squeue_workerwait_tick = 0;
+uintptr_t squeue_drain_stack_needed = 10240;
+uint_t squeue_drain_stack_toodeep;
+
#define MAX_BYTES_TO_PICKUP 150000
#define ENQUEUE_CHAIN(sqp, mp, tail, cnt) { \
@@ -712,6 +721,20 @@ squeue_drain(squeue_t *sqp, uint_t proc_type, hrtime_t expire)
boolean_t sq_poll_capable;
ip_recv_attr_t *ira, iras;
+ /*
+ * Before doing any work, check our stack depth; if we're not a
+ * worker thread for this squeue and we're beginning to get tight on
+ * on stack, kick the worker, bump a counter and return.
+ */
+ if (proc_type != SQS_WORKER && STACK_BIAS + (uintptr_t)getfp() -
+ (uintptr_t)curthread->t_stkbase < squeue_drain_stack_needed) {
+ ASSERT(mutex_owned(&sqp->sq_lock));
+ sqp->sq_awaken = ddi_get_lbolt();
+ cv_signal(&sqp->sq_worker_cv);
+ squeue_drain_stack_toodeep++;
+ return;
+ }
+
sq_poll_capable = (sqp->sq_state & SQS_POLL_CAPAB) != 0;
again:
ASSERT(mutex_owned(&sqp->sq_lock));
diff --git a/usr/src/uts/intel/ip/ip.global-objs.debug64 b/usr/src/uts/intel/ip/ip.global-objs.debug64
index ed9165dc7f..b05d399caf 100644
--- a/usr/src/uts/intel/ip/ip.global-objs.debug64
+++ b/usr/src/uts/intel/ip/ip.global-objs.debug64
@@ -254,6 +254,8 @@ sqset_lock
squeue_cache
squeue_drain_ms
squeue_drain_ns
+squeue_drain_stack_needed
+squeue_drain_stack_toodeep
squeue_workerwait_ms
squeue_workerwait_tick
tcp_acceptor_rinit
diff --git a/usr/src/uts/intel/ip/ip.global-objs.obj64 b/usr/src/uts/intel/ip/ip.global-objs.obj64
index 11a0ba651f..7dd30502a0 100644
--- a/usr/src/uts/intel/ip/ip.global-objs.obj64
+++ b/usr/src/uts/intel/ip/ip.global-objs.obj64
@@ -251,6 +251,8 @@ sqset_lock
squeue_cache
squeue_drain_ms
squeue_drain_ns
+squeue_drain_stack_needed
+squeue_drain_stack_toodeep
squeue_workerwait_ms
squeue_workerwait_tick
tcp_acceptor_rinit
diff --git a/usr/src/uts/sparc/ip/ip.global-objs.debug64 b/usr/src/uts/sparc/ip/ip.global-objs.debug64
index ed9165dc7f..b05d399caf 100644
--- a/usr/src/uts/sparc/ip/ip.global-objs.debug64
+++ b/usr/src/uts/sparc/ip/ip.global-objs.debug64
@@ -254,6 +254,8 @@ sqset_lock
squeue_cache
squeue_drain_ms
squeue_drain_ns
+squeue_drain_stack_needed
+squeue_drain_stack_toodeep
squeue_workerwait_ms
squeue_workerwait_tick
tcp_acceptor_rinit
diff --git a/usr/src/uts/sparc/ip/ip.global-objs.obj64 b/usr/src/uts/sparc/ip/ip.global-objs.obj64
index 11a0ba651f..7dd30502a0 100644
--- a/usr/src/uts/sparc/ip/ip.global-objs.obj64
+++ b/usr/src/uts/sparc/ip/ip.global-objs.obj64
@@ -251,6 +251,8 @@ sqset_lock
squeue_cache
squeue_drain_ms
squeue_drain_ns
+squeue_drain_stack_needed
+squeue_drain_stack_toodeep
squeue_workerwait_ms
squeue_workerwait_tick
tcp_acceptor_rinit