(we've been having some off-list discussions about when to release 0.9.1 -- we decided that we wanted to add dynamic CPU sets as the last feature before release. So now we've been talking about how/what to do for dynamic CPU sets. It only occurred to me mid-thread that there was no reason to have these discussions off-list, so I'm moving the discussion to hwloc-devel. Hopefully that's enough context to pick up this thread mid-stream...)

On Oct 2, 2009, at 8:19 AM, Samuel Thibault wrote:

There's an ugly ABI truth to this methodology that we got bitten by in
OMPI.  :-\  If the struct changes size from version A to B, the ABI
changes (meaning that we'll have to bump the "incompatible" flag in
the so version).  It's completely non-intuitive, but I swear it's
true.  :-(

Err, because we are using inlines that's true, yes, and so recompilation
is needed, but is it really a problem?

Right -- we already established that we're not interested in ABI -- do the Right Things with the so version and let that be enough. I just wanted to point it out because it's a common misconception that just passing a function pointer as a handle makes you future proof (we learned the hard way).

Else we may not inline cpuset functions and in that case the application
never gets in contact with the actual size of the pointed structure, I
don't see how there can be ABI issues.


1) I vote for not inlining -- do we *really* care about the performance that much? I don't think it matters enough to care.

2) The linker needs the actual size of the struct (even if it's not visible in the C language) to link against the .so properly and do addressing / pointer math properly to find global handle symbols. In short, the *executable* has the final size of the struct encoded in it. This is non-intuitive, but I swear it's true. Try this:

private.h:
struct foo {
  int a;
};

private.c:
#include <private.h>
struct foo public_foo_instance;
struct foo *public_handle = &public_foo_instance;

public.h:
struct foo;
typedef struct foo *handle_t;
extern struct foo *public_handle;

Compile, make, and install the above as libmiddleware.so.

my_app.c:
#include <public.h>
handle_t my_handle = public_handle;
int main() { return 0; }

Compile and make my_app, linking against -lmiddleware. It compiles, links, and runs fine.

Now go change private.h and add another member to the struct. Recompile and re-install libmiddleware. Now run my_app again -- without re-compiling/re-linking. You'll get warnings from the linker about how the struct changed size.

This may all be moot if we have no global handle instances (akin to MPI_COMM_WORLD) that are used outside of the middleware...?

--
Jeff Squyres
jsquy...@cisco.com

Reply via email to