Antoine Rougier finished his internship recently so here's a summary of
what he did in the "backends" branch. For the record, the goal of his
work was to explore how to change our backends into proper plugins so
that we can easily avoid hard dependencies between the hwloc core and
external libraries such as CUDA, libpci, ...
He defined three types of backends:
* "Base" is a normal OS backend such as Linux/Solaris/... This guy
manages PU, Cores, Sockets, ... Only one of these can be used at the
* "Additional" is what is added to "Base" backends. This is libpci, and
things added inside PCI devices (CUDA, ...). Multiple of these may be
used at the same time. They are likely invoked sequentially after the
Base backend discovery.
* "Global" is a special case for XML, Synthetic and Custom, which
replaces both Base and Additional. It's not clear that this type will be
needed in the end, "Base" with a special flag to disable "Additional"
backends might be enough.
During init(), all existing backends are placed on a list of "available"
backends. And a list of "enabled" backends is initialized to empty.
Between init() and load(), calling set_xml(), set_synthetic(),
set_fsroot(), ... will append some backends to the "enabled" list
(actually two lists, one for Base, one for Additional).
During load(), we check whether some Base backends are "enabled".
Otherwise we enable the default one of the current OS. Then we actually
discover things using the (unique) enabled Base backend followed by all
enabled Additional backends.
Aside from the main "discover" callback, backends may also define some
callbacks to be invoked when new object are created. The main example is
Linux creating "OS devices" when a new "PCI device" is added by the PCI
backend. CUDA could use that too to fill GPU PCI devices. This is not
strictly needed since adding these devices could still be done later,
once the PCI backend is done. We'll see.
I'll work on putting all this in a branch soon.
All this is about making interaction between backends nicer. Once this
is done, we'll be able to make actual plugins out of all this. One
problem that will come is that some backends are almost directly used
from outside the core. For instance exporting a topology to XML is a
public API call going down to XML plugin. lstopo and hwloc-ps using
Linux-specific tid_get_cpubind() calls causes similar problems.
Instead of allowing random API calls into plugin internals, we could
keep these backends internal, i.e. not making them plugins. At least for
OS backends, it makes sense. "synthetic" and "custom" also have no
reason to be pluginified either, they depend on nothing.
XML would like to be a plugin so that we stop depending on libxml2, but
we have an intermediate level to ease this. The main XML functions do
not depend on libxml2, they can remain internal and call either libxml2
or our minimalistic no-libxml2 support underneath. So we can keep the
common code and the minimalistic support internal, and only move the
libxml2-specific callbacks to a plugin.
Summary of what plugins we could have in the end:
* for main backends:
+ internal: synthetic, xml-core, custom, linux, solaris, ...
+ plugins: pci, cuda, display, ...
* for "low-level" xml backends:
+ internal: minimalistic xml support
+ plugin: libxml2
* and maybe lstopo backends one day
+ internal: console, txt, fig, windows
+ plugin: cairo