Page MenuHomeFreeBSD

locks: provide a macro to extract lock_object from various lock types
AcceptedPublic

Authored by glebius on Sat, Sep 5, 5:49 PM.
Tags
None
Referenced Files
F171686339: D59455.id186148.diff
Sat, Sep 12, 5:06 PM
F171686098: D59455.id186162.diff
Sat, Sep 12, 5:03 PM
F171619058: D59455.diff
Sat, Sep 12, 5:35 AM
F171592419: D59455.id186148.diff
Fri, Sep 11, 11:48 PM
Unknown Object (File)
Fri, Sep 11, 7:56 PM
Unknown Object (File)
Thu, Sep 10, 11:53 AM
Unknown Object (File)
Thu, Sep 10, 11:50 AM
Unknown Object (File)
Thu, Sep 10, 9:57 AM
Subscribers

Details

Reviewers
kib
markj
Group Reviewers
Src Committers

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 76649
Build 73532: arc lint + arc unit

Event Timeline

I believe this directly breaks the aliasing rules for C.

In D59455#1363642, @kib wrote:

I believe this directly breaks the aliasing rules for C.

My reading of the documentation says it is not.

https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Type-Attributes.html#index-transparent_005funion-type-attribute

It will allow to pass pointer to any structure that starts with struct lock_object with calling conventions of struct lock_object.

In D59455#1363642, @kib wrote:

I believe this directly breaks the aliasing rules for C.

My reading of the documentation says it is not.

https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Common-Type-Attributes.html#index-transparent_005funion-type-attribute

It will allow to pass pointer to any structure that starts with struct lock_object with calling conventions of struct lock_object.

But then you access it through the first member which is the pointer to lock_object. I believe that this still breaks the C aliasing rules.
More, I do not see why trying to use this ugly gcc extension. There is C-standard _Generic() facility, which allows to enumerate allowed types for an expression and do something specific to deduced type.
I suspect that uglyness predated C11.

And, I do not understand why you don't do simply

#define callout_init_mtx(c, mtx, flags) callout_init_lock((c), &(mtx)->lock_object, (flags))

and same for all other blocking locks.

I can't see how _Generic() can do the same. AFAIK, _Generic() implies multiple different functions. My goal is the opposite - have single function that accepts arguments of different (but compatible) types.

I can't see how _Generic() can do the same. AFAIK, _Generic() implies multiple different functions. My goal is the opposite - have single function that accepts arguments of different (but compatible) types.

It can, and it can do even more.
But again, I do not see why do you need either the gcc union hack, or even _Generic, for the first-order implementation.

#define	callout_init_lock(c, lk, flags) _callout_init_lock((c), &(lk)->lock_object, (flags))

does it already. It works for any structure that has the lock_object member.
With _Generic(), you can typecheck:

#define	callout_init_lock1(c, lk, flags) _callout_init_lock((c), &(lk)->lock_object, (flags))
#define 		callout_init_lock(c, lk, flags) 		\
	_Generic((lk),				\
	    struct mtx: callout_init_lock1((c), (lk), (flags)),			\
	    struct rmlock: callout_init_lock1((c), (lk), (flags)),			\
	    struct rwlock: callout_init_lock1((c), (lk), (flags)))
#undef callout_init_lock1

@glebius : I appreciate what you're trying to solve, but @kib brings up a very good point.
My concern with the change is that code (especially third-party/ports code) may naïvely assume a lock type is X, when in fact it's Y after the change. Anti-patterns like this seem ripe for improper memory accesses/potential scribblers..

D59456 refactored to use _Generic()

glebius retitled this revision from locks: provide transparent union for all lock classes to locks: provide a macro to extract lock_object from various lock types.

Hijack this revision to a completely different change. However, it is still
a prerequisite to D59456 and D59457. This is why this revision, not a new one.

sys/sys/lock.h
171
This revision is now accepted and ready to land.Mon, Sep 7, 7:18 PM

Any opinion if NOLOCK would be a better name than NULLLOCK?

sys/sys/lock.h
171

Bikeshedding, but can we call it lock2lo() instead? "lock" is the prefix used everywhere in this file. "lk" makes me think of lockmgr locks.

Otherwise looks fine to me.

sys/sys/lock.h
171

My main reason for the shorter macro was that in the _Generic() macros fit into single line :)

Any opinion on NULLLOCK vs NOLOCK?