Skip site navigation (1)Skip section navigation (2)
Date:      31 Oct 1997 00:01:07 +1100
From:      Julian Assange <proff@iq.org>
To:        freebsd-hackers@freebsd.org
Subject:   Re: kernel spinlocks, splbio(), MUTEX etc
Message-ID:  <wxiuufe770.fsf@profane.iq.org>
In-Reply-To: Mike Smith's message of Thu, 30 Oct 1997 22:11:24 %2B1030
References:  <199710301141.WAA00594@word.smith.net.au>

next in thread | previous in thread | raw e-mail | index | archive | help
Mike Smith <mike@smith.net.au> writes:

> > 
> > I have a possible access contention between two peices of code,
> > one hanging off a timeout() interrupt and the other called via
> > the VFS sub-system. I don't want to lock the object they are 
> > accessing by using splbio() as both bits of code use around
> > 32k instructions.
> > 
> > ideas?
> 
> Can you defer one or both of the fragments?  The only real alternatives 
> are to redesign your code to reduce the size of the critical region(s), 
> and that's not always easy...
> 
> mike

I ended up using a combination of splbio(), tsleep(), wakeup() and my
own locking system. maruXORkeys() is the cpu pig that we don't want to
block on.  Below is the locking code. I'm a bit dubious of my usage of
volatile here (I want it to apply to what the pointer points to rather
than the pointer itself) I don't want references to maru->mkeyLock to
end up optimized into a register on the first reference, because by
the time we get to the second another thread may have hit the
original in-memory instance.

static void
maruLockKeys(volatile munit *maru)
{
    int s;
 re:
    s = splbio();
    if (maru->m_keyLock == kl_timer)
	{
	    splx(s);
	    tsleep(maru, PRIBIO, "maru", 0);
	    goto re;
	}
    maru->m_keyLockCount++;
    if (maru->m_keyLock != kl_strategy) /* maybe running concurrently */
	{
	    maru->m_keyLock = kl_strategy;
	    splx(s);
	    if (maru->m_keyState == ks_cipher)
		maruXORkeys(maru);
	}
    else
	splx(s);
}

static void
maruUnlockKeys(volatile munit *maru)
{
    int s;
    s = splbio();
    if (--maru->m_keyLockCount == 0)
	maru->m_keyLock = kl_none;
    splx(s);
}

static void
maruKeyTimer(void *m)
{
    volatile munit *maru = m; /* right semantics for volatile ?*/
    maruInstance *i;
    int s;
    IFOPT(MARU_FOLLOW)
	printf ("maruXORkey(%p)\n", m);
    if (!munits[maru->m_unit])
	return;
    i = maru->m_instance;
    if (!i)
	return;
    s = splbio(); /* where is MUTEX() when you need it */
    switch (maru->m_keyLock)
	{
	case kl_none:
	    break;
	case kl_timer:
	case kl_strategy:
	    splx(s);
	    goto end;
	default:
	    panic("maruKeyTimer() default: wtf are we doing here?");
	}
    maru->m_keyLock = kl_timer;
    maru->m_keyLockCount++;
    splx(s);
    maruXORkeys(maru);
    s = splbio();
    if (maru->m_keyLock == kl_strategy)
	{ 
	    splx(s);
	    wakeup(maru);
	}
    else
	splx(s);
 end:
    timeout(maruKeyTimer, maru, ((maru->m_xorfreq*hz/1000)>0)? (maru->m_xorfreq*hz)/1000: 1);
}

--
Prof. Julian Assange  |"Don't worry about people stealing your ideas. If your
		      | Ideas are any good, you'll have to ram them down
proff@iq.org          | people's throats."
proff@gnu.ai.mit.edu  |                -- Howard Aiken     



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?wxiuufe770.fsf>