On Sun, 17 May 2015, Matt Thomas wrote:
On May 17, 2015, at 3:40 PM, Paul Goyette <[email protected]> wrote:
My crusade for modularity has arrived at the pcppi(4) driver, and I've
discovered that there are a number of places in the code where a #if is used to
determine whether or not some _other_ driver is available to provide certain
routines. For pcppi(4), these dependencies are for the attimer(4) and pckbd(4)
drivers. (While I haven't yet gone searching, I'd be willing to wager that
there are other similar examples in other drivers.)
These #if constructs make it very difficult to modularize these drivers.
I'd like to propose the following new kernel mechanism that will allow us to
remove these #if dependencies.
1. Extend the struct cfattach to have an additional member, and create
a new CFATTACH_DECL4_NEW macro to initialize it (and updates to the
existing CFATTACH_* family to default the value to NULL).
int (*ca_callback)(device_t, int, void *);
(This will require a kernel version bump.)
Ewww. Gross.
I didn't really like it either, but I couldn't think of another way to
reduce the #if spaghetti.
(And I really didn't like the name ca_callback either, but I couldn't
think of any better name.)
It might be better to use weak symbols and then fix them up later.
I thought of using weak symbols, but I wasn't really sure how it would
work....
If you call a routine via a weak symbol, and the routine/symbol isn't
defined, doesn't that just result in a call to "0"? Would the caller
need to check first to see if the routine were defined? (ie, have a
local pointer variable initialized to the weak-symbol, and code checks
to see if the pointer is non-NULL before calling?)
Would the weak-symbol mechanism work in a modular environment, where
either driver could be the first to exist? If neither driver is
included in the kernel, and there is no hard dependency between the
drivers, then you could 'modload a ; modload b' vs 'modload b ; modload
a' and it should work the same in either case. So, weak-symbol fix-up
would need to work regardless of whether the references are already
loaded. (You can't just fix-up things in the module currently being
loaded, you have to see if previously-loaded modules have any weak
"forward" references, too.)
If the module which provides the "real" definition of the weak symbol
gets unloaded, does the symbol "revert" to a weak one? And do any
references which may have already been fixed-up get similarly reverted?
(ie, the local-pointer-variable would need to get reset back to NULL).
I'm not sure that a "passive" linker-based solution would work in all
cases. I don't have any specific examples at hand, but it just "feels"
like a more active mechanism might sometimes be needed, where one driver
can tell the other "I'm being unloaded, so clean up any state you may
have that refers to me and/or abort any in-progress activity."
It seems to me that, if this were only a compile time or static-link
time problem, a weak-symbol solution might work / be appropriate. But
in a run-time/dynamic-link-unlink situation it "feels" insufficient.
Sorry for not being able to replace "feels" with more specific details
and concrete examples.
:)
-------------------------------------------------------------------------
| Paul Goyette | PGP Key fingerprint: | E-mail addresses: |
| (Retired) | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com |
| Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org |
-------------------------------------------------------------------------