diff options
Diffstat (limited to 'usr/src/uts/common/inet/squeue.c')
-rw-r--r-- | usr/src/uts/common/inet/squeue.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/usr/src/uts/common/inet/squeue.c b/usr/src/uts/common/inet/squeue.c index 6d0bf70b2a..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) { \ @@ -546,6 +555,7 @@ squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt, ASSERT(MUTEX_HELD(&sqp->sq_lock)); ASSERT(sqp->sq_first != NULL); now = gethrtime(); + sqp->sq_run = curthread; sqp->sq_drain(sqp, SQS_ENTER, now + squeue_drain_ns); /* @@ -711,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)); |