Mercurial > illumos > illumos-gate
changeset 10641:597455df165a
6882364 networking wedged up behind blocked taskq_thread() worker
author | Krishna Yenduri <Bhargava.Yenduri@Sun.COM> |
---|---|
date | Thu, 24 Sep 2009 10:37:39 -0700 |
parents | ea5904b5cb30 |
children | 3507a45006a0 |
files | usr/src/uts/common/crypto/api/kcf_random.c |
diffstat | 1 files changed, 26 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/crypto/api/kcf_random.c Thu Sep 24 11:59:50 2009 -0400 +++ b/usr/src/uts/common/crypto/api/kcf_random.c Thu Sep 24 10:37:39 2009 -0700 @@ -116,6 +116,7 @@ rnd_stats_t rnd_stats; static boolean_t rng_prov_found = B_TRUE; static boolean_t rng_ok_to_log = B_TRUE; +static boolean_t rngprov_task_idle = B_TRUE; static void rndc_addbytes(uint8_t *, size_t); static void rndc_getbytes(uint8_t *ptr, size_t len); @@ -414,6 +415,7 @@ ASSERT(len <= MAXEXTRACTBYTES); (void) rngprov_getbytes(tbuf, len, B_TRUE); + rngprov_task_idle = B_TRUE; } /* @@ -891,13 +893,34 @@ } if (num_waiters > 0) + /* + * Note: len has no relationship with how many bytes + * a poll thread needs. + */ len = MAXEXTRACTBYTES; else if (rnbyte_cnt < RNDPOOLSIZE) len = MINEXTRACTBYTES; - if (len > 0) { - (void) taskq_dispatch(system_taskq, rngprov_task, - (void *)(uintptr_t)len, TQ_NOSLEEP); + /* + * Only one thread gets to set rngprov_task_idle at a given point + * of time and the order of the writes is defined. Also, it is OK + * if we read an older value of it and skip the dispatch once + * since we will get the correct value during the next time here. + * So, no locking is needed here. + */ + if (len > 0 && rngprov_task_idle) { + rngprov_task_idle = B_FALSE; + + /* + * It is OK if taskq_dispatch fails here. We will retry + * the next time around. Meanwhile, a thread doing a + * read() will go to the provider directly, if the + * cache becomes empty. + */ + if (taskq_dispatch(system_taskq, rngprov_task, + (void *)(uintptr_t)len, TQ_NOSLEEP | TQ_NOQUEUE) == 0) { + rngprov_task_idle = B_TRUE; + } } mutex_enter(&rndpool_lock);