mit krb5 and threads - api

Ken Raeburn raeburn at MIT.EDU
Mon Mar 15 14:18:16 EST 2004

On Monday, Mar 15, 2004, at 09:05 US/Eastern, Barry Jaspan wrote:
> In my experience, re-lockable mutexes making programming easier.  If 
> you have an API with two external entry points a() and b(), both of 
> which lock the object's mutex, but a() is best written by calling b(), 
> what do you do without re-lockable mutexes?  Sure, you can split b() 
> up into an external locking function and an internal non-locking 
> function, but that is just extra bloat, more work for the programmer, 
> it's harder to read and understand, etc.  We are already defining a 
> shim layer, and adding lock reference counting is really simple.  So 
> why not do it?

Because it can also mask the case where you lock a mutex a second time 
because you botched some code and didn't unlock it before.  Because 
that case can sometimes be caught even in a single-threaded program, 
whereas a re-lockable mutex accidentally left locked would only be 
detected when a multi-threaded program stalls some of its operation for 
no obvious reason.

If I run into cases where re-lockable mutexes would make things much 
simpler to understand, I'll consider using them.  Until then, I'd like 
to see how well we can do without them.

>> Most of these will be defined as macros.
> Haven't we regretted using macros for things in the past?  I don't see 
> the advantage.

For interfaces exposed to the application writer, yes, because it means 
exposing underlying data structures, changing library version numbers 
for changes in what should have been internal implementation details, 
not being able to hide those implementation details from application 
writers who wanted to tweak things at a low level we might later want 
to change, etc.  This stuff isn't going to get exposed.  Symbols might 
get exported from a support library, but no header describing them will 
be installed.

>   This is an efficiency hack,

Not entirely.  For debugging purposes, it helps if __FILE__, __LINE__, 
and __func__ describe the point at which the macro is invoked, not the 
source for the inline function.  And macros allow the use of short, 
convenient names without exposing them to users of the library.

>  and a decent compiler with inline hints will optimize code better 
> anyway (let's admit it, krb5 cannot claim to have been written with 
> extreme manual optimization in mind).

I've run into some resistance when suggesting more use of inline 
functions, but personally I wouldn't mind going a little more in that 
direction in general.  However, from my experience working on one 
compiler, I would disagree with your assertion that the compiler will 
generally optimize inline functions better than macros; in fact, 
sometimes it does a poorer job.

I don't consider it a big deal whether these are macros or inline 
functions (or some combination, to get the call-site debug data).  The 
important point I had intended to convey is that there will not be 
external symbols visible by those names.  If any symbols needed to be 
exported, they will use the krb5int_ prefix.  (And if any of the macros 
should grow too unwieldy to maintain as macros or inline functions, 
they'd be put in separate source files under different names, and a new 
macro would effectively rename the function being called.)


More information about the krbdev mailing list