PERFORCE change 65074 for review

John Baldwin jhb at FreeBSD.org
Tue Nov 16 13:41:22 PST 2004


On Monday 15 November 2004 06:41 pm, David Xu wrote:
> John Baldwin wrote:
> >On Sunday 14 November 2004 12:13 am, David Xu wrote:
> >>http://perforce.freebsd.org/chv.cgi?CH=65074
> >>
> >>Change 65074 by davidxu at davidxu_alona on 2004/11/14 05:12:40
> >>
> >>	1. Fix a race between signal and umtx_unlock. a waiter
> >>	   may be resumed by signal and left or exited, heavily
> >>	   loaded test causes kernel to crash.
> >>	2. Use distributed queue locks instead of single giant
> >>	   lock.
> >>
> >>Affected files ...
> >>
> >>.. //depot/projects/davidxu_ksedbg/src/sys/kern/kern_umtx.c#4 edit
> >>
> >>Differences ...
> >>
> >>==== //depot/projects/davidxu_ksedbg/src/sys/kern/kern_umtx.c#4 (text+ko)
> >>====
> >>
> >>@@ -49,25 +49,48 @@
> >> 	pid_t		uq_pid;		/* Pid key component. */
> >> };
> >>
> >> #define	UMTX_QUEUES	128
> >> #define	UMTX_HASH(pid, umtx)						\
> >>-    (((uintptr_t)pid + ((uintptr_t)umtx & ~65535)) % UMTX_QUEUES)
> >>+    ((((uintptr_t)pid << 16) + ((uintptr_t)umtx & 65535)) % UMTX_QUEUES)
> >
> >I'm curious why you changed the hash macro here?  Low order bits of
> > pointers tend to be zero due to alignment, so I think this will result in
> > fewer "useful" bits and more collisions and longer chains.
>
> FYI, I changed back to original hash code:
> I simulate it under userland:
>
> printf("thread lock: %p hash=%d\n", &thread->lock,
>            ((getpid() + ((unsigned)(&thread->lock) & ~0xFFFF))) % 128);
>
> get result:
>
> thread lock: 0x804e014 hash=39
> thread lock: 0x8053014 hash=39
> thread lock: 0x8056014 hash=39
> thread lock: 0x805a014 hash=39
> thread lock: 0x805d014 hash=39
> thread lock: 0x8060014 hash=39
> thread lock: 0x8063014 hash=39
> thread lock: 0x8067014 hash=39
> thread lock: 0x806a014 hash=39
> thread lock: 0x806d014 hash=39
> thread lock: 0x8070014 hash=39
>
> So my version put all locks on chain 0, the orignal version put all
> locks on chain 39. :( Both seem bad algorithm.
> Note it is my private version of libpthread using thr and umtx,
> 1:1 only.

Humm, try changing the hash to not mask off bits from the umtx pointer.  The 
pid is useful because if locks are allocated at the same address in different 
processes (e.g. if you run the same program N times) it will keep them from 
all colliding, but if you mask off all the bits with only 128 queues it will 
currently stick all locks from a process on the same queue.  Maybe use 
something similar to the 4BSD sleep queue hash (still used in 
subr_sleepqueue.c) that looks like:

/*
 * Constants for the hash table of sleep queue chains.  These constants are
 * the same ones that 4BSD (and possibly earlier versions of BSD) used.
 * Basically, we ignore the lower 8 bits of the address since most wait
 * channel pointers are aligned and only look at the next 7 bits for the
 * hash.  SC_TABLESIZE must be a power of two for SC_MASK to work properly.
 */
#define	SC_TABLESIZE	128			/* Must be power of 2. */
#define	SC_MASK		(SC_TABLESIZE - 1)
#define	SC_SHIFT	8
#define	SC_HASH(wc)	(((uintptr_t)(wc) >> SC_SHIFT) & SC_MASK)
#define	SC_LOOKUP(wc)	&sleepq_chains[SC_HASH(wc)]

So maybe use something like:

#define UMTX_HASH(pid, umtx)	\
	(((uintptr_t)(umtx) >> 8 + (uintptr_t)pid) % UMTX_QUEUES)

-- 
John Baldwin <jhb at FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org


More information about the p4-projects mailing list