libthr shared locks

Daniel Eischen deischen at
Wed Dec 23 18:08:33 UTC 2015

On Wed, 23 Dec 2015, Konstantin Belousov wrote:

> A well-known limitation of the FreeBSD libthr implementation of the
> pthread locking objects is the missed support for the process-shared
> locks.  The hardest part of implementing the support is the neccessity
> of providing ABI compatibility for the current implementation.
> Right now, the ABI-visible handle to the locks is a single pointer
> word.  As an example which allows to make the description less vague,
> let consider pthread_mutex_t.  It is defined in
> sys/sys/_pthreadtypes.h as
> typedef struct	pthread_mutex		*pthread_mutex_t;
> The pointer points to the following structure, after the
> pthread_mutex_init(3) is called
> struct pthread_mutex {
> 	struct umutex			m_lock;
> 	int				m_flags;
> 	struct pthread			*m_owner;
> 	int				m_count;
> 	int				m_spinloops;
> 	int				m_yieldloops;
> 	TAILQ_ENTRY(pthread_mutex)	m_qe;
> };
> struct umutex {
> 	volatile __lwpid_t	m_owner;	/* Owner of the mutex */
> 	__uint32_t		m_flags;	/* Flags of the mutex */
> 	__uint32_t		m_ceilings[2];	/* Priority protect ceiling */
> 	__uint32_t		m_spare[4];
> };
> Would the ABI modified to make the pthread_mutex_t large enough to
> hold struct pthread_mutex, the rest of the implementation of the
> shared mutex is relatively trivial, if not already done.
> Changing this ABI is very hard.  libthr provides the symbol
> versioning, which allows to provide compatible shims for the previous
> ABI variant.  But since userspace tends to use the pthread objects in
> the layouts of the library objects, this causes serious ABI issues
> when mixing libraries built against different default versions of
> libthr.
> My idea to provide the shared locks, while not changing the ABI for
> libthr, is to use marker pointers to indicate the shared objects.  The
> real struct pthread_mutex, which carries the locking information, is
> allocated by at the off-page from some anonymous posix shared memory
> object.

I'd rather just change the pthread_foo lock types to include
the space.  I really don't like the way libc, rtld, etc have
to jump through hoops to initialize the locks.  If the lock
types included the storage, then they wouldn't have to.

My idea was to keep the first storage unit of the lock as
a pointer/self-reference, so that it is easy to keep the ABI.
You can set the 0 bit in the pointer to indicate whether the
lock was the old ABI, then just clear it before using it.
And we could hide old ABI implementation compilation behind
WITH_FOO to avoid overhead of checking (ptr & 0x1) != 0.
I think this is similar to what you've done below.

> The marker is defined as
> #define	THR_PSHARED_PTR						\
>    ((void *)(uintptr_t)((1ULL << (NBBY * sizeof(long) - 1)) | 1))
> The bit-pattern is 1000....00001.  There are two tricks used:

[ ... ]

I also don't like to get the kernel involved if it isn't


More information about the freebsd-arch mailing list