Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 30 Aug 2014 01:30:36 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: C threads, v. 6.2

On Fri, Aug 29, 2014 at 09:01:11PM +0200, Jens Gustedt wrote:
> Am Freitag, den 29.08.2014, 11:57 -0400 schrieb Rich Felker:
> > On Fri, Aug 29, 2014 at 10:02:43AM +0200, Jens Gustedt wrote:
> > > Am Freitag, den 29.08.2014, 09:56 +0200 schrieb Jens Gustedt:
> > > > All of this would explode in our face the day a user wants to use
> > > > pthread_mutex_t and mtx_t in the same application. A use case could be
> > > > that he uses one library that protects CS with pthread_mutex_t and
> > > > another that uses mtx_t. Now suddenly we have code that sees two
> > > > different types, with possibly subtle bugs due to aliasing.
> > > > 
> > > > So in conclusion, it is doable, but I don't like it at all.
> > > 
> > > To give it a positive turn, for the moment I'd prefer to roll this
> > > back and have the two types pthread_mutex_t and pthread_cond_t violate
> > > the namespace rules of libc for the moment. This is not perfect, but
> > > also not a serious drawback.
> > > 
> > > This would have the advantage of being conservative on the pthread
> > > side and not to delay the schedule.
> > 
> > I don't think this is an acceptable way to proceed. It creates a
> > C++ ABI that we're planning to remove by changing the struct tags for
> > these types later (fixing the namespace issue will necessarily break
> > the C++ ABI).
> 
> I don't know what you are planning, could you please explain?

Unless the intent is to permanently have namespace violations, mtx_t
must be defined at some point such that it does not have
pthread_mutex_t as its C++ ABI "struct tag". It could have mtx_t
(because the specific name is reserved), or something like __mtx_t
(with a name in a general reserved namespace). This requires being a
different type from pthread_mutex_t.

> There is basically one base choice to make:
> 
>  - we decide if pthread_mutex_t and mtx_t are seen as two different
>    types or not for any application that includes both headers

This is not a choice; it's mandated by the fact that our
pthread_mutex_t has a "struct tag" (in C++) that's a namespace
violation for use as the tag for mtx_t.

However, by the C rules, they're only "different types" when they're
both visible in the same translation unit. To a translation unit where
only one is visible, since the typedef name is not actually part of
the type, just an alias, both are structures without tags, and the one
that is visible is _the same type_ as whichever one it needs to be to
make the code correct.

I don't see any problem if an application has both types visible in
one of it's TUs, since no "aliasing" takes place on the app side. The
tagless structure "struct { union {...} __u; }" (whichever instance of
it) is simply zero-initialized on the application TU side. On the
implementation side, functions like pthread_mutex_trylock access a
tagless structure "struct { union {...} __u; }", of which they have
only one defined: the one referenced by the pthread_mutex_t typedef.

> (This should be made independent of the question if we silently use
> the same hidden type, or similar structured type, under the hood.)
> 
> For C this choice is not so relevant, since all interfaces are just
> pointers to struct, so they are interchangeble, and this helps for the
> implementation.
> 
> For C++ this is not the same because "type" for them means *typename*,
> defined in addition that is determined in some subtle and not so
> obvious way.
> 
> For backward compatibility, the C++ ABI seems to dictate that there
> must be at least one such type that is called pthread_mutex_t. So we
> have to keep the type with that typename for them, it is as simple as
> that.
> 
> Now in a C++ context that choice above boils down to the question
> 
>   - is mtx_t a typedef to pthread_mutex_t or is it a proper type?
> 
> If we want it to be a proper type (for which I would argue, I think)
> we have to think of ways to make C++ believe that the two types are
> different, even if we use the same implementation underneath.

Yes, because of the namespace, C++ has to believe the types are
different. But the (C) implementation of the functions is not subject
to C++ rules about types; it's not C++ code. Thus I think everything
is fine.

If you really still think there's a problem, I still have one trick
I've mentioned before that makes it a 100% non-problem: never using
the pthread_mutex_t or mtx_t type at all internally, but instead using
the type of their first member. I believe I could make this work with
only a few lines of source-level changes, no change to the output
code, and minimal ugliness. Let me know if you still have doubts
whether the above analysis I gave is correct, and if so, I'll give my
trick a try.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.