Subject: Re: CVS commit: src
To: Jason Thorpe <thorpej@wasabisystems.com>
From: Juergen Hannken-Illjes <hannken@netbsd.org>
List: tech-kern
Date: 06/22/2004 12:21:38
On Mon, Jun 21, 2004 at 04:12:24PM -0700, Jason Thorpe wrote:
> 
> On Jun 21, 2004, at 12:36 PM, Bill Studenmund wrote:
> 
> >I'm not fully sure why, but I'm more comfortable with this complexity 
> >in
> >the lock manager.
> 
> I'm not.  The more overhead the locking primitives we have are (and 
> lockmgr is pretty heavy-weight), we can pretty much never hope to have 
> a scalable MP implementation.
> 
> Put complexity in the things that require it, don't add complexity to 
> places where it is seldom needed.

Is this one possible? Should add no overhead to the lock manager.

-- 
Jürgen Hannken-Illjes - hannken@netbsd.org

void
transfer_sleepers(const void *from_ident, const void *to_ident)
{
	struct slpque *qp_from, *qp_to;
	struct lwp *l, **q;
	int s;

	SCHED_ASSERT_UNLOCKED();

	SCHED_LOCK(s);

	qp_from = SLPQUE(from_ident);
	for (q = &qp_from->sq_head; (l = *q) != NULL; ) {
		if (l->l_wchan == from_ident) {
			/* dequeue from old queue */
			*q = l->l_forw;
			if (qp_from->sq_tailp == &l->l_forw)
				qp_from->sq_tailp = q;
			/* change wchan and enqueue */
			l->l_wchan = to_ident;
			qp_to = SLPQUE(to_ident);
			if (qp_to->sq_head == 0)
				qp_to->sq_head = l;
			else
				*qp_to->sq_tailp = l;
			*(qp_to->sq_tailp = &l->l_forw) = 0;
		} else
			q = &l->l_forw;
	}

	SCHED_UNLOCK(s);
}

Then transferlockers() could be as simple as

void
transferlockers(struct lock *from, struct lock *to)
{
	if (from->lk_waitcount == 0)
		return;

	if (from->lk_flags & LK_WAITDRAIN)
		transfer_sleepers((void *)&from->lk_flags,
		    (void *)&to->lk_flags);
	else
		transfer_sleepers((void *)from, (void *)to);
}