RE: [PATCH 2.5.64] Real-time futexes (priority inheritance/protec tion/robust support) take 4

"Perez-Gonzalez, Inaky" <[email protected]>
Newsgroups gmane.comp.lib.phil
Message-ID <[email protected]>
> -----Original Message-----
> From: Ulrich Drepper
>
> > - Does not modify original futexes - a new interface is added
> 
> This is the killer.

I know, but it is the only way I found - either that or you help me convince
Rusty, that I doubt, and I understand his reasons. OTOH, you still need the
normal futexes (see below, for barriers).

Reasons for it:

* We are completely modifying the interface to access the futex
functionality, and in a way, it is a different functionality; we cannot use
counts any more, we need to use fixed values [PIDs] and atomic
compare-and-swap. This is diametrically different and some arches don't
support it (the atomic compare-and-swap, I mean).

* We cannot wake more than one waiter at a time: "correctness" && real time
wise this is calling for trouble.

Why I thus decided to go to a second interface is because we are changing so
much stuff we'd break more than one teeth and that is a no-no. And there is
no way I could find to do a decent and effective implementation using the
current interface that could provide owner identification for PI, PP,
deadlock-detection and robust support across different address spaces
without going to the kernel every time - I'd love to hear of one, though.

So it makes sense to have a separate interface, a new one, that we still
access through the sys_futex() syscall. I guess you would agree with me here
that blending this into the actual futex interface is almost impossible, not
to speak of how much stuff it would break.

> If it's not the same futex interface which is used it is not possible to
> use the non-rt version of the libpthread and the rt version on the same
> system.  The whole thing is complicated by statically binaries.

Agreed - that's what one of my buddies is looking for - how to do a simple
switch, that consistently, and across different processes with redirect each
instance of a mutex to the proper futex API (unless using rtfutex for all
cuts it well enough and without any impact - falling back in compile time to
the normal futex interface for the arches that do not support atomic
compare-and-swap).

> The problem is obvious: what do you do for mutex/condvars/barriers/etc

For mutexes: two options:

1. on _init time, you determine what interface is to be used and set a bit
or setup a function pointer in the mutex structure that indicates which
interface to use for all the call redirection to be done properly (for
example, pthread_mutex_t.__data.__kind). The trick here is to get it right
so that (a) overhead is close to nil [I know, understand and agree on you
being anal about this - me too] (b) it is correctly propagated/shared. If we
are using shared memory to share the mutex, well, the other guy will see the
same bit in pthread_mutex_t [in this case is where a function pointer does
not work, cross that out] and do the proper call forwarding. 

2. or use the rtfutex interface all the time on arches that support atomic
CAS instead of having to switch - falling back to the futex interface
[compile time]. This would also depend on if we can get good performance out
of the rtfutex, close to that of the futex. I think so, although I still
haven been able to measure it properly.

On condvars, I am not that sure - but to me it looks like they can use the
same mechanism as mutexes. It even makes sense to enable PI/PP/robust.

Barriers cannot use the rtfutex interface: think about it, it makes little
sense. For once, you need to wake up N waiters, not just one of them -
barriers don't care about the order, so it makes little sense to do it. In
the same motto, PI/PP does not makes sense for barriers, neither deadlock
detection or robust futex support. Asides, rtfutexes can be woken up only by
the same process that locked them.

Rwlocks: the only thing they can use is deadlock detection, maybe, and also
maybe, robust support - but not that well. How do you determine or record
the fact that two thousand readers own the lock ... well, it'd need a lot of
glue, so rwlocks can keep using the normal futex interface or internally
glue rtfutex and do their stuff manually (as it is done now, btw).

Am I missing anything ... oh, spinlocks. These guys play their own game and
do their own stuff, although it might make sense to convert them to do the
loop using rtfutex_trylock() for so many loops and then falling back to the
kernel to wait if we are too concerned about burning sooooo much CPU from
other processes.

In sum - the idea is not that rtfutex replaces the futex interface - it is
meant to live along with it, as each one has an specific use.

> actually initializes the object to do some more work and tell the kernel
> something.  But if the static initializers are used not even this is
> possible.  For pshared object it is possible since there is no static
> initializer to create such objects.

I think that the scenarios/methods I explained get it done - without needing
any help in the kernel or whatsoever. Let me know if I missed anything. 

> If you insist on not having a unified object the only possibility is to
> have separate libpthreads.  Because of the confusion this creates and
> the support nightmare I strongly oppose this but of course cannot
> prevent it from happening in a separate project.

I am known to be nuts, but not to that extent ...

Iñaky Pérez-González -- Not speaking for Intel -- all opinions are my own
(and my fault)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.